一.Session 1.1 概述 1.2 快速入门 HttpSession也是一个对象
说明 API 存储数据 void setAttribute(String name,Object value) 获取数据 Object getAttribute(String name) 删除数据 void removeAttribute(String name) 步骤分析
将数据存储到session中
说明 API 通过request对象,获取session对象 HttpSession session = req.getSession(); 操作session的API,存储数据 session.setAttribute(“username”,”AAABBBCCCC”); 从session中获取数据 说明 API 通过request对象,获取session对象 HttpSession session = req.getSession(); 操作session的API,获取数据 session.getAttribute(“username”);
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 @WebServlet("/SetSession") public class SetSession extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this .doPost(req, resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); session.setAttribute("username" ,"AAABBBCCCC" ); } } @WebServlet("/GetSession") public class GetSession extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this .doPost(req, resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); String username = (String) session.getAttribute("username" ); System.out.println("GetSession:" +username); } }
1.3 工作原理 Session基于Cookie技术实现 HttpSession session = req.getSession(); 如果用户是第一次访问:表示创建Session对象,生成编号 如果用户是第N次访问,根据浏览器携带编号找session对象
1.4 Session细节 1.4.1 客户端关闭,服务器不关闭,两次获取的Session数据是否相同 默认情况下,浏览器关闭再打开,两次获取的Session不同(基于cookie实现,浏览器关闭,cookie销毁) 设置cookie的存活时间(JESSIONID),代替服务器,覆盖JESSIONID,指定持久化时间
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 @WebServlet("/SessionDemo01") public class SessionDemo01 extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this .doPost(req, resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); session.setAttribute("username" ,"zZZ" ); String id = session.getId(); Cookie cookie = new Cookie ("JESSIONID" , id); cookie.setMaxAge(60 *2 ); cookie.setPath(req.getContextPath()); resp.addCookie(cookie); } }
1.4.2 客户端不关闭,服务器关闭,两次获取的Session数据是否相同 当服务器正常关闭,重启后,两次获取的session数据一样 Tomcat实现了以下功能 钝化(序列化):当服务器正常关闭时,session中当数据,会序列化到磁盘 活化(反序列化):当服务器开启后,从磁盘中读取文件,反序列化到内存中 1.4.3 生命周期 何时创建
用户第一次调用req.getAttribute()时,创建 何时销毁
服务器非正常关闭 非活跃状态30分钟后销毁(tomcat/conf/web.xml官方已配置) session.invalidate();立即销毁 作用范围
一次会话中,多次请求之间 注意:每一个浏览器和服务器之间都是独立的会话 1.4.4 URL重写 Session基于Cookie技术实现;浏览器Cookie可以禁用,一旦禁用,Session会出现问题 开发中,一般不考虑禁用Cookie用户
如果真要处理,可以使用URL重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @WebServlet("/SessionDemo02") public class SessionDemo02 extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this .doPost(req, resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); session.setAttribute("username" , "SIODJOISDJSO" ); String url = "/Day37_war_exploded/GetSession" ; url = resp.encodeURL(url); resp.setContentType("text/html;charset=utf-8" ); resp.getWriter().write("<a href'" + url + "'>Direct to get Session</a>" ); } }
1.5 Session特点 session存储数据在服务器 session存储类型任意(Object) session存储大小和数据没有限制(相对于内存) session存储数据相对安全 cookie和session的选择
cookie将数据保存在浏览器端,数据相对不安全,建议敏感数据不要放在cookie中,且数据大小有限制 成本低,对服务器要求不高 浏览器为了解决该不足,前端使用了localStroage
session将数据保存在服务器端,数据相对安全,数据大小比cookie中灵活 成本较高,对服务器压力大
二. 三大域对象总结 request,session,ServletContext
2.1 API 设置数据 void setAttribute(String name,Object o) 获取数据 Object getAttribute(String name) 删除数据 void removeAttribute(String name) 2.2 生命周期 2.2.1 ServleetContext域对象 何时创建 服务器正常启动,项目加载时创建 何时销毁 服务器关闭或项目卸载时,卸载 作用范围 整个web项目(共享数据) 2.2.2 HttpSession域对象 何时创建 用户第一次调用req.getSession() 方法时创建 用户访问携带的JESSIONID与服务器不匹配时创建 何时销毁 服务器非正常关闭时 未活跃时间30 min session.invalidate();立即销毁 作用范围 一次会话中,多次请求间(共享数据) 2.2.3 HttpServletRequest域对象 何时创建 用户发送请求时创建 何时销毁 服务器做出响应后销毁 作用范围 一次请求中,多次转发间(共享数据) 2.3 小结 能用小的不用大的:request<session<servletContext
常用场景
request 一次查询的结果 (servlet转发jsp) session 存放当前会话的私有数据 (验证码、购物车、等) servletContext:若需要所有的Servlet都能访问到,才使用这个域对象
三.综合案例 3.1 商品购物车 3.1.1 需求分析 addCatrSetvlet
1.获取请求参数name(product) 2.返回:product 商品已加入购物车 3.从session中获取购物车 4.如果购物车为空,创建cart = new HashMap() 5.判断,此商品是否存在于购物车 6.不存在,添加商品数量1 7.存在,在原商品基础上+1 8.将购物车重写到session中
cart.jsp
1.从session中获取购物车对象 2.判断是否为空 3.如果空,显示购物车空 4.如果不为空,遍历展示商品和数量
3.1.2 代码实现 goods.jsp addCartServlet cart.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Goods</title> </head> <body> <h3>商品列表</h3> <a href="/Day37_war_exploded/AddCartServlet?name=TV" >TV,add to cart</a><br> <a href="/Day37_war_exploded/AddCartServlet?name=PC" >PC,add to cart</a><br> <a href="/Day37_war_exploded/AddCartServlet?name=Phone" >Phone,add to cart</a><br> </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 @WebServlet("/AddCartServlet") public class AddCartServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this .doPost(req, resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8" ); resp.setContentType("text/html;charset=utf-8" ); String product = req.getParameter("name" ); resp.getWriter().write(product + ", has add to Cart" ); Map<String, Integer> cart = (Map<String, Integer>) req.getSession().getAttribute("cart" ); if (cart == null ) { cart = new HashMap <>(); } if (cart.containsKey(product)) { Integer oldCount = cart.get(product); cart.put(product, ++oldCount); } else { cart.put(product, 1 ); } req.getSession().setAttribute("cart" , cart); resp.getWriter().write("<br><a href='/Day37_war_exploded/goods.jsp'>Continue View</a><br>" ); resp.getWriter().write("<br><a href='/Day37_war_exploded/cart.jsp'>Check Shopping Cart</a>" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <table border ="1" width ="200px" align ="center" > <tr > <th > Product</th > <th > Quantity</th > </tr > <% //从session中获取购物车 Map<String, Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart"); //判断是否为空 if (cart == null) { out.write("No Product here<br > "); } else { for (String product : cart.keySet()) { out.write("<tr > <td > " + product + "</td > <td > " + cart.get(product) + "</td > <tr /> "); } } %> <a href ='/Day37_war_exploded/goods.jsp' > Continue View</a > </table >
3.2 用户登陆(验证码) 3.2.1 需求分析 3.2.2 代码实现
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 @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8" ); resp.setContentType("text/html;charset=utf-8" ); String checkcode = req.getParameter("checkcode" ); String codeSession = (String) req.getSession().getAttribute("code_session" ); if (!checkcode.equalsIgnoreCase(codeSession)) { req.setAttribute("Error" , "Check Code Wrong" ); req.getRequestDispatcher("/login.jsp" ).forward(req, resp); return ; } String username = req.getParameter("username" ); String password = req.getParameter("password" ); if (!("jack" .equals(username) && "123" .equals(password))) { req.setAttribute("Error" , "Username or Password Wrong" ); req.getRequestDispatcher("/login.jsp" ).forward(req, resp); return ; } req.getSession().setAttribute("username" , username); resp.sendRedirect(req.getContextPath() + "/success.jsp" ); } }
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 <form action="/war_exploded/LoginServlet" method="post" > Name : <input type="text" name="username"><br> Password: <input type="password" name="password"><br> Checkcode: <input type="text" name="checkcode"><img src="/Day37_war_exploded/CheckCodeServlet" id="image1" alt=""><br> <input type="submit" value="Login"> <span style="color: red"> <% String error = (String) request.getAttribute("Error"); if (error != null) { out.write(error); } %> </span> </form> <script> document.getElementById("image1").onclick = function () { this.src = '/Day37_war_exploded/CheckCodeServlet?' + new Date().getTime(); } </script> </body> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Success</title> </head> <body> <% //获取用户信息 String username = (String) request.getSession().getAttribute("username"); if (username != null){ out.write("Welcome ,"+username); } %> </body> </html>
总结 概述 在一次会话的多次请求之间共享数据,将数据保存到服务器端 实现原理 基于Cookie技术 jsessionid=xxxx 常用方法 获取session request.getSession() 使用session setAttribute() getAttribute() remomveAttribute() 生命周期 何时创建 用户第一次执行getSession()方法时,创建 用户携带的jssionid与服务器不匹配时,创建 何时销毁 服务器非正常关闭时 session.invalidate() session默认销毁时间30分钟
tomcat目录/conf/web.xm 作用范围 一次会话中,多次请求之间 特点
session在服务器端存储数据
session存储数据格式可以是任意类型
session存储数据没有大小限制(相对于内存)
session存储数据相对安全 三个域对象 ServletContext 创建 销毁 作用域 HttpSession 创建 销毁 作用域 HttpServletRequest 创建 销毁 作用域 综合案例 商品购物车 用户登录(验证码)