会话技术
会话:
- 一次会话中包含多次请求和响应。
一次会话过程:
- 浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
功能:
- 在一次会话的范围内的多次请求间,共享数据
方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
Cookie
概念:
- 客户端会话技术,将数据存储到客户端
常用方法:
使用步骤:
- 服务器端创建Cookie对象,指定数据
new Cookie(String name,String value)
- 发送Cookie对象给客户端,客户端获取Cookie对象
response.addCookie(Cookie cookie)
- 服务器端获取客户端发送的Cookie,来拿到数据
Cookie[ ] request.getCookies()
这里展示的是部分代码
// "/cookieDemo1"
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 服务器设置Cookie
Cookie cookie = new Cookie("name","value");
// 发送Cookie
response.addCookie(cookie);
}
----------------------------------------------------------
// "/cookieDemo2"
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取Cookie
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name + "---" + value);
}
}
}
原理
- 基于第一次交互服务器做出的响应的响应头
set-cookie
和第二次交互客户端请求体cookie
来实现
原理图
Cookie的细节
-
一次发送多个cookie:创建多个Cookie对象,调用response的addCookie方法多次发送cookie。
-
cookie在浏览器中可以保存的时间:
- 默认情况下,当浏览器关闭后,cookie数据被清除
- 持久化存储:
setMaxAge(int seconds)
- 正数:将Cookie数据写到硬盘的文件中。持久化存储。代表cookie存活时间。
- 负数:默认值,当浏览器关闭后,cookie数据被清除
- 零:删除cookie信息
-
cookie存中文数据:
-
在tomcat 8 版本之前cookie中不能直接存储中文数据。
-
需要将中文数据转码—一般采用URL编码(%E3)
-
Servlet Cookie 处理需要对中文进行编码与解码,方法如下:
String str = java.net.URLEncoder.encode("中文","UTF-8"); //编码 String str = java.net.URLDecoder.decode("编码后的字符串","UTF-8"); // 解码
-
-
在tomcat 8 之后支持中文数据
-
-
cookie获取范围是多大/共享问题?
- 假设在同一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 默认情况下,cookie不能共享
setPath(String path)
:设置cookie的获取范围。默认情况下,设置当前的虚拟目录,String path代表范围,一个url- 如果想要整个服务器上所有项目共享,则可以将path设置为"
/
"
- 假设在同一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
-
不同的tomcat服务器间cookie共享问题?
- 调用
setDomain(String path)
:如果设置一级域名相同,那么多个服务器之间cookie可以共享 - l例如:
setDomain(".baidu.com")
,那么tieba.baidu.com和news.baidu.com里面的cookie可以共享
- 调用
cookie的特点和作用
- 特点:
- cookie存储数据在客户端浏览器,不是那么安全和保险
- 浏览器对应单个cookie 的大小有限制(4kb,不同浏览器不一样) 以及 对同一个域名下的总cookie数量也有限制 (20个,一般情况)
- 作用:
- cookie一般用于存储少量的不太敏感的数据,因为它不怎么安全
- 在不登录的情况下,完成服务器对客户端的身份识别,比如一些网站,在没有登录的情况下,对网站进行设置,保存设置后,会以cookie的形式存在浏览器内,再次打开会依旧保持这个设置
实例:记住上次的访问时间
需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
分析:
- 可以采用Cookie来完成
- 在服务器中的Servlet判断是否有一个名为lastTime的cookie
- 有:不是第一次访问
- 响应数据,欢迎回来,您上次访问时间为:某年某月某日
h:m:s
- 写回Cookie:
lastTime=某年某月某日h:m:s
- 响应数据,欢迎回来,您上次访问时间为:某年某月某日
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问。
- 写回Cookie:
lastTime=某年某月某日h:m:s
- 有:不是第一次访问
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Cookie[] cookies = request.getCookies(); // 获取请求的cookie
boolean flag = false; // 默认cookie中没有lastTime
if (cookies.length > 0) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
if ("lastTime".equals(name)) { // 请求的cookie中有lastTime
flag = true;
String time = cookie.getValue();
time = URLDecoder.decode(time, "utf-8"); // 对中文和特殊字符URL解码
response.getWriter().write("<h1>欢迎回来!上次你登录的时间为" + time + "</h1>");
// 重新设置访问时间
Date date = new Date();
SimpleDateFormat sDate = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String date_format = sDate.format(date);
date_format = URLEncoder.encode(date_format, "utf-8"); // 对中文和特殊字符URL编码
cookie.setValue(date_format);
cookie.setMaxAge(60 * 60 * 24 * 30); // cookie保存一个月
response.addCookie(cookie);
break;
}
}
}
if (cookies.length == 0 || !flag) { // 首次访问
Date date = new Date();
SimpleDateFormat sDate = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String date_format = sDate.format(date);
date_format = URLEncoder.encode(date_format, "utf-8");
Cookie cookie = new Cookie("lastTime",date_format);
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
response.getWriter().write("<h1>您好,欢迎您的首次登录!</h1>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
Session
概念:
服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
常见方法:
- 获取
HttpSession
对象:HttpSession session = request.getSession();
- 使用
HttpSession
对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
原理
服务器如何确保在一次会话范围内,多次获取的Session对象是同一个?
- Session是依赖于Cookie实现的
- 第一次获取Session,没有Cookie,会在内存中创建一个新的Session对象A
- 服务器响应,发送给客户端一个cookie,
set-cookie:JSESSIONID=A
的ID值 - 浏览器将这个cookie存入浏览器
- 再次请求浏览器的时候将cookie随请求头带给服务器
- 服务器根据cookie中的
set-cookie:JSESSIONID=A
的ID值 ,查询内存中是否存在该ID值,如果存在,即可拿出
细节
-
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
-
默认情况下不是的
-
如果期望客户端关闭后,session也能相同,那么按照下面来做
Cookie c = new Cookie("JSESSIONID",session.getId()); c.setMaxAge(60*60); response.addCookie(c);
-
- 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
- 肯定不是同一个,就算是同一个也是巧合
- 虽然session不是同一个,但是一些网站需要重启关闭后也能够保持数据不能丢失,需要按照下面两个过程
- session的钝化
- 在服务器正常关闭之前,将session对象序列化到硬盘中
- session的活化
- 在服务器启动后,将session文件转为内存中的session
- session的钝化
-
session的失效时间问题
-
服务器被关闭
-
session对象调用
invalidate()
-
session有一个默认失效时间:30分钟
-
选择性配置修改(在
web.xml
下)<session-config> <session-timeout>30</session-timeout> </session-config>
-
session的特点
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
session与cookie的区别:
- session存储数据在服务器端,cookie在客户端
- session没有数据大小限制,cookie有
- session数据安全,cookie相对不安全