当前位置:   article > 正文

javaweb--老杜_老杜java web

老杜java web

使用纯servlet做一个单表的CRUD操作–老杜

  • 实现步骤

    • 第一步:准备一张数据库表(sql脚本

      • CREATE TABLE `dept` (
          `deptno` int(11) NOT NULL,
          `dname` varchar(255) DEFAULT NULL,
          `loc` varchar(255) DEFAULT NULL,
          PRIMARY KEY (`deptno`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gm2RN213-1688370861032)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\1.png)]

    ---
    
    • 1
    • 第二步:准备一套HTML页面(项目原型)先把页面项目跑通即可,后面会做功能具体实现

      • 把HTML页面准备好

      • 然后将HTML页面中的链接都能跑通

      • 应该设计那些页面呢?

        • 新增页面:add.html

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title>新增部门</title>
          	</head>
          	<body>
          		<h1>新增部门</h1>
          		<hr>
          		<form action="list.html" method="get">
          			部门编号<input type="text" name="deptno"><br>
          			部门名称<input type="text" name="dname"><br>
          			部门位置<input type="text" name="loc"><br>
          			<input type="submit" value="保存">
          		</form>
          	</body>
          </html>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17

          在这里插入图片描述

        • 修改页面:edit.html

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title>修改部门</title>
          	</head>
          	<body>
          		<h1>修改部门</h1>
          		<hr>
          		<form action="list.html" method="get">
          			部门编号<input type="text" name="deptno" value="20"><br>
          			部门名称<input type="text" name="dname" value="销售部"><br>
          			部门位置<input type="text" name="loc" value="北京"><br>
          			<input type="submit" value="保存">
          		</form>
          	</body>
          </html>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17

          在这里插入图片描述

        • 查看详情页面:detail.html

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title>部门详情</title>
          	</head>
          	<body>
          		<h1>部门详情</h1>
          		<hr>
          		部门编号:20 <br />
          		部门名称:销售部<br />
          		部门位置:北京<br />
          		<input type="button" value="后退" onclick="window.history.back()">
          	</body>
          </html>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15

        在这里插入图片描述

        • 欢迎页面(首页面):index.html

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title>欢迎使用OA系统</title>
          	</head>
          	<body>
          		<a href="list.html">查看部门列表</a>
          	</body>
          </html>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
        • 列表页面:list.html

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title>部门列表</title>
          	</head>
          	<body>
          		<h1 align="center">部门列表</h1>
          		<hr>
          		<table border="1px" align="center"  width="50%">
          			<tr>
          				<th>序号</th>
          				<th>部门编号</th>
          				<th>部门名称</th>
          				<th>操作</th>
          			</tr>
          			<tr>
          				<td>1</td>
          				<td>10</td>
          				<td>销售部</td>
          				<td>
          					<a href="">删除</a>
          					<a href="edit.html">修改</a>
          					<a href="detail.html">详情</a>
          				</td>
          			</tr>
          			<tr>
          				<td>2</td>
          				<td>20</td>
          				<td>研发部</td>
          				<td>
          					<a href="">删除</a>
          					<a href="edit.html">修改</a>
          					<a href="detail.html">详情</a>
          				</td>
          			</tr>
          			<tr>
          				<td>3</td>
          				<td>30</td>
          				<td>运营部</td>
          				<td>
          					<a href="">删除</a>
          					<a href="edit.html">修改</a>
          					<a href="detail.html">详情</a>
          				</td>
          			</tr>
          		</table>
          		<hr>
          		<a href="add.html">新增部门</a>
          	</body>
          </html>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51

          在这里插入图片描述


    • 第三步:分析我们这个系统包括了哪些功能?

      • 什么叫做一个功能?
        • 只要这个操作连接了数据库,就表示一个独立的功能
      • 包括哪些功能?
        • 查看部门列表
        • 新增部门
        • 删除部门
        • 查看部门详细信息
        • 跳转到修改页面
        • 修改部门

    • 第四步:在IDEA当中搭建开发环境

      • 创建一个webapp(给这个webapp添加servlet-api.jar和jsp-api.jar)

        • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Tp7EFLf-1688370813816)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\6.png)]
      • 向webapp中添加数据库jar包(MySQL驱动

        • 必须在WEB-INF目录下新建lib目录,然后将MySQL的驱动jar包拷贝到这个lib目录下,这个必须叫lib。
        • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sq1keVDP-1688370813817)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\7.png)]
        • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7lhGjMxq-1688370813817)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\8.png)]
      • JDBC的工具类

        • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XM9ynL2H-1688370813817)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\9.png)]

        • //配置文件信息
          driver=con.musql.jdbc.Driver
          url=jdbc:mysql://localhost:3306/javaweb
          user=root
          password=123456
          
          • 1
          • 2
          • 3
          • 4
          • 5
        • package ServletProject.utils;
          
          import java.beans.Statement;
          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          import java.util.ResourceBundle;
          
          /*
          * JDBC的工具类
          * */
          public class DButil {
          
              //静态变量,在类加载时执行
              private static ResourceBundle bundle=ResourceBundle.getBundle("resources.jdbc");//绑定资源文件
              //根据属性配置文件的key配置value
              private static String driver=bundle.getString("driver");
              private static String url=bundle.getString("url");
              private static String user=bundle.getString("user");
              private static String password=bundle.getString("password");
              static {
                  //注册驱动,执行一次即可,放在静态代码块当中,类加载时执行
                  try{
                      //"com.mysql.jdbc.Driver"是链接数据库的驱动,不能写死,因为以后可能会链接Oracle数据库,以防修改Java源代码,保证项目正常。
                      Class.forName(driver);
                  }catch (ClassNotFoundException e){
                      e.printStackTrace();
                  }
          
              }
              //获取数据库链接对象
              public static Connection getConnection() throws SQLException {
                  //获取链接
                  Connection conn= DriverManager.getConnection(url,user,password);
                  return conn;
              }
          
              //释放资源
              public static void close(Connection conn, Statement ps, ResultSet rs){
                  if (rs!=null){
                      try {
                          rs.close();
                      }catch (SQLException e){
                          e.printStackTrace();
                      }
                  }
                  if (ps!=null){
                      try {
                          ps.close();
                      }catch (SQLException e){
                          e.printStackTrace();
                      }
                  }
                  if (conn!=null){
                      try {
                          conn.close();
                      }catch (SQLException e){
                          e.printStackTrace();
                      }
                  }
              }
          }
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64

    • 第五步:实现第一个功能:查看部门列表

      • 第一:先修改前端欢迎页面的超链接,因为用户先点击的就是这个超链接

        • <!-- 前端超链接发送请求的时候,请求路径以/开始,并且要带着项目名-->
          		<a href="/ServletProject/dept/list">查看部门列表</a>
          
          • 1
          • 2
      • 第二:编写web.xm文件

            <servlet>
                <servlet-name>list</servlet-name>
                <servlet-class>????</servlet-class>
            </servlet>
            <servlet-mapping>
                <servlet-name>list</servlet-name>
                <url-pattern>/dept/list</url-pattern>
            </servlet-mapping>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      • 第三:编写DeptListServlet类继承HttpServlet类,然后重写doGet方法

        • package action;
          
          import jakarta.servlet.ServletException;
          import jakarta.servlet.http.HttpServlet;
          import jakarta.servlet.http.HttpServletRequest;
          import jakarta.servlet.http.HttpServletResponse;
          
          import java.io.IOException;
          
          public class DeptListServlet extends HttpServlet {
              @Override
              protected void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
                  
              }
          }
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
      • 第四:在DeptListServlet类的doGet方法中链接数据库,查询所有的部门,动态展示部门列表页面

        • 分析list.html页面那部分是固定死的,那部分是变化的

        • package action;
          //查看部门列表功能实现
          import ServletProject.utils.DButil;
          import jakarta.servlet.ServletException;
          import jakarta.servlet.http.HttpServlet;
          import jakarta.servlet.http.HttpServletRequest;
          import jakarta.servlet.http.HttpServletResponse;
          
          import java.io.IOException;
          import java.io.PrintWriter;
          import java.sql.Connection;
          import java.sql.PreparedStatement;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          
          public class DeptListServlet extends HttpServlet {
              @Override
              protected void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
                  response.setContentType("text/html");
                  PrintWriter out= response.getWriter();
          
          out.print("        <!DOCTYPE html>");
          out.print("<html>");
          out.print("	<head>");
          out.print("		<meta charset='utf-8'>");
          out.print("		<title>部门列表</title>");
          out.print("	</head>");
          out.print("	<body>");
          out.print("		<h1 align='center'>部门列表</h1>");
          out.print("		<hr>");
          out.print("		<table border='1px' align='center'  width='50%'>");
          out.print("			<tr>");
          out.print("				<th>序号</th>");
          out.print("				<th>部门编号</th>");
          out.print("				<th>部门名称</th>");
          out.print("				<th>操作</th>");
          out.print("			</tr>");
          
          
          
                  //连接数据库,查询所有的部门
                  Connection conn=null;
                  PreparedStatement ps=null;
                  ResultSet rs=null;
                  try {
                      conn=DButil.getConnection();
                      String sql="select deptno,dname,loc from dept";
                      ps=conn.prepareStatement(sql);
                      rs= ps.executeQuery();
                      int i=0;
                      //获取到的数据库数据
                      while (rs.next()){
                          String deptno=rs.getString("deptno");
                          String dname=rs.getString("dname");
                          String loc=rs.getString("loc");
                          out.print("			<tr>");
                          out.print("				<td>"+(++i)+"</td>");
                          out.print("				<td>"+deptno+"</td>");
                          out.print("				<td>"+dname+"</td>");
                          out.print("				<td>");
                          out.print("					<a href=''>删除</a>");
                          out.print("					<a href='edit.html'>修改</a>");
                          out.print("					<a href='detail.html'>详情</a>");
                          out.print("				</td>");
                          out.print("			</tr>");
                      }
                  } catch (SQLException throwables) {
                      throwables.printStackTrace();
                  }finally {
                      //释放资源
                      DButil.close(conn,ps,rs);
                  }
                  out.print("		</table>");
                  out.print("		<hr>");
                  out.print("		<a href='add.html'>新增部门</a>");
                  out.print("	</body>");
                  out.print("</html>");
              }
          }
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
        • 现在写完这个功能之后,你会有一种感觉,感觉开发很繁琐,只写servlet代码太麻烦了


    • 第六步:实现查看部门详情功能(从前端往后端一步一步实现)

      • 首先要考虑的是,用户点击的是什么?用户点击的东西在哪里?

        • 一定要先找到用户点的“详情”在哪里,在Java程序中找到了

        • <a href='/ServletProject/dept/detail'>详情</a>
          
          • 1
        • 详情这里是需要连接数据库的,所以这个超链接点击之后也是需要执行一段Java代码的,所以这里的超链接路径是servlet对象

        • 注意:修改路径之后,这个路径是需要加项目名的(前端向后端发送请求需要加项目名)

        • 又因为根路径可以动态获取,所以这里可以更改为:

          //获取应用的根路径
          String contextPath = request.getContextPath();
          <a href='"+contextPath+"/dept/detail'>详情</a>
          
          • 1
          • 2
          • 3
        • 又又因为详情需要有判断具体是那个部门的详情,所以在发送请求的时候可以把部门编号发送给后端,后端通过数据库来选出相应的部门信息:

          <a href='"+contextPath+"/dept/detail?"+deptno+"'>详情</a>
          
          • 1
        • 接下来就需要完成该功能的servlet对象就行了:

          • 编写一个DeptDetailServlet继承HttpServlet,重写doGet方法,在该方法中连接数据库,查询相应部门信息

          • package action;
            
            import ServletProject.utils.DButil;
            import jakarta.servlet.ServletException;
            import jakarta.servlet.http.HttpServlet;
            import jakarta.servlet.http.HttpServletRequest;
            import jakarta.servlet.http.HttpServletResponse;
            
            import java.io.IOException;
            import java.io.PrintWriter;
            import java.sql.Connection;
            import java.sql.PreparedStatement;
            import java.sql.ResultSet;
            import java.sql.SQLException;
            
            public class DeptDetailServlet extends HttpServlet {
                @Override
                protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                    //获取请求中url的部门编号
                    String deptno=request.getParameter("deptno");
            
            
                    response.setContentType("text/html");
                    PrintWriter out = response.getWriter();
            
            out.print("        <!DOCTYPE html>");
            out.print("<html>");
            out.print("	<head>");
            out.print("		<meta charset='utf-8'>");
            out.print("		<title>部门详情</title>");
            out.print("	</head>");
            out.print("	<body>");
            out.print("		<h1>部门详情</h1>");
            out.print("		<hr>");
            out.print("                部门编号:"+deptno+" <br />");
            
            
            
                    //连接数据库,根据部门编号查询信息
                    Connection conn=null;
                    PreparedStatement ps=null;
                    ResultSet rs=null;
                    try {
                        conn= DButil.getConnection();
                        String sql="select deptno,dname,loc from dept where deptno=?";
                        ps=conn.prepareStatement(sql);
                        ps.setString(1,deptno);
                        rs= ps.executeQuery();
                        if (rs.next()){
                            String dname= rs.getString("dname");
                            String loc=rs.getString("loc");
                            out.print("                部门名称:"+dname+"<br />");
                            out.print("        部门位置:"+loc+"<br />");
                        }
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }finally {
                        DButil.close(conn,ps,rs);
                    }
                    out.print("		<input type='button' value='后退' οnclick='window.history.back()'>");
                    out.print("	</body>");
                    out.print("</html>");
                }
            }
            
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
            • 53
            • 54
            • 55
            • 56
            • 57
            • 58
            • 59
            • 60
            • 61
            • 62
            • 63
            • 64
            • 65

    • 第七步:删除功能

      • 怎么开始?从哪开始?从前端页面开始,用户点击删除按钮,提示用户是否删除

        <a href='javascript:void(0)' onclick='del("+deptno+")'>删除</a>
        
        out.print("   <script type='text/javascript'>");
        out.print("               function del(dno){");
        out.print("                   if (window.confirm('亲,删了就不能恢复了哦')){");
        out.print("                       document.location.href='/ServletProject/dept/delete?deptno='+dno");
        out.print("                   }");
        out.print("       }");
        out.print("   </script>");
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
      • 以上的前端程序要写到后端的Java代码当中

      • 删除功能servlet对象代码

        package action;
        
        import ServletProject.utils.DButil;
        import jakarta.servlet.ServletException;
        import jakarta.servlet.http.HttpServlet;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        
        import java.io.IOException;
        import java.io.PrintWriter;
        import java.sql.Connection;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        
        public class DeptDeleteServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                String deptno=request.getParameter("deptno");
        
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
        
                int count=0;
                Connection conn=null;
                PreparedStatement ps=null;
        
                try {
                    conn=DButil.getConnection();
        
                    //开启事务
                    conn.setAutoCommit(false);
        
                    String sql ="delete from dept where deptno=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,deptno);
                    //返回值是影响了数据库几行数据的结果
                    count=ps.executeUpdate();
                    //事务提交
                    conn.commit();
                } catch (SQLException throwables) {
                    //遇到异常回滚
                    if (conn!=null){
                        try {
                            conn.rollback();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                }finally {
                    DButil.close(conn,ps,null);
                }
                if (count==1){
                    //删除成功,回到列表页面
                    //目前使用转发
                    request.getRequestDispatcher("/dept/list").forward(request,response);
                }else {
                    //删除失败
                }
            }
        }
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62

    • 第八步:新增部门

      • package action;
        
        import ServletProject.utils.DButil;
        import jakarta.servlet.ServletException;
        import jakarta.servlet.http.HttpServlet;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        
        import java.io.IOException;
        import java.sql.Connection;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        
        public class DeptSaveServlet extends HttpServlet {
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
                //获取部门信息
                //注意乱码问题(tomcat10不会出现)
                request.setCharacterEncoding("UTF-8");
                String deptno=request.getParameter("deptno");
                String dname=request.getParameter("dname");
                String loc=request.getParameter("loc");
        
                //连接数据库执行插入语句
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
                int count=0;
                try {
                    conn=DButil.getConnection();
                    String sql="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')";
                    ps=conn.prepareStatement(sql);
                    count=ps.executeUpdate();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,rs);
                }
                if (count==1){
                    //保存成功跳转到列表页面
                    //转发是一次请求,之前是post请求,后面也是post请求,转发的下一个servlet对象只有doget方法,所以会报405错误
                    //解决这个错误的暂时的方法是在list对象中写一个dopost方法,该方法调用doget方法
                    request.getRequestDispatcher("/dept/list").forward(request,response);
                }else {
                    //保存失败跳转到错误页面
                }
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50

    • 第九步:跳转到修改部门的界面

      • package action;
        
        import ServletProject.utils.DButil;
        import jakarta.servlet.RequestDispatcher;
        import jakarta.servlet.ServletException;
        import jakarta.servlet.http.HttpServlet;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        
        import java.io.IOException;
        import java.io.PrintWriter;
        import java.sql.Connection;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        
        public class DeptEditServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                //获取部门编号
                String deptno = request.getParameter("deptno");
        
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
        
        out.print("        <!DOCTYPE html>");
        out.print("<html>");
        out.print("	<head>");
        out.print("		<meta charset='utf-8'>");
        out.print("		<title>修改部门</title>");
        out.print("	</head>");
        out.print("	<body>");
        out.print("		<h1>修改部门</h1>");
        out.print("		<hr>");
        out.print("		<form action='/dept/list' method='post'>");
        out.print("                部门编号<input type='text'' name='deptno' value='"+deptno+"'><br>");
                try {
                    conn= DButil.getConnection();
                    String sql="select deptno,dname,loc from dept where deptno=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,deptno);
                    rs=ps.executeQuery();
                    if (rs.next()){
                        String dname=rs.getString("dname");
                        String loc=rs.getString("loc");
                        out.print("                部门名称<input type='text'' name='dname'' value='"+dname+"'><br>");
                        out.print("                部门位置<input type='text' name='loc' value='"+loc+"'><br>");
                        String sql1="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')";
                    }
        
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,rs);
                }
        out.print("			<input type='submit'' value='保存'>");
        out.print("		</form>");
        out.print("	</body>");
        out.print("</html>");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
    • 第十步:修改部门功能实现

      package action;
      
      import ServletProject.utils.DButil;
      import jakarta.servlet.ServletException;
      import jakarta.servlet.http.HttpServlet;
      import jakarta.servlet.http.HttpServletRequest;
      import jakarta.servlet.http.HttpServletResponse;
      
      import java.io.IOException;
      import java.io.PrintWriter;
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      
      public class DeptModifyServlet extends HttpServlet {
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              request.setCharacterEncoding("UTF-8");
              response.setContentType("text/html");
              PrintWriter out = response.getWriter();
              //获取修改表单的数据
              String deptno = request.getParameter("deptno");
              String dname = request.getParameter("dname");
              String loc = request.getParameter("loc");
              //连接数据库,执行更新语句
              Connection conn=null;
              PreparedStatement ps=null;
              int count=0;
              try {
                  conn= DButil.getConnection();
                  String sql="update dept set dname=?,loc=? where deptno=?";
                  ps=conn.prepareStatement(sql);
                  ps.setString(1,dname);
                  ps.setString(2,loc);
                  ps.setString(3,deptno);
                  count=ps.executeUpdate();
              } catch (SQLException throwables) {
                  throwables.printStackTrace();
              }finally {
                  DButil.close(conn,ps,null);
              }
              if (count==1){
                  //更新成功,返回list页面
                  request.getRequestDispatcher("/dept/list").forward(request,response);
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 注意犯得一个错误:

        			String sql="update dept set dname=?,loc=? where deptno=?";
                    ps=conn.prepareStatement(sql);//这一句要写在下面三句前面,否则无法执行成功,浏览器报500错误
                    ps.setString(1,dname);
                    ps.setString(2,loc);
                    ps.setString(3,deptno);
        
        • 1
        • 2
        • 3
        • 4
        • 5

最后的项目结构:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fpk3riYg-1688370813818)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\10.png)]

