Servlet第五篇【介紹會(huì)話技術(shù)粥庄、Cookie的API、詳解豺妓、應(yīng)用】

什么是會(huì)話技術(shù)

基本概念: 指用戶開(kāi)一個(gè)瀏覽器惜互,訪問(wèn)一個(gè)網(wǎng)站,只要不關(guān)閉該瀏覽器,不管該用戶點(diǎn)擊多少個(gè)超鏈接琳拭,訪問(wèn)多少資源训堆,直到用戶關(guān)閉瀏覽器,整個(gè)這個(gè)過(guò)程我們稱為一次會(huì)話.


為什么我們要使用會(huì)話技術(shù)白嘁?

會(huì)話跟蹤技術(shù)可以解決我們很多很多問(wèn)題坑鱼。

  • 在論壇登陸的時(shí)候,很多時(shí)候會(huì)有一個(gè)小框框問(wèn)你是否要自動(dòng)登陸,當(dāng)你下次登陸的時(shí)候就不用輸入密碼了
image
  • 根據(jù)我以前瀏覽過(guò)的商品鲁沥,猜我喜歡什么商品
image

Cookie

會(huì)話跟蹤技術(shù)有Cookie和Session呼股,Cookie技術(shù)是先出現(xiàn)的。我們先講Cookie技術(shù)吧画恰。

什么是Cookie

Cookie是由W3C組織提出彭谁,最早由netscape社區(qū)發(fā)展的一種機(jī)制

  • 網(wǎng)頁(yè)之間的交互是通過(guò)HTTP協(xié)議傳輸數(shù)據(jù)的,而Http協(xié)議是無(wú)狀態(tài)的協(xié)議允扇。無(wú)狀態(tài)的協(xié)議是什么意思呢缠局?一旦數(shù)據(jù)提交完后,瀏覽器和服務(wù)器的連接就會(huì)關(guān)閉考润,再次交互的時(shí)候需要重新建立新的連接甩鳄。
  • 服務(wù)器無(wú)法確認(rèn)用戶的信息,于是乎额划,W3C就提出了:給每一個(gè)用戶都發(fā)一個(gè)通行證妙啃,無(wú)論誰(shuí)訪問(wèn)的時(shí)候都需要攜帶通行證,這樣服務(wù)器就可以從通行證上確認(rèn)用戶的信息俊戳。通行證就是Cookie
image

Cookie的流程:瀏覽器訪問(wèn)服務(wù)器揖赴,如果服務(wù)器需要記錄該用戶的狀態(tài),就使用response向?yàn)g覽器發(fā)送一個(gè)Cookie抑胎,瀏覽器會(huì)把Cookie保存起來(lái)燥滑。當(dāng)瀏覽器再次訪問(wèn)服務(wù)器的時(shí)候,瀏覽器會(huì)把請(qǐng)求的網(wǎng)址連同Cookie一同交給服務(wù)器阿逃。

Cookie API

  • Cookie類用于創(chuàng)建一個(gè)Cookie對(duì)象
  • response接口中定義了一個(gè)addCookie方法铭拧,它用于在其響應(yīng)頭中增加一個(gè)相應(yīng)的Set-Cookie頭字段
  • request接口中定義了一個(gè)getCookies方法,它用于獲取客戶端提交的Cookie

常用的Cookie方法:

  • public Cookie(String name,String value)
  • setValue與getValue方法
  • setMaxAge與getMaxAge方法
  • setPath與getPath方法
  • setDomain與getDomain方法
  • getName方法

簡(jiǎn)單使用Cookie

  • 創(chuàng)建Cookie對(duì)象恃锉,發(fā)送Cookie給瀏覽器搀菩、

        //設(shè)置response的編碼
        response.setContentType("text/html;charset=UTF-8");

        //創(chuàng)建Cookie對(duì)象,指定名稱和值
        Cookie cookie = new Cookie("username", "zhongfucheng");

        //向?yàn)g覽器給一個(gè)Cookie
        response.addCookie(cookie);

        response.getWriter().write("我已經(jīng)向?yàn)g覽器發(fā)送了一個(gè)Cookie");

  • 瀏覽器本身沒(méi)有任何Cookie
