servlet之cookie簡介_動力節(jié)點Java學院整理
首先來了解什么是“會話”。會話是web技術中的一個術語,可以簡單的理解為:用戶打開一個瀏覽器,點擊多個超鏈接,訪問服務器多個web資源,然后關閉瀏覽器,這個過程稱為一個會話。
如果在打開一個瀏覽器訪問一個頁面后,再打開一個瀏覽器訪問同一個頁面,那這就是有兩個會話;而打開一個瀏覽器訪問一個頁面后,通過這個頁面上的某個超鏈接是從新的瀏覽器打開的,那依然只算一個會話。
每個用戶在使用瀏覽器與服務器進行會話的過程中,各自不可避免地會產(chǎn)生一些數(shù)據(jù),而程序要想辦法為每個用戶保存這些數(shù)據(jù)。比如,用戶點擊超鏈接通過一個產(chǎn)品Servlet購買了一個商品,程序應該想辦法保存這個商品,以便于用戶在點擊付款超鏈接時能再從付款Servlet中看到這個商品并為其買單。
使用Request對象是無法保存數(shù)據(jù)的,因為在點擊商品和付款各自的Servlet是發(fā)送兩個不同的Request請求對象,而使用ServletContext對象則會發(fā)生多個用戶的線程安全問題,使用轉發(fā)功能理論上可行,但是用戶體驗將會大打折扣,每次點擊一個商品就會被要求付款。所以根據(jù)以上的需求,有兩種技術來保存會話過程中產(chǎn)生的數(shù)據(jù):一個是Cookie,一個是Session,Session技術將會在之后的篇章中介紹學習。
本篇主要先講述Servlet中的Cookie技術。Cookie技術是客戶端技術,程序把每個用戶的數(shù)據(jù)以cookie的形式寫給用戶各自的瀏覽器。當用戶使用瀏覽器再去訪問服務器時,就會帶著各自的數(shù)據(jù)過去,這樣web服務器處理的就是用戶各自的數(shù)據(jù)了。
下圖是一個會話過程中設置上一次訪問時間的Cookie的簡單過程:
創(chuàng)建一個Cookie對象就像平常創(chuàng)建一個Java對象一樣簡單:
在使用構造器時傳入Cookie的名和值這樣的鍵值對即可,我們在服務器端要獲取從瀏覽器發(fā)來的Cookie數(shù)據(jù)可以使用請求對象的request.getCookies方法獲得一個Cookie數(shù)組,而我們想向瀏覽器輸出Cookie時可以使用響應對象的response.addCookie(Cookie)方法。
同時Cookie對象還有如下一些方法:
getName方法用來獲取某個Cookie對象的名稱。
setValue方法和getValue方法分別用來設置和獲取某個Cookie對象的值。
setMaxAge(int expires)方法是設置Cookie的有效期,如果沒有這句代碼,Cookie的有效期就是一個會話時間(即關閉瀏覽器該Cookie就不存在了),當設置了Cookie的有效期后,Cookie會保存在瀏覽器指定的硬盤文件中,同時在這段時間內,每次訪問服務器都會帶著Cookie過去。如果將該方法參數(shù)置為“0”,則服務器會指示瀏覽器刪除該Cookie。
setPath方法是設置Cookie的有效路徑。表示在訪問某些特定URL時才會帶Cookie過去。假設某個web應用為【myservlet】,如果我們將setPath方法中的參數(shù)設置為“/myservlet”,那么訪問該web應用下所有的資源都會使瀏覽器發(fā)送Cookie過去;而如果我們將setPath方法中的參數(shù)設置為“/myservlet/pages”,那么只有訪問該web應用中的【pages】下的資源才會帶Cookie過去,而訪問該web應用中的其他資源則不會帶Cookie給服務器。如果我們沒有設置setPath方法,那么該Cookie的有效路徑默認為創(chuàng)建Cookie對象的當前程序所在目錄。注意,Cookie的路徑是給瀏覽器使用的(詳見《Servlet的學習之web路徑問題》)
setDomain方法是設置Cookie的有效域名,如: .sina.com(注意最前面有一個點)。表示當瀏覽器訪問該域名時才會帶Cookie過去。但是現(xiàn)在瀏覽器基本全面阻止了這個可能作為不安全的功能,所以幾乎已經(jīng)被棄用。
舉例:我們訪問某個Servlet,而在訪問這個Servlet時會將當前訪問時間作為Cookie中的值返回給客戶端,同時下次再次訪問該Servlet時,會顯示上一次客戶端來訪問的時間:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("您上次訪問的時間是:");
//獲取用戶上一次的訪問時間并顯示
Cookie[] cookies = request.getCookies(); //從請求中獲取客戶端發(fā)來的Cookie
for(int i=0;cookies!=null && i<cookies.length;i++) {
if(cookies[i].getName().equals("lastAccessTime")) { //獲取最后訪問時間的Cookie
Long mTime = Long.parseLong(cookies[i].getValue());
String lastAccessTime = new Date(mTime).toLocaleString();
writer.write(lastAccessTime);
}
}
//將本次登錄時間重新裝載進Cookie中并返回給客戶端
Cookie timeCookie = new Cookie("lastAccessTime", System.currentTimeMillis()+"");
timeCookie.setMaxAge(1*24*60*60); //將Cookie有效期置為一天
response.addCookie(timeCookie); //將Cookie傳回客戶端
}
第一次訪問是沒有Cookie的,所以看不到訪問時間:
但是我們通過HttpWatch觀察Response響應包中的內容已經(jīng)有了“Set-Cookie”響應頭:
刷新后的第二次訪問就可以看到了:
同時觀察HttpWatch中Request請求包的“Cookie”請求頭可以發(fā)現(xiàn):
現(xiàn)在我們再來通過一個案例來學習Cookie,這是一個很常見的案例,比如我們在訪問購物網(wǎng)站的時候經(jīng)常會發(fā)現(xiàn)當瀏覽了這個網(wǎng)站內的某個商品的時候,下次繼續(xù)來訪問這個網(wǎng)站,會有一個上次瀏覽物品的顯示。
如果我們不是用登錄后將記錄保存在服務器端,而是使用Cookie技術來將記錄保存在客戶端的瀏覽器中(現(xiàn)實生活中當然很少這樣使用,這里只是作為案例學習),那么我們應該怎么做呢?
首先我們必須在服務器要有兩個Servlet,一個在用戶眼中是用來顯示所有商品的,一個是用來顯示點擊某個商品之后詳細信息的。
⑴.用來顯示所有商品的Servlet需要完成如下功能:
?、?nbsp; 在一個部分以超鏈接形式將數(shù)據(jù)庫中所有的商品顯示在該Servlet上。
?、?nbsp; 在另一個部分獲取用戶請求中的Cookie將之前瀏覽過的商品(通過Cookie中的商品id)顯示在該Servlet上。
?、? 用來顯示點擊某個商品之后詳細信息的Servlet需要完成如下功能:
① 在頁面上通過超鏈接的URL跟隨的參數(shù)(即商品id)來獲取該商品對象,同時將該商品對象的詳細信息輸出到Servlet頁面上。
?、?nbsp; 如果是用戶首次訪問,將用戶瀏覽商品的id作為Cookie直接返回,而如果是用戶再次訪問,則需要根據(jù)一定的條件來將這些Cookie的值進行調整,以便易于顯示和滿足用戶體驗。
當然,在這之前我們還需要做些準備工作,我們需要建立商品對象,這里簡單的以書為商品建立對象:
public class Product {
private String id;
private String name;
private String author;
public Product() {
super();
}
public Product(String id, String name, String author) {
super();
this.id = id;
this.name = name;
this.author = author;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
我們還需要一個數(shù)據(jù)庫來保存商品,這里我們先用一個類來來保存(數(shù)據(jù)庫還沒學嘛T_T?。4鏀?shù)據(jù)采用Map集合,這是因為如果有檢索會方便:
public class ProductDatabase {
private static Map<String,Product> map = new HashMap<String, Product>();
static{
map.put("1", new Product("1","《Java編程思想》","JB"));
map.put("2", new Product("2","《Java核心技術》","fdaf"));
map.put("3", new Product("3","《Java并發(fā)編程》","什么鬼"));
map.put("4", new Product("4","《Head first 設計模式》","老王"));
map.put("5", new Product("5","《HTML5權威手冊》","hhaa"));
}
public static Map<String,Product> getMap() {
return map;
}
}
做完了這兩步,那么我們可以安心的去搞Servlet了,首先是在顯示所有商品的Servlet:
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//從數(shù)據(jù)庫中取出要顯示在購物網(wǎng)站首頁的商品
Map<String,Product> map = ProductDatabase.getMap();
if(map == null) {
writer.print("您訪問的寶貝已下架");
return ;
}
for(Map.Entry<String, Product> en : map.entrySet()) {
writer.print("<a href='/CookieProductProject/servlet/DetailGoodServlet?id="+en.getKey()+"' target='_blank' >"
+en.getValue().getName()+" <br/>");
}
//顯示用戶之前瀏覽過的商品,要從用戶發(fā)送的請求中的Cookie里取得
writer.print("<br/><br/>");
writer.print("您最近瀏覽過的商品: <br/>");
Cookie[] cookies = request.getCookies();
for(int i=0;cookies!=null && i<cookies.length;i++ ) {
if(cookies[i].getName().equals("productHistory")) {
Cookie cookie = cookies[i];
String productId = cookie.getValue();
String[] splitId = productId.split("\\_");
for(String sId:splitId) {
Product book = ProductDatabase.getMap().get(sId);
writer.print(book.getName()+"<br/>");
}
}
}
}
最后是點擊某個商品顯示詳細信息的Servlet:
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
//通過用戶點擊商品的超鏈接而跟隨URL來的ID參數(shù)來獲取商品的詳細信息
String productId = request.getParameter("id");
Map<String, Product> map = ProductDatabase.getMap();
Product book = map.get(productId);
writer.print("商品名:"+book.getName()+"<br />");
writer.print("作者:"+book.getAuthor());
//同時通過Cookie將用戶觀看的商品以Cookie的形式回傳給用戶瀏覽器
Cookie[] allCookies = request.getCookies();
Cookie cookie = creCookie(book.getId(),allCookies);
cookie.setMaxAge(24*60*60);
response.addCookie(cookie);
其中creCookie(String,Cookie[])是自定義方法,用于獲取用戶的cookie并添加本次瀏覽商品id再作為cookie返回:
private Cookie creCookie(String id, Cookie[] cookies) {
Cookie cookie = null;
if(cookies == null) { //如果cookies為空,說明用戶首次訪問
cookie = new Cookie("productHistory", id);
System.out.println(cookie.getValue());
return cookie;
}
for(int i=0; i<cookies.length; i++) {
if(cookies[i].getName().equals("productHistory")){
cookie = cookies[i];
}
}
String historyStr = cookie.getValue(); //此時獲取到的之前瀏覽過數(shù)據(jù)的歷史記錄,有多種情況
String[] produIds = historyStr.split("\\_");
//為了檢測數(shù)組中是否有包含當前的id,建議使用集合,而且是使用鏈表結構的集合
LinkedList<String> list = new LinkedList<String>(Arrays.asList(produIds));
if(list.contains(id)) {
list.remove(id);
}
else if(list.size()>=3){
list.removeLast();
}
list.addFirst(id);
StringBuilder sb = new StringBuilder();
for(String sId :list) {
sb.append(sId+"_");
}
sb.deleteCharAt(sb.length()-1);
cookie.setValue(sb.toString());
System.out.println(cookie.getValue());
return cookie;
}
我們在瀏覽器中進行首次訪問:
隨便點擊個連接,可以看到該商品的詳細信息(其實瀏覽器也偷偷將該商品的id以cookie傳回了瀏覽器):
我們訪問商品顯示頁面再次【刷新】就可以看到剛才瀏覽過的商品了:
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- 如何使用會話Cookie和Java實現(xiàn)JWT身份驗證
- Java后端Cookie實現(xiàn)(時間戳)代碼實例
- Java接口測試Cookie與token原理解析
- Java 模擬cookie登陸簡單操作示例
- 在java中http請求帶cookie的例子
- Java 對 Cookie增刪改查的實現(xiàn)示例
- Java Web學習之Cookie和Session的深入理解
- java使用Cookie判斷用戶登錄情況的方法
- JavaWeb 中Cookie實現(xiàn)記住密碼的功能示例
- java中Servlet Cookie取不到值原因解決辦法
- JavaWeb使用Session和Cookie實現(xiàn)登錄認證
- Cookie在Java中的使用
相關文章
java微信公眾號開發(fā)(搭建本地測試環(huán)境)
這篇文章主要介紹了java微信公眾號開發(fā),主要內容有測試公眾號與本地測試環(huán)境搭建,需要的朋友可以參考下2015-12-12
Java之Springcloud Gateway內置路由案例講解
這篇文章主要介紹了Java之Springcloud Gateway內置路由案例講解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-08-08
Spring事務處理Transactional,鎖同步和并發(fā)線程
本文詳細講解了Spring事務處理Transactional,鎖同步和并發(fā)線程。對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-12-12
Java import static及import原理區(qū)別解析
這篇文章主要介紹了Java import static及import原理區(qū)別解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10

