Session

1. Session 的概念

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

2. Session 的快速入门

  1. 获取 HttpSession 对象

    HttpSession session = request.getSession();
    
  2. 使用 HttpSession 对象

    1. 获取数据
      • Object getAttribute(String name)
    2. 存储数据
      • void setAttribute(String name, Object value)
    3. 移除数据
      • void removeAttribute(String name)
  3. Session 练习

    在 SessionDemo1 中创建 Session,在 SessionDemo2 获取 Session

    @WebServlet("/SessionDemo1")
    public class SessionDemo1 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 获取 Session 对象
            HttpSession session = request.getSession();
            // 存储数据
            session.setAttribute("session1","hello");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    @WebServlet("/SessionDemo2")
    public class SessionDemo2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 获取 Session 对象
            HttpSession session = request.getSession();
            // 获取 session 数据
            Object session1 = session.getAttribute("session1");
            System.out.println(session1);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    

3. Session 的原理

在这里插入图片描述

  1. Session 的实现是依赖于 Cookie 的
  2. 在一次会话中,获取的 Session 对象是同一个

4. Session 的细节

4.1 浏览器关闭后,服务器不关闭,两次获取的 Session 对象是同一个吗?

  1. 默认情况下,不是同一个。

  2. 如果需要为同一个,则可以创建一个 Cookie,键为 JSESSIONID,设置最大存活时间,让 Cookie 持久化保存。

    @WebServlet("/SessionDemo3")
    public class SessionDemo3 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 获取 Session 对象
            HttpSession session = request.getSession();
            System.out.println(session);
    
            // 浏览器关闭后,session 也能相同
            Cookie cookie = new Cookie("JSESSIONID",session.getId());
            cookie.setMaxAge(60*60);
            response.addCookie(cookie);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    

4.2 浏览器不关闭,服务器关闭后,两次获取的 Session 对象是同一个吗?

不是同一个,但是要确保数据不丢失,Tomcat 自动完成以下工作:

  1. Session 的钝化:在服务器正常关闭之前,将 Session 对象序列化到硬盘上
  2. Session 的活化:在服务器启动后,将 Session 文件转化为内存中的 Session 对象。

注意:

  1. 在 IDEA 中只能完成 Session 的钝化,但重启服务器后会删除 work 目录,由于 Session 文件存储于 work 目录中,所以无法完成 Session 的活化

  2. 但用本地的 Tomcat 部署项目是可以完成 Session 的钝化和活化的

4.3 Session 什么时候被销毁?

  1. 服务器关闭

  2. Session 对象调用 invalidate() 方法

  3. Session 默认失效时间 30 分钟过后

    1. 选择性配置修改

      在 apache-tomcat-8.5.31\conf\web.xml 中修改

      <session-config>
      	<session-timeout>30</session-timeout>
      </session-config>
      

5. Session 的特点

  1. Session 用于存储一次会话的多次请求的数据,存储服务器端
  2. Session 可以存储任意类型,任意大小的数据

6. Session 与 Cookie 的区别

  1. Session 存储数据在服务器端,Cookie 存储数据在客户端
  2. Session 没有数据大小限制,Cookie 有数据大小限制
  3. Session 数据安全,Cookie 相对数据不安全

7. 验证码登录案例

  1. 需求分析

    1. 访问带有验证码的登录页面 login.jsp
    2. 用户输入用户名,密码以及验证码
      • 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
      • 如果验证码输入有误,跳转登录页面,提示:验证码错误
      • 如果全部输入正确,则跳转到主页 success.jsp,显示:用户名,欢迎您
  2. 概要设计

    在这里插入图片描述

  3. 编码实现

    login.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <script>
        // 页面完成加载在能执行
        window.onload = function () {
            // 获取图片对象
            var img = document.getElementById("checkCode");
            // 获取改变图片对象
            var change = document.getElementById("change");
    
            // img 绑定单击事件
            img.onclick = function () {
                // 加时间戳,实现切换图片
                var date = new Date().getTime();
                img.src = "/checkCodeServlet?time="+date;
            }
            // change 绑定单击事件
            change.onclick = function () {
                // 加时间戳,实现切换图片
                var date = new Date().getTime();
                img.src = "/checkCodeServlet?time="+date;
            }
        }
    </script>
    <body>
    <form action="/LoginServlet" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td>验证码:</td>
                <td><input type="text" name="checkCode"></td>
            </tr>
            <tr>
                <td><img id="checkCode" src="/checkCodeServlet"></td>
                <td><a id="change" href="javascript:void(0);">看不清换一张</a></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="登录"></td>
            </tr>
        </table>
    </form>
    <div><%= request.getAttribute("checkCode_error") == null ? "" : request.getAttribute("checkCode_error")%></div>
    <div><%= request.getAttribute("up_error") == null ? "" : request.getAttribute("up_error")%></div>
    </body>
    </html>
    
    

    CheckCodeServlet:

    package com.zt.servlet;
    
    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    @WebServlet("/checkCodeServlet")
    public class CheckCodeServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            
            int width = 100;
            int height = 50;
    
            //1.创建一对象,在内存中图片(验证码图片对象)
            BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    
    
            //2.美化图片
            //2.1 填充背景色
            Graphics g = image.getGraphics();//画笔对象
            g.setColor(Color.PINK);//设置画笔颜色
            g.fillRect(0,0,width,height);
    
            //2.2画边框
            g.setColor(Color.BLUE);
            g.drawRect(0,0,width - 1,height - 1);
    
            String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
            //生成随机角标
            Random ran = new Random();
    
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 1; i <= 4; i++) {
                int index = ran.nextInt(str.length());
                //获取字符
                char ch = str.charAt(index);//随机字符
                stringBuilder.append(ch);
                //2.3写验证码
                g.drawString(ch+"",width/5*i,height/2);
            }
            // 将验证码转为 String 类型
            String s = stringBuilder.toString();
            // 将验证码存入 Session
            request.getSession().setAttribute("checkCode_session",s);
    
            //2.4画干扰线
            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);
            }
    
    
            //3.将图片输出到页面展示
            ImageIO.write(image,"jpg",response.getOutputStream());
    
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    

    LoginServlet:

    package com.zt.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.设置 request 编码
            request.setCharacterEncoding("utf-8");
            // 2.获取参数
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String checkCode = request.getParameter("checkCode");
    
            // 3.获取生成的验证码
            HttpSession session = request.getSession();
            String checkCode_session = (String) session.getAttribute("checkCode_session");
            // 删除 checkCode_session,因为页面后退验证码图片不变
            session.removeAttribute("checkCode_session");
    
            // 4.判断用户输入验证码是否与生成的验证码一致
            // 验证码忽略大小写
            if(checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)){
                // 验证码一致
                // 判断用户名和密码是否一致
                if("张三".equals(username) && "123".equals(password)){
                    // 用户名和密码一致
                    // 存储 Session 信息
                    session.setAttribute("username",username);
                    // 重定向到 success.jsp
                    response.sendRedirect(request.getContextPath()+"/success.jsp");
                }else {
                    // 用户名和密码不一致
                    // 存储提示信息到 request
                    request.setAttribute("up_error","用户名或密码不正确");
                    // 转发到登陆页面
                    request.getRequestDispatcher("/login.jsp").forward(request,response);
                }
            }else {
                // 验证码不一致
                // 存储提示信息到 request
                request.setAttribute("checkCode_error","验证码不正确");
                // 转发到登陆页面
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    

    success.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%= request.getSession().getAttribute("username")%>,欢迎你!
    </body>
    </html>
    
  4. 案例效果

    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bm1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值