image
  • 訪問(wèn)Servlet1破托,再回到文件夾中肪跋,還是沒(méi)有發(fā)現(xiàn)Cookie,這是為什么呢土砂?我明明向?yàn)g覽器發(fā)送了一個(gè)Cookie的州既。
  • 原來(lái)發(fā)送Cookie給瀏覽器是需要設(shè)置Cookie的時(shí)間的。在給瀏覽器之前萝映,設(shè)置一下Cookie的時(shí)間

        //設(shè)置Cookie的時(shí)間
        cookie.setMaxAge(1000);
  • 再次訪問(wèn)吴叶,已經(jīng)發(fā)現(xiàn)文件夾中多了個(gè)Cookie的文本了
image

Cookie細(xì)節(jié)

Cookie不可跨域名性

  • 很多人在初學(xué)的時(shí)候可能有一個(gè)疑問(wèn):在訪問(wèn)Servlet的時(shí)候?yàn)g覽器是不是把所有的Cookie都帶過(guò)去給服務(wù)器會(huì)不會(huì)修改了別的網(wǎng)站的Cookie
  • 答案是否定的序臂。Cookie具有不可跨域名性蚌卤。瀏覽器判斷一個(gè)網(wǎng)站是否能操作另一個(gè)網(wǎng)站的Cookie的依據(jù)是域名。所以一般來(lái)說(shuō),當(dāng)我訪問(wèn)baidu的時(shí)候造寝,瀏覽器只會(huì)把baidu頒發(fā)的Cookie帶過(guò)去磕洪,而不會(huì)帶上google的Cookie。

Cookie保存中文

  • 上面我們的例子保存的是英文字符诫龙,下面我們來(lái)看下保存中文字符會(huì)怎么樣析显。

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

        String name = "中國(guó)";
        Cookie cookie = new Cookie("country", name);
        cookie.setMaxAge(2000);
        response.addCookie(cookie);

        printWriter.write("我頒發(fā)了一個(gè)Cookie,值保存的是中文數(shù)據(jù)");
  • 訪問(wèn)Servlet1签赃,好吧谷异。出異常了!
image
  • 中文屬于Unicode字符锦聊,英文數(shù)據(jù)ASCII字符歹嘹,中文占4個(gè)字符或者3個(gè)字符,英文占2個(gè)字符孔庭。
  • 解決:Cookie使用Unicode字符時(shí)需要對(duì)Unicode字符進(jìn)行編碼尺上。

        //對(duì)Unicode字符進(jìn)行編碼
        Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
  • 再次訪問(wèn)Servlet1,已經(jīng)把Cookie成功頒發(fā)給瀏覽器了
image
image
  • 我們發(fā)現(xiàn)Cookie保存在硬盤的中文數(shù)據(jù)是經(jīng)過(guò)編碼的圆到,那么我們?cè)?strong>取出Cookie的時(shí)候要對(duì)中文數(shù)據(jù)進(jìn)行解碼

        Cookie[] cookies = request.getCookies();
        for (int i = 0; cookies != null && i < cookies.length; i++) {
            String name = cookies[i].getName();

            //經(jīng)過(guò)URLEncoding就要URLDecoding
            String value = URLDecoder.decode(cookies[i].getValue(), "UTF-8");

            printWriter.write(name + "------" + value);
        }
  • 取出存進(jìn)Cookie的值
image

Cookie的有效期

Cookie的有效期是通過(guò)setMaxAge()來(lái)設(shè)置的怎抛。

  • 如果MaxAge為正數(shù)瀏覽器會(huì)把Cookie寫到硬盤中芽淡,只要還在MaxAge秒之前马绝,登陸網(wǎng)站時(shí)該Cookie就有效【不論關(guān)閉了瀏覽器還是電腦】
  • 如果MaxAge為負(fù)數(shù)Cookie是臨時(shí)性的挣菲,僅在本瀏覽器內(nèi)有效富稻,關(guān)閉瀏覽器Cookie就失效了,Cookie不會(huì)寫到硬盤中白胀。Cookie默認(rèn)值就是-1椭赋。這也就為什么在我第一個(gè)例子中,如果我沒(méi)設(shè)置Cookie的有效期纹笼,在硬盤中就找不到對(duì)應(yīng)的文件纹份。
  • 如果MaxAge為0苟跪,則表示刪除該Cookie廷痘。Cookie機(jī)制沒(méi)有提供刪除Cookie對(duì)應(yīng)的方法,把MaxAge設(shè)置為0等同于刪除Cookie

