初學(xué)Java Web(5)——cookie-session學(xué)習(xí)

HTTP 協(xié)議

Web 瀏覽器Web 服務(wù)器之間的一問一答的交互過程必須遵守一定的規(guī)則,這樣的規(guī)則就是 HTTP 協(xié)議。

HTTPhypertext transfer protocol(超文本傳輸協(xié)議)的簡寫,它是 TCP/IP 協(xié)議之上的一個應(yīng)用層的協(xié)議,用于定義 Web 瀏覽器與 Web 服務(wù)器之間交互數(shù)據(jù)的過程以及數(shù)據(jù)本身的格式。

  • 特點:無狀態(tài),默認(rèn)端口 80

HTTP 協(xié)議到底約束了什么?

  1. 約束了瀏覽器以何種格式向服務(wù)端發(fā)送數(shù)據(jù)
  2. 約束了服務(wù)器應(yīng)該以何種格式接收客戶端發(fā)送的數(shù)據(jù)
  3. 約束了服務(wù)器應(yīng)該以何種格式反饋數(shù)據(jù)給瀏覽器
  4. 約束了瀏覽器應(yīng)該以何種格式接收服務(wù)器的反饋數(shù)據(jù)
  • 總結(jié):
    瀏覽器給服務(wù)器發(fā)送數(shù)據(jù):一次請求
    服務(wù)器給瀏覽器反饋數(shù)據(jù):一次響應(yīng)

HTTP 無狀態(tài)協(xié)議

HTTP 是一個無狀態(tài)的協(xié)議,也就是沒有記憶力,這意味著每一次的請求都是獨立的,缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須要重傳,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。另一方面,在服務(wù)器不需要先前信息時它的應(yīng)答就很快。

HTTP 的這種特性有優(yōu)點也有缺點:

  • 優(yōu)點:解放了服務(wù)器,每一次的請求“點到為止”,不會造成不必要的連接占用。
  • 缺點:每次請求會傳輸大量重復(fù)的內(nèi)容信息,并且,在請求之間無法實現(xiàn)數(shù)據(jù)的共享。

主要問題:請求之間無法實現(xiàn)數(shù)據(jù)的共享

  • 解決方案:
    1.使用參數(shù)傳遞機制:
    將參數(shù)拼接在請求的 URL 后面,實現(xiàn)數(shù)據(jù)的傳遞(GET方式),例如:/param/list?username=wmyskxz
    問題:可以解決數(shù)據(jù)共享的問題,但是這種方式一不安全,二數(shù)據(jù)允許傳輸量只有1kb
    2.使用Cookie技術(shù)
    3.使用Session技術(shù)

Cookie 技術(shù)

  • 特點:客戶端的技術(shù),將共享數(shù)據(jù)保存在客戶端(瀏覽器)中

英文直接翻譯過來就是小甜品,Cookie 的作用呢,通俗的說就是當(dāng)一個用戶通過 HTTP 訪問一個服務(wù)器時,這個服務(wù)器會將一些 Key/Value 鍵值對返回給客戶端瀏覽器,并給這些數(shù)據(jù)加上一些限制條件,在條件符合時這個用戶下次訪問這個服務(wù)器時,數(shù)據(jù)又被完整地帶回給服務(wù)器。

這個作用就像是你去超市購物時,第一次給你辦了一張購物卡,在這個購物卡里存放了一些你的個人信息,下次你再來這個超市的時候,你就只需要帶上你的購物卡,直接購物就好了。

Cookie 操作

  1. 創(chuàng)建 Cookie 對象,設(shè)置共享數(shù)據(jù)
Cookie c = new Cookie(String name,String value);  // 相當(dāng)于辦卡
  • 注意:一個Cookie只能存儲一個字符串類型的數(shù)據(jù),不能存儲其他類型的數(shù)據(jù)
  1. 將 Cookie 響應(yīng)給瀏覽器
response對象.addCookie(cookie對象)                // 相當(dāng)于把卡交給用戶
  1. 獲取請求中的 Cookie 信息
Cookie[] cs = request對象.getCookies();
for(Cookie c : cs){
    if(“username”.equals(c.getName())){
        String value = c.getValue();
    }
}
  1. 修改 Cookie 中的共享數(shù)據(jù)
    1.重新創(chuàng)建一個新的 Cookie,名稱要和要修改的數(shù)據(jù)一致
    2.現(xiàn)獲取到要修改的 Cookie 對象,再調(diào)用 setValue(String newValue) 重新設(shè)置
  • 注意:修改 Cookie 中的數(shù)據(jù),需要再次發(fā)送給瀏覽器(第2點)
  1. 操作 Cookie 的生命周期
  • 默認(rèn):在關(guān)閉瀏覽器的時候銷毀 Cookie 對象
  • 語法:void setMaxAge(int expiry)
    expiry > 0:設(shè)置 Cookie 對象能夠存活 expiry 秒,即使關(guān)閉瀏覽器,也不影響 Cookie 中的共享數(shù)據(jù),比如設(shè)置一個月:setMaxAge(60*60*24*30);
    expiry = 0:立即刪除當(dāng)前的 Cookie 信息
    expiry < 0:關(guān)閉瀏覽器時銷毀
  1. 刪除 Cookie 中的共享數(shù)據(jù)
    通過setMaxAge(0)來實現(xiàn)

  2. Cookie 中的 key 和 value 不支持中文
    設(shè)置 Cookie 時需要對中文字符串進行編碼:

    Cookie c = new Cookie("username", URLEncoder.encode(username,"UTF-8"));
    

    在獲取 Cookie 數(shù)據(jù)的時候再進行解碼:

    username = URLDecoder.decode(value, "UTF-8");
    
  3. Cookie 的路徑和域范圍

  • Cookie 的路徑
    Cookie 在創(chuàng)建的時候,會根據(jù)當(dāng)前的Servlet的相對路徑來設(shè)置自己的路徑,比如 Servlet 的url-pattern/cookie/login,相對路徑則為:/cookie/
    • 出現(xiàn)的問題:
      只有在訪問路徑為 /cookie/ 下面的資源的時候,才會將該 Cookie 發(fā)送到服務(wù)器
    • 解決方案:
      設(shè)置 Cookie 的路徑:void setPath(String uri)
      Cookie對象.setPath("/"); 表示當(dāng)前應(yīng)用中的所有的資源都能夠共享該Cookie信息
  • 域范圍:(了解)
    在多個應(yīng)用之間實現(xiàn)數(shù)據(jù)的共享,那么就需要設(shè)置域范圍,比如:
    www.baidu.com / news.baidu.com / map.baidu.com
  • 語法:Cookie對象.setDomain("baidu.com");

