会话
对于用户的第一次请求,容器会生成一个唯一的会话id,并通过响应把它返回给客户。客户再在以后的每一个请求中发回这个会话id。容器看到id后,就会找到匹配的会话,并把这个会话与请求关联。
容器必须以某种方式把会话id作为响应的一部分交给客户,而客户必须把会话id作为请求的一部分发回。
那客户和容器如何交换会话id和信息呢?
- 最简单,最常用的方式是通过 cookie 交换信息。Cookie 只是请求中发送的另一个首部(请求头信息),即 Set-Cookie。当然,这些我们了解就好,容器会做几乎所有关于 cookie 的工作。
我们也可以调用 HttpSession 在响应用发送一个 cookie :
HttpSession session = request.getSession();
HttpSession 有如下几种方法:
- isNew():判断会话是已经存在,还是刚刚创建。如果客户还没有用这个会话做个响应,返回 true。
- getSession(false):不新建会话,获取一个已有的会话,如果没有已有的会话,返回 null。这个是 getSession() 重载的方法。
URL 重写
在某些情况下,服务器发送 cookie 的会话信息,但是客户并没有接受或者拒绝接受 cookie 的话,这就意味着服务器接受不到给客户生成的会话id,便会造成 a 用户的数据跑到 b 用户的数据里面的这种情况。
那要怎么解决呢?
- URL 重写:如果客户不接受 cookie ,可以将会话id放置在访问应用的各个 URL 的最后。
当 cookie 不能工作时,容器就会使用 URL 重新的方式来获取会话id,但是使用这种方式,我们需要对响应中的所有 URL 进行编码:
response.encodeURL("/BeerTest.do");
当容器对一个 getSession 的调用没有得到会话id时,容器给客户返回的第一个响应,总是会使用 cookie 方式和 URL 重写这两种做法。
使用 SendRedirect() 重定向时,也可以使用 URL 重写,将当前的会话一起传输过去,可以使用:
response.encodeRedirectURL("/BeerTest.do");
注意:
URL 重写是自动的,但是只有对 URL 完成了编码后才有效。而且必须通过响应对象的一个方法(encodeURL() 或 eccodeRedirectURL())来运行所有的 URL,其他的事情容器会自动完成。
删除会话
HttpSession 的另一项可能用到的方法:
- getCreationTime():返回第一次创建会话的时间。
- getLastAccessedTime():返回容器最后一次得到有此会话id的请求的时间(毫秒数)。
- setMaxInactiveInterval():对于此对话,指定客户请求的最大间隔时间(秒数)。
- getMaxInactiveInterval():对应此对话,返回客户请求的最大间隔时间(秒数)。
- invalidate():结束会话,当前存储在这个会话中的所有会话属性解绑。
三种情况下,会话会被销毁:
- 会话超时。
- 会话对象调用了 invalidate() 方法。
- 应用结束。
会话超时需要设置,有两种设置方法,在web.xml中配置以及 servlet 中配置。
web.xml配置:
<web-app>
<servlet>
<servlet-name>beer</servlet-name>
<servlet-class>com.example.web.BeerSelect</servlet-class>
</servlet>
<session-config>
<!-- 配置会话超时时间 15是分钟-->
<session-timeout>15</session-timeout>
</session-config>
</web-app>
servlet 中配置:
HttpSession session = request.getSession();
// 这里设置是秒
session.setMaxInactiveInterval(20*60);
操作 cookie
新建一个 Cookie 实例:
Cookie cookie = new Cookie("cookie","这是一个cookie");
cookie 的常用方法:
- setMaxAge():传参为秒值,设置 cookie 在客户端上的存活时间,时间到达后,cookie 消失。
- response.addCookie(cookie):把 cookie 发送给客户。
- request.getCookies():返回 Cookie 的数组,需要遍历数组才可以拿到自己想要的值。