Cookie的修改和刪除

  • 上面我們已經(jīng)知道了Cookie機(jī)制沒(méi)有提供刪除Cookie的方法件已。其實(shí)細(xì)心點(diǎn)我們可以發(fā)現(xiàn)笋额,Cookie機(jī)制也沒(méi)有提供修改Cookie的方法。那么我們怎么修改Cookie的值呢篷扩?
  • Cookie存儲(chǔ)的方式類似于Map集合兄猩,如下圖所示
image
  • Cookie的名稱相同,通過(guò)response添加到瀏覽器中,會(huì)覆蓋原來(lái)的Cookie枢冤。

  • 以country為名保存的是%E4%B8%AD%E5%9B%BD鸠姨,下面我再以country為名,把值改變一下淹真。

    image


        String name = "看完博客就點(diǎn)贊";

        //對(duì)Unicode字符進(jìn)行編碼
        Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
  • 再次查看Cookie的時(shí)候讶迁,值已經(jīng)改變了,但是文件還是那一份
image
  • 現(xiàn)在我要?jiǎng)h除該Cookie核蘸,把MaxAge設(shè)置為0巍糯,并添加到瀏覽器中即可

        String name = "看完博客就點(diǎn)贊";

        //對(duì)Unicode字符進(jìn)行編碼
        Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));

        //一定不要忘記添加到瀏覽器中
        cookie.setMaxAge(0);
        response.addCookie(cookie);

        printWriter.write("我刪除了該Cookie");
  • 訪問(wèn)Servlet,在硬盤已經(jīng)找不到Cookie的文件了客扎!
image
image
  • 注意:刪除祟峦,修改Cookie時(shí),新建的Cookie除了value徙鱼、maxAge之外的所有屬性都要與原Cookie相同宅楞。否則瀏覽器將視為不同的Cookie,不予覆蓋袱吆,導(dǎo)致刪除修改失敗咱筛!

  • 我們來(lái)試驗(yàn)一下把。


        String name = "看完博客就點(diǎn)贊";

        //對(duì)Unicode字符進(jìn)行編碼
        Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));

        //一定不要忘記添加到瀏覽器中
        cookie.setMaxAge(10000);
        response.addCookie(cookie);
image
  • 上面新建了一個(gè)Cookie杆故,我修改下Cookie的其他屬性迅箩,再刪除,看能否把Cookie刪除掉

        //一定不要忘記添加到瀏覽器中

        cookie.setPath("/ouzicheng");
        cookie.setMaxAge(0);
        response.addCookie(cookie);

        printWriter.write("刪除一個(gè)Cookie");
  • 結(jié)果Cookie還在硬盤中
image

Cookie的域名

Cookie的domain屬性決定運(yùn)行訪問(wèn)Cookie的域名处铛。domain的值規(guī)定為“.域名”

image
image

        Cookie cookie = new Cookie("name", "zhongfucheng");
        cookie.setMaxAge(1000);
        response.addCookie(cookie);

        printWriter.write("使用www.zhongfucheng.com域名添加了一個(gè)Cookie");
image
  • 首先龄砰,證明了Cookie不可跨名性,localhost域名拿不到www.zhongfucheng.com頒發(fā)給瀏覽器的Cookie
image
  • 再使用www.image.zhongfucheng.com域名訪問(wèn),證明即使一級(jí)域名相同讨衣,二級(jí)域名不同换棚,也不能獲取到Cookie
image
  • 當(dāng)然,使用www.zhongfucheng.com當(dāng)然能獲取到Cookie反镇,Cookie通過(guò)請(qǐng)求頭帶給服務(wù)器
