搜索
首页Javajava教程Java中关于servlet之cookie的简单介绍(图文)

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
Java中'类::实例方法”方法引用如何正确理解和应用?Java中'类::实例方法”方法引用如何正确理解和应用?Apr 19, 2025 pm 03:39 PM

Java方法引用“类::实例方法”的疑惑解答在Java编程中,方法引用是一种简洁而强大的功能,它允许开发者通过�...

Spring Boot异步任务中,子线程如何访问主线程的Request信息?Spring Boot异步任务中,子线程如何访问主线程的Request信息?Apr 19, 2025 pm 03:36 PM

SpringBoot项目中子线程无法访问主线程Request信息的问题及解决方案在Spring...

如何在Java中动态配置实体类注解参数以适应不同环境?如何在Java中动态配置实体类注解参数以适应不同环境?Apr 19, 2025 pm 03:33 PM

如何在Java中动态配置实体类注解参数在开发过程中,常常会遇到需要根据不同环境动态配置参数的问题。特别�...

如何确保Spring Retry的@Retryable注解中自定义监听器仅在指定时被调用?如何确保Spring Retry的@Retryable注解中自定义监听器仅在指定时被调用?Apr 19, 2025 pm 03:30 PM

使用SpringRetry的@Retryable注解时如何正确指定自定义监听器在使用Spring...

如何在SpringBoot中使用@RequestBody注解正确接收非JSON格式的字符串参数?如何在SpringBoot中使用@RequestBody注解正确接收非JSON格式的字符串参数?Apr 19, 2025 pm 03:27 PM

在SpringBoot中使用@RequestBody注解接收非JSON格式的字符串参数在SpringBoot开发中,我们经常使用@RequestBody注解来处理...

如何优化热点数据的筛选以提高数据同步效率?如何优化热点数据的筛选以提高数据同步效率?Apr 19, 2025 pm 03:24 PM

热点数据筛选优化策略的探讨在处理数据同步时,如何有效地筛选热点数据是一个关键问题。我们的场景是:上...

Nacos注册中心下,OpenFeign如何实现跨命名空间服务调用?Nacos注册中心下,OpenFeign如何实现跨命名空间服务调用?Apr 19, 2025 pm 03:21 PM

Nacos注册中心与OpenFeign跨命名空间服务调用本文探讨在使用Nacos作为注册中心的情况下,OpenFeign能否实现不同命�...

在使用Netty4开发WebSocket服务器时,如何确保浏览器正确识别401响应?在使用Netty4开发WebSocket服务器时,如何确保浏览器正确识别401响应?Apr 19, 2025 pm 03:18 PM

使用Netty4开发WebSocket服务器时,如何让浏览器正确识别401响应?在使用Netty开发WebSocket服务器时,经常会遇到需�...

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中