当前位置: 首页 > news >正文

Javaweb (二) | Cookie、Session

7.Cookie、Session

新建项目 session-cookie,修改 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

在这里插入图片描述

pom.xml 中所有的插件什么的都可以去掉,只留下如下内容

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>session-cookie</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging></project>

将 Servlet 和 JSP 的 API 放入到 pom.xml 中

  <dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version></dependency></dependencies>

下面这里可以看到是否成功导入
在这里插入图片描述

7.1、会话

会话: 用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话;

有状态会话: 一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;

你怎么证明你是学校的学生?

  1. 发票, 学校给你发票(报名的发票)
  2. 学校登记, 学校标记你来过了

一个网站,怎么证明你来过?

客户端, 服务端

  1. 服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下次你来的时候我来匹配你; seesion

7.2、保存会话的两种技术

cookie

  • 客户端技术 (服务器通过 响应 发送 cookie 给客户端,客户端通过 请求 带到服务器上),服务器不需要管什么。

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息? 我们可以把信息或者数据放在Session中!
    常见:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!

常见场景:网站登录之后,下次不用再登录了,第二次访问直接就上去了!

7.3、Cookie

实现保存用户上一次访问的时间(按照之前学得,可以用 IO 实现,即先保存到本地,然后再读,方法很 low)

服务器告诉你来的时间,把这个时间封装成一个信件(Cookie),下次你来的时候带上,就知道你来了

新建一个 CookieDemo01 类,在 doGet 中写入相关逻辑

// 保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 服务器告诉你来的时间,把这个时间封装成一个信件(Cookie),下次你来的时候带上,就知道你来了//解决中文乱码问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=UTF-8");PrintWriter out = resp.getWriter();//cookie服务器从客户端获取Cookie[] cookies = req.getCookies();//这里返回数组说明cookie可能存在多个//判断cookie是否存在if (cookies!=null){//如果存在怎么办out.print("你上一次来的时间是:");for (Cookie cookie : cookies) {//获取cookie 的名字if (cookie.getName().equals("lastTime")){//获取cookie中的值Long l = Long.parseLong(cookie.getValue());Date date = new Date(l);out.write(date.toLocaleString());}}}else {out.print("第一次来");}// 服务器给客户端响应一个cookie,放在客户端Cookie cookie = new Cookie("lastTime", System.currentTimeMillis() + "");resp.addCookie(cookie); // 这里服务器到时候就会响应这个 cookie 给客户端}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册 servlet

  <servlet><servlet-name>CookieDemo01</servlet-name><servlet-class>com.uestc.servlet.CookieDemo01</servlet-class></servlet><servlet-mapping><servlet-name>CookieDemo01</servlet-name><url-pattern>/c1</url-pattern></servlet-mapping>

配置 tomcat
在这里插入图片描述

启动 tomcat,请求 c1,但是没有输出代码逻辑中的 “第一次来”,说明 Cookie 中有东西
在这里插入图片描述

那这个东西到底在哪里呢? 查看网页的检查/审查元素等,可能不同浏览器称呼不同
在这里插入图片描述

在这里插入图片描述

我们再次请求 c1,这里就看到时间了
在这里插入图片描述

在这里插入图片描述

现在我们进入检查,把 lastTime 删除掉,服务器就需要再一次返回一个新的,请求 c1,成功,时间没有了

在这里插入图片描述

为什么能够拿到这个时间? 进入检查的网络(Network),看看响应:可以看到 c1 这个请求下,执行了 Set-Cookie
在这里插入图片描述
来看请求头,可以看到我们设置的 lastTime
在这里插入图片描述

然后我们关闭浏览器,重新打开,又没有了,因为浏览器关闭了,会话就结束了
在这里插入图片描述

Cookie 类中一个方法 cookie.setMaxAge,可以设置 Cookie 有效期,比如设置为一天就是 cookie.setMaxAge(24*60*60); ,按 s 开始的,加入到 doGet 添加 Cookie 的步骤中

在这里插入图片描述

此时重启 tomcat,关闭浏览器再打开,请求,依然可以拿到
在这里插入图片描述
在这里插入图片描述

但是浏览器都关闭了,Cookie 还存在,不安全!

总结

  1. 从请求中拿到cookie信息(客户端发送过来的)
  2. 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得Cookie(获得的是下面最后一行代码最后一次响应给客户端的,第一次没有)
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie,也可以响应多个

浏览各种网站后的 cookie:一般会保存在本地的 用户目录下 AppData;

一个网站cookie是否存在上限!聊聊细节问题(比如学生证,一个人能给他发一万个学生证吗?肯定不能这样)

  • 一个 Cookie 只能保存一个信息;new Cookie 的时候产生
  • 一个 web 站点可以给浏览器发送多个 cookie,最多存放 20 个 cookie;
  • Cookie 大小有限制4kb;
  • 300 个 cookie 浏览器上限

删除 Cookie

  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效期时间为 0 ;