在一个web应用中应该如何完成一个资源的跳转

  • 在一web应用中有两种方式完成资源的跳转:

    • 转发:在一次请求中,像是通过当前网页加载到要跳转的网页,请求资源不变(张三问李四借钱,李四没钱就向王五借了钱,然后李四把借到的钱再借给张三)

      request.getRequestDispatcher("/dept/list").forward(request,response);
      
      • 1
    • 重定向:不在一次请求中,像当前网页告诉web应用它像进入的网页的url,然后web应用再通过该网址加载到目标网页(张三问李四借钱,李四没钱,就告诉张三,王五有钱,然后张三就直接向王五借到钱)

      response.sendRedirect(request.getContextPath()+"/dept/list");
      
      • 1

将项目中的资源跳转修改为合适的跳转方式

  • 删除之后,重定向
  • 修改之后,重定向
  • 保存之后,重定向

Servlet注解,简化配置

  • 分析项目中的web.xml文件

    • 现在只是一个增删改查的项目,配置文件就需要写很多代码,那么对一个大项目来说,这个配置文件就会很大。
    • 并且在web.xml文件中继续Servlet的信息配置,开发效率也比较低,该文件的信息也基本不改变,可不可以直接放到Java代码里面?可以的。
  • Servlet3.0版本之后,推出了各种Servlet基于注解开发

    • 优点:开发效率高,不要编写大量配置信息。

    • 有一些需要改变的信息,还是要配置到web.xml文件。

         XML文件的内容
      	<servlet>
              <servlet-name>delete</servlet-name>
              <servlet-class>action.DeptDeleteServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>delete</servlet-name>
              <url-pattern>/dept/delete</url-pattern>
          </servlet-mapping>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
  • 我们的第一个注解:

    import jakarta.servlet.annotation.WebServlet;
    
    • 1
    • 在Servlet类上使用:@WebServlet,WebSevlet注解中有哪些属性呢?

      • name属性:用来指定Servlet的名字,等同于delete

      • urlPatterns属性:用来指定Servlet的映射路径,可以指定多个字符串,等同于/dept/delete

      • loadOnStartup属性:用来指定在服务器启动阶段是否加载该Servlet,等同于

      • value属性,等同于urlPatterns,在此以上还可以省略value不写**@WebServlet(“/url”)**

        package servlet;
        
        import jakarta.servlet.ServletException;
        import jakarta.servlet.annotation.WebInitParam;
        import jakarta.servlet.annotation.WebServlet;
        import jakarta.servlet.http.HttpServlet;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        
        import java.io.IOException;
        
        @WebServlet(name="hello",urlPatterns = {"/hello1","/hello2"},loadOnStartup = 1,
                initParams = {@WebInitParam(name="username",value ="root"),@WebInitParam(name = "password",value = "123456")})
        public class HelloServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
    • 注解对象使用格式:

      • @注解名称(属性名=属性值,属性名=属性值…)

