概念

  • 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。->HttpSession

入门

HttpSession对象:

  • 获取HttpSession对象
    • request.getSession()
  • 使用HttpSession对象
    • Object getAttribute(String name)
    • void setAttribute(String name, Object value)
    • void removeAttribute(String name)

原理

服务器如何确保在一次会话范围内多次获取的Session对象是同一个?

Session是基于Cookie的**

  • 响应:set-cookie : JSESSIONID=xxxx
  • 请求:set-cookie: JSESSIONID=xxxx

第一次获取Session对象时,假设当时的服务器响应头cookie信息中没有JSESSIONID,则新建一个Session对象并赋予ID,最后通过请求头设置cookie返回到服务器
第二次请求服务器时就会在服务器响应头中携带JSESSIONID,那么第二次请求创建的Session对象就是服务器中已存的Session

细节

  • 当客户端关闭后,服务器不关闭,那么两次获取session是否为同一个?

    • 默认情况下不是
    • 持久化保存Session:
      1. //1-获取session
      2. HttpSession session = request.getSession();
      3. System.out.println(session);
      4. //期望客户端关闭后,session也能相同
      5. Cookie c= new Cookie("JSESSIONID",session.getId());
      6. c.setMaxAge(60*60);
      7. response.addCookie(c);//发送cookie
  • 客户端不关闭,服务器重启后,两次获取的session是同一个吗?

    • 不是同一个,但是要确保数据不丢失
      • session的钝化
        • 在服务器正常关闭之前,将session对象序列化到硬盘上
      • session的活化
        • 在服务器启动后,将session文件转化为内存中的session对象即可
  • session什么时候被销毁?

    • 服务器被关闭时
    • session对象调用invalidate()方法
    • session默认失效时间 30分钟
      • 在web.xml中选择性配置修改
        1. <session-config>
        2. <session-timeout>30</session-timeout>
        3. </session-config>

        特点

  • Session用于存储一次会话的多次请求的数据,存在服务器

  • Session可以存储任意类型,任意大小的数据

    Session和Cookie的区别

  • session存储数据在服务器端,cookie在客户端

  • session没有数据大小限制,cookie有
  • session数据安全,cookie相对不安全

案例

验证码案例

需求

  • 访问带有验证码的登陆页面login.jsp
  • 用户输入用户名,密码以及验证码

    • 如果用户名和密码输入有误,跳转登陆页面,提示:用户名或密码错误
    • 如果验证码输入有误,跳转登陆页面,提示:验证码错误
    • 如果全部输入正确,跳转到主页succes.jsp,显示:用户名,欢迎你

      分析

      截屏2020-11-24 20.26.40.png

      login.jsp

      1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      2. <html>
      3. <head>
      4. <title>login</title>
      5. <script>
      6. window.onload=function () {
      7. document.getElementById("img").onclick = function () {
      8. this.src="/Cookie_Session/checkCode?time="+new Date().getTime();
      9. }
      10. }
      11. </script>
      12. <style>
      13. div{
      14. color: red;
      15. }
      16. </style>
      17. </head>
      18. <body>
      19. <form action="/Cookie_Session/loginServlet" method="post">
      20. <table>
      21. <tr>
      22. <td>用户名</td>
      23. <td><input type="text" name="username"></td>
      24. </tr>
      25. <tr>
      26. <td>密码</td>
      27. <td><input type="password" name="password"></td>
      28. </tr>
      29. <tr>
      30. <td>验证码</td>
      31. <td><input type="text" name="checkCode"></td>
      32. </tr>
      33. <tr>
      34. <td colspan="2"><img id="img" src="/Cookie_Session/checkCode" alt=""></td>
      35. </tr>
      36. <tr>
      37. <td colspan="2"><input type="submit" value="登陆"></td>
      38. </tr>
      39. </table>
      40. <div><%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error") %></div>
      41. <div><%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error") %></div>
      42. </form>
      43. </body>
      44. </html>

      LoginServlet.java

      /**
      * 验证码登陆
      */
      @WebServlet("/loginServlet")
      public class LoginServlet extends HttpServlet {
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         //request编码
         request.setCharacterEncoding("utf-8");
         //获取参数map
         String username = request.getParameter("username");
         String password = request.getParameter("password");
         String checkCode = request.getParameter("checkCode");
      
         //获取生成的验证码
         HttpSession session = request.getSession();
         String checkCode_session = (String) session.getAttribute("checkCode_session");
         //删除session存储的验证码
         session.removeAttribute("checkCode_session");
         //判断验证码是否正确
         if (checkCode_session!=null && checkCode_session.equalsIgnoreCase(checkCode)){
             //忽略大小写比较字符串
             //判断用户名密码是否一致
             //验证码正确
             if ("roderick".equals(username) && "123".equals(password)) //参略查询数据库
             {
                 //登陆成功
                 //存储用户信息
                 session.setAttribute("user",username);
                 //重定向到success.jsp
                 response.sendRedirect(request.getContextPath()+"/success.jsp");
                         //由于重定向是给浏览器看的,所以需要虚拟目录!!
             }
             else
             {
                 //登陆失败
                 //存储提示信息到request
                 request.setAttribute("login_error","用户名或密码错误");
                 //转发到登陆页面
                 request.getRequestDispatcher("/login.jsp").forward(request,response);
             }
      
         }
         else {
             //验证码不一致
             //存储提示信息到request
             request.setAttribute("cc_error","验证码错误");
             //转发到登陆页面
             request.getRequestDispatcher("/login.jsp").forward(request,response);
         }
      
      }
      
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         this.doPost(request, response);
      }
      }
      

      CheckCode.java

      ```java @WebServlet(“/checkCode”) public class CheckCode extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int width=100; int height=50; //创建一个对象,在内存中代表一个图片(验证码图片对象) BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //美化图片 //填充背景色 Graphics g = image.getGraphics();//画笔对象 g.setColor(Color.PINK);//设置画笔颜色 g.fillRect(0,0,width,height);//填充

      //画边框 g.setColor(Color.BLUE); g.drawRect(0,0,width-1,height-1);//画线条

      String str =”ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopgqrstuvwxyz0123456789”; //生成随机角标 Random ran = new Random(); StringBuilder sb=new StringBuilder(); for (int i = 1; i <=4 ; i++) {

         int index = ran.nextInt(str.length());//随机角标
         //获取字符
         char ch = str.charAt(index);//随机字符
         sb.append(ch);
         //写验证码
         g.drawString(ch+"",width/5*i,height/2);
      

      } String checkCode_session = sb.toString();

      //将验证码存入session req.getSession().setAttribute(“checkCode_session”,checkCode_session);

      //画干扰线 g.setColor(Color.green); for (int i = 0; i <10 ; i++) {

         //随机生成坐标点
         int x1 = ran.nextInt(width);
         int x2 = ran.nextInt(width);
         int y1 = ran.nextInt(height);
         int y2 = ran.nextInt(height);
         g.drawLine(x1,y1,x2,y2);
      

      }

    //将图片输出到页面展示
    /*ServletOutputStream outputStream = resp.getOutputStream();
    outputStream.write("<h1>image</h1>".getBytes());*/
    ImageIO.write(image,"jpg",resp.getOutputStream());
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    this.doPost(req,resp);
}

}

<a name="QbJDT"></a>
#### success.jsp
```java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1><%=request.getSession().getAttribute("user") %>欢迎您</h1>
</body>
</html>