session和cookies弄懂了!!!
粗略概述
方式:
客户端会话技术: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在浏览器中可以保存的时间:
1:默认情况下,当浏览器关闭后,cookie数据被清除
持久化存储: setMaxAge(int seconds)
2:正数:将Cookie数据写到硬盘的文件中。持久化存储。代表cookie存活时间。
3:负数:默认值,当浏览器关闭后,cookie数据被清除
零:删除cookie信息
4: 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获取范围是多大/共享问题?
1: 假设在同一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
默认情况下,cookie不能共享
setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录,String path代表范围,一个url
如果想要整个服务器上所有项目共享,则可以将path设置为"/"
不同的tomcat服务器间cookie共享问题?
2: 调用setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
例如:setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com里面的cookie可以共享
cookie的特点和作用
特点:
1: cookie存储数据在客户端浏览器,不是那么安全和保险
浏览器对应单个cookie 的大小有限制(4kb,不同浏览器不一样) 以及 对同一个域名下的总cookie数量也有限制 (20个,一般情况)
作用:
2: cookie一般用于存储少量的不太敏感的数据,因为它不怎么安全
在不登录的情况下,完成服务器对客户端的身份识别,比如一些网站,在没有登录的情况下,对网站进行设置,保存设置后,会以cookie的形式存在浏览器内,再次打开会依旧保持这个设置
实例:记住上次的访问时间
需求:
1: 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
2: 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
分析:
1: 可以采用Cookie来完成
在服务器中的Servlet判断是否有一个名为lastTime的cookie
有:不是第一次访问
2: 响应数据,欢迎回来,您上次访问时间为:某年某月某日hⓂ️s
写回Cookie: lastTime=某年某月某日hⓂ️s
没有:是第一次访问
响应数据:您好,欢迎您首次访问。
写回Cookie: lastTime=某年某月某日hⓂ️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
概念:
1: 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存2: 在服务器端的对象中。HttpSession
常见方法:
获取HttpSession对象:HttpSession session = request.getSession();
使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
原理
1: 服务器如何确保在一次会话范围内,多次获取的Session对象是同一个?
2: Session是依赖于Cookie实现的
第一次获取Session,没有Cookie,会在内存中创建一个新的Session对象A
服务器响应,发送给客户端一个cookie,set-cookie:JSESSIONID=A的ID值
3: 浏览器将这个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不是同一个,但是一些网站需要重启关闭后也能够保持数据不能丢失,需要按照下面两个过程
1: session的钝化
在服务器正常关闭之前,将session对象序列化到硬盘中
2: 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相对不安全