使用模板方法设计模式优化项目

  • 上面的注解解决了配置文件的问题,但是现在项目仍然存在一个比较臃肿的问题:

    • 一个单表的CRUD,就写了6个Servlet。如果一个复杂的业务系统,这种开发方式,显然会导致类爆炸。
    • 怎么解决这个类爆炸问题?可以使用模板方法设计模式。
  • 怎么解决类爆炸问题?

    • 以前的设计是一个请求一个Servlet类。100个请求对应100个Servlet类,导致类爆炸。
    • 可以这样做:一个请求对应一个方法,一个业务对应一个Servlet类。
    package action;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import utils.DButil;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    @WebServlet({"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"})
    public class DeptServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //获取Servlet Path
            String servletPath=request.getServletPath();
            if ("/dept/list".equals(servletPath)){
                doList(request,response);
            }else if ("/dept/save".equals(servletPath)){
                doSave(request,response);
            }else if ("/dept/edit".equals(servletPath)){
                doEdit(request,response);
            }else if ("/dept/detail".equals(servletPath)){
                doDetail(request,response);
            }else if ("/dept/delete".equals(servletPath)){
                doDel(request,response);
            }else if ("/dept/modify".equals(servletPath)){
                doModify(request,response);
            }
        }
    
        private void doModify(HttpServletRequest request, HttpServletResponse response) throws IOException {
            request.setCharacterEncoding("UTF-8");
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            //获取修改表单的数据
            String deptno = request.getParameter("deptno");
            String dname = request.getParameter("dname");
            String loc = request.getParameter("loc");
            //连接数据库,执行更新语句
            Connection conn=null;
            PreparedStatement ps=null;
            int count=0;
            try {
                conn= DButil.getConnection();
                String sql="update dept set dname=?,loc=? where deptno=?";
                ps=conn.prepareStatement(sql);
                ps.setString(1,dname);
                ps.setString(2,loc);
                ps.setString(3,deptno);
                count=ps.executeUpdate();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DButil.close(conn,ps,null);
            }
            if (count==1){
                //更新成功,返回list页面
                response.sendRedirect(request.getContextPath()+"/dept/list");
    
            }
        }
    
        private void doDetail(HttpServletRequest request, HttpServletResponse response) throws IOException {
            //获取请求中url的部门编号
            String deptno=request.getParameter("deptno");
    
    
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
    
            out.print("        <!DOCTYPE html>");
            out.print("<html>");
            out.print("	<head>");
            out.print("		<meta charset='utf-8'>");
            out.print("		<title>部门详情</title>");
            out.print("	</head>");
            out.print("	<body>");
            out.print("		<h1>部门详情</h1>");
            out.print("		<hr>");
            out.print("                部门编号:"+deptno+" <br />");
    
    
    
            //连接数据库,根据部门编号查询信息
            Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            try {
                conn= DButil.getConnection();
                String sql="select deptno,dname,loc from dept where deptno=?";
                ps=conn.prepareStatement(sql);
                ps.setString(1,deptno);
                rs= ps.executeQuery();
                if (rs.next()){
                    String dname= rs.getString("dname");
                    String loc=rs.getString("loc");
                    out.print("                部门名称:"+dname+"<br />");
                    out.print("        部门位置:"+loc+"<br />");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DButil.close(conn,ps,rs);
            }
            out.print("		<input type='button' value='后退' οnclick='window.history.back()'>");
            out.print("	</body>");
            out.print("</html>");
        }
    
        private void doEdit(HttpServletRequest request, HttpServletResponse response) throws IOException {
            //获取部门编号
            String deptno = request.getParameter("deptno");
            //获取根路径
            String contextPath = request.getContextPath();
    
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
    
            out.print("        <!DOCTYPE html>");
            out.print("<html>");
            out.print("	<head>");
            out.print("		<meta charset='utf-8'>");
            out.print("		<title>修改部门</title>");
            out.print("	</head>");
            out.print("	<body>");
            out.print("		<h1>修改部门</h1>");
            out.print("		<hr>");
            out.print("		<form action='"+contextPath+"/dept/modify' method='post'>");
            out.print("                部门编号<input type='text'' name='deptno' value='"+deptno+"'><br>");
            try {
                conn= DButil.getConnection();
                String sql="select deptno,dname,loc from dept where deptno=?";
                ps=conn.prepareStatement(sql);
                ps.setString(1,deptno);
                rs=ps.executeQuery();
                if (rs.next()){
                    String dname=rs.getString("dname");
                    String loc=rs.getString("loc");
                    out.print("                部门名称<input type='text'' name='dname'' value='"+dname+"'><br>");
                    out.print("                部门位置<input type='text' name='loc' value='"+loc+"'><br>");
                }
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DButil.close(conn,ps,rs);
            }
            out.print("			<input type='submit'' value='保存'>");
            out.print("		</form>");
            out.print("	</body>");
            out.print("</html>");
        }
    
        private void doSave(HttpServletRequest request, HttpServletResponse response) throws IOException {
            //获取部门信息
            //注意乱码问题(tomcat10不会出现)
            request.setCharacterEncoding("UTF-8");
            String deptno=request.getParameter("deptno");
            String dname=request.getParameter("dname");
            String loc=request.getParameter("loc");
    
            //连接数据库执行插入语句
            Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            int count=0;
            try {
                conn=DButil.getConnection();
                String sql="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')";
                ps=conn.prepareStatement(sql);
                count=ps.executeUpdate();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DButil.close(conn,ps,rs);
            }
            if (count==1){
                //保存成功跳转到列表页面
                //转发是一次请求,之前是post请求,后面也是post请求,转发的下一个servlet对象只有doget方法,所以会报405错误
                //解决这个错误的暂时的方法是在list对象中写一个dopost方法,该方法调用doget方法
                response.sendRedirect(request.getContextPath()+"/dept/list");
            }else {
                //保存失败跳转到错误页面
            }
        }
    
        private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException {
            //获取应用的根路径
            String contextPath = request.getContextPath();
    
            response.setContentType("text/html");
            PrintWriter out= response.getWriter();
    
            out.print("        <!DOCTYPE html>");
            out.print("<html>");
            out.print("	<head>");
            out.print("		<meta charset='utf-8'>");
            out.print("		<title>部门列表</title>");
    
            out.print("   <script type='text/javascript'>");
            out.print("               function del(dno){");
            out.print("                   if (window.confirm('亲,删了就不能恢复了哦')){");
            out.print("                       document.location.href='/ServletProject/dept/delete?deptno='+dno");
            out.print("                   }");
            out.print("       }");
            out.print("   </script>");
    
            out.print("	</head>");
            out.print("	<body>");
            out.print("		<h1 align='center'>部门列表</h1>");
            out.print("		<hr>");
            out.print("		<table border='1px' align='center'  width='50%'>");
            out.print("			<tr>");
            out.print("				<th>序号</th>");
            out.print("				<th>部门编号</th>");
            out.print("				<th>部门名称</th>");
            out.print("				<th>操作</th>");
            out.print("			</tr>");
    
    
    
            //连接数据库,查询所有的部门
            Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            try {
                conn=DButil.getConnection();
                String sql="select deptno,dname,loc from dept";
                ps=conn.prepareStatement(sql);
                rs= ps.executeQuery();
                int i=0;
                //获取到的数据库数据
                while (rs.next()){
                    String deptno=rs.getString("deptno");
                    String dname=rs.getString("dname");
                    String loc=rs.getString("loc");
                    out.print("			<tr>");
                    out.print("				<td>"+(++i)+"</td>");
                    out.print("				<td>"+deptno+"</td>");
                    out.print("				<td>"+dname+"</td>");
                    out.print("				<td>");
                    out.print("					<a href='javascript:void(0)' οnclick='del("+deptno+")'>删除</a>");
                    out.print("					<a href='"+contextPath+"/dept/edit?deptno="+deptno+"'>修改</a>");
                    out.print("					<a href='"+contextPath+"/dept/detail?deptno="+deptno+"'>详情</a>");
                    out.print("				</td>");
                    out.print("			</tr>");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                //释放资源
                DButil.close(conn,ps,rs);
            }
            out.print("		</table>");
            out.print("		<hr>");
            out.print("		<a href='"+contextPath+"/add.html'>新增部门</a>");
            out.print("	</body>");
            out.print("</html>");
        }
    
        private void doDel(HttpServletRequest request, HttpServletResponse response) throws IOException{
            String deptno=request.getParameter("deptno");
    
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
    
            int count=0;
            Connection conn=null;
            PreparedStatement ps=null;
    
            try {
                conn=DButil.getConnection();
    
                //开启事务
                conn.setAutoCommit(false);
    
                String sql ="delete from dept where deptno=?";
                ps=conn.prepareStatement(sql);
                ps.setString(1,deptno);
                //返回值是影响了数据库几行数据的结果
                count=ps.executeUpdate();
                //事务提交
                conn.commit();
            } catch (SQLException throwables) {
                //遇到异常回滚
                if (conn!=null){
                    try {
                        conn.rollback();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }finally {
                DButil.close(conn,ps,null);
            }
            if (count==1){
                //删除成功,回到列表页面
    
                response.sendRedirect(request.getContextPath()+"/dept/list");
            }else {
                //删除失败
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315

分析使用纯粹的Servlet开发web应用的缺陷

  • 在Servlet当中编写HTML/CSS/JS等前端代码,有什么问题?
    • Java程序中编写前端代码,编写难度大,麻烦、程序耦合度非常高、代码不美观、维护成本太高。
  • 思考以下,如果是你,你准备怎么解决这个问题?
    • 使用JSP

关于B/S结构系统的会话机制(session机制)

  • 什么是会话:

    • 用户打开浏览器,进行一系列操作,最后关闭浏览器,这个过程叫一次会话。会话在服务器端也有一个对应的Java对象session。
    • 回顾:什么是一次请求:用户在浏览器上点击了一下,然后页面停下来,可以粗略地看做一次请求(因为代码里可能在第一次请求的时候会有转发和重定向的代码)。请求对应服务器的Java对象是request。
    • 一次会话包含多次请求。
  • 在Java的servlet规范中,session对应的类名:HttpSession()

  • session机制属于B/S结构的一部分:如果使用php语言开发web项目也有这个机制

  • session对象最主要的作用是:保存会话状态(用户登陆成功了,这是一种登陆成功的状态,你怎么把登陆成功的状态一直抱持,使用session对象可以保留会话状态)

  • 为什么要session对象来保存会话状态?

    • HTTP协议是一种无状态协议
    • 什么是无状态协议:点开百度页面请求的时候,B和S是连接的,百度页面呈现在页面时,B和S断开。为什么要这么做:减轻服务器压力。
  • 打开一个浏览器发送请求,分配一个session对象,在同一浏览器下再次发送请求,同样时这一个session对象,直至浏览器关闭,重新打开,或者打开其他的浏览器发送请求。

  • 为什么不使用request对象保存会话状态?为什么不使用ServletContext对象保存会话状态?

    • request对象是一次请求一个对象,该对象域太小
    • ServletContext对象是服务器启动创建,服务器关闭销毁,该对象域太大。
    • request请求域(HttpServletRequest)<session(HttpSession)<application域(ServletContext)(把这三个域比作购物:request是一次只能拿一个商品,再拿第二个商品时前面的就销毁了,application是使用服务器的用户都可以拿商品放进去,不能分清楚是谁的商品,session正好像自己的购物车,每个人进入一个浏览器九相当于进入一个超市,进入超市后每个人都拿一辆自己的购物车,自己往自己购物车放商品,如果去了其他的超市,这个购物车不能推出去,只能在后去的超市推一辆属于自己的购物车,购物结束后离开城市,归还购物车,离开超市就相当于关闭浏览器
  • session对象的实现原理:

    • HttpSession session = request.getSession();
      
      • 1
      • 这段代码很神奇,为什么每个人访问的都是自己的session?

        • 浏览器访问服务器,服务器会新建一个专属的session对象,然后session对象是存储在服务器当中,相当于浏览器对该session对象做了一个标记,如果在同一浏览器,并且浏览器没关闭的时候再次访问,可以找到该专属的session。
      • session对象什么时候销毁:

        • 因为HTTP协议是无状态协议,服务器不知道浏览器什么时候关闭,所以在关闭浏览器的时候session对象不一定销毁,而是服务器有一个session超时机制,如果界面长时间不操作,session对象也会销毁
      • session对象怎么获取:

        • HttpSession session = request.getSession();(从服务器获取当前session对象,如果没有获取到任何session对象,则新建)
        • HttpSession session = request.getSession(false);(从服务器中获取当前session对象,如果获取不到session对象,则返回一个null)
      • session的实现原理:

        • 在web服务中有一个session列表,类似map集合。
        • 这个map集合的key存储的是session的编号
        • 这个map集合的value存储的是对应的session对象
        • 用户发送第一次请求的时候:服务器会创建一个新的session对象,同时给session对象生成一个id,然后web服务器会将session的id发送给浏览器,浏览器将session的编号保存在浏览器的缓存中(session的编号是以cookie的形式保存在浏览器里的)。
        • 用户发送第二次请求的时候:会自动将浏览器缓存中的session的编号自动发送给服务器,服务器获取到编号,从session列表去获得对应的session对象。
        • 关闭浏览器后,浏览器缓存消失,浏览器中的session对象的编号消失了,web服务器的session对象依靠session超时机制,在一段时间后自动销毁,或者系统提供了安全退出功能,手动安全退出会话,手动销毁。
      • //在web.xml文件中设置session超时时间    
        	<session-config>
                <session-timeout>20</session-timeout>
            </session-config>
        
        • 1
        • 2
        • 3
        • 4
      • Cookie禁用了,session还能找到吗?

        • cookie禁用:服务器正常发送cookie给浏览器,但是浏览器拒收了。
        • 不能找到,每次请求都会新建一个session对象。
        • cookie禁用了,session机制还能实现吗?
          • 可以,使用URL重写机制(http://localhost:8080/ServletSession/sessions;JSESSIONID=A161F7B87F8AE95D86A793D8BBCD57F1)
          • 在URL后面加上sessionid,就可以找到session对象。但是重写机制会提高开发者成本,大部分网站设计的是如果你禁用cookie,网站就不能正常显示。
      • 总结一下目前我们所了解的域对象:

        request请求域(HttpServletRequest)<session(HttpSession)<application域(ServletContext)

        他们三个域都有一下三个公共方法:setAttribute,getAttribute,removeAttribute,向域当中绑定数据及管理数据

  • session掌握之后,怎么解决项目中的登录问题,怎么让登录起作用?

    • 登录成功后,将用户的登录信息存储到session当中。也就是说session中如果有用户的信息就代表用户登录成功了。

    • 注意:在jsp中会默认创建一个session,所以在获取session对象时只判断是否存在session对象是不能判断登录成功,如果想访问jsp不自动生成session,则可以添加这样一条语句:

      • <%--访问jsp的时候不生成session对象--%>
        <%@page session="false" %>
        
        • 1
        • 2
        package action;
        
        import jakarta.servlet.ServletException;
        import jakarta.servlet.annotation.WebServlet;
        import jakarta.servlet.http.HttpServlet;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        import jakarta.servlet.http.HttpSession;
        import utils.DButil;
        
        import java.io.IOException;
        import java.sql.Connection;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        
        @WebServlet("/dept/login")
        public class UserServlet extends HttpServlet {
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                //验证用户名和密码是否正确
                //获取用户名和密码
                String username = request.getParameter("username");
                String password = request.getParameter("password");
                //链接数据库验证
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
                int count=0;
                try {
                    conn=DButil.getConnection();
                    String sql="select * from users where username=? and password=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,username);
                    ps.setString(2,password);
                    rs=ps.executeQuery();
                    if (rs.next()){
                        count=1;
                    }
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,rs);
                }
                if (count==1){
                    //登陆成功
                    //获取session对象
                    HttpSession session = request.getSession();
                    session.setAttribute("username",username);
                    response.sendRedirect(request.getContextPath()+"/dept/list");
                }else {
                    response.setContentType("text/html");
                    System.out.println("登陆失败");
                }
            }
        }
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        package action;
        
        import bean.Dept;
        import jakarta.servlet.ServletException;
        import jakarta.servlet.annotation.WebServlet;
        import jakarta.servlet.http.HttpServlet;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        import jakarta.servlet.http.HttpSession;
        import utils.DButil;
        
        import java.io.IOException;
        import java.io.PrintWriter;
        import java.sql.Connection;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        import java.util.ArrayList;
        import java.util.List;
        
        @WebServlet({"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"})
        public class DeptServlet extends HttpServlet {
            @Override
            protected void service(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
                //获取session,不需要新建,只是获取当前session
                HttpSession session = request.getSession(false);
                if (session != null && session.getAttribute("username") != null) {
                    //获取Servlet Path
                    String servletPath = request.getServletPath();
                    if ("/dept/list".equals(servletPath)) {
                        doList(request, response);
                    }/*else if ("/dept/save".equals(servletPath)){
                    doSave(request,response);
                }else if ("/dept/edit".equals(servletPath)){
                    doEdit(request,response);
                }else if ("/dept/detail".equals(servletPath)){
                    doDetail(request,response);
                }else if ("/dept/delete".equals(servletPath)){
                    doDel(request,response);
                }else if ("/dept/modify".equals(servletPath)){
                    doModify(request,response);
                }*/
                }
            }
        
            private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
                //获取应用的根路径
                String contextPath = request.getContextPath();
        
                //设置一个存放部门信息的集合
                List<Dept> depts=new ArrayList();
        
                //连接数据库,查询所有的部门
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
                try {
                    conn=DButil.getConnection();
                    String sql="select deptno,dname,loc from dept";
                    ps=conn.prepareStatement(sql);
                    rs= ps.executeQuery();
                    int i=0;
                    //获取到的数据库数据
                    while (rs.next()){
                        String deptno=rs.getString("deptno");
                        String dname=rs.getString("dname");
                        String loc=rs.getString("loc");
                        //将以上零散的数据封装成Java对象,并装入集合再通过请求域提交到jsp文件
                        Dept dept=new Dept();
                        dept.setDeptno(deptno);
                        dept.setDname(dname);
                        dept.setLoc(loc);
                        depts.add(dept);
                    }
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    //释放资源
                    DButil.close(conn,ps,rs);
                }
                //将集合放入请求域
                request.setAttribute("deptList",depts);
                //转发(不能重定向,因为重定向是不同的请求,请求域存放的信息不能传给其他使用)
                request.getRequestDispatcher("/list.jsp").forward(request,response);
            }
        
            private void doModify(HttpServletRequest request, HttpServletResponse response) throws IOException {
                request.setCharacterEncoding("UTF-8");
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
                //获取修改表单的数据
                String deptno = request.getParameter("deptno");
                String dname = request.getParameter("dname");
                String loc = request.getParameter("loc");
                //连接数据库,执行更新语句
                Connection conn=null;
                PreparedStatement ps=null;
                int count=0;
                try {
                    conn= DButil.getConnection();
                    String sql="update dept set dname=?,loc=? where deptno=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,dname);
                    ps.setString(2,loc);
                    ps.setString(3,deptno);
                    count=ps.executeUpdate();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,null);
                }
                if (count==1){
                    //更新成功,返回list页面
                    response.sendRedirect(request.getContextPath()+"/dept/list");
        
                }
            }
        
            private void doDetail(HttpServletRequest request, HttpServletResponse response) throws IOException {
                //获取请求中url的部门编号
                String deptno=request.getParameter("deptno");
        
        
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
        
                out.print("        <!DOCTYPE html>");
                out.print("<html>");
                out.print("	<head>");
                out.print("		<meta charset='utf-8'>");
                out.print("		<title>部门详情</title>");
                out.print("	</head>");
                out.print("	<body>");
                out.print("		<h1>部门详情</h1>");
                out.print("		<hr>");
                out.print("                部门编号:"+deptno+" <br />");
        
        
        
                //连接数据库,根据部门编号查询信息
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
                try {
                    conn= DButil.getConnection();
                    String sql="select deptno,dname,loc from dept where deptno=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,deptno);
                    rs= ps.executeQuery();
                    if (rs.next()){
                        String dname= rs.getString("dname");
                        String loc=rs.getString("loc");
                        out.print("                部门名称:"+dname+"<br />");
                        out.print("        部门位置:"+loc+"<br />");
                    }
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,rs);
                }
                out.print("		<input type='button' value='后退' οnclick='window.history.back()'>");
                out.print("	</body>");
                out.print("</html>");
            }
        
            private void doEdit(HttpServletRequest request, HttpServletResponse response) throws IOException {
                //获取部门编号
                String deptno = request.getParameter("deptno");
                //获取根路径
                String contextPath = request.getContextPath();
        
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
        
                out.print("        <!DOCTYPE html>");
                out.print("<html>");
                out.print("	<head>");
                out.print("		<meta charset='utf-8'>");
                out.print("		<title>修改部门</title>");
                out.print("	</head>");
                out.print("	<body>");
                out.print("		<h1>修改部门</h1>");
                out.print("		<hr>");
                out.print("		<form action='"+contextPath+"/dept/modify' method='post'>");
                out.print("                部门编号<input type='text'' name='deptno' value='"+deptno+"'><br>");
                try {
                    conn= DButil.getConnection();
                    String sql="select deptno,dname,loc from dept where deptno=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,deptno);
                    rs=ps.executeQuery();
                    if (rs.next()){
                        String dname=rs.getString("dname");
                        String loc=rs.getString("loc");
                        out.print("                部门名称<input type='text'' name='dname'' value='"+dname+"'><br>");
                        out.print("                部门位置<input type='text' name='loc' value='"+loc+"'><br>");
                    }
        
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,rs);
                }
                out.print("			<input type='submit'' value='保存'>");
                out.print("		</form>");
                out.print("	</body>");
                out.print("</html>");
            }
        
            private void doSave(HttpServletRequest request, HttpServletResponse response) throws IOException {
                //获取部门信息
                //注意乱码问题(tomcat10不会出现)
                request.setCharacterEncoding("UTF-8");
                String deptno=request.getParameter("deptno");
                String dname=request.getParameter("dname");
                String loc=request.getParameter("loc");
        
                //连接数据库执行插入语句
                Connection conn=null;
                PreparedStatement ps=null;
                ResultSet rs=null;
                int count=0;
                try {
                    conn=DButil.getConnection();
                    String sql="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')";
                    ps=conn.prepareStatement(sql);
                    count=ps.executeUpdate();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }finally {
                    DButil.close(conn,ps,rs);
                }
                if (count==1){
                    //保存成功跳转到列表页面
                    //转发是一次请求,之前是post请求,后面也是post请求,转发的下一个servlet对象只有doget方法,所以会报405错误
                    //解决这个错误的暂时的方法是在list对象中写一个dopost方法,该方法调用doget方法
                    response.sendRedirect(request.getContextPath()+"/dept/list");
                }else {
                    //保存失败跳转到错误页面
                }
            }
        
            private void doDel(HttpServletRequest request, HttpServletResponse response) throws IOException{
                String deptno=request.getParameter("deptno");
        
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
        
                int count=0;
                Connection conn=null;
                PreparedStatement ps=null;
        
                try {
                    conn=DButil.getConnection();
        
                    //开启事务
                    conn.setAutoCommit(false);
        
                    String sql ="delete from dept where deptno=?";
                    ps=conn.prepareStatement(sql);
                    ps.setString(1,deptno);
                    //返回值是影响了数据库几行数据的结果
                    count=ps.executeUpdate();
                    //事务提交
                    conn.commit();
                } catch (SQLException throwables) {
                    //遇到异常回滚
                    if (conn!=null){
                        try {
                            conn.rollback();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                }finally {
                    DButil.close(conn,ps,null);
                }
                if (count==1){
                    //删除成功,回到列表页面
        
                    response.sendRedirect(request.getContextPath()+"/dept/list");
                }else {
                    //删除失败
                }
            }
        }
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101
        • 102
        • 103
        • 104
        • 105
        • 106
        • 107
        • 108
        • 109
        • 110
        • 111
        • 112
        • 113
        • 114
        • 115
        • 116
        • 117
        • 118
        • 119
        • 120
        • 121
        • 122
        • 123
        • 124
        • 125
        • 126
        • 127
        • 128
        • 129
        • 130
        • 131
        • 132
        • 133
        • 134
        • 135
        • 136
        • 137
        • 138
        • 139
        • 140
        • 141
        • 142
        • 143
        • 144
        • 145
        • 146
        • 147
        • 148
        • 149
        • 150
        • 151
        • 152
        • 153
        • 154
        • 155
        • 156
        • 157
        • 158
        • 159
        • 160
        • 161
        • 162
        • 163
        • 164
        • 165
        • 166
        • 167
        • 168
        • 169
        • 170
        • 171
        • 172
        • 173
        • 174
        • 175
        • 176
        • 177
        • 178
        • 179
        • 180
        • 181
        • 182
        • 183
        • 184
        • 185
        • 186
        • 187
        • 188
        • 189
        • 190
        • 191
        • 192
        • 193
        • 194
        • 195
        • 196
        • 197
        • 198
        • 199
        • 200
        • 201
        • 202
        • 203
        • 204
        • 205
        • 206
        • 207
        • 208
        • 209
        • 210
        • 211
        • 212
        • 213
        • 214
        • 215
        • 216
        • 217
        • 218
        • 219
        • 220
        • 221
        • 222
        • 223
        • 224
        • 225
        • 226
        • 227
        • 228
        • 229
        • 230
        • 231
        • 232
        • 233
        • 234
        • 235
        • 236
        • 237
        • 238
        • 239
        • 240
        • 241
        • 242
        • 243
        • 244
        • 245
        • 246
        • 247
        • 248
        • 249
        • 250
        • 251
        • 252
        • 253
        • 254
        • 255
        • 256
        • 257
        • 258
        • 259
        • 260
        • 261
        • 262
        • 263
        • 264
        • 265
        • 266
        • 267
        • 268
        • 269
        • 270
        • 271
        • 272
        • 273
        • 274
        • 275
        • 276
        • 277
        • 278
        • 279
        • 280
        • 281
        • 282
        • 283
        • 284
        • 285
        • 286
        • 287
        • 288
        • 289
        • 290
        • 291
        <%@ page import="java.util.List" %>
        <%@ page import="bean.Dept" %>
        <%@ page contentType="text/html;charset=UTF-8" language="java" %>
        <!DOCTYPE html>
        <html>
        	<head>
        		<meta charset="utf-8">
        		<title>部门列表</title>
        	</head>
        	<body>
        
        		<h1>欢迎<%=session.getAttribute("username")%></h1>
        		<h1 align="center">部门列表</h1>
        		<hr>
        		<table border="1px" align="center"  width="50%">
        			<tr>
        				<th>序号</th>
        				<th>部门编号</th>
        				<th>部门名称</th>
        				<th>操作</th>
        			</tr>
        			<%
        				//从request取集合
        				List<Dept> deptList = (List) request.getAttribute("deptList");
        				int i=0;
        				for (Dept dept:deptList){
        			%>
        
        			<tr>
        				<td><%=++i%></td>
        				<td><%=dept.getDeptno()%>></td>
        				<td><%=dept.getDname()%>></td>
        				<td>
        					<a href="">删除</a>
        					<a href="<%=request.getContextPath()%>/edit.jsp">修改</a>
        					<a href="<%=request.getContextPath()%>/detail.jsp">详情</a>
        				</td>
        			</tr>
        
        			<%
        				}
        			%>
        
        		</table>
        		<hr>
        		<a href="<%=request.getContextPath()%>/add.jsp">新增部门</a>
        	</body>
        </html>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
  • 项目增加一个安全退出(手动销毁session对象)

        private void doLOginout(HttpServletRequest request, HttpServletResponse response) throws IOException {
            //获取session对象,销毁session
            HttpSession session = request.getSession();
            if (session!=null){
                //手动销session对象
                session.invalidate();
                //跳转到登陆页面
                response.sendRedirect(request.getContextPath());
           
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

Cookie

  • session的实现原理中,每一个session对象都会关联一个sessionId,例如:

    • JSESSIONID=EA251A29E8E17C955D9A4C3A47730F83
    • 以上这个键值对数据其实就是cookie对象。
    • 对于session关联的cookie来说,这个cookie是被保存在浏览器的“运行内存”当中。
    • 只要浏览器不关闭,用户再次发送请求的时候,会自动将运行内存中的cookie发送给服务器。
    • 例如这个cookie:JSESSIONID=EA251A29E8E17C955D9A4C3A47730F83就会再次发送给浏览器。
    • 服务器就是根据:EA251A29E8E17C955D9A4C3A47730F83这个值来找到对应的session对象。
  • cookie怎么生成?保存在什么地方?有什么用?什么时候发送cookie?发送哪些cookie?

    • cookie最终是保存在浏览器客户端,可以保存在运行内存中(浏览器关闭就消失),也可以保存在硬盘文件上(永久保存)。
    • cookie和session机制都是为了保存会话状态;cookie是将会话保存在浏览器客户端上,session将会话状态保存在服务器端。
  • cookie的经典案例:

    • 旧版京东商城,在未登录情况下,向购物车放商品,然后关闭浏览器,再次打开浏览器,访问京东商城,购物车的商品还在。这就是将购物车商品编号放到cookie中并存储在到硬盘文件,再次打开会自动读取硬盘cookie,将cookie里的商品自动添加到购物车。
    • 123邮箱中的十天内免登录功能:用户输入正确的账号密码,登录成功后,浏览器客户端会保存一个cookie,这个cookie保存了用户名和密码等信息,这个cookie是保存在硬盘文件当中的。十天内有效。十天内再次访问123邮箱,浏览器自动提交cookie给服务器,服务器接收到cookie之后,获取用户名和密码,验证。通过,自动登陆成功。
    • 浏览器ctrl+shift+delete可以选择清除cookie。
  • cookie和session机制都不属于Java的机制,实际上是HTTP协议的一部分。

  • HTTP协议中规定:然后一个cookie都是由name和value组成的,name和value都是字符串类型。

  • 在Java的servlet中,对cookie提供了哪些支持呢?

    • 提供了一个Cookie类来专门表示cookie数据:Jakarta.servlet.http.Cookie;
  • 关于cookie的path,cookie关联的路径:(只要路径正确,浏览器就会自动发送cookie给服务器

    • 假设现在发送的请求路径是“localhost:8080/Servlet_cookie/servletcookie”生成的路径,如果cookie没有设置path,默认的path是什么?

      • 默认的path是localhost:8080/Servlet_cookie以及它的子路径。
      • 也就是说:以后浏览器的请求路径是localhost:8080/Servlet_cookie这个路径以及其子路径,cookie都会被发送到服务器。
    • 手动设置cookie的path

      • cookie.setPath("/Servlet-cookie");//表示只要是这个Servlet-cookie项目的请求路径,都会提交cookie给浏览器
        
        • 1
  • 浏览器发送cookie给服务器,服务器的Java程序怎么接收?

    • Cookie[] cookies=request.getCookies();
      
      • 1
  • 使用Cookie实现十天免登录功能:

    • 先实现登录功能
      • 登陆成功
        • 跳转到部门页面
      • 登陆失败
    • 修改前端界面
      • 在登录页面给一个复选框,是否同样十天免登录
    • 修改servlet的登录方法
      • 如果登陆成功,用户名密码存储到cookie,有效期十天
    • 用户再次访问该网页的时候,有两个走向:
      • 要么跳转到部门列表页面
      • 要么跳转到登录页面
  • Cookie使用方法:

    //创建cookie对象存储用户账号密码
    Cookie cookie1 = new Cookie("username", username);
    Cookie cookie2 = new Cookie("password", password);
    //设置cookie有效期10天
    cookie1.setMaxAge(60*60*24*10);
    cookie2.setMaxAge(60*60*24*10);
    //设置cookie的path
    cookie1.setPath(request.getContextPath());
    cookie2.setPath(request.getContextPath());
    //响应cookie给浏览器
    response.addCookie(cookie1);
    response.addCookie(cookie2);
    
    //获取cookie
    Cookie[] cookies = request.getCookies();
    String username=null;
    String password=null;
    if (cookies!=null){
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            if ("username".equals(name)){
                username = cookie.getValue();
            }else if ("password".equals(name)){
                password = cookie.getValue();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

JSP

  • jsp的底层原理:

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xtW36Vgq-1688627297644)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\image-20230705144414215.png)]
    • Using CATALINA_BASE: “C:\Users\26332\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\df5d7a1b-693a-40d9-9a66-d3042ad40355”(找到这个路径,在文件管理器打开,再点击work文件,直到看到最后有一个后缀为Java和class的文件)
    • 所以:JSP是由Tomcat翻译成Java文件,再编译Java文件生成class文件,所以访问index.jsp,底层执行的就是index.jsp.class这个Java程序
  • JSP实际上就是一个Servlet

    • index.jsp访问的时候,会自动翻译成index.jsp.java,会自动编译成index_jsp.class,那么index_jsp就是一个类。
    • index.jsp类继承HttpJspBase,而HttpJspBase类继承的是HttpServlet。所以index_jsp类就是一个Servlet类。
    • jsp的生命周期和Servlet的生命周期完全相同。完全就是一个东西,没有任何区别。
  • jsp文件第一次访问比较慢,为什么?

    • 运维人员在给客户演示项目的时候,为什么提前先把所有的jsp文件先访问一遍?
      • 因为jsp文件第一次执行需要翻译成Java文件,再编译成class文件,需要一定的时间。
  • jsp的基础语法

    • 在jsp文件中直接编写文字,都会被翻译到哪里?

      • 翻译到Servlet类的service方法的out.write(“翻译到这里”),被Java程序当做普通的字符串打印到浏览器。
    • jsp的page指令,解决响应时的中文乱码问题:

      • 通过page指令来设置响应的内容类型,在内容类型的最后面添加:charset=UTF-8

        • <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          
          • 1
    • 怎么在jsp中编写Java程序:

      • <%Java语句; %>
            //该符号中语句写在service方法里的Java代码
            <%System.out.println("hello jsp");%>
        
        • 1
        • 2
        • 3
        • 在这个符号当中编写的被视为Java程序,被翻译到Servlet类的service方法内部。

        • 在这个符号里写代码,就相当于在Servlet类的service方法里写代码,所以该符号里的代码要遵守方法里代码的书写规范。

        • jsp中的专业注释:<%–jsp专业注释,不会被翻译到Java源代码中–%>

        • 在同一个jsp当中可以写多个<%%>

      • <%!Java语句;%>
            //该符号中语句写在service方法外的Java代码
            <%!
            //成员变量
            private String name="hetao";
        
            //静态代码块
            static {
                System.out.println("静态方法执行");
            }
        
            //方法
            public static void m1(){
                System.out.println("m1方法执行了");
            }
        %>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
      • <%! %>这个语法基本上不建议用,因为在service方法外写静态变量和实例变量,都会存在线程安全问题,jsp就是servlet,servlet是单例的,多线程并发的环境下,这个静态变量和实例变量一旦有修改操作,必然会存在线程安全问题。

      • jsp的输出语句:怎么把一个Java变量输出到浏览器?

        • 在<%%>符号里写out.print(“输出的变量”)

        • 直接写在<%= %>符号里

        • <%--
            Created by IntelliJ IDEA.
            User: 26332
            Date: 2023/7/5
            Time: 15:40
            To change this template use File | Settings | File Templates.
          --%>
          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <html>
          <head>
              <title>Title</title>
          </head>
          <body>
          <%
              int a=1;
              out.print(a);
          %>
          <%=a%>
          </body>
          </html>
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
    • JSP基础语法总结:

      • JSP中直接编写普通字符串

        • 翻译到service方法的out.write(“这里”)
      • <% %>

        *翻译到service方法体内部,里面是一条条Java语句。

      • <%= %>

        • 翻译到service方法体之外,不建议使用,易引发线程安全问题。
      • <%= %>

        • 翻译到service方法体内部,翻译成:out.print()。
      • <%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

        • 配置指令,通过contentType属性用来设置响应的内容类型。

使用Servlet+JSP完成项目的改造

  • 使用Servlet处理业务,收集数据。

  • 使用JSP展示数据。

  • 将之前原型中的HTML文件全部修改为jsp文件,然后再jsp文件头部添加page指令(指定contextType防止中文乱码,将所有的jsp直接拷贝到web目录下)

  • 完成所有的页面正常跳转。

  • 在Servlet中连接数据库,查询所有的部门,遍历结果集。

    • 遍历所有结果集的过程中,取出部门编号、部门号、位置等信息,封装成Java对象。

    • 将Java对象存放到List集合。

    • 将List集合存储到request域当中。

    • 转发到jsp。

    • Servlet代码:

      @WebServlet({"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"})
      public class DeptServlet extends HttpServlet {
          @Override
          protected void service(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException {
              //获取Servlet Path
              String servletPath=request.getServletPath();
              if ("/dept/list".equals(servletPath)){
                  doList(request,response);
              }
      private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
              //获取应用的根路径
              String contextPath = request.getContextPath();
      
              //设置一个存放部门信息的集合
              List<Dept> depts=new ArrayList();
      
              //连接数据库,查询所有的部门
              Connection conn=null;
              PreparedStatement ps=null;
              ResultSet rs=null;
              try {
                  conn=DButil.getConnection();
                  String sql="select deptno,dname,loc from dept";
                  ps=conn.prepareStatement(sql);
                  rs= ps.executeQuery();
                  int i=0;
                  //获取到的数据库数据
                  while (rs.next()){
                      String deptno=rs.getString("deptno");
                      String dname=rs.getString("dname");
                      String loc=rs.getString("loc");
                      //将以上零散的数据封装成Java对象,并装入集合再通过请求域提交到jsp文件
                      Dept dept=new Dept();
                      dept.setDeptno(deptno);
                      dept.setDname(dname);
                      dept.setLoc(loc);
                      depts.add(dept);
                  }
              } catch (SQLException throwables) {
                  throwables.printStackTrace();
              }finally {
                  //释放资源
                  DButil.close(conn,ps,rs);
              }
              //将集合放入请求域
              request.setAttribute("deptList",depts);
              //转发(不能重定向,因为重定向是不同的请求,请求域存放的信息不能传给其他使用)
              request.getRequestDispatcher("/list.jsp").forward(request,response);
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
  • 在jsp中:

    • 从request域当中取出List集合。

    • 遍历List集合,取出每个部门对象,动态生成tr

    • <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <!DOCTYPE html>
      <html>
      	<head>
      		<meta charset="utf-8">
      		<title>欢迎使用OA系统</title>
      	</head>
      	<body>
      		<a href="<%=request.getContextPath()%>/dept/list">查看部门列表</a>
      	</body>
      </html>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • <%@ page import="java.util.List" %>
      <%@ page import="bean.Dept" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <!DOCTYPE html>
      <html>
      	<head>
      		<meta charset="utf-8">
      		<title>部门列表</title>
      	</head>
      	<body>
      		<h1 align="center">部门列表</h1>
      		<hr>
      		<table border="1px" align="center"  width="50%">
      			<tr>
      				<th>序号</th>
      				<th>部门编号</th>
      				<th>部门名称</th>
      				<th>操作</th>
      			</tr>
      			<%
      				//从request取集合
      				List<Dept> deptList = (List) request.getAttribute("deptList");
      				int i=0;
      				for (Dept dept:deptList){
      			%>
      
      			<tr>
      				<td><%=++i%></td>
      				<td><%=dept.getDeptno()%>></td>
      				<td><%=dept.getDname()%>></td>
      				<td>
      					<a href="">删除</a>
      					<a href="<%=request.getContextPath()%>/edit.jsp">修改</a>
      					<a href="<%=request.getContextPath()%>/detail.jsp">详情</a>
      				</td>
      			</tr>
      
      			<%
      				}
      			%>
      
      		</table>
      		<hr>
      		<a href="<%=request.getContextPath()%>/add.jsp">新增部门</a>
      	</body>
      </html>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
  • jsp文件的拓展名必须是XXX.jsp吗?

    • jsp文件的拓展名是可以配置的

    • 在CATALINA_HOME/conf/web.xml,在这个文件当中配置jsp文件的拓展名。

    •     <servlet-mapping>
              <servlet-name>jsp</servlet-name>
              <url-pattern>*.jsp</url-pattern>
              <url-pattern>*.jspx</url-pattern>
          </servlet-mapping>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • xxx.jsp文件对Tomcat来说就是普通文档,web容器都会将该文件翻译成Java程序,真正执行时,和jsp文件没关系。


当前的项目存在的问题:需要一个登录功能

  • 实现登录功能步骤:

    • 步骤1:先实现一个登录页面。
      • 登录页面应该有一个登录表单,提交用户名和密码。form是post方式提交
    • 步骤2:数据库添加一个用户表(users)。
    • 步骤3:后台要有一个Servlet处理登录请求。
    jsp代码
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>欢迎使用OA系统</title>
    	</head>
    	<body>
    		<%--<a href="<%=request.getContextPath()%>/dept/list">查看部门列表</a>--%>
    		<h1>用户登录</h1><hr>
    		<form action="<%=request.getContextPath()%>/dept/login" method="post">
    			username:<input type="text" name="username"><br>
    			password:<input type="password" name="password"><br>
    			<input type="submit" value="登录">
    		</form>
    	</body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    Servlet代码
    package action;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import utils.DButil;
    
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    @WebServlet("/dept/login")
    public class UserServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //验证用户名和密码是否正确
            //获取用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            //链接数据库验证
            Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            int count=0;
            try {
                conn=DButil.getConnection();
                String sql="select * from users where username=? and password=?";
                ps=conn.prepareStatement(sql);
                ps.setString(1,username);
                ps.setString(2,password);
                rs=ps.executeQuery();
                if (rs.next()){
                    count=1;
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DButil.close(conn,ps,rs);
            }
            if (count==1){
                response.sendRedirect(request.getContextPath()+"/dept/list");
            }else {
                response.setContentType("text/html");
                System.out.println("登陆失败");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

JSP的指令

  • 指令的作用:指导JSP翻译引擎如何翻译JSP文件

  • 指令包括哪些?

    • include指令:包含指令,在JSP中完成静态包含,很少有。
    • taglib指令:引入标签库的指令。这个到JSTL标签库的时候再学习。
    • page指令:目前重点学习page指令。
  • 指令的使用语法是什么?

    • <%@指令名 属性名=属性值 属性名=属性值…%>
  • 关于page当中都有哪些常用的指令:

    //是否启用JSP内置对象session,false表示不启用
    <%@page session="false" %>
    
    //设置响应的内容类型和响应时的字符集
    <%@page contentType="text/html;" pageEncoding="UTF-8" %>
    
    //导包
    <%@page import="com" %>
    
    //当前页面出错就跳转到这个页面,errorPage这个属性用来指定出错之后的跳转位置
    <%@page errorPage="2.jsp" %>
    
    //跳转到出错页面后,无异常信息,程序员不知道要怎么做,则使用下面的标签和九大内置对象之一,把错误信息打印到控制台
    <%@page isErrorPage="true" %>
    <%
      exception.printStackTrace();
    %>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

JSP九大内置对象

  • jakarta.servlet.jsp.PageContext pageContext 页面作用域

  • jakarta.servlet.http.HttpServletRequest request 请求作用域

  • jakarta.servlet.http.HttpSession session 会话作用域

  • jakarta.servlet.ServletContext application 应用作用域

    • pageContext<request<session<application

    • 以上四个域都有setAttribute、getAttribute、removeAttribute方法。

    • 以上作用域使用原则:尽可能使用小的域

  • java.lang.Throwable exception

  • jakarta.servlet.ServletConfig config

  • java.lang.Object page (其实时this,当前servlet对象)

  • jakarta.servlet.jsp.JspWriter out (负责输出)

  • jakarta.servlet.http.HttpServletResponse response (负责响应)


EL表达式

  • EL表达式是干什么用的?

    • Expression Language(表达式语言)
    • EL表达式可以代替JSP中的Java代码,让JSP文件中的程序看起来更加整洁美观
    • EL表达式属于JSP的一部分
  • EL表达式出现在JSP中只要是:

    • 从某个作用域中取数据,然后将其转换成字符串,然后将其输出到浏览器,这就是EL表达式的功效。三大功效:
      • 第一功效:从某个域中取数据
        • 四个域:
          • pageContext
          • request
          • session
          • application
      • 第二功效:将取出数据转成字符串
        • 如果是一个Java对象,也会调用Java的toString方法将其转换成字符串
      • 第三功效:将字符串输出到浏览器
        • 和<%=%>这个效果一样,将其输出到浏览器。
  • EL表达式很好用,基本的语法格式:

    • ${表达式}

    • <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%
        //向request作用域存储username为hetao
        request.setAttribute("username","hetao");
      %>
      <%=request.getAttribute("username")%>
      
      <%--使用EL表达式--%>
      ${username}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
  • EL表达式的使用:

    • <%@ page import="action.User" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%
           //创建User对象
           User user = new User();
           user.setUsername("hetao");
           user.setPassword("20021008");
           user.setAge(20);
      
           //将User对象存储到request域当中(将对象存储到某个域当中,一定要存,因为EL表达式只能从某个范围中取数据)
      	//数据必须存储到四大范围之一
           request.setAttribute("userObj",user);
      %>
      
      <%--使用EL表达式,从request域当中,取出User对象,并将其输出到浏览器--%>
      <%--1、EL表达式会自动从某个范围取出数据。2、将其转换成字符串。3、将其输出到浏览器--%>
      ${userObj}   //输出结果:User{username='hetao', password='20021008', age=20}
      <br>
      
      <%--输出user对象的username属性--%>
      ${userObj.username}  //输出结果:hetao
      <br>
      
      ${userObj.email}  //输出结果:hetao
      				  //看下面的User类中的getEmail方法
      
      ${"userObj"}和${userObj}的区别:
      				 第一个总结输出字符串userObj,后面的输出User{username='hetao', password='20021008', age=20}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      package action;
      
      import jakarta.servlet.annotation.WebServlet;
      
      public class User {
          private String username;
          private String password;
          private int age;
      
      
      
          public String getUsername() {
              return username;
          }
      
          public void setUsername(String username) {
              this.username = username;
          }
      
          public String getPassword() {
              return password;
          }
      
          public void setPassword(String password) {
              this.password = password;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "User{" +
                      "username='" + username + '\'' +
                      ", password='" + password + '\'' +
                      ", age=" + age +
                      '}';
          }
          
          public String getEmail(){
              return "hetao";
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
  • 总结:EL表达式中,这个语法实际上就是调用底层的getxxx()方法,如果没有对应的get方法,浏览器就会报500错误。如果同时多个域都有相同名字的变量,EL表达式优先从小域取。

  • ${userObj.username}相当于${userObj["username"]}
    加入一个名称为abc.a的要输出,第一种方式输出为空白,第二种方式可以正常输出
    
    • 1
    • 2

摘抄EL表达式

版权声明:本文为CSDN博主「代码怎么撕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_57151612/article/details/123693754


JSTL标签库

  • 什么是JSTL标签库

    • Java Standard Tag Lib(Java标准的标签库)
    • JSTL标签库通常结合EL表达式一起使用,目的是让JSP中的Java代码消失
  • 使用JSTL标签库的步骤

    • 第一步:引入JSTL标签库对应的jar包

      • Tomcat10之后引入的jar包是:
        • jakarta.servlet.jsp.jstl-2.0.0.jar
        • jakarta.servlet.jsp.jstl-api-2.0.0.jar
      • 在IDEA当中怎么引入?
        • 在WEB-INF下新建lib目录,然后将jar包拷贝到lib当中
        • 想MySQL驱动一样
        • 什么时候需要将jar包放到lib下:Tomcat服务器没有的jar包
    • 第二步:在JSP中引入需要的标签库(使用taglib指令引入标签库)

      • JSTL提供了多种标签,你要引入哪个标签???(重点掌握核心标签库)

      • <%--引入标签库,这里引入的是JSTL的核心标签库--%>
        <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
        这就是核心标签库
        prefix="" 这里随便起一个名字就行了,核心标签库,大家默认的叫做c
        url是对应jar包里的东西
        
        • 1
        • 2
        • 3
        • 4
        • 5
    • 第三步:在需要标签的位置使用即可(表面是标签,实际上是Java程序)

  • JSTL标签的原理

    • <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
      以上uri 后面的路径实际上指向了一个xx.tld文件。
      tld文件实际上是一个xml配置文件。
      在tld文件中描述了“标签”和java类之间的关系。
      以上核心标签库对应的tld文件是c.tld文件。
      在jakarta.servlet.jsp.jstl-2.0.0.jar里面META-INF目录下,有一个c.tld文件。
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 源码解析:配置文件tld解析

      • <tag>
           <description>对该标签的描述 </description>
           <name>catch</name> 标签的名字
           <tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>标签对应的java类。
           <body-content>JSP</body-content>标签体当中可以出现的内容,如果是JSP,就表示标签体重可以出现符合JSP所有语法的代码。例如EL表达式。
           <attribute>
               <description>对这个属性的描述 </description>
               <name>var</name> 属性名
               <required>false</required> false 表示该属性不是必须的。true表示该属性是必须的。
               <rtexprvalue>false</rtexprvalue>这个描述说明了该属性是否支持EL表达式。false表示不支持。true表示支持EL表达式。
           </attribute>
         </tag>
         
        <c:catch 属性名=“”>
        		JSP...
        </c:catch>
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
    • 总结JSTL标签的格式就是:

      • <库名:标签名 标签中包含的属性名=“”>
        		其他代码(JSP什么的)
        </库名:标签名>
        
        • 1
        • 2
        • 3
  • JSTL中的核心标签库core当中有哪些常用的标签呢?

    • <%--核心库的if标签
          test属性是必须的,test属性支持EL表达式
          test属性只能是Boolean类型
          if标签还有var属性,不是必须的
          if标签还有scope属性,用来指定var的存储域,var是保存test属性的值,也不是必须的(四个域)
      --%>
      <c:if test="${empty param.username}">
          <h1>用户名不能为空</h1>
      </c:if>
      <c:if test="${not empty param.username}">
          <h1>欢迎您${param.username}</h1>
      </c:if>
      <%--存储到request域--%>
      <c:if test="${not empty param.username}" var="v" scope="request">
          <h1>欢迎您${param.username}</h1>
      </c:if>
      <%--通过EL表达式将request域当中的v取出--%>
      ${v}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    • 1.
      <%--
      forEach标签:
          var用来指定循环中的变量
          begin开始
          end结束
          step步长
          底层实际会将i存储到pageContext域当中
      --%>
      <c:forEach var="i" begin="1" end="10" step="1">
          ${i}<br>
      </c:forEach>
      
      2.
      <%--
      forEach标签:
          取集合元素
      --%>
      <%
          List<User> users=new ArrayList<>();
          User user=new User();
          user.setAge(20);
          user.setUsername("hetao");
          user.setPassword("20021008");
          User user1=new User();
          user1.setAge(20);
          user1.setUsername("hetao");
          user1.setPassword("20021008");
          User user2=new User();
          user2.setAge(20);
          user2.setUsername("hetao");
          user2.setPassword("20021008");
          users.add(user);
          users.add(user1);
          users.add(user2);
          request.setAttribute("users",users);
      %>
      <%--var="s"这个s代表的是集合中的每个User对象--%>
      <c:forEach items="${users}" var="s">
          user:${s.username},password=${s.password},age=${s.age}<br>
      </c:forEach>
      3.
      <%--varStatus这个属性表示var的状态对象,这里是一个Java对象,这个Java对象代表了var的状态
          varStatus=”名字随意“
          varStatus这个状态对象有count属性,可以直接使用
      --%>
      <c:forEach items="${users}" var="s" varStatus="userStatus">
      <%--主要用于编号,从1递增--%>
          编号:${userStatus.count},
          user:${s.username},password=${s.password},age=${s.age}<br>
      </c:forEach>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
    • <%--
      相当于if else
      --%>
      <c:choose>
          <c:when test="${param.age<18}">青少年</c:when>
          <c:when test="${param.age<35}">青年</c:when>
          <c:when test="${param.age<55}">中年</c:when>
          <c:otherwise>老年</c:otherwise>
      </c:choose>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
  • 拓展:HTML头部的标签,可以用来设置根路径


Filter过滤器

  • 当前的项目有什么缺陷?

    • 每个Servlet都需要判断session对象用户是否登录,要写字符集类型…重复代码,怎么解决?
      • 使用Servlet规范的Filter过滤器
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sjuMoGDt-1688717410092)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\image-20230707111134150.png)]

  • Filter是什么,有什么用,执行原理是什么?

    • Filter是过滤器
    • Filter可以在Servlet这个目录程序执行之前添加代码,以可以在Servlet执行之后添加代码,之前之后都可以添加过滤规则
    • 一般情况下,都是在过滤器当中编写公共代码
  • 一个过滤器怎么写呢?

    • 第一步:编写一个Java类实现一个接口import jakarta.servlet.Filter,并且实现接口中所有的方法
      • init方法:在Filter对象第一次创建之后调用,并且只调用一次
      • doFilter方法:只要用户发生一次请求,就执行一次
      • dostroy方法:在Filter对象被释放/销毁之前调用,只调用一次
    • 第二步:在web.xml配置,类似Servlet配置
  • 注意:

    • Servlet对象默认情况下,在服务器启动的时候是不会新建对象的。
    • Filter对象默认情况下,在服务器启动的时候会新建对象。
    • Servlet是单例的,Filter也是单例的(单实例)。
  • package action;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    @WebServlet("/a.do")
    public class Aservlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("Aservlet的doget方法执行...");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • package action;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    @WebServlet("/b.do")
    public class BServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("Bservlet的doget方法执行...");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • //过滤器
    package action;
    
    import jakarta.servlet.*;
    import jakarta.servlet.annotation.WebFilter;
    
    import java.io.IOException;
    
    @WebFilter("*.do")
    public class Filter1 implements Filter {
        public Filter1() {
            System.out.println("构造方法执行");
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("init。。。");
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("doFilter开始执行。。。");
            //执行下一个过滤器,如果下面没有过滤器,则执行目标Servlet
            chain.doFilter(request,response);
    		//如果执行完Servlet,就会在执行下面这条语句
            System.out.println("doFilter方法执行结束");
    
        }
    
        @Override
        public void destroy() {
            System.out.println("dostroy。。。");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
  • Filter优先级高于Servlet


Listener(监听器)

  • 什么是Listener

    • 监听器也是servlet规范的一员,就像Filter一样是规范之一。
    • 在Servlet中,所有的监听器接口都是以“Listener”结尾
  • 监听器有什么用?

    • 监听器实际上是Servlet规范留给我们JavaWeb程序员的特殊时机。
    • 特殊时刻如果想执行这段代码,你需要想到使用对应的监听器。
  • Servlet规范中提供了哪些监听器?(监听器里的方法调用根据域,例如Context,服务器启动执行一个方法,服务器关闭执行一个方法。request一次请求就执行一次)

    • jakarta.servlet包下:
      • ServletContextListener(服务器启动调用init方法,关闭调用destroy方法)
      • ServletContextAttributeListener(向ServletContext域存数据调用add方法,删除数据调用remove方法,替换数据调用replace方法)
      • ServletRequestListener(一次请求启动调用init方法,请求结束调用destroy方法)
      • ServletRequestAttributeListener(向request域存数据调用add方法,删除数据调用remove方法,替换数据调用replace方法)
    • jakarta.servlet.http包下:
      • HttpSessionListener(session创建调用init方法,session销毁调用destroy方法)
      • HttpSessionAttributeListener(向Session域存数据调用add方法,删除数据调用remove方法,替换数据调用replace方法)
      • HttpSessionBindingListener(该监听器不需要使用@WebListener进行标注。假设User类实现了该监听器,那么User对象在被放入session的时候触发bind事件,User对象从session中删除的时候,触发unbind事件。假设Customer类没有实现该监听器,那么Customer对象放入session或者从session删除的时候,不会触发bind和unbind事件。)
      • HttpSessionIdListener(session的id发生改变的时候,监听器中的唯一一个方法就会被调用。)
      • HttpSessionActivationListener(监听session对象的钝化和活化的。钝化:session对象从内存存储到硬盘文件。活化:从硬盘文件把session恢复到内存。)
  • 实现一个监听的步骤:(以ServletContextListener为例:)

    • 第一步:编写一个类实现ServletContextListener接口。并且实现里面的方法

      • import jakarta.servlet.ServletContextEvent;
        import jakarta.servlet.ServletContextListener;
        
        public class MyServletContextListener implements ServletContextListener {
            @Override
            public void contextInitialized(ServletContextEvent sce) {
        
            }
        
            @Override
            public void contextDestroyed(ServletContextEvent sce) {
        
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
    • 第二步:在web.xml文件中对MyServletContextListener进行配置:

      • <listener>
                <listener-class>MyServletContextListener</listener-class>
            </listener>
        
        • 1
        • 2
        • 3
      • 也可以使用注解:

        • import jakarta.servlet.ServletContextEvent;
          import jakarta.servlet.ServletContextListener;
          import jakarta.servlet.annotation.WebListener;
          
          @WebListener
          public class MyServletContextListener implements ServletContextListener {
              @Override
              public void contextInitialized(ServletContextEvent sce) {
          
              }
          
              @Override
              public void contextDestroyed(ServletContextEvent sce) {
          
              }
          }
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
  • 注意:所有监听器中的方法都是不需要javaweb程序员调用,由服务器自动调用。什么时候调用?

    • 监听器的方法不需要手动调用。是发生某个事件服务器自动调用。
  • 做网站用户在线人数功能:

    • 什么代表了用户登录在线?
      • session.setAttribute(“user”,userObj);user类型对象只要往session中存储,表示新用户登录
    • 什么代表用户退出?
      • session对象移除
      • session销毁(session超时)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/386926
推荐阅读
相关标签
  

闽ICP备14008679号

        
cppcmd=keepalive&