一、会话跟踪技术
1、会话跟踪技术介绍
* 会话: 用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。
在一次会话中可以包含"多次请求和响应"
2、为什么需要会话跟踪技术?
* 因为HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,
因此我们需要"会话跟踪技术来实现会话内数据共享"
* 实现方式:
"客户端会话跟踪技术": "Cookie"
"服务端会话跟踪技术": "Session"
二、 Cookie和Seesion详解
1、Cookie
(1)Cookie是什么 ?
Cookie: "客户端会话技术",将数据保存到客户端,以后"每次请求都携带Cookie数据进行访问"
(2)为什么要使用Cookie?解决了什么问题 ?
* "web程序是使用HTTP协议传输的",而HTTP协议是"无状态的协议","对于事务处理没有记忆能力"
"缺少状态意味着如果后续处理需要前面的信息,则它必须重传",这样可能导致每次连接传送的数据量增大
另一方面,如果服务器不需要获取之前的信息的时候它的应答就较快
* "使用cookie可以解决这个问题,实现数据的共享"
(3)Cookie什么时候产生 ?
* 客户端向服务器端发送一个请求时,服务端向客户端发送一个Cookie然后浏览器将Cookie保存
* Cookie有两种保存方式:
1.Cookie保存在内存中
2.保存在客户端的硬盘中, 之后每次HTTP请求浏览器都会将Cookie发送给服务器端
(4)Cookie的工作原理
1. 浏览器端第一次发送请求到服务器端
2. "服务器端创建Cookie",该Cookie中包含用户的信息,然后将该Cookie发送到浏览器端
3. 浏览器端"再次访问服务器端"时会"携带服务器端创建的Cookie"
4. 服务器端"通过Cookie中携带的数据区分不同的用户"
(5)Cookie的基本使用
* 发送 Cookie
1. 创建Cookie对象,设置数据
Cookie cookie = new Cookie("key","value");
2. 发送Cookie到客户端:使用response对象
response.addCookie(cookie);
------------------------------------------------------------------------------------------------------------
* 获取 Cookie
3. 获取客户端携带的所有Cookie,使用request对象
Cookie[] cookies = request.getCookies();
4. 遍历数组,获取每一个Cookie对象: for
5. 使用Cookie对象方法获取数据
cookie.getName();
cookie.getValue();
?代码演示
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.URLEncoder;
@WebServlet("/a")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("username", "zhangsan");
response.addCookie(cookie);
}
}
------------------------------------------------------------------------------------------------------------
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;
@WebServlet("/b")
public class BServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if(cookies !=null){
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name+":"+value);
}
}else {
System.out.println("浏览器没有cookie");
}
}
}
(6)Cookie 存活时间
* 默认情况下,Cookie 存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁
* setMaxAge(int seconds): 设置Cookie存活时间, 秒为单位
正数: 将 Cookie写入浏览器所在电脑的硬盘,"持久化存储" , 到时间自动删除
负数: "默认值" , Cookie在当前浏览器内存中,当"浏览器关闭,则 Cookie被销毁"
零: 立马删除对应 Cookie
?代码演示
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.URLEncoder;
@WebServlet("/a")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("username", "zhangsan");
cookie.setMaxAge(60*60*24*3);
response.addCookie(cookie);
}
}
(7)Cookie 存储中文
* Tomcat7 Cookie 不能直接存储中文
* Tomcat8 Cookie 可以存储中文但不能存储空格
* 如需要存储,则需要进行转码: URL编码
* " 转码: URLEncoder.encode("需要转码的内容" , "编码格式")
* " 解码: URLDecoder.decode("解码的内容" , "用什么码来解")
?转码解码代码演示
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.URLEncoder;
@WebServlet("/a")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = URLEncoder.encode(" 张 三", "utf-8");
Cookie cookie = new Cookie("username", username);
cookie.setMaxAge(60*60);
response.addCookie(cookie);
}
}
------------------------------------------------------------------------------------------------------------
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;
@WebServlet("/b")
public class BServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if(cookies !=null){
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
if(name.equals("username")){
value=URLDecoder.decode(value,"utf-8");
}
System.out.println(name+","+value);
}
}else {
System.out.println("浏览器没有cookie");
}
}
}
?未转码代码演示
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.URLEncoder;
@WebServlet("/a")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("username", "张 三");
cookie.setMaxAge(60*60);
response.addCookie(cookie);
}
}
(8)Cookie的缺点
* "数量受到限制":
单个cookie保存的数据<=4KB,一个站点一般保存20~50个Cookie
(不同浏览器不一样,Sarafi和Chrome对每个域的Cookie数目没有严格限制)
* "是不安全的":
cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,
所以它是不安全的
* "浏览器可以禁用Cookie",禁用Cookie后,也就无法享有Cookie带来的方便
(9)Cookie的使用场景
1.对安全性要求不高
2.不需要大量数据
2、Seesion
(1)Session是什么 ?
* Session: "服务端会话跟踪技术,将数据保存到服务端"
JavaEE 提供 "HttpSession接口", 来实现"一次会话的多次请求间数据共享功能"
(2)Session的基本使用
?
* request.getSession();
* Session对象功能
* void setAttribute(String name, Object o): "存储数据到 session 域中"
* Object getAttribute(String name) : 根据 key,"获取值"
* void removeAttribute(String name): 根据 key,"删除该键值对"
?代码演示
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/demo01")
public class SessionDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("username","zhangsan");
session.setAttribute("money",1000);
}
}
------------------------------------------------------------------------------------------------------------
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/demo02")
public class SessionDemo02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
Integer money = (Integer) session.getAttribute("money");
System.out.println("username = " + username);
System.out.println("money = " + money);
}
}
(3)Session的工作原理
1. 浏览器端第一次发送请求到服务器端,服务器端创建一个Session
同时会创建一个特殊的Cookie(name为JSESSIONID的固定值,value为session对象的ID)
然后将该Cookie发送至浏览器端
2.浏览器端发送第N次请求到服务器端,浏览器端访问服务器端时就会携带该name为JSESSIONID的Cookie对象
3.服务器端根据name为JSESSIONID的Cookie的value(sessionId),去查询Session对象,从而区分不同用户
(4)Session 的钝化、活化
* 服务器重启后,Session中的数据是否还在?
* 钝化: 在"服务器正常关闭后" , "Tomcat自动将 Session数据写入硬盘的文件中"
* 活化: "再次启动服务器后", 从"文件中加载数据到Session中"
步骤演示
(5)Seesion的销毁和存活
* "默认情况下" , 无操作 , "30分钟自动销毁"
* 怎么可以立即销毁 ?
* invalidate();
* 怎么查看Seesion的存活时间?
* getMaxInactiveInterval();
* 怎么设置Seesion的存活时间?
* 在WEB-INF中的web.xml中设置
<session-config>
<session-timeout>30</session-timeout>
</session-config>
?查看存活时间代码演示
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/demo02")
public class SessionDemo02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
int max = session.getMaxInactiveInterval();
System.out.println(max);
String username = (String) session.getAttribute("username");
Integer money = (Integer) session.getAttribute("money");
System.out.println("username = " + username);
System.out.println("money = " + money);
session.invalidate();
}
}
?设置存活时间代码演示
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
3、Cookie和Session的区别(面试题)
1.存储位置不同
* "Cookie"的数据信息存放在"客户端浏览器"上
* "Session"的数据信息存放在"服务器"上
2.存储容量不同
* "单个Cookie保存的数据<=4KB,一个站点一般保存20~50个Cookie"
(不同浏览器不一样,Sarafi和Chrome对每个域的Cookie数目没有严格限制)
* 对于Session来说并"没有上限",但出于对服务器端的性能考虑,
Session内不要存放过多的东西,并且设置Session删除机制 (或者采用缓存技术代替session)
3.存储方式不同
* Cookie中"只能保管ASCII字符串",并需要通过编码方式存储为Unicode字符或者二进制数据
* Session中能够"存储任何类型的数据" ,包括且不限于string,integer,list,map等
4.安全性不同
* "Cookie对客户端是可见的",别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,
所以它是"不安全"的
* "Session存储在服务器上,不存在敏感信息泄漏的风险"
5.存储时间不同
* Cookie默认浏览器关闭
* Session 默认30分钟
* 开发可以通过设置cookie的属性,达到使cookie长期有效的效果
* session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,
只需关闭窗口该session就会失效,因而session不能达到长期有效的效果
6.服务器压力不同
* Cookie保管在客户端,"不占用服务器资源", "对于并发用户十分多的网站,cookie是很好的选择"
(Cookie不占用服务器资源)
* session是保管在服务器端的,每个用户都会产生一个session, 假如并发访问的用户十分多,会产生十分
多的session,耗费大量的内存
(Session 占用服务器资源)
7.键值对数量不同
* Cookie 存一个键和一个值
* Session 存n个键和值
作者:KJ.JK
文章对你有所帮助的话,欢迎给个赞或者 star,你的支持是对作者最大的鼓励,不足之处可以在评论区多多指正,交流学习
|