首頁  >  文章  >  Java  >  Java中關於servlet之cookie的簡單介紹(圖文)

Java中關於servlet之cookie的簡單介紹(圖文)

黄舟
黄舟原創
2017-07-26 15:06:061640瀏覽

Cookie技術誕生以來,它就成了廣大網路使用者和Web開發人員爭論的一個焦點。以下這篇文章主要為大家介紹了關於servlet之cookie簡介的相關資料,文中介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。

  首先來了解什麼是「會話」。會話是web技術中的一個術語,可以簡單的理解為:用戶打開一個瀏覽器,點擊多個超鏈接,訪問伺服器多個web資源,然後關閉瀏覽器,這個過程稱為一個會話。

  如果在開啟一個瀏覽器造訪一個頁面後,再開啟一個瀏覽器造訪同一個頁面,那麼這就是有兩個會話;而開啟一個瀏覽器造訪一個頁面後,透過這個頁面上的某個超連結是從新的瀏覽器開啟的,那依然只算一個會話。

  每個使用者在使用瀏覽器與伺服器進行會話的過程中,各自不可避免地會產生一些數據,而程式要想辦法為每個使用者保存這些資料。例如,用戶點擊超連結透過一個產品Servlet購買了一個商品,程式應該想辦法保存這個商品,以便於用戶在點擊付款超連結時能再從付款Servlet中看到這個商品並為其買單。

  使用Request對像是無法保存資料的,因為在點擊商品和付款各自的Servlet是發送兩個不同的Request請求對象,而使用ServletContext對象則會發生多個用戶的線程安全問題,使用轉發功能理論上可行,但使用者體驗將會大打折扣,每次點擊一個商品就會被要求付款。所以根據以上的需求,有兩種技術來保存會話過程中產生的資料:一個是Cookie,一個是Session,Session技術將會在之後的篇章中介紹學習。

  本篇主要先講述Servlet中的Cookie技術。 Cookie技術是客戶端技術,程式把每個使用者的資料以cookie的形式寫給使用者各自的瀏覽器。當使用者使用瀏覽器再去存取伺服器時,就會帶著各自的資料過去,這樣web伺服器處理的就是使用者各自的資料了。

下圖是一個會話過程中設定上一次存取時間的Cookie的簡單過程:

#  

建立一個Cookie物件就像平常會建立一個Java對象一樣簡單:

  

在使用建構器時傳入Cookie的名稱和值這樣的鍵值對即可,我們在伺服器端要取得從瀏覽器發送的Cookie資料可以使用請求物件的request.getCookies方法來取得一個Cookie數組,而我們想向瀏覽器輸出Cookie時可以使用回應物件的response.addCookie(Cookie)方法。

同時Cookie物件還有以下一些方法:

  

#  getName方法用來取得某個Cookie物件的名稱。

  setValue方法和getValue方法分別用來設定和取得某個Cookie物件的值。

  setMaxAge(int expires)方法是設定Cookie的有效期限,如果沒有這句程式碼,Cookie的有效期限就是一個會話時間(即關閉瀏覽器該Cookie就不存在了),當設定了Cookie的有效期限後,Cookie會保存在瀏覽器指定的硬碟檔案中,同時在這段時間內,每次存取伺服器都會帶著Cookie過去。如果將該方法參數置為“0”,則伺服器會指示瀏覽器刪除該Cookie。

  setPath方法是設定Cookie的有效路徑。表示在存取某些特定URL時才會帶Cookie過去。假設某個web應用為【myservlet】,如果我們將setPath方法中的參數設為“/myservlet”,那麼訪問該web應用下所有的資源都會使瀏覽器發送Cookie過去;而如果我們將setPath方法中的參數設定為“/myservlet/pages”,那麼只有存取該web應用程式中的【pages】下的資源才會帶Cookie過去,而存取該web應用程式中的其他資源則不會帶Cookie給伺服器。如果我們沒有設定setPath方法,那麼該Cookie的有效路徑預設為建立Cookie物件的目前程式所在目錄。請注意,Cookie的路徑是給瀏覽器使用的(詳見《Servlet的學習之web路徑問題》)

  setDomain方法是設定Cookie的有效域名,如:.sina.com(注意最前面有一個點)。表示當瀏覽器造訪該網域時才會帶Cookie過去。但是現在瀏覽器基本上全面阻止了這個可能作為不安全的功能,所以幾乎已經被棄用。 

  举例:我们访问某个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();   //从请求中获取客户端发来的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响应包中的内容已经有了“Set-Cookie”响应头:

  

刷新后的第二次访问就可以看到了:

  

同时观察HttpWatch中Request请求包的“Cookie”请求头可以发现:

  

  现在我们再来通过一个案例来学习Cookie,这是一个很常见的案例,比如我们在访问购物网站的时候经常会发现当浏览了这个网站内的某个商品的时候,下次继续来访问这个网站,会有一个上次浏览物品的显示。

  如果我们不是用登录后将记录保存在服务器端,而是使用Cookie技术来将记录保存在客户端的浏览器中(现实生活中当然很少这样使用,这里只是作为案例学习),那么我们应该怎么做呢?

  首先我们必须在服务器要有两个Servlet,一个在用户眼中是用来显示所有商品的,一个是用来显示点击某个商品之后详细信息的。

  ⑴.用来显示所有商品的Servlet需要完成如下功能:

   ①     在一个部分以超链接形式将数据库中所有的商品显示在该Servlet上。

   ②     在另一个部分获取用户请求中的Cookie将之前浏览过的商品(通过Cookie中的商品id)显示在该Servlet上。

  ⑵.   用来显示点击某个商品之后详细信息的Servlet需要完成如下功能:

   ①     在页面上通过超链接的URL跟随的参数(即商品id)来获取该商品对象,同时将该商品对象的详细信息输出到Servlet页面上。

   ②     如果是用户首次访问,将用户浏览商品的id作为Cookie直接返回,而如果是用户再次访问,则需要根据一定的条件来将这些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;
 }
}

我们还需要一个数据库来保存商品,这里我们先用一个类来来保存(数据库还没学嘛T_T!),保存数据采用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并发编程》","什么鬼"));
  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();
  //从数据库中取出要显示在购物网站首页的商品
  Map<String,Product> map = ProductDatabase.getMap();
  if(map == null) {
   writer.print("您访问的宝贝已下架");
   return ;
  }
  for(Map.Entry<String, Product> en : map.entrySet()) {
   writer.print("<a href=&#39;/CookieProductProject/servlet/DetailGoodServlet?id="+en.getKey()+"&#39; target=&#39;_blank&#39; >"
              +en.getValue().getName()+" <br/>");
  }
  
  
  //显示用户之前浏览过的商品,要从用户发送的请求中的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参数来获取商品的详细信息
  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(); //此时获取到的之前浏览过数据的历史记录,有多种情况
  String[] produIds = historyStr.split("\\_");
  
  //为了检测数组中是否有包含当前的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传回了浏览器):

  

我们访问商品显示页面再次【刷新】就可以看到刚才浏览过的商品了:

  

总结

以上是Java中關於servlet之cookie的簡單介紹(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn