HTTP 協議
Web 瀏覽器與 Web 服務器之間的一問一答的交互過程必須遵守一定的規則,這樣的規則就是 HTTP 協議。
HTTP 是 hypertext transfer protocol(超文本傳輸協議)的簡寫,它是 TCP/IP 協議之上的一個應用層的協議,用於定義 Web 瀏覽器與 Web 服務器之間交互數據的過程以及數據本身的格式。
- 特點:無狀態,默認端口 80
HTTP 協議到底約束了什么?
- 約束了瀏覽器以何種格式向服務端發送數據
- 約束了服務器應該以何種格式來接收客戶端發送的數據
- 約束了服務器應該以何種格式來反饋數據給瀏覽器
- 約束了瀏覽器應該以何種格式來接收服務器的反饋數據
- 總結:
瀏覽器給服務器發送數據:一次請求
服務器給瀏覽器反饋數據:一次響應
HTTP 無狀態協議
HTTP 是一個無狀態的協議,也就是沒有記憶力,這意味着每一次的請求都是獨立的,缺少狀態意味着如果后續處理需要前面的信息,則它必須要重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就很快。
HTTP 的這種特性有優點也有缺點:
- 優點:解放了服務器,每一次的請求“點到為止”,不會造成不必要的連接占用。
- 缺點:每次請求會傳輸大量重復的內容信息,並且,在請求之間無法實現數據的共享。
主要問題:請求之間無法實現數據的共享
- 解決方案:
1.使用參數傳遞機制:
將參數拼接在請求的 URL 后面,實現數據的傳遞(GET方式),例如:/param/list?username=wmyskxz
問題:可以解決數據共享的問題,但是這種方式一不安全,二數據允許傳輸量只有1kb
2.使用Cookie技術
3.使用Session技術
Cookie 技術
- 特點:客戶端的技術,將共享數據保存在客戶端(瀏覽器)中
英文直接翻譯過來就是小甜品,Cookie 的作用呢,通俗的說就是當一個用戶通過 HTTP 訪問一個服務器時,這個服務器會將一些 Key/Value 鍵值對返回給客戶端瀏覽器,並給這些數據加上一些限制條件,在條件符合時這個用戶下次訪問這個服務器時,數據又被完整地帶回給服務器。
這個作用就像是你去超市購物時,第一次給你辦了一張購物卡,在這個購物卡里存放了一些你的個人信息,下次你再來這個超市的時候,你就只需要帶上你的購物卡,直接購物就好了。
Cookie 操作
- 創建 Cookie 對象,設置共享數據
Cookie c = new Cookie(String name,String value); // 相當於辦卡
- 注意:一個Cookie只能存儲一個字符串類型的數據,不能存儲其他類型的數據
- 將 Cookie 響應給瀏覽器
response對象.addCookie(cookie對象) // 相當於把卡交給用戶
- 獲取請求中的 Cookie 信息
Cookie[] cs = request對象.getCookies();
for(Cookie c : cs){
if(“username”.equals(c.getName())){
String value = c.getValue();
}
}
- 修改 Cookie 中的共享數據
1.重新創建一個新的 Cookie,名稱要和要修改的數據一致
2.現獲取到要修改的 Cookie 對象,再調用setValue(String newValue)
重新設置
- 注意:修改 Cookie 中的數據,需要再次發送給瀏覽器(第2點)
- 操作 Cookie 的生命周期
- 默認:在關閉瀏覽器的時候銷毀 Cookie 對象
- 語法:
void setMaxAge(int expiry)
expiry > 0:設置 Cookie 對象能夠存活 expiry 秒,即使關閉瀏覽器,也不影響 Cookie 中的共享數據,比如設置一個月:setMaxAge(60*60*24*30);
expiry = 0:立即刪除當前的 Cookie 信息
expiry < 0:關閉瀏覽器時銷毀
-
刪除 Cookie 中的共享數據
通過setMaxAge(0)
來實現 -
Cookie 中的 key 和 value 不支持中文
設置 Cookie 時需要對中文字符串進行編碼:Cookie c = new Cookie("username", URLEncoder.encode(username,"UTF-8"));
在獲取 Cookie 數據的時候再進行解碼:
username = URLDecoder.decode(value, "UTF-8");
-
Cookie 的路徑和域范圍
- Cookie 的路徑
Cookie 在創建的時候,會根據當前的Servlet的相對路徑來設置自己的路徑,比如 Servlet 的url-pattern
為 /cookie/login,相對路徑則為:/cookie/- 出現的問題:
只有在訪問路徑為 /cookie/ 下面的資源的時候,才會將該 Cookie 發送到服務器 - 解決方案:
設置 Cookie 的路徑:void setPath(String uri)
Cookie對象.setPath("/");
表示當前應用中的所有的資源都能夠共享該Cookie信息
- 出現的問題:
- 域范圍:(了解)
在多個應用之間實現數據的共享,那么就需要設置域范圍,比如:
www.baidu.com / news.baidu.com / map.baidu.com
- 語法:
Cookie對象.setDomain("baidu.com");
Cookie 的缺陷
Cookie 的作用其實就是一種會話跟蹤技術,但存在一些缺陷:
- 獲取 Cookie 信息比較麻煩
- Cookie 不支持中文
- 一個 Cookie 只能存儲一個字符串類型的數據
- Cookie 在瀏覽器中有大小和數量上的限制(不同瀏覽器存在不同的限制,例如FireFox一個站點最多存儲50個 Cookie ,瀏覽器最多存儲 4097個字大小的 Cookie)
- 共享數據時保存在瀏覽器中,容易造成數據的泄露,不安全
- 最好的解決方案:將數據保存在服務端(session)
Session 技術
Session:會話,從瀏覽器打開開始,直到瀏覽器關閉結束,無論在這個網站中訪問了多少頁面,點擊了多少鏈接,都屬於同一個會話。Session 也可以稱為會話 Cookie
- 特點:服務端技術,將數據保存在服務器
理解 Session
前面已經介紹了 Cookie 可以讓服務端程序跟蹤每個客戶端的訪問,但是每次客戶端的訪問都必須傳回這些 Cookie,如果 Cookie 很多,則無形增加了客戶端與服務端的數據傳輸量,而 Session 的出現正是為了解決這個問題。
同一個客戶端每次和服務端交互時,不需要每次都傳回所有的 Cookie 值,而是只要傳回一個 ID,這個 ID 就是客戶端第一次訪問服務器生成的,而且每個客戶端是唯一的。這樣每個客戶端就有了一個唯一的 ID,客戶端只要傳回這個 ID 就行了,這個 ID 通常是 NAME 為 JSESIONID 的一個 Cookie。
Session 基本操作
- 獲取 Session 對象
request對象.getSession()
和參數為true的一樣
request對象.getSession(true)
獲取Session對象,如果沒有Session對象,直接創建一個新的返回,缺省值
request對象.getSession(false)
獲取Session對象,如果沒有返回null - 設置共享數據
Session對象.setAttribute(String name, Object value)
- 注意:Session 可以存儲任何類型的數據,比如登陸用戶的信息,可以封裝到User對象中
-
修改共享數據
重新設置一個同名的共享數據 -
獲取共享數據
Object value = Session對象.getAttribute(String name);
- 刪除 Session 中的共享數據
Session對象.removeAttribute(String name);
- 銷毀 Session
void invalidate()
- Session 的超時管理
- 超時:在訪問當前的資源的過程中,不和網頁進行任何的交互,超過設定的時間就是超時
在 Tomcat 服務器中有默認的配置為30分鍾,一般不需要去修改 - 語法:
void setMaxInactiveInterval(int interval)
Session 擴展
- Seesion 中的共享數據的屬性名的命名規范:
通常為:XXX_IN_SESSION,例如:Session對象.setAttribute(“USER_IN_SESSION”,user)
- 序列化與反序列化:
Session 中存儲的對象通常需要實現序列化接口,因為在網絡之間傳輸的數據格式為二進制數據:- 序列化:將對象轉換成二進制數據
- 反序列化:將二進制數據轉換成對象
- URL 重寫
出現的問題:
當瀏覽器禁用Cookie之后,那么我們的jsessionid就不能在瀏覽器中保存,那么后面的請求中就不會將 jsessionid 發送到服務器,服務器這面就找不到數據
解決方案:
1.在url后手動的拼接上 jsessionid
傳遞格式如/path/Servlet;jsessionid=sessionid
2.使用響應對象中的encodeURL(String path)實現 jsessionid 的自動拼接
String path = resp.encodeURL("path/Servlet");
- 推薦方式:②
歡迎轉載,轉載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關注公眾微信號:wmyskxz_javaweb
分享自己的Java Web學習之路以及各種Java學習資料