Cookie&Session
2021/5/10 10:26:03
本文主要是介绍Cookie&Session,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
15.Cookie&Session
15.1.会话技术
- 会话:一次会话中包含多次请求和响应。
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能:在一次会话的范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
- 原因:因为Html的无状态无标记性,浏览器无法识别当前HTTP报文是哪一个客户端发送过来的,引入会话技术解决浏览器存储数据问题
15.2.Cookie
- 概念:客户端会话技术,将数据保存到客户端
- 使用步骤:
- public Cookie(String name, String value):构造方法,创建Cookie对象,绑定数据
- response.addCookie(Cookie cookie) : 发送Cookie对象
- Cookie[] request.getCookies() : 获取Cookie,拿到数据
- 实现原理
- 基于响应头set-cookie和请求头cookie实现
- cookie的细节
- 一次可以发送多个cookie
- 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
- cookie在浏览器中保存时间
- 默认情况下,当浏览器关闭后,Cookie数据被销毁
- 持久化存储:setMaxAge(int seconds)
- 正整数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
- 负整数:默认值
- 零:删除cookie信息,删除之前,一定要setPath相同的路径,浏览器要比对是否一致
@WebServlet("/del") public class DelCookieServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //通过访问该servlet,将cookie信息删除 Cookie[] cookies = request.getCookies(); if(cookies != null){ for (Cookie cookie : cookies) { if("username".equals(cookie.getName())){ cookie.setMaxAge(0); //需要把这个告诉给浏览器 response.addCookie(cookie); } } } } }
- cookie存储中文
- 在tomcat 8 之前 cookie中不能直接存储中文数据。
- 需要将中文数据转码—一般采用URL编码(%E3)
- 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
- 在tomcat 8 之前 cookie中不能直接存储中文数据。
- cookie共享问题
- 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 默认情况下cookie不能共享
- setPath(String path) : 设置cookie的获取范围。默认情况下,设置当前的虚拟目录
- 不可以设置一个和当前域名无关的cookie信息,如当前localhost,设置一个baidu.com域名的cookie是不成功的,原因是出于安全性考虑。
- 如果要共享,则可以将path设置为"/"
- 删除cookie时,如果当前cookie没有设置path,那么直接设置MaxAge=0即可删除cookie
- 但是如果cookie设置了path,那么删除cookie的时候,一定要再把path写一遍。
cookie.setMaxAge(0); cookie.setPath(request.getContextPath() + "/info"); response.addCookie(cookie);
- 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 不同的tomcat服务器间cookie共享问题
- setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
- setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享
- Cookie的特点和作用
- cookie存储数据在客户端浏览器
- 浏览器对于单个cookie 的大小有限制(4kb) ,浏览器的cookie总数一般限制300个,对同一个域名下的总cookie数量也有限制(20-50个)
- 作用:
- cookie一般用于存出少量的不太敏感的数据,且只能存储字符串
- 在不登录的情况下,完成服务器对客户端的身份识别
- 案例:记住上一次访问时间
- 需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
- 分析:
- 可以采用Cookie来完成
- 在服务器中的Servlet判断是否有一个名为lastTime的cookie
- 有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:2018年6月10日11:50:20
- 写回Cookie:lastTime=2018年6月10日11:50:01
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=2018年6月10日11:50:01
@WebServlet("/cookieTest") public class CookieTest extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置响应的消息体的数据格式以及编码 response.setContentType("text/html;charset=utf-8"); //1.获取所有Cookie Cookie[] cookies = request.getCookies(); boolean flag = false;//没有cookie为lastTime //2.遍历cookie数组 if(cookies != null && cookies.length > 0){ for (Cookie cookie : cookies) { //3.获取cookie的名称 String name = cookie.getName(); //4.判断名称是否是:lastTime if("lastTime".equals(name)){ //有该Cookie,不是第一次访问 flag = true;//有lastTime的cookie //设置Cookie的value //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String str_date = sdf.format(date); System.out.println("编码前:"+str_date); //URL编码 str_date = URLEncoder.encode(str_date,"utf-8"); System.out.println("编码后:"+str_date); cookie.setValue(str_date); //设置cookie的存活时间 cookie.setMaxAge(60 * 60 * 24 * 30);//一个月 response.addCookie(cookie);//响应数据 //获取Cookie的value,时间 String value = cookie.getValue(); System.out.println("解码前:"+value); //URL解码: value = URLDecoder.decode(value,"utf-8"); System.out.println("解码后:"+value); response.getWriter().write("<h1>欢迎回来,您上次访问时间为:"+value+"</h1>"); break; } } } if(cookies == null || cookies.length == 0 || flag == false){ //没有,第一次访问 //设置Cookie的value //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String str_date = sdf.format(date); System.out.println("编码前:"+str_date); //URL编码 str_date = URLEncoder.encode(str_date,"utf-8"); System.out.println("编码后:"+str_date); Cookie cookie = new Cookie("lastTime",str_date); //设置cookie的存活时间 cookie.setMaxAge(60 * 60 * 24 * 30);//一个月 response.addCookie(cookie); response.getWriter().write("<h1>您好,欢迎您首次访问</h1>"); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
15.3.Session
15.3.1.概念
- 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession是一个接口,所以不能直接new
- 获取HttpSession对象:
- HttpSession session = request.getSession()
- 如果有HttpSession对象,那么返回已有的HttpSession对象
- 如果浏览器不存在HttpSession对象,那么创建一个,
- HttpSession session = request.getSession(boolean creat):
- 如果有HttpSession对象,那么返回已有的HttpSession对象,与creat无关
- 如果没有HttpSession对象
- 如果creat参数为true,返回null
- 如果creat参数为false,创建一个新的
- HttpSession session = request.getSession()
15.3.2.session域
- 作用域介于request域和context域之间,每个客户端的浏览器访问会生成一个session域
- Object getAttribute(String name)
- void setAttribute(String name, Object value)
- void removeAttribute(String name)
- 对于一个商城类网站来说
- Session域可以用来存储和用户相关的数据,比如用户的用户名、用户的信息、购物车等
- Context域可以用来存储和用户无关的数据,比如当前商城的商品分类,数码、服装、食品
@WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); //不做任何校验,只要输入就当作登录成功 request.getSession().setAttribute("username", username); response.getWriter().println("登录成功,即将跳转至个人主页...."); response.setHeader("refresh", "2;url=" + request.getContextPath() + "/info"); //Context域不可以 } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } @WebServlet("/info") public class InfoServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // String username = (String) request.getSession().getAttribute("username"); if(username == null){ username = ""; } response.setContentType("text/html;charset=utf-8"); response.getWriter().println("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + "<head>\n" + " <meta charset=\"UTF-8\">\n" + " <title>Title</title>\n" + "</head>\n" + "<body>"); response.getWriter().println("欢迎您," + username); response.getWriter().println("</body>\n" + "</html>"); } }
15.3.3.原理
- Session的实现是依赖于Cookie的。
- request.getSession()方法会判断当前请求种是否含有一个有效的cookie:JSESSIONID=xxxx
- 如果有的话,则根据这个id找到对应的session对象;
- 如果没有的话,或者说是一个无效的id,那么这个时候给它创建一个新的session对象。
- 本质上就是利用set-Cookie:JSESSIONID=xxxx
15.3.4.细节
- 当浏览器关闭后,服务器不关闭,两次获取session是否为同一个?
- 默认情况下。不是。此时session对象处于一个不可达的状态,即无法访问到
- Session丢失的根本原因是Cookie消失,因为Session是依赖于Cookie存在的,关闭浏览器Cookie会销毁
- 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
Cookie c = new Cookie("JSESSIONID",session.getId()); c.setMaxAge(60*60); response.addCookie(c);
- 浏览器不关闭,服务器关闭后,两次获取的session是同一个吗?
- 不是同一个,因为Session对象的地址变了,但是要确保数据不丢失。tomcat自动完成以下工作
- session的钝化:
- 在服务器正常关闭之前,将session对象将ID和数据内容序列化到硬盘上
- session的活化:
- 在服务器启动后,将session文件转化为内存中的session对象即可。
可以理解为JSESSIONID及其数据内容是灵魂,寄居在一个新的对象上(全新的内存地址)
- session的钝化:
- 不是同一个,因为Session对象的地址变了,但是要确保数据不丢失。tomcat自动完成以下工作
- session销毁时间
- 服务器关闭
- session对象调用invalidate() 。
- session默认失效时间 30分钟
- 选择性配置修改
<session-config> <session-timeout>30</session-timeout> </session-config>
我们通过一个管理系统来验证应用的卸载。
-
本地安装的tomcat的webapps有manager应用
-
本地安装的tomcat的conf/tomcat-users.xml文件配置如下
15.3.5.session与Cookie的区别
- session存储数据在服务器端,Cookie在客户端
- session没有数据大小限制,Cookie有
- session数据安全,Cookie相对于不安全
15.3.6.Cookie被禁用
- session依赖于cookie,那么如果cookie被禁用了,可以使用URL进行重写
- JSESSIONID会附着在地址栏的url后面
15.4.简单的商城案例
- 实现如下简单功能:
- 查看购物车
- 添加购物车
- 查看商品详情
//商品类 public class Product { private String id; private String name; private Double price; private String description; public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public void setId(String id) { this.id = id; } public String getId() { return id; } public Product(String id, String name, Double price, String description) { this.id = id; this.name = name; this.price = price; this.description = description; } @Override public String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + ", description='" + description + '\'' + '}'; } } //网站首页 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.io.IOException; import java.util.ArrayList; import java.util.List; @WebServlet(value = "/index",loadOnStartup = 1) public class IndexServlet extends HttpServlet { @Override public void init() throws ServletException { List<Product> products = new ArrayList<>(); Product model3 = new Product("1", "Tesla Model 3", 240000.0, "国产Tesla model3"); Product nio = new Product("2", "Nio ES6", 450000.0, "国产电动车"); Product xpeng = new Product("3", "Xpeng P7", 230000.0, "国产电动"); Product li = new Product("4", "Li one", 250000.0, "国产电动三"); products.add(model3); products.add(nio); products.add(xpeng); products.add(li); getServletContext().setAttribute("products", products); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //显示出来 List<Product> products = (List<Product>) getServletContext().getAttribute("products"); response.getWriter().println("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + "<head>\n" + " <meta charset=\"UTF-8\">\n" + " <title>Title</title>\n" + "</head>\n" + "<body>"); for (Product product : products) { String detail = response.encodeURL(request.getContextPath() + "/detail?id=" + product.getId()); response.getWriter().println("<div><a href='" + detail + "'>" + product.getName() + "</a></div>"); } response.getWriter().println("\n" + "</body>\n" + "</html>"); } } //商品详情 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.io.IOException; import java.util.List; @WebServlet("/detail") public class DetailServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String id = request.getParameter("id"); //判断是否为空 List<Product> products = (List<Product>) getServletContext().getAttribute("products"); for (Product product : products) { if(product.getId().equals(id)){ response.getWriter().println(product); } } String index = response.encodeURL(request.getContextPath() + "/index"); String addCart = response.encodeURL(request.getContextPath() + "/addCart?id=" + id); String viewCart = response.encodeURL(request.getContextPath() + "/viewCart"); response.getWriter().println("<a href='" + index + "'>返回首页</a>"); response.getWriter().println("<a href='" + addCart + "'>加入购物车</a>"); response.getWriter().println("<a href='" + viewCart + "'>查看购物车</a>"); } } //添加购物车 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; import java.util.ArrayList; import java.util.List; @WebServlet("/addCart") public class AddCartServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String id = request.getParameter("id"); HttpSession session = request.getSession(); //判断是否为空 学有余力的同学可以晚上加上数量 // list //要先取出来,再塞进去 List<String> cart = (List<String>) session.getAttribute("cart"); if(cart == null){ cart = new ArrayList<>(); session.setAttribute("cart", cart); } cart.add(id); response.getWriter().println("加入购物车成功,即将跳转回首页"); String index = response.encodeURL(request.getContextPath() + "/index"); response.setHeader("refresh", "2;url=" + index ); } } //查看购物车 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; import java.util.List; @WebServlet("/viewCart") public class ViewCartServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); HttpSession session = request.getSession(); List<String> cart = (List<String>) session.getAttribute("cart"); if(cart == null){ response.getWriter().println("购物车为空"); return; } List<Product> products = (List<Product>) getServletContext().getAttribute("products"); for (Product product : products) { for (String id : cart) { if(id.equals(product.getId())){ response.getWriter().println(product); } } } String index = response.encodeURL(request.getContextPath() + "/index"); response.getWriter().println("<a href='" + index + "'>返回首页</a>"); } }
这篇关于Cookie&Session的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26终极指南:Scrum中如何设置需求优先级
- 2024-06-26AI大模型企业应用实战(25)-为Langchain Agent添加记忆功能
- 2024-06-26小白家庭 nas 搭建方案-icode9专业技术文章分享
- 2024-06-23AI大模型企业应用实战(14)-langchain的Embedding
- 2024-06-23AI大模型企业应用实战(15)-langchain核心组件
- 2024-06-23AI大模型企业应用实战(16)-langchain核心组件
- 2024-06-23AI 大模型企业应用实战(06)-初识LangChain
- 2024-06-19EntBot.ai: AI Website Chatbot for Product Guides and Development Doc
- 2024-06-17zero-shot-learning-definition-examples-comparison
- 2024-06-06Package Easy(基于 NSIS 的打包exe安装包工具)使用方法-icode9专业技术文章分享