目录
一、前言
会话跟踪技术
- 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中,可以包含
多次
请求与响应。 - 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间
共享数据
。 - HTTP协议是
无状态
的,每次浏览器向服务器请求时,服务器都会将该请求视为新的
请求,因此我们需要会话跟踪技术来实现会话内数据共享。
Cookie
和Session
指的是什么?
- Cookie与Session是域对象,所谓域就相当于给存储的内容设置一个边界,将存储的内容存储到这片区域内。例如我们要实现购物车添加或删除商品,就需要使用Cookie与Session技术。
二、Cookie
1. Cookie基本原理及使用
Cookie
:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问。
- Cookie的实现基于
HTTP协议
- 请求头:cookie
- 响应头:set-cookie
- Cookie的工作原理
① 客户端第一次发送请求到服务器端。
② 服务器端创建Cookie,该Cookie中包含相关信息,然后将该Cookie发送到客户端。
③ 客户端再次访问服务器端时会携带服务器端创建的Cookie。
④ 服务器端通过Cookie中携带的数据区分不同的用户。
- Cookie使用:
发送Cookie
①创建Cookie对象,设置数据
Cookie cookie = new Cookie(key, value);
②发送Cookie到客户端:使用Response对象
response.addCookie(cookie);
测试代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Cookie 对象
Cookie cookie = new Cookie("key", "value");
// 2. 发送 Cookie
response.addCookie(cookie);
}
获取Cookie
①获取客户端携带的所有Cookie:使用Request对象
Cookie[] cookies = request.getCookies();
②遍历数组,获取每一个Cookie对象
③使用Cookie对象方法获取数据
cookie.getName(); // 获取键的内容
cookie.getValue(); // 获取值的内容
测试代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取 cookie
Cookie[] cookies = request.getCookies();
// 遍历数组
for(Cookie cookie:cookies){
// 获取数据
String name = cookie.getName();
if(name.equals("所需要的cookie键值")){
String value = cookie.getValue();
// 相应处理
}
}
}
2. 关于Cookie
Cookie存活时间
默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,Cookie被销毁。
设置方法:
setMaxAge(int seconds)
设置Cookie存活时间。
- 正数:将Cookie写入浏览器所在电脑的硬盘,
持久化
存储。到时间自动删除
。- 负数:默认值,Cookie在当前浏览器内存中,当
浏览器关闭
,则Cookie销毁
- 零:
删除
对应Cookie
Cookie存储中文数据
Cookie不能直接存储中文。 若需要存储,则需要进行
转码
:URL编码,一般使用UTF-8
编码即可。不推荐使用GBK等中文编码,因为浏览器不一定支持,而且JavaScript也不支持GBK编码。
示例如下:
创建Cookie:
String value = "划水艺术家";
// URL 编码
value = URLEncoder.encode(value, "UTF-8");
Cookie cookie = new Cookie("username", value);
获取Cookie:
String name = cookie.getName();
if(name.equals("username")){
String value = URLDecoder.decode(cookie.getValue(), "UTF-8");
}
Cookie获取范围
- 同一服务器中多项目Cookie共享问题
- 默认情况下不能共享
setPath(String path)
:设置Cookie的获取范围,默认为当前虚拟目录路径。
如果想要同一服务器中多项目共享Cookie,可以将path设置为 “/”,即setPath("/")
- 不同服务器Cookie共享问题
setDomain(String path)
:如果设置一级域名相同,那么多个服务器之间Cookie可以共享,path变量必须以.
开头setDomain(".abc.com")
:那么aaa.abc.com和bbb.abc.com中Cookie可以共享
Cookie常用API
Cookie 对象操作方法
// 设置与 Cookie 对象的值。
void setValue()
// 获取与 Cookie 对象的值。
String getValue()
// 设置 Cookie 存活时间(以秒为单位)
void setMaxAge()
// 获取 Cookie 存活时间(以秒为单位)
int getMaxAge()
// 设置 Cookie 适用的路径
void setPath()
// 获取 Cookie 适用的路径
String getPath()
// 设置 Cookie 适用的域
void setDomain()
// 获取 Cookie 适用的域
String getDomain()
Response 对象操作方法
// 在响应头中增加一个相应的 Set-Cookie头字段
void addCookie();
Request 对象操作方法
// 获取客户端携带的 Cookie
Cookie[] GetCookie()
三、Session
1. Session基本原理及使用
Session
:服务端会话技术,将数据保存到服务端。- 本质上:Session技术就是一种基于后端有别于数据库的临时存储技术。
- JavaEE提供
HttpSession
接口,来实现一次会话的多次请求间数据共享功能。
- Session的常用实现有两种方式:
① 基于Cookie
客户端第一次发送请求时,服务器会创建一个Session,同时创建的特殊Cookie(key为
JSESSIONID
,value为一个唯一
的Session的id
),然后将该Cookie发送至客户端。Session保存在服务器端,为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除
。这个时间就是Session的超时时间
。如果超过了超时时间没访问过服务器,Session就自动失效了。
②URL重写
URL地址重写是对客户端
不支持
Cookie的解决方案。URL地址重写的原理是将该用户Session的id
信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。
HttpServletResponse类提供了两个URL地址重写的方法:
encodeURL(String url)
:用于对表单action和超链接的url地址进行重写encodeRedirectURL(String url)
:用于对sendRedirect
方法后的url地址进行重写
这两个方法会
自动判断
该浏览器是否支持Cookie,如果支持Cookie,重写后的URL地址就不会带有JSESSIONID
了【即使浏览器支持Cookie,第一次输出URL地址时仍然会出现JSESSIONID
(因为没有任何Cookie可带)】
URL重写测试代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取 session 对象
HttpSession session = request.getSession();
// 获取URL
String url = String.valueOf(request.getRequestURL());
// URL 重写
url = response.encodeURL(url);
// 存储 数据
session.setAttribute("username", "划水艺术家");
// 请求转发
response.sendRedirect(url);
}
可在
第一次
在URL重写后,将JSESSSIONID
返给前端,前端在以后的每次请求都携带上JSESSSIONID。
- Session的工作原理(基于Cookie)
① 客户端第一次发送请求到服务器端,服务器端创建一个Session,同时会创建一个特殊的Cookie(key为
JSESSIONID
,value为一个唯一
的Session的id
),然后将该Cookie发送至客户端。
② 客户端发送第N(N>1)次请求到服务端,客户会携带该key为JSESSIONID
的Cookie对象。
③ 服务端再次接收到来自客户端的请求时,会先去检查是否存在SessionID,不存在就新建一个SessionID并重复1,2的流程;如果存在就去遍历服务端的session文件,找到与这个SessionID相对应的文件,确定当前用户信息。此后的请求都会交换这个 SessionID,进行有状态的会话。
- Session使用:
①获取Session对象
HttpSession session = request.getSession();
②Session对象功能
// 存储数据到Session域中
void setAttribute(String key, Object o);
// 根据key,获取值
Object gettAttribute(String key);
// 根据key,删除该键值对
void removeAttribute(String key);
测试代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 存储数据到 session
// 1. 获取 session 对象
HttpSession session = request.getSession();
// 2. 存储 数据
session.setAttribute("username", "划水艺术家");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 从 session 获取数据
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
}
2. 关于Session
Session钝化、活化
① 钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘文件
② 活化:再次启动服务器后,从文件中加载数据到Session
Session销毁
①默认情况,无操作,30分钟自动销毁(自动销毁为防止内存溢出),可在web.xml
配置或使用setMaxInactiveInterval(int time)
设置。
<session-config>
<session-timeout>30</session-timeout>
</session-config>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 设置超时时间
session.setMaxInactiveInterval(30);
}
②调用Session对象的invalidate()
方法
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 销毁
session.invalidate();
}
Session常用API
以下API均由 Session 对象操作
// 设置 Session 属性
void setAttribute(String key, Object var)
// 获取 Session 属性
Object getAttribute(String key)
// 删除 Session 属性
void removeAttribute(String key)
// 销毁 Session
void invalidate()
// 获取 Session 创建时间
long getCreationTime()
// 获取 Session 的id
String getId()
// 获取 Session 最后活跃的时间
long getLastAccessedTime()
// 设置 Session 超时时间
void setMaxInactiveInterval(int var1)
// 获取 Session 超时时间
int getMaxInactiveInterval()
// 判断该 Session 是否为新建
boolean isNew()
四、Cookie与Session总结
- Cookie与Session都是为完成一次会话内多次请求间
数据共享
。
两者区别对比:
存储位置
:Cookie将数据存储在客户端;Session将数据存储在服务端存储容量
:Cookie最大4KB;Session无大小限制存储时间
:Cookie可长期存储;Session默认30分钟存储方式
:Cookie只能存储ASCII字符,存储unicode字符需要编码;Session能存储任何类型数据,包括但不限于String、Integer、List、Map等。安全性
:Cookie不安全;Session安全服务器性能
:Cookie不占服务器资源;Session占用服务器资源存活时间
:Cookie是按累积时间计算生命周期;Session周期指的是不活动的时间,若设置Session超时时间是10s,在10s内,没有访问Session,Session中属性失效,如果在9s的时候,访问了Session,则会重新计时跨域名
:Cookie可以设置domain属性来实现跨域名;Session只在当前的域名内有效,不可跨域名