image
  • 現(xiàn)在我希望一級(jí)域名相同的網(wǎng)頁(yè)Cookie之間可以相互訪問(wèn)固蚤。也就是說(shuō)www.image.zhongfucheng.com可以獲取到www.zhongfucheng.com的Cookie就需要使用到domain方法。

        Cookie cookie = new Cookie("name", "ouzicheng");
        cookie.setMaxAge(1000);
        cookie.setDomain(".zhongfucheng.com");
        response.addCookie(cookie);

        printWriter.write("使用www.zhongfucheng.com域名添加了一個(gè)Cookie,只要一級(jí)是zhongfucheng.com即可訪問(wèn)");
image

Cookie的路徑

Cookie的path屬性決定允許訪問(wèn)Cookie的路徑

  • 一般地衡奥,Cookie發(fā)布出來(lái),整個(gè)網(wǎng)頁(yè)的資源都可以使用∶ぱ幔現(xiàn)在我只想Servlet1可以獲取到Cookie,其他的資源不能獲取禽作。

  • 使用Servlet2頒發(fā)一個(gè)Cookie給瀏覽器,設(shè)置路徑為"/Servlet1"。


        Cookie cookie = new Cookie("username", "java");
        cookie.setPath("/Servlet1");
        cookie.setMaxAge(1000);
        response.addCookie(cookie);

        printWriter.write("該Cookie只有Servlet1獲取得到");

  • 使用Servlet3訪問(wèn)服務(wù)器揩页,看看瀏覽器是否把Cookie帶上领迈。顯然,瀏覽器訪問(wèn)Servlet3并沒(méi)有把Cookie帶上碍沐。
image
  • 使用Servlet1訪問(wèn)服務(wù)器狸捅,看看瀏覽器是否把Cookie帶上。答案是肯定的累提!
image

Cookie的安全屬性

  • HTTP協(xié)議不僅僅是無(wú)狀態(tài)的尘喝,而且是不安全的!如果不希望Cookie在非安全協(xié)議中傳輸斋陪,可以設(shè)置Cookie的secure屬性為true朽褪,瀏覽器只會(huì)在HTTPS和SSL等安全協(xié)議中傳輸該Cookie
  • 當(dāng)然了无虚,設(shè)置secure屬性不會(huì)將Cookie的內(nèi)容加密缔赠。如果想要保證安全,最好使用md5算法加密【后面有】友题。

Cookie的應(yīng)用

顯示用戶上次訪問(wèn)的時(shí)間

  • 其實(shí)就是每次登陸的時(shí)候嗤堰,取到Cookie保存的值,再更新下Cookie的值度宦。

  • 訪問(wèn)Serlvet有兩種情況

  • 第一次訪問(wèn)

  • 已經(jīng)訪問(wèn)過(guò)了

  • 全部代碼如下:


        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter printWriter = response.getWriter();

        //獲取網(wǎng)頁(yè)上所有的Cookie
        Cookie[] cookies = request.getCookies();

        //判斷Cookie的值是否為空
        String cookieValue = null;
        for (int i = 0; cookies != null && i < cookies.length; i++) {

            //獲取到以time為名的Cookie
            if (cookies[i].getName().equals("time")) {
                printWriter.write("您上次登陸的時(shí)間是:");
                cookieValue = cookies[i].getValue();
                printWriter.write(cookieValue);

                cookies[i].setValue(simpleDateFormat.format(new Date()));
                response.addCookie(cookies[i]);

                //既然已經(jīng)找到了就可以break循環(huán)了
                break;
            }
        }

        //如果Cookie的值是空的踢匣,那么就是第一次訪問(wèn)
        if (cookieValue == null) {
            //創(chuàng)建一個(gè)Cookie對(duì)象,日期為當(dāng)前時(shí)間
            Cookie cookie = new Cookie("time", simpleDateFormat.format(new Date()));

            //設(shè)置Cookie的生命期
            cookie.setMaxAge(20000);

            //response對(duì)象回送Cookie給瀏覽器
            response.addCookie(cookie);

            printWriter.write("您是第一次登陸案瓿离唬!");
        }
  • 按照正常的邏輯來(lái)寫,程序流程應(yīng)該是這樣子的划鸽。先創(chuàng)建Cookie對(duì)象输莺,回送Cookie給瀏覽器。再遍歷Cookie裸诽,更新Cookie的值嫂用。