删除 Cookie 示例,新建一个 CookieDemo02

public class CookieDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 创建一个 cookie,名字必须要和要鹏除的名字一致Cookie cookie = new Cookie("lastTime", System.currentTimeMillis() + "");// 将 cookie 的有效期设置为 0,立马过期cookie.setMaxAge(0);resp.addCookie(cookie); // 这里服务器到时候就会响应这个 cookie 给客户端}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册 Servlet

  <servlet><servlet-name>CookieDemo02</servlet-name><servlet-class>com.uestc.servlet.CookieDemo02</servlet-class></servlet><servlet-mapping><servlet-name>CookieDemo02</servlet-name><url-pattern>/c2</url-pattern></servlet-mapping>

访问 c1 有时间,访问 c2,c1 的 cookie 就被删除了!

中文数据传递

// 中文数据传递
public class CookieDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决中文乱码问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=UTF-8"); // 一定要加上这行,负责后网页乱码//cookie服务器从客户端获取Cookie[] cookies = req.getCookies();//这里返回数组说明cookie可能存在多个PrintWriter out = resp.getWriter();//判断cookie是否存在if (cookies!=null){//如果存在怎么办out.print("你上一次来的时间是:");for (Cookie cookie : cookies) {//获取 cookie 的名字if (cookie.getName().equals("name")){//获取cookie中的值System.out.println(cookie.getValue()); // 输出编码的内容out.write(URLDecoder.decode(cookie.getValue(),"utf-8")); // 解码输出到网页}}}else {out.print("第一次来");}// 创建一个 cookie,名字必须要和要鹏除的名字一致Cookie cookie = new Cookie("name", URLEncoder.encode("青年有志", "utf-8")); // 一定要进行上面的解码操作resp.addCookie(cookie); // 这里服务器到时候就会响应这个 cookie 给客户端}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册Servlet

  <servlet><servlet-name>CookieDemo03</servlet-name><servlet-class>com.uestc.servlet.CookieDemo03</servlet-class></servlet><servlet-mapping><servlet-name>CookieDemo03</servlet-name><url-pattern>/c3</url-pattern></servlet-mapping>

启动 Tomcat ,网页上就可以成功啦!
在这里插入图片描述

后台输出了编码后未解码的情况
在这里插入图片描述

注意: 编码解码,快速解决中文乱码问题

URLEncoder.encode("秦疆","utf-8")
URLDecoder.decode(cookie.getValue(),"UTF-8")

7.4、Session(重点)

什么是Session:

  • 服务器会给每一个用户(浏览器)创建一个Session对象;
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
  • 用户登录之后,整个网站它都可以访问! → \to 保存用户的信息;保存购物车的信息……(比如进入B站,点击所有跳转,仍处于登录状态,进入淘宝等也是如此)

进入 HttpSession 类查看

在这里插入图片描述

创建 SessionDemo01 类

public class SessionDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();//给Session中存东西session.setAttribute("name", "青年有志");//获取Session的IDString sessionId = session.getId();//判断Session是不是新创建if (session.isNew()){resp.getWriter().write("session创建成功,ID:"+sessionId);}else {resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);}//Session创建的时候做了什么事情;会将上面的 session.getId() 放入到cookie中
//        Cookie cookie = new Cookie("JSESSIONID",sessionId);
//        resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

注册 Servlet

  <servlet><servlet-name>SessionDemo01</servlet-name><servlet-class>com.uestc.servlet.SessionDemo01</servlet-class></servlet><servlet-mapping><servlet-name>SessionDemo01</servlet-name><url-pattern>/s1</url-pattern></servlet-mapping>

启动 tomcat,请求 s1
在这里插入图片描述

可以看到,只要打开了浏览器就有这个
在这里插入图片描述

同时 cookie 里面也可以看到
在这里插入图片描述

Session 创建的时候做了什么事情?实际上会将上面的 sessionId 放入到 cookie 中

下面我们去另外一个 servlet 中取出上面存的 session

创建类 SessionDemo02,

public class SessionDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();String name = (String) session.getAttribute("name");// 打印 nameSystem.out.println(name);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

注册 Servlet

  <servlet><servlet-name>SessionDemo02</servlet-name><servlet-class>com.uestc.servlet.SessionDemo02</servlet-class></servlet><servlet-mapping><servlet-name>SessionDemo02</servlet-name><url-pattern>/s2</url-pattern></servlet-mapping>

启动 tomcat,第一次请求 s2,后台打印 null
在这里插入图片描述

然后通过 s1,向 session 内存入数据
在这里插入图片描述

然后再次请求 s2,获取到了内容!
在这里插入图片描述

下面再创建一个 Person 类

public class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}

修改 SessionDemo01 类,设置为类对象

public class SessionDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();//给Session中存东西session.setAttribute("name", new Person("青年有志", 18));//获取Session的IDString sessionId = session.getId();//判断Session是不是新创建if (session.isNew()){resp.getWriter().write("session创建成功,ID:"+sessionId);}else {resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);}//Session创建的时候做了什么事情;会将上面的 session.getId() 放入到cookie中
//        Cookie cookie = new Cookie("JSESSIONID",sessionId);
//        resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