Cookie 的缺陷

Cookie 的作用其實就是一種會話跟蹤技術(shù),但存在一些缺陷:

  1. 獲取 Cookie 信息比較麻煩
  2. Cookie 不支持中文
  3. 一個 Cookie 只能存儲一個字符串類型的數(shù)據(jù)
  4. Cookie 在瀏覽器中有大小和數(shù)量上的限制(不同瀏覽器存在不同的限制,例如FireFox一個站點最多存儲50個 Cookie ,瀏覽器最多存儲 4097個字大小的 Cookie)
  5. 共享數(shù)據(jù)時保存在瀏覽器中,容易造成數(shù)據(jù)的泄露,不安全
  • 最好的解決方案:將數(shù)據(jù)保存在服務(wù)端(session)

Session 技術(shù)

Session:會話,從瀏覽器打開開始,直到瀏覽器關(guān)閉結(jié)束,無論在這個網(wǎng)站中訪問了多少頁面,點擊了多少鏈接,都屬于同一個會話。Session 也可以稱為會話 Cookie

  • 特點:服務(wù)端技術(shù),將數(shù)據(jù)保存在服務(wù)器

理解 Session

前面已經(jīng)介紹了 Cookie 可以讓服務(wù)端程序跟蹤每個客戶端的訪問,但是每次客戶端的訪問都必須傳回這些 Cookie,如果 Cookie 很多,則無形增加了客戶端與服務(wù)端的數(shù)據(jù)傳輸量,而 Session 的出現(xiàn)正是為了解決這個問題。

同一個客戶端每次和服務(wù)端交互時,不需要每次都傳回所有的 Cookie 值,而是只要傳回一個 ID,這個 ID 就是客戶端第一次訪問服務(wù)器生成的,而且每個客戶端是唯一的。這樣每個客戶端就有了一個唯一的 ID,客戶端只要傳回這個 ID 就行了,這個 ID 通常是 NAME 為 JSESIONID 的一個 Cookie。

Session 基本操作

  1. 獲取 Session 對象
    request對象.getSession()
    和參數(shù)為true的一樣
    request對象.getSession(true)
    獲取Session對象,如果沒有Session對象,直接創(chuàng)建一個新的返回,缺省值
    request對象.getSession(false)
    獲取Session對象,如果沒有返回null
  2. 設(shè)置共享數(shù)據(jù)
Session對象.setAttribute(String name, Object value)
  • 注意:Session 可以存儲任何類型的數(shù)據(jù),比如登陸用戶的信息,可以封裝到User對象中
  1. 修改共享數(shù)據(jù)
    重新設(shè)置一個同名的共享數(shù)據(jù)

  2. 獲取共享數(shù)據(jù)

Object value = Session對象.getAttribute(String name);
  1. 刪除 Session 中的共享數(shù)據(jù)
Session對象.removeAttribute(String name);
  1. 銷毀 Session
void invalidate() 
  1. Session 的超時管理
  • 超時:在訪問當(dāng)前的資源的過程中,不和網(wǎng)頁進行任何的交互,超過設(shè)定的時間就是超時
    在 Tomcat 服務(wù)器中有默認(rèn)的配置為30分鐘,一般不需要去修改
  • 語法:void setMaxInactiveInterval(int interval)

Session 擴展

  • Seesion 中的共享數(shù)據(jù)的屬性名的命名規(guī)范:
    通常為:XXX_IN_SESSION,例如:Session對象.setAttribute(“USER_IN_SESSION”,user)
  • 序列化與反序列化:
    Session 中存儲的對象通常需要實現(xiàn)序列化接口,因為在網(wǎng)絡(luò)之間傳輸?shù)臄?shù)據(jù)格式為二進制數(shù)據(jù)
    • 序列化:將對象轉(zhuǎn)換成二進制數(shù)據(jù)
    • 反序列化:將二進制數(shù)據(jù)轉(zhuǎn)換成對象
  • URL 重寫
    出現(xiàn)的問題:
    當(dāng)瀏覽器禁用Cookie之后,那么我們的jsessionid就不能在瀏覽器中保存,那么后面的請求中就不會將 jsessionid 發(fā)送到服務(wù)器,服務(wù)器這面就找不到數(shù)據(jù)
    解決方案:
    1.在url后手動的拼接上 jsessionid
    傳遞格式如 /path/Servlet;jsessionid=sessionid
    2.使用響應(yīng)對象中的encodeURL(String path)實現(xiàn) jsessionid 的自動拼接
    String path = resp.encodeURL("path/Servlet");
    • 推薦方式:②

歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz
分享自己的學(xué)習(xí) & 學(xué)習(xí)資料 & 生活
想要交流的朋友也可以加qq群:3382693

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容