会话管理
会话概述:
日常生活中:从拨通电话到挂断电话之间的一连串你问我答的过程就是一个会话
B/S架构中:从浏览器第一次给服务器发送请求时,建立会话,直到有一方断开,会话结束。
一次会话:包含多次请求响应
会话技术:
问题:Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解
作用:用于存储浏览器与服务器在请求和响应过程中产生的数据
客户端会话技术:cookie
服务器会话技术:session
Cookie
Cookie概述:
它具有name必须的*single value:单一的值必须的*---------以下都可选的---------------------domain它是指定Cookie的域(范围)path它是指定Cookie的路径maxage它是指定Cookie的最大存活时间*------在可选的里面,这两个是一般的---------commentsversion定位Cookie通过的是domain+path+namedomain:path:name:
cookie的值中,不能有 ; , 这些字符。它不支持。
Cookie作用:在一次会话的多次请求之间共享数据,将数据保存到客户端(浏览器)
例如:JD购物车
Cookie快速入门
设置数据到cookie中
// 1.创建cookie对象,设置数据
Cookie cookie = new Cookie(String name,String value);
// 2.通过response,响应(返回)cookie
response.addCookie(cookie);
从cookie中获取数据
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
@WebServlet("/SetServlet")public class SetServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1.创建cookie对象,设置数据Cookie cookie = new Cookie("name","jack");// 2.通过response,响应(返回)cookieresponse.addCookie(cookie);}}
@WebServlet("/GetServlet")public class GetServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1.通过request对象,接收cookie数组Cookie[] cookies = request.getCookies();// 2.遍历数组if(cookies!=null){for (Cookie c : cookies) {String name = c.getName();String value = c.getValue();System.out.println(name + " : " + value);}}}}
工作原理
基于HTTP协议:请求头cookie和响应set-cookie
Cookie细节
服务器发送多个Cookie
答案是可以的// 1. 创建多个cookie对象
Cookie cookie1 = new Cookie(“name”,“lucy”);
Cookie cookie2 = new Cookie(“age”,“18”);
// 2. 通过response响应多个
response.addCookie(cookie1);
response.addCookie(cookie2);
@WebServlet("/MultipleCookie")public class MultipleCookie extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 创建多个cookie对象Cookie cookie1 = new Cookie("name","lucy");Cookie cookie2 = new Cookie("age","18");// 2. 通过response响应多个response.addCookie(cookie1);response.addCookie(cookie2);}}
Cookie在浏览器保存时间
默认情况下
浏览器关闭(会话结束),cookie销毁(内存)
设置cookie的存活时间
cookie.setMaxAge(int second); – 单位是秒
正数:指定存活时间,持久化浏览器的磁盘中,到期后自动销毁
负数:默认浏览器关闭,cookie销毁
零:立即销毁(自杀)
@WebServlet("/MaxAgeCookie")public class MaxAgeCookie extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1.创建cookie对象Cookie cookie = new Cookie("product", "xiaomi10");// 2.设置cookie存活时间// cookie.setMaxAge(-1); // 默认值,浏览器关闭自动销毁// cookie.setMaxAge(60);// 存活30秒,到期自动销毁cookie.setMaxAge(0); // 立即销毁...//3. response响应cookieresponse.addCookie(cookie);}}
Cookie存储中文
tomcat8之前的版本,不支持中文
URLEncoder 编码
URLDecoder 解码
tomcat8以后的版本,支持中文…
Rfc6265Cookie规范,不允许使用 分号、空格、逗号等一些特殊符号…
@WebServlet("/EncodeCookie")public class EncodeCookie extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String product = "华为荣耀 30X,";product= URLEncoder.encode(product, "UTF-8");// 1.创建cookie对象Cookie cookie = new Cookie("product", product);// 2.response响应cookieresponse.addCookie(cookie);}}
@WebServlet("/GetServlet")public class GetServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1.通过request对象,接收cookie数组Cookie[] cookies = request.getCookies();// 2.遍历数组if(cookies!=null){for (Cookie c : cookies) {String name = c.getName();String value = c.getValue();// 解码value = URLDecoder.decode(value, "UTF-8");System.out.println(name + " : " + value);}}}}
Cookie共享数据的范围
在一个tomcat服务器中部署多个web项目,那么这些web项目的Cookie能否共享?默认情况下不可以
默认cookie的携带路径,是当前设置cookie的serlvet父路径。。。。
设置cookie:http://localhost:8080/day11_cookie/EncodeCookie
默认携带路径:http://localhost:8080/day11_cookie
指定cookie的携带路径
cookie.setPath(String path);
举例:
cookie.setPath("/");
/ 相当于 http://localhost:8080/
此cookie携带路径
访问
http://localhost:8080/day11_cookie
http://localhost:8080/day10_response
注意
cookie的携带路径不同,名称可以重复…
练习题
设置cookie
http://localhost:8080/day11_cookie/aa/SetCookie
接收cookie
http://localhost:8080/day11_cookie/bb/GetCookie
默认情况下,是否能获取aa目录下的cookie数据?
答案是不可以…
在当前项目下共享cookie
cookie.setPath("/项目名")
* 课下练习题设置cookiehttp://localhost:8080/day11_cookie/aa/SetCookie接收cookiehttp://localhost:8080/day11_cookie/bb/GetCookie默认情况下,是否能获取aa目录下的cookie数据?答案是不可以....在当前项目下共享cookiecookie.setPath("/项目名")
不同tomcat服务器之间Cookie能否共享 默认情况下不可以多个服务器之间的数据共享cookie,需要在同一个一级域名下
cookie.setDomain(".")
Cookie特点
cookie存储数据都在客户端(浏览器)cookie的存储数据智能是字符串cookie单个大小不能超过4KB同一个域名下cookie数量不能超过50个cookie路径不同,可以重名出现cookie存储的数据不太安全综合案例
用户上次访问记录
需求:
访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您的到来
如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:XXXX。
代码实现
LastTimeServlet@WebServlet("/LastTimeServlet")public class LastTimeServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");// 1.接收cookie数组,取出指定名称cookie对象Cookie cookie = CookieUtils.findByName("last_time", request.getCookies());// 2.判断if (cookie == null) {// 不存在response.getWriter().write("<h1>欢迎您,首次访问....</h1>");} else {// 存在String value = cookie.getValue();response.getWriter().write("<h1>欢迎回来,您上次访问时间:" + value + "</h1>");}// 3.创建cookie对象,记录本次访问时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日-HH:mm:ss");String currentTime = simpleDateFormat.format(new Date());cookie = new Cookie("last_time", currentTime);// 4.设置cookie存活1年cookie.setMaxAge(60 * 60 * 24 * 365);// 5.response响应cookieresponse.addCookie(cookie);}}
CookieUtils
public class CookieUtils {/*根据指定名称,查找cookie对象*/public static Cookie findByName(String name, Cookie[] cookies) {// 非空判断if (cookies != null && cookies.length > 0) {// 遍历for (Cookie cookie : cookies) {// 判断是否有指定名称的cookieif (name.equals(cookie.getName())) {return cookie;}}}// 没找到返回nullreturn null;}}
JSP初体验
Java服务器端页面(Java Server Pages)简单来说:一个特殊的页面,即可定义html标签,又可以定义java代码作用:简化书写,展示动态页面本质:是servlet脚本:Jsp通过脚本方式来定义java代码
<% java代码 %> 就相当于servlet中service方法…
内置对象:在Jsp页面中不需要获取和创建,可以直接使用的对象
request
response
out
注意:在jsp响应内容,使用out
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>demo</title></head><body><h3>我是标题</h3><table border="1" width="200" align="center"><tr><td>我是静态资源...</td></tr></table><%System.out.println("我是jsp哈哈哈...");request.getServletContext();out.write("out输出的hehe");// response.getWriter().write("hehe");%></body></html>
商品浏览记录
需求
做一个商品页面,当我们访问后,在页面上点击查看商品浏览记录后,可以查看到以前浏览过的商品信息
需求分析:
代码实现
goods.html<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><title>goods</title></head><body><h3>商品列表</h3><a href="/day11_cookie/GoodsInfoServlet?name=小米10">小米10</a> <br><a href="/day11_cookie/GoodsInfoServlet?name=华为P40">华为P40</a> <br><a href="/day11_cookie/GoodsInfoServlet?name=iphoneSE">iphoneSE</a> <br><a href="/day11_cookie/GoodsInfoServlet?name=锤子T2">锤子T2</a> <br></body></html>
GoodsInfoServlet
@WebServlet("/GoodsInfoServlet")public class GoodsInfoServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8"); // 请求解码response.setContentType("text/html;charset=utf-8"); // 响应编码// 1.获取请求参数 name 小米10String product = request.getParameter("name");// 2.展示当前商品详情response.getWriter().write("您当前浏览的商品为:" + product);// 3.获取指定名称cookie对象Cookie cookie = CookieUtils.findByName("goods_name", request.getCookies());// 4.判断是否存在...if (cookie == null) {// 5.如果不存在,将当前商品设置到cookie对象中...cookie = new Cookie("goods_name", product);} else {// 6.如果有,将浏览记录取出,格式:小米10-华为P40String value = cookie.getValue();// 7.判断当前商品是否在此cookie中List<String> list = Arrays.asList(value.split("-"));// 8.如果不包含,追加if (!list.contains(product)) {value = value + "-" + product; // 格式:小米10-华为P40}// 9.将value,重置到cookie中cookie = new Cookie("goods_name", value);}// 10.通过response响应到浏览器// 设置存活时间 为1年cookie.setMaxAge(60 * 60 * 24 * 365);response.addCookie(cookie);// 11.制作a标签,实现记录浏览商品功能response.getWriter().write("<br><a href='/day11_cookie/goods.html'>继续浏览</a>");// 12.制作a标签,实现查看浏览记录功能response.getWriter().write("<br><a href='/day11_cookie/history.jsp'>浏览记录</a>");}}
history.jsp
<%@ page import="cn.itcast.f_lasttime.CookieUtils" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>history</title></head><body><%// java的代码...// 1.获取指定名称cookie对象Cookie cookie = CookieUtils.findByName("goods_name", request.getCookies());// 2.判断是否存在浏览记录if(cookie == null){// 没有提示out.write("暂无浏览记录....");}else{// 有的话,遍历显示out.write("浏览记录如下:<br>");String value = cookie.getValue(); // 格式:小米10-华为P40for (String product : value.split("-")) {out.write(product+"<br>");}}%></body></html>
Session
Session概述
先来看看使用Cookie的问题(缺点):
1. 最多存储4KB字符串
2. 存储数据不太安全(由于Cookie是在客户端,很多操作用户都能自己去修改获取查看)
session作用:在一次会话的多次请求之间共享数据,将数据保存到服务器端
Session快速入门
HttpSession也是一个域对象
API 存储数据
void setAttribute(String name,Object value)获取数据
Object getAttribute(String name)删除数据
void removeAttribute(String name)
步骤分析:
将数据存储到session中
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,存储数据
session.setAttribute(“username”,“哈哈,呵呵”);
从session中获取数据
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,获取数据
session.getAttribute(“username”);
@WebServlet("/SetSession")public class SetSession extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1.通过rquest对象,获取session对象HttpSession session = request.getSession();// 2.操作session的API,存储数据session.setAttribute("username", "哈哈,呵呵");}}
@WebServlet("/GetSession")public class GetSession extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1.通过rquest对象,获取session对象HttpSession session = request.getSession();// 2.操作session的API,获取数据String username = (String) session.getAttribute("username");System.out.println("GetSession获取:" + username);}}
工作原理:
Session基于Cookie技术实现
Session细节
客户端关闭,服务器不关闭
两次获取的Session数据是否相同?
默认情况下,浏览器关闭,再次打开二次获取的session不一样
基于cookie实现(浏览器关闭,cookie销毁)
设置cookie的存活时间(JESSIONID)
这里我们代替服务器,做一个小操作,覆盖这个JSESSIONID,指定持久化时间
客户端不关闭,服务器关闭
两次获取的Session数据是否相同?
当服务器正常关闭,重启后,二次获取的session数据一样
tomcat这哥们实现以下二个功能
钝化(序列化)
当服务器正常关闭时,session中的数据,会序列化到磁盘
活化(反序列化)
当服务器开启后,从磁盘文件中,反序列化到内存中
我们使用的idea工具有坑…
支持钝化
我们可以强制设置idea重启时不清除session会话
生命周期
何时创建用户第一次调用request.getSession()方法时,创建何时销毁
服务器非正常关闭
非活跃状态30分钟后
tomcat进行配置 /tocmat安装目录/conf/web.xml
session.invalidate(); 自杀作用范围
一次会话中,多次请求之间
注意:每一个浏览器跟服务器都是独立的会话…
URL重写
Session基于Cookie技术实现;浏览器的Cookie是可以禁用的,一旦禁用后Session就会出现问题。
开发中,一般我们是不关注用户的cookie是否禁用的,若用户禁用了cookie,智能用别的网站了。
如果真想处理用户端的cookie禁用,我们可以使用url重写技术:
@WebServlet("/SessionDemo2")public class SessionDemo2 extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取session对象HttpSession session = request.getSession();// 向session中存数据session.setAttribute("username", "哈哈,即使浏览器禁用了cookie,也不影响我使用");// 定义urlString url = "/day12_session/GetSession";// 重写url,拼接JSESSIONIDurl = response.encodeURL(url); // /day12_session/GetSession?JSESSIONID=xxsdfasdfSystem.out.println(url);response.setContentType("text/html;charset=utf-8");response.getWriter().write("<a href='" + url + "'>跳转到获取session内容</a>");}}
Session特点:
session存储数据在服务器中session存储类型任意(Object)session存储大小和数量没有限制(相对于内存)session存储相对安全cookie和Session的选择
cookie将数据保存在浏览器端,数据相对不安全.建议敏感的数据不要放在cookie中,而且数据大小是有限制的 成本低,对服务器要求不高 session将数据保存在服务器端,数据相对安全.数据的大小要比cookie中数据灵活很多 成本较高,对服务器压力较大综合案例:
商品购物车:
需求:
有一个商品页面,可以点击超链接将商品添加到购物车,还有一个超链接,点击它可以查看购物车中的商品信息
代码实现:
goods.jsp<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>goods.jsp</title></head><body><h3>商品列表</h3><a href="/day12_session/AddCartServlet?name=电视机">电视机,加入购物车</a><br><a href="/day12_session/AddCartServlet?name=冰箱">冰箱,加入购物车</a><br><a href="/day12_session/AddCartServlet?name=洗衣机">洗衣机,加入购物车</a><br><a href="/day12_session/AddCartServlet?name=电脑">电脑,加入购物车</a><br></body></html>
AddCartServlet
@WebServlet("/AddCartServlet")public class AddCartServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8"); // 请求解码response.setContentType("text/html;charset=utf-8");// 响应编码// 1.获取请求参数String product = request.getParameter("name");// 2.返回结果response.getWriter().write(product + ",商品已成功加入购物车 <br>");// 3.从session中获取购物车Map<String, Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");// 4.判断购物车是否为空if (cart == null) {cart = new HashMap<>();}// 5.判断购物车中是否包含本次添加的商品if (cart.containsKey(product)) {// 6.存在,数量+1Integer oldCount = cart.get(product); // 之前数量cart.put(product, oldCount + 1);// 数量加1} else {// 7.不存在,直接添加商品,数量为1cart.put(product, 1);}// 8.重新将购物车,写入到session中request.getSession().setAttribute("cart", cart);// 9.继续浏览response.getWriter().write("<a href='/day12_session/goods.jsp'>继续浏览</a><br>");// 10.查看购物车response.getWriter().write("<a href='/day12_session/cart.jsp'>查看购物车</a><br>");}}
cart.jsp
<%@ page import="java.util.Map" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>cart</title></head><body><h3>购物车页面</h3><table border="1" width="200px" align="center"><tr><th>商品</th><th>数量</th></tr><%// 1.从session中获取购物车Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");// 2.判断是否为空if(cart == null){out.write("购物车内暂时没有商品<br>");}else{for (String s : cart.keySet()) {out.write("<tr><td>"+s+"</td><td>"+cart.get(s)+"</td></tr>");}}%></table></body></html>
用户登录(验证码)
需求:
用户访问带有验证码的登陆页面,输入用户名,密码以及验证码实现登录功能
代码实现:
创建web项目导入验证码Servletlogin.jsp<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>login.jsp</title></head><body><h3>用户登录</h3><form action="/day12_login/LoginServlet" method="post">用户:<input type="text" name="username"> <br>密码:<input type="password" name="password"><br>验证码:<input type="text" name="checkcode"> <img src="/day12_login/CheckcodeServlet" alt=""><br><input type="submit" value="登录"><span style="color:red"><%String error = (String) request.getAttribute("error");if (error != null) {out.write(error);// 输出提示信息}%></span></form></body></html>
LoginServlet
@WebServlet("/LoginServlet")public class LoginServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}// 课下作业,实现非空判断...protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");// 1.获取用户输入的验证码String checkcode = request.getParameter("checkcode");// 2.获取session中验证码String codeSession = (String) request.getSession().getAttribute("code_session");// 3.校验是否匹配if (!checkcode.equalsIgnoreCase(codeSession)) {// 验证码不配,友情提示...request.setAttribute("error", "验证码输入错误...");// 转发到login.jsprequest.getRequestDispatcher("/login.jsp").forward(request, response);// 代码不在往下执行....return;}// 4.获取用户输入的用户名和密码String username = request.getParameter("username");String password = request.getParameter("password");// 5.判断用户名密码不正确if (!("jack".equals(username) && "123".equals(password))) {// 友情提示request.setAttribute("error", "用户名或密码错误...");// 转发到login.jsprequest.getRequestDispatcher("/login.jsp").forward(request, response);// 代码不在往下执行....return;}// 6. 将用户名存入到session中request.getSession().setAttribute("username", username);// 7.重定向到success.jspresponse.sendRedirect(request.getContextPath() + "/success.jsp");}}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>success</title></head><body><h3><%// 获取用户信息String username = (String) request.getSession().getAttribute("username");if (username != null) {out.write("用户您好,登录成功:"+username);}%></h3></body></html>
如果觉得《会话管理:Cookie和Session》对你有帮助,请点赞、收藏,并留下你的观点哦!