会话
什么是会话
会话可以简单理解为:用户打开一个浏览器,点击多个超链接访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
会话过程中要解决的一些问题
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自回产生一些数据,成需要想办法为每个用户保存这些数据。
保存会话的两种技术:
Cookie
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
Session
Session是服务器端的技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一的其独享的HttpSession对象。由于Session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的Session中。当用户再去访问服务器中其他的web资源时,其他的web资源再从用户各自的Session中取出数据为用户服务。
Cookie API
javax.servlet.http.Cookie
- javax.servlet.http.Cookie类用于创建一个Cookie。
- response接口中定义了一个addCookie的方法,它用户在其响应头中增加一个相应的Set-Cookie头字段。
- request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。
Cookie应用场景
记录上次访问时间
1 | "/Servlet01") ( |
Cookie的maxAge方法
maxAge():cookie的缓存时间。默认是-1,默认存在浏览器的缓存中。单位是秒。
- 负数:表示cookie的数据存在浏览器缓存中。
- 0:表示删除cookie。
- 正数:缓存在持久化硬盘上的时间。
Cookie细节
- 一个cookie只能标识一种信息,它至少含有一个标识该信息的名称(name)和设置值(value)。
- 一个web站点可以给一个web浏览器发送多个cookie,一个web浏览器也可以存储多个web站点提供的cookie。
- 浏览器一般只允许存放300个cookie,每个站点最多存放20个cookie,每个cookie的大小限制为4KB。
- 如果创建了一个cookie,并把它发送到浏览器,默认情况下他是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则须使用maxAge,并给出一个以秒为单位的时间。将最大时效设置为0则是命令浏览器删除该cookie。
案例:记住用户名
login.jsp
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
RemLogin.java
1 | package com.Retur0.web.servlet; |
历史记录
查看书的浏览记录
客户端:Cookie:historyBookIds=1-3-5
原理
在访问过条目1之后将条目1的id存到cookie中反回给客户端,客户端访问条目2的时候将这个cookie发给服务器,并把条目2的id也存进cookie中。如果客户端要显示历史记录,则通过cookie中记载的id信息调出相应的条目信息并显示在浏览器上。在cookie中id通过键值对以字符串的形式进行保存。
Session API
- 服务器可以为浏览器创建一个session对象,一个浏览器独占一个session。在需要保存用户数据时,可以把用户数据写道浏览器独占的session中。当用户浏览器访问其他程序时,替他程序可以从用户的session中取出用户的数据,为用户服务。
- session和cookie的区别在于:
- cookie是把用户的数据写给用户浏览器。
- session是把用户的数据写道用户独占的session中。
- session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
举个例子
SessionDemo1:
1 | "/SessionDemo1") ( |
SessionDemo2:
1 | "/SessionDemo2") ( |
结果:在访问SessionDemo1时会跳转到SessionDemo2并显示Retur0
。
如果访问SessionDemo1和SessionDemo2的浏览器不同,则无法显示出Retur0
。
关闭浏览器再打开,session是不同的。
服务器如何实现一个session服务一个用户浏览器
服务器会为每个浏览器分配一个session ID,然后把Session ID通过Cookie的形式存储在客户端。
第一次访问session1时,服务器创建一个session对象,jsessionid在响应头cookie中发送给浏览器并保存。此时如果再次访问session1,jsessionid不会再发给浏览器。
访问seesion2会将jsessionid在请求头中发送给服务器,服务器用这个id找到对应的session读取数据。
Session的应用场景
购物车
用户买书-书放在购物车
获取书的id
String bookid = req.getParameter("id");
通过书的id找到这本书
Book book = DBUtils.findBookById(Integer.parseInt(bookId));
把这本书放在购物车
List<Book> cart
1
2
3
4
5
6List<Book> cart = (List<Book>)req.getSession().getAttribute("cart");
//如果第一次没有创建过购物车,不加判断会重复创建新cart,cart中没有以前添加的东西。
if(cart == null){
cart = new ArrayList<Book>();
}
cart.add(book);把这个cart放入session中
req.getSession().setAttribute("cart", cart);
这种方法的问题:
- 重启浏览器数据会丢失。(解决:把书的id放在cookie中)
- 重启服务器数据会丢失。(解决:1. 把书的id放在cookie中。2. 把session数据保存起来)
验证码
在登陆过程中,生成验证码和验证登录在不同的servlet中,验证码数据在ValidateServet中,LoginServlet中只能获得用户输入的验证码,为了检验这两个码是否相同,需要使用session来共享数据。
将ValidateServlet中的码存入到session中,LoginServlet从session中取出码并和用户输入的码进行比较。
忽略大小写的字符串比较可以使用equalsIgnoreCase()方法。
使用equals方法是一般将字符串放在前面,变量作为参数,这样可以避免空指针异常。
验证结束后需要将验证码服务器中删除。
req.getSession().removeAttribute("code");
或者使用invalidate方法,这个方法让session失效,会使session中的所有数据都删除。
HttpSession的常用方法
- 把数据保存在HttpSession中,该对象也是一个域对象。
- void setAttribute(String name, Object value); 存数据。
- Object getAttribute(String name); 取数据。
- void removeAttribute(String name); 通过key删除数据。
- HttpSession.getId() 取session的id。
- setMaxInactiveInterval(int interval); 设置session的存活时间。
- invalidate; 使此会话无效。
getSession内部执行原理
获取名称为JSESSIONID的Cookie的值。
如果没有这样的cookie,创建一个新的HttpSession对象,分配一个唯一的SessionID,并且向客户端写了一个名字为JSESSIONID = sessionid的cookie。
有这样的cookie,获取cookie中JSESSIONID的值,在服务器内存中根据ID找到那个HttpSession对象。
找到了就取出来使用,找不到从2开始。
使用getSession时可以传进一个布尔值参数,这个参数是true就正常使用。
这个参数是false则根据id查找session对象,找到就返回,找不到返回null,不会创建新的。
Session的状态
创建:当浏览器第一次访问浏览器的动态资源就被创建。
活着:服务器运行时。
死亡:
session.invalidate():强制销毁。
超时:默认30分钟。
setMaxInactiveInterval(int):设置存活时间,秒。
在web.xml中配置session有效时间。
1
2
3
4<session-config>
<!--30分钟有效时间-->
<session-timeout>30</session-timeout>
</session-config>
Session的持久化
确保服务器或单个web应用重启后,能恢复重启前的会话。
把session中存的对象实现Serializable接口。若不实现序列化接口,则在重启服务器的时候会出现session无法序列化的警告。
会话持久化在硬盘中保存的路径是:/work/Catalina/localhost/项目名/SESSION.ser。
持久化状态转化
Session在其生命周期中,可能会在运行时状态和持久化状态之间转换。
搁置:
会话从运行时状态转化为持久化状态的过程称为搁置。
以下情况发生时,Session会被搁置:
- 当服务器重启或单个web应用终止时,web应用中的session会被搁置。
- 会话处于不活动的时间太长,达到了特定值。
- web应用中处于运行状态的会话数目太多部分Session被搁置。
激活:
会话从持久化状态变为运行时状态的过程称为激活。
以下情况发生时,Session会被激活:
- 当服务器重启或单个web应用重启时,web应用中的Session会被激活。
- 处于Session中的客户端向web应用发出http请求,相应的Session会被激活。