文章目录
1. Session 的概念
服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。
2. Session 的快速入门
-
获取 HttpSession 对象
HttpSession session = request.getSession();
-
使用 HttpSession 对象
- 获取数据
- Object getAttribute(String name)
- 存储数据
- void setAttribute(String name, Object value)
- 移除数据
- void removeAttribute(String name)
- 获取数据
-
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 的原理
- Session 的实现是依赖于 Cookie 的
- 在一次会话中,获取的 Session 对象是同一个
4. Session 的细节
4.1 浏览器关闭后,服务器不关闭,两次获取的 Session 对象是同一个吗?
-
默认情况下,不是同一个。
-
如果需要为同一个,则可以创建一个 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 自动完成以下工作:
- Session 的钝化:在服务器正常关闭之前,将 Session 对象序列化到硬盘上
- Session 的活化:在服务器启动后,将 Session 文件转化为内存中的 Session 对象。
注意:
-
在 IDEA 中只能完成 Session 的钝化,但重启服务器后会删除 work 目录,由于 Session 文件存储于 work 目录中,所以无法完成 Session 的活化
-
但用本地的 Tomcat 部署项目是可以完成 Session 的钝化和活化的
4.3 Session 什么时候被销毁?
-
服务器关闭
-
Session 对象调用 invalidate() 方法
-
Session 默认失效时间 30 分钟过后
-
选择性配置修改
在 apache-tomcat-8.5.31\conf\web.xml 中修改
<session-config> <session-timeout>30</session-timeout> </session-config>
-
5. Session 的特点
- Session 用于存储一次会话的多次请求的数据,存储服务器端
- Session 可以存储任意类型,任意大小的数据
6. Session 与 Cookie 的区别
- Session 存储数据在服务器端,Cookie 存储数据在客户端
- Session 没有数据大小限制,Cookie 有数据大小限制
- Session 数据安全,Cookie 相对数据不安全
7. 验证码登录案例
-
需求分析
- 访问带有验证码的登录页面 login.jsp
- 用户输入用户名,密码以及验证码
- 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
- 如果全部输入正确,则跳转到主页 success.jsp,显示:用户名,欢迎您
-
概要设计
-
编码实现
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>
-
案例效果