此时修改 SessionDemo02,获取到的不再是 String,而是一个 Person 对象

public class SessionDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();Person person = (Person) session.getAttribute("name");// 打印 nameSystem.out.println(person.toString());}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

重启 Tomcat,请求 s1,然后请求 s2,可以看到结果,因此 session 不只是可以存字符串,还可以存用户信息,同时跨 Servlet!。后续还会有更多 session 强大的部分
在这里插入图片描述

上面我们讲过将数据保存到 ServletContext 中,不建议,数据多了服务器会炸的!这里给出了多的一个选择,保存到 session 中。

同时可以注销 Session,我们新建一个 SessionDemo03

注册 Servlet

  <servlet><servlet-name>SessionDemo03</servlet-name><servlet-class>com.uestc.servlet.SessionDemo03</servlet-class></servlet><servlet-mapping><servlet-name>SessionDemo03</servlet-name><url-pattern>/s3</url-pattern></servlet-mapping>

重启 tomcat,然后通过火狐和 Edge 浏览器(不同的浏览器),获取到了不同的 session。相同的浏览器无论开多少个窗口,session 都相同,不会变
在这里插入图片描述

然后我们先请求 s3 注销掉 session,再请求 s2,获取 session 就报错如下了,因为已经没有 session 了!
在这里插入图片描述

然后再请求 s1,获得了一个新的 session,因为一旦注销后,就会获取一个新的 session
在这里插入图片描述

Cookie 我们设置了一个时间,Session 同样可以设置一个超时时间,会话自动过期:web.xml 配置如下:

<!--设置Session默认的失效时间-->
<session-config><!--15分钟后Session自动失效,以分钟为单位--><session-timeout>15</session-timeout>
</session-config>

上面这个设置后,在 15 分钟后,session 就会变,打印 sessionID 可以观察到

Session 和 cookie 的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务创建;

使用场景:

  • 保存一个登录用户的信息;
  • 购物车信息;
  • 在整个网站中经常会使用的数据,我们将它保存在 Session 中;(因为每次不需要 new 新的了,直接去取即可)

得到Session

//得到Session
HttpSession session = req.getSession();Person person = (Person) session.getAttribute("name");System.out.println(person.toString());HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销Session
session.invalidate();


s1 s2 s3 … 表示不同的 Servlet 请求,请求需要浏览器 URL 输入操作请求才能访问,即客户端,请求最终是交给服务器访问。服务器如何证明你来过?第一种方案:第一次来,给客户端发送一个 Cookie,客户端在每次请求的时候携带 Cookie,这样就知道啦!第二种方案:客户端发送请求,服务器会登记一个唯一的 Session ID,每个用户都有一个 Session ID,用户拿到这个 Session ID 自己也保存了一份,Session 所有数据都保存到服务器,当客户端来请求时,客户端的这个 Session ID 与服务器的 Session ID 一致,就会拿到自己对应的那份数据,就好比淘宝,每个人登录进入后信息是不同的,而 Cookie 的数据是保存到客户端。 而ServletContext保存数据的形式,如同多加了一个中间商,所有不同的 s1 s2 s3 … 都可以去拿到 ServletContext 的内容

Cookie 原理如下:
在这里插入图片描述

Session 原理如下:
在这里插入图片描述

ServletContext 原理如下:
在这里插入图片描述


http://www.mrgr.cn/news/81415.html

相关文章:

  • WebRtc webrtc-streamer部署
  • 鸿蒙Next之har工程依赖库接口二次导出
  • 基于卷积神经网络融合Inception模块的人脸识别
  • springboot容器无法获取@Autowired对象,报null对象空指针问题的解决方式
  • 如何在 QGIS 中打开 Esri 文件地理数据库(GDB)
  • 机器学习1-简单神经网络
  • clickhouse解决suspiciously many的异常
  • Debian12 安装配置 ODBC for GaussDB
  • 攻防世界 PHP2
  • Python8-写一些小作业
  • AI科研助手开发总结:向量与数据权限的应用(一)
  • 【ROS2】坐标TF发布(静态)
  • 攻防世界 view_source
  • 攻防世界 ics-06
  • 【linux】NFS实验
  • WebRTC服务质量(08)- 重传机制(05) RTX机制
  • 用VBA将word文档处理成支持弹出式注释的epub文档可用的html内容
  • 【RAII | 设计模式】C++智能指针,内存管理与设计模式
  • 51c自动驾驶~合集42
  • Hot100刷题计划-Day3 二分查找专题【持续更新】
  • lodash常用函数
  • 路由器做WPAD、VPN、透明代理中之间一个
  • Git使用经历
  • 06 - Django 视图view
  • Avalonia实例实战五:Carousel自动轮播图
  • 【linux】 unshare -user -r /bin/bash命令详解