詳解Javaweb狀態(tài)管理的Session和Cookie
問題引入
- HTTP協(xié)議是無轉(zhuǎn)態(tài)的,不能保存提交的信息
- 如果用戶發(fā)來一個新的請求,服務(wù)器無法知道它是否與上次的請求聯(lián)系
- 對于那些需要多次提交數(shù)據(jù)才能完成的web操作,比如登錄,就難以完成
概念
將瀏覽器與web服務(wù)器之間多次交互當(dāng)做一個整體來處理,并且多次交互所涉及的數(shù)據(jù)(狀態(tài))保存下來
狀態(tài)管理分類
- 客戶端狀態(tài)管理技術(shù):將轉(zhuǎn)態(tài)保存在客戶端,代表性的是Cooklie技術(shù)
- 服務(wù)器狀態(tài)管理技術(shù):將狀態(tài)保存在服務(wù)器端,代表性的是session技術(shù)(服務(wù)器傳遞session時需要使用Cookie的方式)和application
Cookie
- Cookie是瀏覽器訪問Web服務(wù)器某個資源時,由Web服務(wù)器在HTTP響應(yīng)消息頭中附帶傳送給瀏覽器的小段數(shù)據(jù)
- 一旦Web服務(wù)器保存了某個Cookie,那么它在以后每次訪問該Web服務(wù)器時,都應(yīng)在HTTP請求中將這個Cookie回傳給Web服務(wù)器
- 一個Cookie主要由標(biāo)識該信息的名稱name和值value組成
Cookie的創(chuàng)建、獲取、修改
Cookie創(chuàng)建
@WebServlet(value = "/cs")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服務(wù)端創(chuàng)建Cookie對象
Cookie cookie = new Cookie("username","weishuo");
//設(shè)置Cookie的訪問路徑
cookie.setPath("/Servlet_Projects_war/get");
//設(shè)置Cookie的有效期 >0有效期,單位秒 =0瀏覽器關(guān)閉 <0內(nèi)存存儲 默認(rèn)-1
cookie.setMaxAge(60*60); //1小時
//添加到response對象中,將Cookie響應(yīng)給客戶端
resp.addCookie(cookie); //將Cookie添加到response對象中,響應(yīng)給客戶端
}
}Cookie獲取
@WebServlet(value = "/get")
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通過request對象獲取所有的cookie
Cookie[] cookies = req.getCookies();
if (cookies!=null){ //判斷cookies數(shù)組是否為空,避免空指針異常
//通過循環(huán)遍歷Cookie
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + ":" + cookie.getValue());
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}Cookie修改
如果修改Cookie的name和有效路徑會新建cookie,而改變Cookie值,有效期會覆蓋原有的Cookie
@WebServlet(value = "/cs2")
public class CookieServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服務(wù)端創(chuàng)建Cookie對象
Cookie cookie = new Cookie("username","given");
//設(shè)置Cookie的訪問路徑
cookie.setPath("/Servlet_Projects_war/get");
//設(shè)置Cookie有效期
cookie.setMaxAge(60*60*24*7); //7天
//添加到response對象中,將Cookie響應(yīng)給客戶端
resp.addCookie(cookie);
}
}Cookie編碼與解碼
Cookie默認(rèn)不支持中文,只能包含ASCII字符,所以Cookie需要對Unicode字符進(jìn)行編碼,否則會出現(xiàn)亂碼
- 編碼可以使用
java.net.URLEncoder類的encode(String str,String encoding)方法- 解碼使用
java.net.URLDecoder類的decode(String str,String encoding)方法
//Cookie設(shè)置
@WebServlet(value = "/cs3")
public class CookieServlet3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服務(wù)端創(chuàng)建Cookie對象,使用Cookie編碼
Cookie cookie = new Cookie(URLEncoder.encode("姓名","UTF-8"),URLEncoder.encode("張三","UTF-8"));
//設(shè)置Cookie的訪問路徑
cookie.setPath("/Servlet_Projects_war/get");
//設(shè)置Cookie有效期
cookie.setMaxAge(600);
//添加到response對象中,將Cookie響應(yīng)給客戶端
resp.addCookie(cookie);
}
}
//Cookie讀取
@WebServlet(value = "/get")
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通過request對象獲取所有的cookie
Cookie[] cookies = req.getCookies();
if (cookies!=null){ //判斷cookies數(shù)組是否為空,避免空指針異常
//通過循環(huán)遍歷Cookie
for (Cookie cookie : cookies) {
//使用Cookie解碼
System.out.println(URLDecoder.decode(cookie.getName(),"UTF-8") + ":" + URLDecoder.decode(cookie.getValue(),"UTF-8"));
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}總結(jié)
Cookie優(yōu)點(diǎn)
可配置到期規(guī)則Cookie是一種基于文本的輕量級結(jié)構(gòu),包含簡單的鍵值對Cookie默認(rèn)在過期之前是可以一直存在在客戶端瀏覽器上
Cookie的缺點(diǎn)
大小受到限制,瀏覽器對Cookie大小有4K,8K字節(jié)限制用戶配置為禁用,用戶禁用了瀏覽器或客戶端接受Cookie的能力Cookie可能被篡改,存在潛在風(fēng)險
Session
概述
- Session用于記錄用戶的狀態(tài),Session指的是一段時間,單個客戶端與web服務(wù)器的一連串交互過程
- 一個Session中,客戶可能會多次請求訪問同一個資源,也可能請求訪問各種不同的服務(wù)器資源
原理
Tip:
Session和Cookie都是由服務(wù)器端創(chuàng)建
- 服務(wù)器為每一次會話分配一個Session對象
- 同一個瀏覽器發(fā)起的多次請求,同屬于一次會話(Session)
- 首次使用Session,服務(wù)器自動創(chuàng)建Session,并且創(chuàng)建Cookie存儲SessionID發(fā)送回客戶端
session使用
Session作用域:擁有存儲數(shù)據(jù)的空間,作用范圍是一次會話有效
- 一次會話是使用同一瀏覽器發(fā)送到多次請求,瀏覽器關(guān)閉則會話結(jié)束
- 可以將數(shù)據(jù)存入Session中,一次會話的任意位置進(jìn)行獲取
- 可以傳遞任何數(shù)據(jù)(基本數(shù)據(jù)類型、對象、集合、數(shù)組)
獲取session
//獲取Session對象
HttpSession session = request.getSession();
System.out.println("id"+session.getId()); //唯一標(biāo)識package com.woniu.sessions;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "Servlet", value = "/ss")
public class Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通過request對象獲取session對象
HttpSession session = request.getSession();
System.out.println(session.getId());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}Session保存數(shù)據(jù)
- 保存數(shù)據(jù)到session中
setAttribute(屬性名,Objects);
session.setAttribute("key",value);//以鍵值對形式存儲在session作用域中Session獲取數(shù)據(jù)
- 獲取session中數(shù)據(jù)
getAttribute(屬性名);
session.getAttribute("key"); //通過String類型的key訪問Object類型的valueSession移除數(shù)據(jù)
- 從Session中刪除數(shù)據(jù)
removeAttribute(屬性名);
session.removeAttribute("key");//通過移除session作用域中的值應(yīng)用
- Servlet類
@WebServlet(name = "Servlet", value = "/ss")
public class Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通過request對象獲取session對象
HttpSession session = request.getSession();
//使用session保存數(shù)據(jù)
session.setAttribute("username","given");
//通過產(chǎn)生的session對象獲取sessionId
System.out.println(session.getId());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}- GetValueServlet類
@WebServlet(name = "GetValueServlet", value = "/getValue")
public class GetValueServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
System.out.println("從session中獲得了" + username); //從session中獲得了given
}
}- RemoveServlet類
@WebServlet(name = "RemoveServlet", value = "/remove")
public class RemoveServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.removeAttribute("username");
}
}- 結(jié)果
543D0EA33CB586691A02C00564E34CEA
從session中獲得了given
從session中獲得了null
Session & Request 區(qū)別
- request是一次請求有效,請求改變,則request改變
- session是一次會話有效,瀏覽器改變,則session改變
SessionServlet類
@WebServlet(name = "Servlet", value = "/ss")
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通過request對象獲取session對象
HttpSession session = request.getSession();
//使用session保存數(shù)據(jù)
session.setAttribute("username","given");
//使用request保存數(shù)據(jù)
request.setAttribute("password",123456);
//重定向跳轉(zhuǎn)到/getValue
response.sendRedirect("/Servlet_Projects_war/getValue");
//通過產(chǎn)生的session對象獲取sessionId
System.out.println(session.getId());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}GetValueServlet類
@WebServlet(name = "GetValueServlet", value = "/getValue")
public class GetValueServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String password = (String) request.getAttribute("password");
System.out.println("從request中獲得了" + password);
String username = (String) session.getAttribute("username");
System.out.println("從session中獲得了" + username); //從session中獲得了given
}
}結(jié)果
從request中獲得了null 從session中獲得了given
總結(jié)
sendRedirect跳轉(zhuǎn)時,地址欄發(fā)生改變,代表客戶端重新發(fā)送請求,屬于兩次請求;response沒有作用域,兩次request請求中的數(shù)據(jù)無法共享;而session只要瀏覽器不關(guān)閉屬于一次會話,一次會話中瀏覽器數(shù)據(jù)可以共享
Session生命周期
- 開始:第一次使用到Session的請求產(chǎn)生,則創(chuàng)建Session
- 結(jié)束
- 瀏覽器關(guān)閉,則失效
- Session超時,則失效
- session.SetMaxInactivelnterval(seconds); 設(shè)置最大有效時間(單位/秒)
- 手工銷毀,則失效
- session.invalidate(); 登錄退出、注銷
- Session超時,則失效
LifeSessionServlet類
@WebServlet(name = "LifeSessionServlet", value = "/life")
public class LifeSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取session
HttpSession session = request.getSession();
//設(shè)置session有效過期時間為10s
session.setMaxInactiveInterval(10);
//通過產(chǎn)生的session對象獲取sessionId
System.out.println(session.getId());
}
}GetSessionServlet類
@WebServlet(name = "GetSessionServlet", value = "/getSession")
public class GetSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取session
HttpSession session = request.getSession();
System.out.println(session.getId());
//手工銷毀,立即失效
//session.invalidate();
}
}結(jié)果
瀏覽器輸入/life,獲取到的sessionId 71A9B2141F22840E0BE7EA67B49EC9B3 10秒內(nèi),瀏覽器輸入/getSession,獲取到的sessionId 71A9B2141F22840E0BE7EA67B49EC9B3 10秒后,瀏覽器輸入/getSession,獲取到的sessionId EDF2E31978DE8295486C2657016F5202
瀏覽器禁用Cookie解決方案
瀏覽器禁用Cookie后果
服務(wù)器在默認(rèn)情況下,會使用Cookie的方式將sessionID發(fā)送給服務(wù)器,如果用戶禁止Cookie,則sessionID不會被瀏覽器保存,此時,服務(wù)器使用如URL重寫這樣的方式來發(fā)送sessionID
URL重寫
瀏覽器在訪問服務(wù)器上的某個地址時,不再使用原來的那個地址,而是使用經(jīng)過改寫的地址(即在原來的地址后面加上sessionID)
實(shí)現(xiàn)URL重寫
- response.encodeRedirectURL(String url); //生成重寫的URL
//實(shí)現(xiàn)URL重寫
String url = response.encodeRedirectURL("/Servlet_Projects_war/getSession");
//輸出URL重寫地址
System.out.println(url);
//重定向轉(zhuǎn)發(fā)
response.sendRedirect(url);結(jié)果
重寫URL地址 /Servlet_Projects_war/getSession;jsessionid=A38B1C92B9CDE10F6ED5E7AA19E919F0 瀏覽器輸入/life,獲取到的sessionId A38B1C92B9CDE10F6ED5E7AA19E919F0 重定向轉(zhuǎn)發(fā)地址:/Servlet_Projects_war/getSession,獲取到的sessionId A38B1C92B9CDE10F6ED5E7AA19E919F0
到此這篇關(guān)于詳解Javaweb狀態(tài)管理的Session和Cookie的文章就介紹到這了,更多相關(guān)Javaweb的Session和Cookie內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java 單例的五種實(shí)現(xiàn)方式及其性能分析
這篇文章主要介紹了java 單例的五種實(shí)現(xiàn)方式及其性能分析。的相關(guān)資料,需要的朋友可以參考下2017-07-07
淺析SpringMVC中的適配器HandlerAdapter
這篇文章主要介紹了SpringMVC中的適配器HandlerAdapter的相關(guān)資料,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
SpringBoot整合Jackson超詳細(xì)用法(附Jackson工具類)
這篇文章主要介紹了SpringBoot整合Jackson超詳細(xì)教程,本篇講的是Jackson的詳細(xì)用法,Jackson工具類在文章最后,直接復(fù)制粘貼即可使用,需要的朋友可以參考下2023-03-03
Spring Boot整合MybatisPlus逆向工程(MySQL/PostgreSQL)
MyBatis-Plus是MyBatis的增強(qiáng)工具,本文主要介紹了Spring Boot整合MybatisPlus逆向工程(MySQL/PostgreSQL),具有一定的參考價值,感興趣的可以了解一下2021-07-07
Java中遇到的For?input?string問題解決辦法
這篇文章主要給大家介紹了關(guān)于Java中遇到的For?input?string問題的解決辦法,如果出現(xiàn)這樣的異常報錯,是指的數(shù)據(jù)轉(zhuǎn)換時出錯,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
Java實(shí)現(xiàn)大文件的切割與合并操作示例
這篇文章主要介紹了Java實(shí)現(xiàn)大文件的切割與合并操作,結(jié)合實(shí)例形式分析了java基于io及util操作大文件按指定個數(shù)分割與合并相關(guān)操作技巧,需要的朋友可以參考下2018-07-07
Spring核心容器之ApplicationContext上下文啟動準(zhǔn)備詳解
這篇文章主要介紹了Spring核心容器之ApplicationContext上下文啟動準(zhǔn)備詳解,ApplicationContext 繼承自 BeanFactory ,其不僅包含 BeanFactory 所有功能,還擴(kuò)展了容器功能,需要的朋友可以參考下2023-11-11
基于@AllArgsConstructor與@Value共用的問題解決
這篇文章主要介紹了基于@AllArgsConstructor與@Value共用的問題解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
Springboot工具類FileCopyUtils使用教程
這篇文章主要介紹了Springboot內(nèi)置的工具類之FileCopyUtils的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12

