詳解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)點
可配置到期規(guī)則Cookie是一種基于文本的輕量級結(jié)構(gòu),包含簡單的鍵值對Cookie默認(rèn)在過期之前是可以一直存在在客戶端瀏覽器上
Cookie的缺點
大小受到限制,瀏覽器對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類型的value
Session移除數(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)
實現(xiàn)URL重寫
- response.encodeRedirectURL(String url); //生成重寫的URL
//實現(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)文章
Mybatis的TypeHandler加解密數(shù)據(jù)實現(xiàn)
在我們數(shù)據(jù)庫中有些時候會保存一些用戶的敏感信息,所以就需要對這些數(shù)據(jù)進(jìn)行加密,那么本文就介紹了Mybatis的TypeHandler加解密數(shù)據(jù)實現(xiàn),感興趣的可以了解一下2021-06-06Mybatis如何實現(xiàn)@Select等注解動態(tài)組合SQL語句
這篇文章主要介紹了Mybatis如何實現(xiàn)@Select等注解動態(tài)組合SQL語句,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07Spring?Security實現(xiàn)用戶名密碼登錄詳解
這篇文章主要為大家詳細(xì)介紹了Spring Security如何實現(xiàn)用戶名密碼登錄功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2022-10-10微信游戲打飛機(jī)游戲制作(java模擬微信打飛機(jī)游戲)
java模擬微信打飛機(jī)游戲,大家參考使用吧2013-12-12Java中Date類和Calendar類的常用實例小結(jié)
這篇文章主要介紹了Java中Date類和Calendar類的常用實例小結(jié),是Java入門學(xué)習(xí)中的基礎(chǔ)知識的運用,需要的朋友可以參考下2015-08-08Java和C++通過new創(chuàng)建的對象有何區(qū)別?
Java和C++都是面向?qū)ο蟮木幊陶Z言,然而Java和C++在創(chuàng)建對象時卻存在不同的方式,由于方式的不同導(dǎo)致在內(nèi)存中管理的不同。這篇文章主要給大家介紹了關(guān)于Java和C++通過new創(chuàng)建對象區(qū)別的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-11-11UniApp?+?SpringBoot?實現(xiàn)微信支付和退款功能
這篇文章主要介紹了UniApp?+?SpringBoot?實現(xiàn)微信支付和退款功能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06