会话跟踪技术
会话可以简单的理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应。例如,用户在某个浏览器中访问某一个 Web
应用,只要不关闭该浏览器,不管该用户点击该 Web
应用的多少个超链接,访问多少资源,直到关闭浏览器之前,整个的这个访问过程我们称为一次会话
在一个会话的多个请求中共享数据,这就是会话跟踪技术。会话跟踪技术可以解决我们很多问题。比如最常见的就是一个用户在登陆一个网站之后,请求该网站的其他页面和资源时免登录的功能,又比如购物网站中常见的显示曾经浏览过的商品的功能,又比如某些购物网站允许未登录用户可以添加商品到临时购物车中的功能
常见的会话跟踪技术有 Cookie
和 Session
,Cookie
是先出现的
Cookie
概述
由于 HTTP
是一种无状态的协议,但为了实现期望的保持状态功能,于是引入了 Cookie
技术。Cookie
技术通过在请求和响应报文中写入 Cookie
信息来控制客户端的状态
简单的说:Cookie
是由服务器创建,然后通过响应发送给客户端的一个键值对,这个键值对中包含了要该会话想要记住的状态信息,客户端会保存这个 Cookie
,并会标注出 Cookie
的来源(哪个网站的 Cookie
)。当客户端再一次向该网站发出请求时会把所有这个网站的 Cookie
包含在请求报文头中发送给服务器,这样服务器就可以根据该请求携带的 Cookie
信息识别客户端,并且得到之前的状态信息了
第一次,没有 Cookie
信息状态下的请求
第二次开始,存有 Cookie
信息状态的请求
Cookie
的简单使用
在 Java
的 Servlet
规范中,可以非常简单的设置和获取 Cookie
,Cookie
被抽象成为一个 Cookie
类
- 当要设置
Cookie
的时候,需要创建Cookie
对象并且设置key
和value
,随后通过response
响应对象的addCookie()
方法添加这个Cookie
即可,Web
服务器会自动将response
中的Cookie
发送给客户端 - 客户端在随后对该
Web
应用的其他资源进行访问的时候,将会自动带上服务器发送的Cookie
(同一个服务器的其他Web
应用也不会发送)
@WebServlet("/cookie-servlet")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
// 生成一个随机字符串
String id = UUID.randomUUID().toString();
// 创建Cookie对象,指定名字和值。Cookie类只有这一个构造器
Cookie cookie = new Cookie("id", id);
// 在响应中添加Cookie对象
resp.addCookie(cookie);
resp.getWriter().print("已经给你发送了ID");
}
}
在访问 /hello-servlet
资源时,用于测试 Cookie
,该 Servlet
中通过 request
请求对象的 getCookies()
方法获取 Cookie
@WebServlet("/hello-servlet")
public class HelloServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Cookie[] cookies = request.getCookies();
// 如果请求中存在Cookie
if (cookies != null) {
// 遍历所有Cookie
for (Cookie c : cookies) {
// 获取Cookie名字,如果Cookie名字是id
if ("id".equals(c.getName())) {
response.getWriter().print("您的ID是:" + c.getValue());
}
}
}
}
}
Cookie
细节
Cookie
的覆盖
如果服务器端多次发送重复 key
的 Cookie
,那么后发送的 Cookie
会覆盖原有的 Cookie
,例如客户端的第一个请求服务器端发送的 Cookie
是:Set-Cookie: a=A
;第二请求服务器端发送的是:Set-Cookie: a=AA
,那么客户端只留下一个 Cookie
,即:a=AA
如果服务器端一次发送多个重复 key
的 cookie
,那么当客户端再次请求的时候,只携带最后一个设置的 Cookie
的值
Cookie
有效期
所谓 Cookie
的有效期就是 Cookie
在客户端的最大有效时间,我们可以通过 setMaxAge(int)
方法来设置 Cookie
的有效时间,单位秒
cookie.setMaxAge(-1)
:cookie
的maxAge
属性的默认值是-1
,表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么cookie
就会消失。生命值为负数的Cookie
也被称为内存Cookie
cookie.setMaxAge(60*60)
:表示cookie
对象可存活1
小时。当生命值大于0
时,浏览器会把Cookie
保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie
也会存活1
小时,除非将Cookie
从硬盘上手动清理了。生命值为正数的Cookie
也被称为硬盘Cookie
cookie.setMaxAge(0)
:cookie
生命值等于0
是一个特殊的值,它表示cookie
被作废。也就是说,如果原来浏览器已经保存了这个Cookie
,那么可以通过Cookie
的setMaxAge(0)
来要求浏览器删除这个Cookie
。无论是在浏览器内存中,还是在客户端硬盘上都会删除这个Cookie
Cookie
修改和删除
Cookie
并没有提供直接的修改和删除功能,但是根据前面 Cookie
的覆盖和有效期属性,可以间接的修改和删除 Cookie
当想要修改 Cookie
时,可以发送同名 key
的 Cookie
,这样以前的旧 Cookie
就被覆盖了。当想要删除 Cookie
时,同样设置同名 key
的 Cookie
的 maxAge = 0
即可
Cookie
与跨域问题
默认情况下,不同的域名中设置的 Cookie
不可以共享,即跨域问题
cookie
有一个 setDomain()
方法,可以设置 Cookie
的 domain
属性(域名),表示 Cookie
在域名级别中的作用范围。如果不设置,那么默认范围就是当前域名