image
  • 但是,按照上面的邏輯是做不到的崭捍!因?yàn)槊看卧L問(wèn)Servlet的時(shí)候都會(huì)覆蓋原來(lái)的Cookie尸折,取到Cookie的值永遠(yuǎn)都是當(dāng)前時(shí)間,而不是上次保存的時(shí)間殷蛇。

  • 我們換一個(gè)邏輯寫:先檢查(遍歷)所有Cookie有沒(méi)有我要的实夹,如果得不到我想要的Cookie,Cookie的值是null粒梦,那么就是第一次登陸亮航,于是就有了上面的代碼了。

  • 我們來(lái)看下效果吧匀们!當(dāng)我第一次登陸的時(shí)候

image
  • Cookie保存在硬盤中缴淋。
image
  • 再次訪問(wèn)Servlet。明顯地泄朴,取到的就是Cookie的值
image

顯示上次瀏覽過(guò)商品

  • 我就以書籍為例子了重抖!首先設(shè)計(jì)Book對(duì)象

    private String id ;
    private String name ;
    private String author;

    public Book() {
    }

    public Book(String id, String name, String author) {
        this.id = id;
        this.name = name;
        this.author = author;
    }

    ...各種set、get方法
  • 設(shè)計(jì)一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù)祖灰。就用LinkedHashMap集合【根據(jù)商品的id找書籍所以用Map钟沛,刪改較多所以用Linked】

    private static LinkedHashMap<String, Book> linkedHashMap = new LinkedHashMap();

    //簡(jiǎn)化開(kāi)發(fā)復(fù)雜度,book的id和商品的id相同
    static {
        linkedHashMap.put("1", new Book("1", "javaweb", "zhong"));
        linkedHashMap.put("2", new Book("2", "java", "fu"));
        linkedHashMap.put("3", new Book("3", "oracle", "cheng"));
        linkedHashMap.put("4", new Book("4", "mysql", "ou"));
        linkedHashMap.put("5", new Book("5", "ajax", "zi"));
    }

    //獲取到所有書籍
    public static LinkedHashMap getAll() {
        return linkedHashMap;
    }

  • 顯示網(wǎng)頁(yè)上所有的書籍【首頁(yè)】

        printWriter.write("網(wǎng)頁(yè)上所有的書籍:"+"<br/>");

        //拿到數(shù)據(jù)庫(kù)所有的書
        LinkedHashMap<String, Book> linkedHashMap = DB.getAll();
        Set<Map.Entry<String, Book>> entry = linkedHashMap.entrySet();

        //顯示所有的書到網(wǎng)頁(yè)上
        for (Map.Entry<String, Book> stringBookEntry : entry) {
            Book book = stringBookEntry.getValue();
            printWriter.write(book.getId() +"           "+ book.getName()+"<br/>");
        }

image
  • 接著局扶,我們要做的就是給顯示的書籍掛上一個(gè)超鏈接恨统,當(dāng)用戶點(diǎn)擊想看的書籍時(shí),就跳轉(zhuǎn)到該書籍的詳細(xì)信息頁(yè)面
  • 超鏈接應(yīng)該把書的id傳遞過(guò)去三妈,不然處理頁(yè)面是不知道用戶想看的是哪一本書的畜埋!

        //顯示所有的書到網(wǎng)頁(yè)上
        for (Map.Entry<String, Book> stringBookEntry : entry) {
            Book book = stringBookEntry.getValue();
            printWriter.write("<a href='/ouzicheng/Servlet2?id=" + book.getId() + "''target=_blank' +" + book.getName() + "</a>");
            printWriter.write("<br/>");
        }
