Cookie作为一个客户端技术被广泛的应用着。我今天也来谈一谈我对Cookie的理解。

先来一个小菜(实现“上次登录时间”)


具体的思路如下:

  • 通过request.getCookies()方法找到目标Cookie,然后获取内容
  • 将最新的时间记录存储到Cookie中,并进行更新的操作

    下面是详细的代码:
package cookie;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class MyCookieDemo
 */
@WebServlet("/MyCookieDemo")
public class MyCookieDemo extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public MyCookieDemo() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());

        response.setContentType("text/html;charset=UTF-8");

        PrintWriter writer = response.getWriter();
        writer.write("<br>这是网站首页!<br/><br/>");
        writer.write("您上次的访问时间是:");
        //得到上次访问的时间
        Cookie [] cookies = request.getCookies();
        for(int i=0; cookies!=null&&i<cookies.length;i++){
            Cookie cookie = cookies[i];
            if(cookie.getName().equals("lastAccessTime")){
                Long time = Long.parseLong(cookie.getValue());
                Date date = new Date(time);
                writer.write(date.toLocaleString());

            }
        }

        //给用户以cookie的形式发送更新过的时间
        Cookie cookie = new  Cookie("lastAccessTime",System.currentTimeMillis()+"");
        response.addCookie(cookie);

    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

需要注意的是以下问题:

  • 有中文出现时记得使用response.setContentType("text/html;charset=UTF-8");
  • 获得Cookie是获取了一个cookie的数组,我们需要找出符合名字的目标Cookie才能对其进行操作
  • 更新数据需要调用response.addCookie(targetCookie);即可

Cookie实例(显示用户浏览商品记录)


说是商品记录,这里只是一个简单的示意,所以并没有连接数据库进行相关的操作,而是利用一个DB类进行了模拟。下面是我的思路:


商品首页:

  • 首先是要显示网站上所拥有的商品的名称,用户可以通过点击超链接浏览商品的详细的信息
  • 显示用户的商品浏览记录(tongguo cookie 进行实现)

商品的详细的信息界面:

  • 首先是从超链接中获取到用户点击的商品的id,然后通过这个id 来从模拟的数据库中获得商品的详细的信息。
  • 更新用户的商品浏览历史信息(这里发生的情况较为的复杂,详见代码中的注释信息)

下面是代码详情:

首先是WebTitle.java(实际是一个Servlet文件):

package lastskim;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class WebTitle
 */
@WebServlet("/WebTitle")
public class WebTitle extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public WebTitle() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=UTF-8");
        //1.显示所有的商品信息
        PrintWriter out = response.getWriter();
        out.write("本网站有如下商品,任君挑选:"+"<br><br>");

        Set<Map.Entry<String , Item>> set = DB.getItems().entrySet();
        for(Map.Entry<String, Item> me: set){
            Item item = me.getValue();
            out.write("<a href='/ServletStudy/ItemInfo?id="+item.getId()
            +"' target='_blank'>"+item.getName()+"</a>");
            out.write("<br>");
        }

        //2.显示已经浏览过的商品的信息
        out.write("<br>您曾经浏览过的商品的信息如下:<br><br>");
        Cookie [] cookies = request.getCookies();
        for(int i=0 ;cookies!=null && i<cookies.length;i++){
            Cookie cookie = cookies[i];
            if(cookie.getName().equals("itemHistory")){
                String itemHistory = cookie.getValue();
                //使用正则表达式,确保以下划线进行分割!
                String[] ids = itemHistory.split("\\_");
                for(String id : ids){
                    Item item = (Item) DB.getItems().get(id);
                    out.write(item.getName()+"<br>");
                }
            }
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

//模拟数据库进行加载商品信息
class DB {
    private static Map<String ,Item> map = new LinkedHashMap<String ,Item>();

    //由于需要在初始化的时候进行加载数据,所以在同步的静态的代码块中进行声明即可
    static{
        map.put("1", new Item("1","C语言入门","小郭","19$"));
        map.put("2", new Item("2","C++语言入门","赵老师","21$"));
        map.put("3", new Item("3","Java语言入门","Jemas","32$"));
        map.put("4", new Item("4","JUnit","Juit","12$"));
        map.put("5", new Item("5","PHP","老毛","32$"));
        map.put("6", new Item("6","JavaScript","阿布","27$"));
    }

    public static Map getItems(){
        return map;
    }
}

//模拟的商品Item信息
class Item {
    private String id;
    private String name;
    private String author;
    private String price;

    public Item() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Item(String id, String name, String author, String price) {
        super();
        this.id = id;
        this.name = name;
        this.author = author;
        this.price = price;
    }
    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;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }

}

