目录
1 会话
web会话:用户开一个浏览器,访问某一个web网站,在这个网站点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
注意:如果一个浏览器里面有多个选显卡,关闭其中一个,还剩下其他选项卡,则该会话不关闭,直到把整个浏览器关掉,会话才会结束。重新打开浏览器就是第二个会话。
2 Cookie
2.1 什么是Cookie
Cookie可以把服务器传递过来的一些数据记录在客户端浏览器中,解决会话从什么时候开始,到什么时候结束。
生成Cookie对象在服务器中完成,而往Cookie对象中存数据是在客户端浏览器中完成的。
在浏览器中Cookie是以文本的形式保存数据。
2.2 Cookie的作用
(1)判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须从新填写登录的相关信息。
(2)保存上次登录的时间等信息。
(3)保存上次查看的页面
(4)浏览计数。
2.3 服务器生成Cookie对象发送给客户端
服务器向客户端发送Cookie
Cookie对象是用来存储键值对数据的,Cookie对象的产生在服务器端,但是往Cookie对象中存数据是在客户端浏览器
Cookie类的构造方法:
Cookie(String name, String value) Cookie对象实际上就是一个存储键值对的容器,这个name可以理解为key
至于把来自于服务器端的Cookie传给客户端的方法,这就用到了服务器端的响应对象response
response对象中有个方法addCookie(),把来自于服务器端的Cookie返回给客户端(通过响应头)
/**
* 服务器向客户端发送Cookie
* Cookie对象是用来存储键值对数据的,Cookie对象的产生在服务器端,但是往Cookie对象中存数据是在客户端浏览器
* Cookie类的构造方法:
* Cookie(String name, String value) Cookie对象实际上就是一个存储键值对的容器,这个name可以理解为key
* 至于把来自于服务器端的Cookie传给客户端的方法,这就用到了服务器端的响应对象response
* response对象中有个方法addCookie(),把来自于服务器端的Cookie返回给客户端(通过响应头)
*/
@WebServlet(urlPatterns = "/sendCookie")
public class SendCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建Cookie对象
Cookie cookie = new Cookie("cookie_name", "cookie_value");
//response对象将cookie返回给客户端
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.4 服务器获取浏览器在请求时所携带的Cookie
浏览器在访问服务器的时候, 会携带保存的Cookie数据, 服务器端可使用request对象获取Cookie数据; Cookie数据放在请求头。
/**
* 在客户端浏览器获取来自服务器的Cookie对象
* 客户端在访问服务器时,会生成Cookie数据,客户端浏览器会将Cookie数据放到http协议的请求头中
* 通过request对象获取请求头数据(只拿cookie)方法:getCookies()
*/
@WebServlet(urlPatterns = "/getCookie")
public class GetCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过request对象获取客户端的Cookie数据
Cookie[] cookies = request.getCookies();
//这里本应该判断一下cookies是不是null,否则如果浏览器中没有Cookie时会报空指针异常
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println("key:" + cookie.getName() + " value:" + cookie.getValue());
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
到这里我发现:一旦关闭整个浏览器(结束会话),之前生成的Cookie就消失了!所以说,Cookie的生命周期究竟是多久呢(详情见Cookie的生命周期)?
2.5 Cookie的携带路径
浏览器访问服务器,是否携带Cookie?答:默认情况下,Cookie在哪产生的,在哪里访问才携带!
接下来解释上面这句话:
如果我在/web03/pathCookie 路径下创建一个Cookie对象传给浏览器,浏览器如果要想在请求时带上这个Cookie,则浏览器的请求地址必须是/web03/*
如果我在/web03/aaa/pathCookie 路径下创建一个Cookie对象传给浏览器,浏览器如果要想在请求时带上这个Cookie,则浏览器的请求地址必须是/web03/aaa/*
如果我在/web03/aaa/pathCookie中创建一个Cookie,然后下一次访问的时候url是web03/bbb/* 那就肯定不会携带Cookie
但是在开发中,我们需要“只要访问的是web03这个web项目就要携带Cookie”而不是“在哪产生,在哪里访问才能携带”
完成上述要求的做法为:通过Cookie对象的setPath方法设置Cookie的携带路径
@WebServlet(urlPatterns = "/aaa/pathCookie")
public class PathCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("path", "cookiePath");
//一旦设置了cookie的携带路径,那么即使在web03/aaa/bbb/ccc/* 产生的Cookie,在web03/下的任意路径下访问时都会携带有该Cookie
cookie.setPath(request.getContextPath()); //写的是web应用程序的名称,这个名称不要写死,而是通过request对象的getContextPath方法获取
//保存Cookie到服务器
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.6 Cookie的生命周期
Cookie是会话对象,它是有生命周期的,它的生命周期和会话有关,一旦关闭浏览器,Cookie对象也就消失了。
通过Cookie对象的setMaxAge方法可以设置Cookie的生命周期,可能由于浏览器的不同,导致即使设置了很长时间的cookie生存周期,但是一旦关闭浏览器Cookie就没了,这是浏览器本身的问题!
@WebServlet(urlPatterns = "/lifeCookie")
public class LifeCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("cookie_name3", "cookie_value3");
cookie.setMaxAge(60); //60秒
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.7 清除Cookie对象
清除某个Cookie对象有两个方法:
(1)浏览器 ctrl + shift + delete 直接删除Cookie
(2)“覆盖”,要保证新Cookie和要被覆盖的Cookie的(键名,携带路径)是一样的,然后让新Cookie的携带时间为0 就能清除当前Cookie(但是这个方法似乎不好使,我测试不出来,也可能是浏览器本身的问题)
/**
* 清除Cookie的方法:
* (1)浏览器 ctrl + shift + delete 直接删除Cookie
* (2)清除Cookie通过“覆盖”,要保证新Cookie和要被覆盖的Cookie的(键名,携带路径)是一样的,然后让新Cookie的携带时间为0 就能清除当前Cookie
*/
@WebServlet(urlPatterns = "/clearCookie")
public class ClearCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//新Cookie的名字和旧Cookie一样
Cookie cookie = new Cookie("cookie_name3", "value");
//让新Cookie的携带路径和旧Cookie一样
cookie.setPath(request.getContextPath());
//设置新Cookie的时间为0秒
cookie.setMaxAge(0);
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.8 Cookie记录上一次的访问时间
记录客户端上一次访问的时间,并且在浏览器上响应上一次访问的时间。
这个时间存在Cookie里面,由服务器创建传给浏览器,浏览器每次访问服务器时,都会携带该时间Cookie
服务器获取到该Cookie,把这个时间打印到浏览器页面上。
实现思想:
1、获取客户端携带的Cookie
2、判断
A: 客户端的请求中没有携带Cookie
欢迎语打在浏览器
创建Cookie,值是当前时间
响应回客户端
B: 客户端的请求中携带了Cookie
获取Cookie中的键值对,值就是客户端上次访问的时间
响应客户端(上一次访问的时间)
创建Cookie,值是当前时间
响应回客户端
@WebServlet(urlPatterns = "/lastTime")
public class LastTimeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应,处理中文乱码
response.setContentType("text/html;charset=utf-8");
//1、获取客户端携带的Cookie数据
Cookie[] cookies = request.getCookies();
//2、判断Cookies数组是不是空,如果是空,则认为是客户端第一次访问服务器
if (cookies == null) {
//客户端第一次访问
response.getWriter().write("欢迎首次访问");
//Cookie记录现在的时间
createCookie(request, response);
} else {
System.out.println(cookies.length);
//客户端不是第一次访问,则取出Cookie中的键值对,在浏览器上显示“上一次的访问时间”
for (Cookie cookie : cookies) { //cookies里面一直只有一个cookie,这个循环实际上没啥用
String name = cookie.getName();
String value = cookie.getValue(); //值是上一次的访问时间
response.getWriter().write("上一次访问的时间是:" + value);
//新创建一个Cookie,记录现在的时间
createCookie(request, response);
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//创建Cookie:该Cookie的值是一个日期,生存时间10分钟、所有访问web03项目的请求都会携带该Cookie
public void createCookie(HttpServletRequest request, HttpServletResponse response){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); //Cookie不允许有空格和冒号,所以采用此种形式
String format = simpleDateFormat.format(new Date());
Cookie new_Cookie = new Cookie("time", format);
new_Cookie.setMaxAge(60 * 10); //设置Cookie的生存时间(前提是不关闭浏览器)
new_Cookie.setPath(request.getContextPath()); //设置Cookie的携带路径,让请求只要是访问web03项目的,则都会携带该Cookie
response.addCookie(new_Cookie); //把Cookie回传给浏览器
}
}
3 Session
3.1 Session对象的ID
session域对象的id值
session对象获取id的方法:getId
唯一性(在一个Tomcat服务器之中,开启了web项目还不能关闭,如果重启了web项目,session对象的id值就变了,详情见Session对象的生命周期)
其实,服务器创建、获取Session对象是这样的过程:
(1)浏览器访问服务器,会携带Cookie,如果没有用于存放Session_ID的Cookie,那么服务器就自己创建一个新的Session对象,该对象作用于该会话。
(2)但是这不意味着服务器中本来就没有Session对象,可能服务器中本来就有Session对象,但是由于没有用于保存Session_ID的Cookie(比如不小心删除了Cookie),所以服务器才只能创建新的Session对象。
(3)如果浏览器访问服务器时,携带的Cookie正好存了Session_ID,那就直接用服务器中现成的这个Session对象,而不去创建新对象了。
每次关闭浏览器后再打开,之前存在session对象中的数据就没了,这是为什么?
答:session对象以及存的数据是在服务器中的,并没消失,只不过关闭浏览器后,该session对象所对应的cookie(携带有session Id)没了
没了cookie就没了session ID,没了session ID自然就找不到之前存在session对象中的数据了(即:数据没丢,只是没了id所以找不到了)。
而此时,由于新的浏览器访问,已经创建了新的session对象(服务器中旧的session对象可能仍然还在,这就要看session对象的生命周期了)
如果我想即便关掉浏览器后再打开,之前存在session对象中的数据不消失,怎么办?
答:延长用于存放session id 的Cookie的生存时间,不要让它一关闭浏览器就消失(这是默认情况,cookie的生命周期即为一次会话)
@WebServlet(urlPatterns = "/session3")
public class Session3Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getSession().getId();
System.out.println(id); //只要浏览器不关闭,session对象的id值就不会变(沿用之前的session对象而不会创建新的session对象,所以id不变)
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.2 Session对象的持久化
Session域对象的持久化,实际上是在持久化Cookie
客户端保存的Cookie(它的值是Session对象的id),如果要想持久化,就要保证即便关掉浏览器再打开,这个Cookie还是存在的。
@WebServlet(urlPatterns = "/session3")
public class Session3Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//拿到session对象的id
String id = request.getSession().getId();
System.out.println(id); //只要浏览器不关闭,session对象的id值就不会变(沿用之前的session对象而不会创建新的session对象,所以id不变)
//往这个session对象中存储一些数据,看看一会儿重启浏览器后能不能再次访问到这个数据
request.getSession().setAttribute("key","value");
//创建cookie对象,存储当前session的id,设置Cookie的生存时间,把这个Cookie返回给浏览器
Cookie cookie = new Cookie("JSESSIONID", id); //注意:此时的键必须是“JSESSIONID”
//设置Cookie的生存时间
cookie.setMaxAge(60 * 10);
//设置Cookie携带路径
cookie.setPath(request.getContextPath());
//把cookie返回给客户端浏览器
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
//测试session对象是否被持久化:即使关闭浏览器,之前存到session对象中的数据仍然能被访问到
@WebServlet(urlPatterns = "/session4")
public class Session4Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//取出session3 中session域对象中的值
Object value = request.getSession().getAttribute("key");
System.out.println(value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.3 Session对象的销毁
前面说了那么多,似乎忽略了一个问题:Session对象本身的生命周期,如果Session对象到时间被销毁了,即使Cookie里面存了它的ID也是无济于事的(类似于野指针吧···)
Session域对象的销毁:
方法1:Tomcat服务器默认30分钟后销毁Session对象(tomcat包中的conf文件下的web.xml配置文件中配置了这个时间)
但是不建议直接改tomcat配置文件,而是自己在项目的web.xml中进行配置
Session对象的生命周期,从它被创建出来开始,如果一直不去使用它(一旦使用则重新刷新时间),则默认30min后服务器会销毁该对象。
关于Session对象存活时间的设置,可以在项目中的web.xml文件中配置,如下图,而不是去修改Tomcat本身的配置文件。
方法2:调用session对象的invalidate()方法,如下下图。
@WebServlet(urlPatterns = "/session5")
public class Session5Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.invalidate();
//测试一下这个session对象有没有被销毁(直接状态码500:空指针异常)
Object value = session.getAttribute("key");
System.out.println(value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.4 Session对象的生命周期
Session对象的生命周期:
session创建时机
(1)这个浏览器在servlet中第一次使用session时候,通过getSession一旦被调用,会先去客户端请求中寻找键为“JSESSIONID”的Cookie,
如果没找到,就创建一个Session对象,如果找到了就去内存中查看是否真的有该对象,如果没有就还要重新创建。如果有则返回这个现成的对象。
(2)这个浏览器第一次访问jsp的时候,服务器也会为这个浏览器创建一个session对象;
session销毁时机
(1)程序员调用invalidate方法(立刻销毁)
(2)设置的存活时间到了(默认是30分钟)
(3)服务器非正常关闭(突然断电,然而正常关闭服务器后session对象是不会被销毁的,而是通过文件被的形式被序列化到电脑硬盘中,一旦重新打开服务器,该文件会被反序列化到内存中(文件随之消失),于是之前创建的session对象又出现了)。
注意:
正常关闭服务器,session不会销毁,而是直接序列化到硬盘上,下一次服务器启动的时候,会重新创建出来。
如果浏览器单方面关闭会话,服务器上对应的session不会死亡 ,但是会导致服务器给浏览器创建的JSESSIONID的cookie死亡,当cookie死亡后,会导致浏览器无法找到上一个session对象,会造成服务器中session死亡的假象。