image
  • 接收id,找到用戶想要看哪一本書畴蒲,輸出該書的詳細(xì)信息

        String id = request.getParameter("id");

        //由于book的id和商品的id是一致的悠鞍。獲取到用戶點(diǎn)擊的書
        Book book = (Book) DB.getAll().get(id);

        //輸出書的詳細(xì)信息
        printWriter.write("書的編號(hào)是:" + book.getId()+"<br/>");
        printWriter.write("書的名稱是:" + book.getName()+"<br/>");
        printWriter.write("書的作者是:" + book.getAuthor()+"<br/>");
  • 點(diǎn)擊想要的書籍。
image
  • 得到書籍的詳細(xì)信息
image
  • 既然用戶點(diǎn)擊了書籍模燥,那么服務(wù)器就應(yīng)該頒發(fā)Cookie給瀏覽器狞玛,記住用戶點(diǎn)擊了該書籍

  • 現(xiàn)在問(wèn)題來(lái)了,Cookie的值應(yīng)該是什么呢涧窒?試想一下心肪,待會(huì)還要把瀏覽過(guò)的書籍顯示出來(lái),所以用書籍的id是最好不過(guò)的纠吴。想到了用書籍的id作為Cookie的值硬鞍,我們還要定義一些規(guī)則!

  • 我們可能有非常多的書籍戴已,不可能把用戶瀏覽過(guò)的書籍都顯示出來(lái)固该。所以我們定義只能顯示3本瀏覽過(guò)的書籍

  • 書籍的id都是數(shù)字,如果不做任何修改糖儡,存到Cookie里邊可能就是231伐坏,345,123此類的數(shù)字握联,這樣取出某一個(gè)id的時(shí)候就十分費(fèi)勁并且后面還要判斷該書是否存在Cookie里邊了桦沉,所以我們要把存儲(chǔ)到Cookie的書籍id分割起來(lái)每瞒。所以我們定義”_“作為分隔符

  • 按上面的應(yīng)用,我們的邏輯應(yīng)該是:先遍歷下Cookie纯露,看下有沒(méi)有我們想要的Cookie剿骨。如果找到想要的Cookie,那就取出Cookie的值


        String bookHistory = null;
        Cookie[] cookies = request.getCookies();
        for (int i = 0; cookies != null && i < cookies.length; i++) {
            if (cookies[i].getName().equals("bookHistory")) {
                bookHistory = cookies[i].getValue();
            }
        }
  • 取出了Cookie的值也分幾種情況

    1. Cookie的值為null【直接把傳入進(jìn)來(lái)的id當(dāng)做是Cookie的值】
    2. Cookie的值長(zhǎng)度有3個(gè)了【把排在最后的id去掉埠褪,把傳進(jìn)來(lái)的id排在最前邊】
    3. Cookie的值已經(jīng)包含有傳遞進(jìn)來(lái)的id了【把已經(jīng)包含的id先去掉浓利,再把id排在最前面】
    4. Cookie的值就只有1個(gè)或2個(gè),直接把id排在最前邊

        if (bookHistory == null) {
            return id;
        }

        //如果Cookie的值不是null的钞速,那么就分解Cookie的得到之前的id贷掖。
        String[] strings = bookHistory.split("\\_");

        //為了增刪容易并且還要判斷id是否存在于該字符串內(nèi)-----我們使用LinkedList集合裝載分解出來(lái)的id
        List list = Arrays.asList(strings);
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.addAll(list);

        if (linkedList.contains(id)) {
            linkedList.remove(id);
            linkedList.addFirst(id);
        }else {
            if (linkedList.size() >= 3) {
                linkedList.removeLast();
                linkedList.addFirst(id);
            } else {
                linkedList.addFirst(id);
            }
        }

  • 這么折騰完了,我們的Cookie值就在LinkedList集合里邊了渴语。接下來(lái)苹威,我們要做的就是把集合中的值取出來(lái),拼接成一個(gè)字符串

        StringBuffer stringBuffer = new StringBuffer();

        //遍歷LinkedList集合遵班,添加個(gè)下劃線“_”
        for (String s : linkedList) {
            stringBuffer.append(s + "_");
        }

        //最后一個(gè)元素后面就不需要下劃線了
        return stringBuffer.deleteCharAt(stringBuffer.length() - 1).toString();

  • 好的屠升,我們現(xiàn)在已經(jīng)完成了Cookie值了。接下來(lái)設(shè)置Cookie的生命周期狭郑,回送給瀏覽器即可

        String bookHistory = makeHistory(request, id);
        Cookie cookie = new Cookie("bookHistory", bookHistory);
        cookie.setMaxAge(30000);
        response.addCookie(cookie);
  • 既然我們已經(jīng)把Cookie回送給瀏覽器了腹暖。那么接下來(lái)我們就在首頁(yè)上獲取Cookie的值,顯示用戶瀏覽過(guò)什么商品就行了翰萨!

        printWriter.write("您曾經(jīng)瀏覽過(guò)的商品:");
        printWriter.write("<br/>");

        //顯示用戶瀏覽過(guò)的商品
        Cookie[] cookies = request.getCookies();
        for (int i = 0; cookies != null && i < cookies.length; i++) {

            if (cookies[i].getName().equals("bookHistory")) {

                //獲取到的bookHistory是2_3_1之類的
                String bookHistory = cookies[i].getValue();

                //拆解成每一個(gè)id值
                String[] ids = bookHistory.split("\\_");

                //得到每一個(gè)id值
                for (String id : ids) {

                    //通過(guò)id找到每一本書
                    Book book = linkedHashMap.get(id);

                    printWriter.write(book.getName());
                    printWriter.write("<br/>");

                }
                break;
            }

        }
  • 好的脏答,我們來(lái)試驗(yàn)一下吧!亩鬼!殖告,第一次訪問(wèn)首頁(yè),并沒(méi)有瀏覽過(guò)的商品