注意:

  • 里面有bean层(item),数据库操作层(DB),和界面显示View层
  • 注意超链接的写法,是服务器内部进行的跳转,所以应该用网站目录进行使用

然后是商品详情界面:

package lastskim;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ItemInfo
 */
@WebServlet("/ItemInfo")
public class ItemInfo extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ItemInfo() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=UTF-8");
        //1.根据用户带过来的id号,现实上皮的详细的信息
        String id  = request.getParameter("id");
        Item item = (Item) DB.getItems().get(id);

        PrintWriter out = response.getWriter();
        out.write("<br>您所浏览的商品的详细的信息如下:<br>");
        out.write(item.getId()+"<br>");
        out.write(item.getName()+"<br>");
        out.write(item.getAuthor()+"<br>");
        out.write(item.getPrice()+"<br>");

        //2.将更新的cookie信息写回到原来的Cookie中
        String itemHistory = makeItemHistory(request, id);
        Cookie cookie = new Cookie("itemHistory",itemHistory);
        response.addCookie(cookie);
    }

    private String makeItemHistory(HttpServletRequest request, String id) {
        // TODO Auto-generated method stub
        String itemHistory =null;

        Cookie cookies[] = request.getCookies();
        for(int i=0 ;cookies!=null && i<cookies.length;i++){
            if(cookies[i].getName().equals("itemHistory")){
                itemHistory = cookies[i].getValue();
            }
        }

        //一般来说在浏览记录中添加数据呼吁道如下几种情况
        //itemHistory= null         1    itemHistory = 1
        //超过了一页显示的最大个数 :itemHistory= 2_3_4         1    itemHistory = 1_2_3
        //itemHistory= 2_3_4         1    itemHistory = 1_2_3
        //itemHistory= 2_1_4         1    itemHistory = 1_2_4

        //itemHistory= null         1    itemHistory = 1
        if(itemHistory== null){

            return id;
        }

        //这个代码块的作用是分解出一个个的信息,并用于字符串内容的验证
        List l = (List) Arrays.asList(itemHistory.split("\\_"));
        LinkedList<String> list = new LinkedList();
        list.addAll(l);

        if(list.contains(id)){
            list.remove(id);
            list.addFirst(id);
        }else{
            //超过了一页显示的最大个数 :itemHistory= 2_3_4         1    itemHistory = 1_2_3
            if(list.size()>=3){
                list.removeLast();
                list.addFirst(id);
            }else{
                //未超过一页显示的最大个数 :itemHistory= 2_3         1    itemHistory = 1_2_3
                list.addFirst(id);
            }
        }

        StringBuilder sb = new StringBuilder();
        for(String listId : list){
            sb.append(listId+"_");
        }

        return sb.deleteCharAt(sb.length()-1).toString();
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

总结:

  • 含金量第一层就是makeItemHistory方法,其处理了开发中可能遇到的很多的信息。
  • LinkedList的使用是为了判断分解后的元素列表中是否有正在访问的id信息

下面是代码的测试结果:

第一次访问网站:

第一次点击超链接可以看到商品的详细的信息

第二次点击超链接返回后,刷新首页即可看到商品浏览的历史

第三次点击超链接后就达到了商品历史记录的上限

第四次访问后,返回首页,刷新一下,便会将第一次的浏览历史记录去除,添加上最新的浏览记录

在包含有三个历史记录中访问了其中一个,便会更新历史记录的顺序:


总结:

  • Cookie技术应用到的地方很广泛,应该对其进行更加灵活的研究
  • 上述案例应该加上cookie生存期限。否则用户退出后就会清空cookie的历史记录

Cookie 进阶的更多相关文章

  1. javascript 进阶篇1 正则表达式,cookie管理,userData

    首先,什么事正则表达式呢,其实引入概念很多时候并不能帮我们明白它到底是什么,所以我先简单描述下,正则表达式,其实就是一个记录字符串规则则的字符串,等我们看完这一部分,也就能明白它到底是什么了. 基本语 ...

  2. 进阶——scrapy登录豆瓣解决cookie传递问题并爬取用户参加过的同城活动©seven_clear

    最近在用scrapy重写以前的爬虫,由于豆瓣的某些信息要登录后才有权限查看,故要实现登录功能.豆瓣登录偶尔需要输入验证码,这个在以前写的爬虫里解决了验证码的问题,所以只要搞清楚scrapy怎么提交表单 ...

  3. (进阶篇)浅谈COOKIE和SESSION关系和区别

    COOKIE介绍 cookie 常用于识别用户.cookie 是服务器留在用户计算机中的小文件.每当相同的计算机通过浏览器请求页面时,它同时会发送 cookie.通过 PHP,您能够创建并取回 coo ...

  4. (进阶篇)Cookie与 Session使用详解

    1.Cookie和Session简介与区别 在非常多时候,我们需要跟踪浏览者在整个网站的活动,对他们身份进行自动或半自动的识别(也就是平时常说的网站登陆之类的功能),这时候,我们常采用Cookie与 ...

  5. AngularJS进阶(十五)Cookie 'data' possibly not set or overflowed because it was too large

    Cookie 'data' possibly not set or overflowed because it was too large (5287 > 4096 bytes)! 注:请点击此 ...

  6. 性能测试六:jmeter进阶之Cookie与header管理器

    一.http cookie管理器 可以在浏览器中抓取到cookie信息,然后通过http cookie管理器为http请求添加cookie信息 添加cookie管理器后,Jmeter可以自动处理coo ...

  7. Django进阶(路由系统、中间件、缓存、Cookie和Session、Ajax发送数据

    路由系统 1.每个路由规则对应一个view中的函数 url(r'^index/(\d*)', views.index), url(r'^manage/(?P<name>\w*)/(?P&l ...

  8. 【JavaScript-基础-cookie从入门到进阶】

    cookie 关于cookie 用于方便服务端管理客户端状态提出的一种机制. document.cookie 客户端JavaScript可通过document.cookie方式获取非HTTPOnly状 ...

  9. django 2 ORM操作 ORM进阶 cookie和session 中间件

    ORM操作 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...

随机推荐

  1. Python【第三课】 函数基础

    本篇内容 函数基本语法及特性 嵌套函数 递归函数 匿名函数 高阶函数 内置函数 1.函数的基本语法及特性 1.1 函数概念 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提 ...

  2. Python【第一课】 Python简介和基础

    本节内容 Python安装(windows) 第一个程序(windows中的python) 变量 字符编码 注释 用户输入 模块初步认识 数据类型 数据运算 表达式if...else 表达式for l ...

  3. 一个使用 Python 的人工智能聊天机器人框架

    一个Python 的 AI Chatbot框架 建立一个聊天室可以听起来很棒,但它是完全可行的. IKY是一个内置于Python中的AI动力对话对话界面. 使用IKY,很容易创建自然语言会话场景,无需 ...

  4. Windows 2008 R2_NLB网络负载均衡(图文详解)(转)

    目录 前言 软件环境 DNS域名服务器 DNS服务器原理 DNS域名空间 DNS区域 DNS服务器的类别 DNS查询模式 缓存文件 配置DNS服务器 DNS服务的应用 新建子域 在DNS正向解析中新建 ...

  5. Dynamic Web Module 3.0 requires Java 1.6 or newer.的解决

    在项目的pom.xml增加 <build> <finalName>xxxxxxxx</finalName> <plugins> <plugin&g ...

  6. manjaro备忘录

    updated 2018/4/3 manjaro 使用Linux发行版时需要注意几个方面的问题: 包管理器 包管理器无疑时各家发行版的最大特色之一.软件同时也是一个平台是否能够产生足够的吸引力的来源之 ...

  7. Java面试18|关于进程、线程与协程

    1.IPC(Inter-Process Communication,进程间通信)与线程通信的几种方式 # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进 ...

  8. leetcode刷题笔记231 2的幂

    题目描述: 给定一个整数,写一个函数来判断它是否是2的幂. 题目分析: 判断一个整数是不是2的幂,可根据二进制来分析.2的幂如2,4,8,等有一个特点: 二进制数首位为1,其他位为0,如2为10,4为 ...

  9. Jmeter(二)_基础元件

    测试计划(Test Plan) 它用来描述一个测试方案,包含与本次性能测试所有相关的功能.也就说本次测试的所有内容是于基于一个计划的. "函数测试模式"复选框,如果被选择,它会使J ...

  10. 【java集合系列】---HashSet

    在前面的博文中,小编主要简单介绍了java集合中的总体框架,以及list接口中典型的集合ArrayList和LinkedList,接着,我们来看set的部分集合,set集合和数学意义上的集合没有差别, ...