本篇将会讲解Cookie 与 Session
阅读本篇需要的前置知识有:Java基础、HTML、http协议、Servlet等
如果你缺乏这些前置知识阅读本篇可能会遭遇困难,建议你先阅读我整理的以下笔记后再来阅读本篇^_^:
JavaWeb笔记整理——HTML、CSS、JavaScript_html css java-优快云博客
JavaWeb开发笔记图解整理(二)——XML、Tomcat、Servlet-优快云博客
一、会话
浏览器打开到浏览器关闭
什么是会话
我们打开浏览器进行一系列的操作,一直到浏览器关闭这一整个过程,用户和浏览器服务器之间的交互,就是一次会话。
在一次会话过程中会产生很多数据,如服务器发送给浏览器的Cookie,和服务器保存在本地的Session
二、Cookie
在登录一些网站的时候,我们常常会看到这些网站要求我们接收Cookie,那什么是Cookie呢?
1、什么是Cookie?
Cookie是一种由服务器发送并存储在用户浏览器中的小型文本文件,用于保存用户的会话信息和其他少量数据。它们可以帮助网站记住用户的偏好、登录状态以及其他个性化设置,从而提供更好的用户体验。
Cookie的应用场景
设想这样一个场景:我们登录了一个视频网站,当我们切换视频时,浏览器会自动帮我们存储观看过的视频到历史记录中。
通常,我们可以通过Servlet将这些数据存储到数据库中。然而,对于一些小型应用来说,每次访问历史记录都需要连接数据库,这会影响应用的性能。为了解决这个问题,我们可以使用Cookie。
使用Cookie存储历史记录
我们可以将访问的历史记录制作成一个Cookie,存储在浏览器中。这样,每次访问时,浏览器只需读取本地的Cookie即可显示观看过的视频,而不需要每次都访问数据库。这不仅减少了服务器的负担,也提高了应用的响应速度。
跨浏览器的数据同步
如果我们希望在不同的浏览器中也能看到观看过的视频,可以在用户首次登录时从数据库读取历史记录,然后将这些数据制作成Cookie存储在浏览器中。以后用户在同一浏览器中访问时,就不需要再访问服务器了,从而提高了运行速度。
Cookie是浏览器存储的一段小数据(Cookie 直译为 曲奇 可见其数据量并不大)。
它有着自己的生命周期,浏览器会根据Cookie设定的生命周期自动的将其销毁。
浏览器持有Cookie时,在访问服务器的资源时,Cookie会封装在Request对象中,然后服务器会根据Request对象中的Cookie对返回给浏览器的资源进行相应的变化和改动。这也就达到了每个用户所看到的内容不一样的实现。
2、Cookie 的基本使用
Cookie的结构
Cookie的数据结构比较像一个HashMap,它也是由一对键值对构成的,分别是name - value 两个数据都是String类型的。
创建一个Cookie对象
在Servlet中,我们可以创建一个Cookie对象:
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建一个Cookie对象
Cookie cookie = new Cookie("username", "aaa");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
添加Cookie对象
创建一个Cookie对象后,不意味着Cookie对象就会被发送会浏览器并保存,我们还需要进行添加操作。
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建一个Cookie对象
Cookie cookie = new Cookie("username", "aaa");
// 添加一个Cookie对象 把cookie对象添加到 response响应中
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
添加了Cookie后,Cookie就会被服务器返回给浏览器,然后浏览器就会将Cookie对象保存起来,从而下一次返回给服务器。
读取Cookie
当浏览器给服务器一个request请求后,如果有Cookie对象,服务器自然会读取Cookie,并进行相应的处理。
我们在Servlet中自然可以进行读取Cookie的操作:
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建一个Cookie对象
Cookie cookie = new Cookie("username", "aaa");
// 添加一个Cookie对象 把cookie对象添加到 response响应中
response.addCookie(cookie);
// 读取Cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie1 : cookies) {
System.out.println(cookie1.getName() + "-"
+ cookie1.getValue());//username-aaa
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
先获取一个Cookie数组,然后就可以读取每个Cookie的name和value。
Cookie的生命周期
Cookie有的时候我们不希望浏览器一直保存,所以Cookie 会有一个生命周期。
Cookie的默认生命周期是会话级别的,也就是当一个浏览器关闭时,Cookie就会被自动销毁。
如果我们不想Cookie在浏览器关闭时就被销毁,可以自行设置生命周期。
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建一个Cookie对象
Cookie cookie = new Cookie("username", "aaa");
// 设置Cookie生命周期
// 这里填写一个int值,以秒为单位
cookie.setMaxAge(3600); //一小时
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
手动删除一个Cookie
手动删除一个Cookie其实就是把一个Cookie的生命周期设置为0,并添加进去。
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建一个Cookie对象
Cookie cookie = new Cookie("username", "aaa");
//设置生命周期为0
cookie.setMaxAge(0);
// 添加后,cookie对象将从浏览器中直接被删
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
Cookie的有效路径
我们可以设置Cookie的有效路径,从而让不同的资源可以获取到不同的Cookie,而不是一股脑的获取全部的Cookie。
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建一个Cookie对象
Cookie cookie1 = new Cookie("username1", "aaa");
Cookie cookie2 = new Cookie("username2", "bbb");
//当访问 /cookie/aaa资源 时才会发送这个cookie1对象
cookie1.setPath("/cookie/aaa");
//当访问 /cookie 路径下的资源时 会发送这个cookie2对象
cookie1.setPath("/cookie");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3、Cookie的注意细节
一个Cookie只能表示一个信息,即一个 name - value对。
一个web站点可以给一个浏览器发送多个Cookie,而一个浏览器也可以存放多个web站点的多个Cookie。
删除Cookie时,必须要保持路径一致,不然不会删除。
在删除cookie时,如果这个cookie已经设置了路径,那么删除时要确保cookie添加生命周期为0时,添加的路径保持和之前一致。
三、Session
1、什么是Session?
有时候我们登录一些网站时,会自动的登录。这是因为我们之前登录过这个网站,所以网站记住了我们曾经登录过这个信息。
这样我们就可以无需重新登录就使用网站上的内容。
这样的功能我们显然使用Cookie就可以实现,但是由于Cookie是保存在浏览器中的,我们甚至可以直接看到Cookie的信息。所以如果我们使用Cookie来实现上面的功能就有很大的安全性问题。
所以我们引出了Session,把浏览器发送的数据保存在服务端,只要用户登录过,在接下来一段时间内,服务器检测到有登录的Session对象,用户就无需登录,实现自动登录的功能。
而Session是每个用户的浏览器独享的,服务器不会将一个用户A的Session数据发送给用户B。
2、Session的基本使用
Session的结构
Session也是一个类似HashMap的结构,前面一个String 对应一个 Object对象 存储在服务器中。
Session使用方法
public class SessionServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// session 对象的获取
HttpSession session = request.getSession();
// Session 属性的获取
Object username = session.getAttribute("username");
// Session 属性修改
session.setAttribute("username", "abc");
// Session 删除
session.removeAttribute("username");
// 判断是不是新创建出来的 Session对象
boolean aNew = session.isNew();
System.out.println(aNew);
// 获取Session所对应的id
// 这个id对应着浏览器存储着的一个Cookie
String id = session.getId();
System.out.println(id);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3、Session的底层实现机制(重、难点)
这里是一个Session底层的简单示意图。
我们要着重的关注getSession()这个方法。 这个方法使我们之后学习的重点。
浏览器A访问Session数据时,首先会看服务器中是否有一个自己对应的Session对象,如果没有就会在Tomcat服务器中通过getSession()创建一个Session对象(是的,getSession方法会创建Session对象),放入相应的数据,如果有就直接进行相应的操作。
而这个getSession()方法中发生了很多事情,我们下面画个图继续讲解:
第一次访问
首先,我们第一次打开一个浏览器,此时浏览器中是没有任何Cookie的,我们给浏览器发送一个请求,服务器帮浏览器创建一个Session,这时候就会调用getSession方法。
然后getSession方法会判断浏览器的请求中是否带有Cookie = JSessionId ,如果没有,getSession方法就会咋服务器的内存中创建一个Session对象并给这个Session对象创建一个SessionId,并赋给这个Session对象:
然后服务器在返回http响应时,会根据Session对象是否被创建而返回Cookie,如果创建了一个Session对象,那么就会给浏览器返回一个Cookie: name = JSessionId - value = 1736481 (我随便取的) 。
然后浏览器中的Cookie 就不再是空了,而是存储了一个JSessionId。
第二次访问
第二次浏览器访问服务器,调用服务器的getSession()方法,依然会判断是否有JSessionId存在,这里第二次访问时显然是存在的。
发现存在JSessionId后,会进行下一次判断,看看服务器内存中是否有与这个Id相对应的Session对象。因为Session可能已经被销毁,服务器此时可能会没有对应的Session对象,所以这里需要进行这个判断。
这里的服务器内存中存在这个对象,所以服务器会直接进行相关的操作,而不会再创建一个新的Session。
第三次访问,第一次的Session对象已被服务器销毁
第三次 访问时,由于Session生命周期已经到了,Session被服务器销毁,进行判断浏览器是否有SessionId时,浏览器确实有,但是这个SessionId却没有与之对应的Session对象,所以此时依然会创建一个Session并分配一个新的SessionId。
此时由于新创建了一个Session对象,所以此时服务器会给浏览器发送一个新的Cookie,从而让浏览器保存新的JSessionId。
这里需要补充一点:
服务器设置Cookie时,新的Cookie如果是同名name的,那么就会覆盖掉原来的Cookie。
而Session也是一样,会覆盖掉同名的值。
所以这里浏览器的JSessionId就会被覆盖为新的Id
4、Session的生命周期
Session的生命周期和Cookie有较大不同。
设置生命周期
我们可以在Servlet中设置生命周期:
public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位), 超过指定的时长,Session 就会被销毁。如果设置为负值则永远不会被销毁。
这里的超时时间,指的是Session的访问最大时间间隔,如果超过这个时间间隔还没有访问,那么这个Session对象就会被销毁。
举个例子,我这里设置Session的生命周期为30min,我第一次访问这个Session的时间是5:00,
然后第二次访问的时间是5:29 ,那么这个Session就还没有超时,因为两次访问的时间间隔是29min,没有超过我们设置的最大时间间隔,所以Session不会被销毁。
但如果我们第一次访问的时间是5:00 ,而第二次访问的时间是5:31,那么就超过了两次访问的最大时间间隔,这里就不会访问到这个Session因为已经被销毁了。
需要注意的是,第一次访问这个Session的时间是5:00,然后第二次访问的时间是5:29,那么5:31时,Session不会被销毁,而是在5:59时被销毁,因为最新一次访问的时间的5:29,所以最大的访问时间间隔会在5:59时达到,所以在5:31时Session并不会被销毁。
public void invalidate() 让当前 Session 会话立即无效
如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长,Tomcat 会以 Session 默认时长为准,Session 默认的超时为 30 分钟, 可以在 tomcat 的 web.xml 设置默认超时时间
下一篇我来继续讲解JSP,求点赞收藏关注~^_^