image
  • 當(dāng)我點(diǎn)擊javaweb書籍再訪問(wèn)首頁(yè)的時(shí)候
image
  • 再點(diǎn)擊ajax然后訪問(wèn)首頁(yè)
image
  • 再點(diǎn)擊javaweb然后訪問(wèn)首頁(yè)
image
  • 點(diǎn)擊oracle然后訪問(wèn)首頁(yè)
image
  • 好的雳锋,經(jīng)過(guò)測(cè)試黄绩,該程序應(yīng)該沒(méi)有什么問(wèn)題了!

如果文章有錯(cuò)的地方歡迎指正玷过,大家互相交流爽丹。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號(hào):Java3y

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辛蚊,一起剝皮案震驚了整個(gè)濱河市粤蝎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袋马,老刑警劉巖初澎,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異虑凛,居然都是意外死亡碑宴,警方通過(guò)查閱死者的電腦和手機(jī)软啼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)墓懂,“玉大人焰宣,你說(shuō)我怎么就攤上這事霉囚〔蹲校” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵盈罐,是天一觀的道長(zhǎng)榜跌。 經(jīng)常有香客問(wèn)我,道長(zhǎng)盅粪,這世上最難降的妖魔是什么钓葫? 我笑而不...
    開(kāi)封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮票顾,結(jié)果婚禮上础浮,老公的妹妹穿的比我還像新娘。我一直安慰自己奠骄,他們只是感情好豆同,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著含鳞,像睡著了一般影锈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蝉绷,一...
    開(kāi)封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天鸭廷,我揣著相機(jī)與錄音,去河邊找鬼熔吗。 笑死辆床,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桅狠。 我是一名探鬼主播讼载,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼垂攘!你這毒婦竟也來(lái)了维雇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤晒他,失蹤者是張志新(化名)和其女友劉穎吱型,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陨仅,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡津滞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年铝侵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片触徐。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咪鲜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撞鹉,到底是詐尸還是另有隱情疟丙,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布鸟雏,位于F島的核電站享郊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏孝鹊。R本人自食惡果不足惜炊琉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望又活。 院中可真熱鬧苔咪,春花似錦、人聲如沸柳骄。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夹界。三九已至馆里,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間可柿,已是汗流浹背鸠踪。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留复斥,地道東北人营密。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像目锭,于是被迫代替她去往敵國(guó)和親评汰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容