【网络编程】——Java实现(6)——使用Cookie(Working With Cookies)

这里是Java网络编程Java Socket编程相关的学习手记。这里按照官方的Java 8 Toturial教程的Custom Networking学习路径,对相关的一些内容进行解读(并不完全,如果有错请联系我,谢谢^ _ ^),同时在学习的过程中加入个人的理解与对代码运行的思考。

下面是整个专栏的文章链接,用于快速的导航。

摘要与说明

原文来自Java 8官方Tutorial
文章会加入自己的学习时想到的一些内容。

原文也没给什么代码例子,我看的时候比较难理解,感觉是为了桌面应用开发准备的。这里懂HTTP cookie就好,后面如果感兴趣我再回头。

虽然你可能已经熟悉cookie了,但是你可能并不知道在你的Java程序中好好地利用它们。本文就带你研究Cookie的概念,讲解如何在你的HTTP URL connections中设置cookie处理器(handler ),并使用它。

Java SE提供了一个类来实现此功能:java.net.CookieHandler,还有下面的支持类和接口类:java.net.CookieManager, java.net.CookiePolicy接口, java.net.CookieStore接口java.net.HttpCookie

使用Cookie对HTTP状态进行管理(HTTP State Management With Cookies)

HTTP状态管理机制指定了一种在HTTP 请求/回应中创建有状态会话(stateful session)的方法

通常来说,HTTP 请求/回应 对( request/response pairs)互相独立的,然而,状态管理机制能让C/S两端交换状态信息,以实现将这些请求/回应对置于一个更大的上下文( a larger context)之中,这个上下文我们称之为session

cookie是能存储在浏览器缓存的数据。如果你访问一个web站点,关闭之后重新返回此站点,cookie数据可以标识出你是一个回头客( a return visitor)。Cookies能保存状态信息,例如在线购物车的货物。cookie可能是短期的,此时可用于保存单个web session(web回话),直到浏览器关闭之前会话都存在。cookie当然也可能是长期的,此时可能会保存数据数周或者一年也不一定。
有关HTTP state management更多的信息,可以查看 RFC 2965: HTTP State Management Mechanism.

CookieHandler 回调机制(CookieHandler Callback Mechanism)

Java SE中是通过java.net.CookieHandler类来实现HTTP状态管理的。CookieHandler对象用一种回调机制来提供一种对HTTP协议处理器中HTTP状态管理策略的实现。例如,使用HTTP作为URL的协议:
new URL("http://example.com"),这里将会使用HTTP协议处理器。如果设置了CookieHandler的话,此协议处理器会回调CookieHandler对象来处理状态管理。

CookieHandler 类是一个抽象类。他有两对方法,getDefault()setDefault(cookieHandler)分别能让你找到当前被载入的handler 和设置自己的handler

如果没有载入默认的handler,那么系统就会在底层默认载入一个handler。对于运行在安全环境下的应用,他们有一个安全管理被载入,你必须有特定的权限来获取和设置handler。对于更多的信息,可以查看java.net.CookieHandler.getDefault.

另外还有方法:put(uri, responseHeaders)get(uri, requestHeaders),能让你从制定的URI的请求/回应头中设置和获取所有可用的cookie。这些方法是抽象的,CookieHandler 必须提供具体的实现。
Java Web Start 还有Java Plug-in有默认的CookieHandler 被安装。然而,如果你正运行一个单机程序并想要维持HTTP 状态管理,你必须要设置系统级的handler(system-wide handler)。下两节介绍如何做。

默认CookieManager(Default CookieManager)

java.net.CookieManager提供了CookieHandler的具体实现,对大多数用户来说,足够处理HTTP 状态管理了。CookieManager将Cookie的存储与cookie的接受和拒绝的策略分开。CookieManager用java.net.CookieStorejava.net.CookiePolicy初始化。CookieStore管理cookie的存储,CookiePolicy做出接受或者拒绝cookie的决定。

下面的代码展示了如何创建和设置一个系统级的Cookie管理器(CookieManager):

    java.net.CookieManager cm = new java.net.CookieManager();
    java.net.CookieHandler.setDefault(cm);

代码第一行通过调用CookieManager默认构造函数,用一个默认的cookie store 和 accept policy来创建一个新的CookieManager实例。CookieStore 是所有已接受的HTTP cookie存储的地方。如果创建的时候不特别制定的话,CookieManager 实例将使用内存实现。这种实现并不持久,并且只能存活在Java虚拟机的生命周期内。如果用户需要持久的存储方式,他们必须实现他们自己的存储方式。

CookieManager 默认的cookie策略是CookiePolicy.ACCEPT_ORIGINAL_SERVER,它只会接收来自原服务(original server)器的cookie。所以来自服务端的Set-Cookie回应必须要有一个域(domain)属性设置,并且它必须匹配URL中相应主机的域。更多的信息,可以查看API java.net.HttpCookie.domainMatches。用户需要一种不同的策略,必须要实现CookiePolicy 接口,并传递它给CookieManager 的构造器或者通过方法setCookiePolicy(cookiePolicy)设置它到一个CookieManager对象。

当从cookie存储器取出cookie时,CookieManager 也会强制执行路径匹配规则(path-match rule from section 3.3.4 of RFC 2965)。所以,cookie必须也要拥有它的“路径”属性以至于路径匹配规则在cookie被取出来之前能被应用上。

总的来说,CookieManager 类提供了处理cookie的框架,也提供了较好的CookieStore实现。CookieManager 是高度可定制的,因为它能让你设置自己的CookieStore,CookiePolicy。

定制CookieManager(Custom CookieManager)

从两个方面来考虑怎么定制CookieManager:CookieStore,CookiePolicy

CookiePolicy

为了方便,CookiePolicy定义了如下预定义(pre-defined)的策略应对接收的cookie:

  • CookiePolicy.ACCEPT_ORIGINAL_SERVER只接收源服务器的cookie
  • CookiePolicy.ACCEPT_ALL接收所有的cookie
  • CookiePolicy.ACCEPT_NONE不接收cookie

当然通过实现CookiePolicy的shouldAccept方法 也能定义自己的cookie策略。之后可以传递此CookiePolicy给CookieManager 构造函数,或者通过调用CookieManager 的setCookiePolicy(cookiePolicy)方法来改变CookieManager 默认的CookiePolicy

下面是一个cookie policy的例子,在应用CookiePolicy.ACCEPT_ORIGINAL_SERVER policy策略之前,它先拒绝已经纳入域黑名单的cookie:

import java.net.*;

public class BlacklistCookiePolicy implements CookiePolicy {
    String[] blacklist;

    public BlacklistCookiePolicy(String[] list) {
        blacklist = list;
    }

    public boolean shouldAccept(URI uri, HttpCookie cookie)  {
        String host;
        try {
            host =  InetAddress.getByName(uri.getHost()).getCanonicalHostName();
        } catch (UnknownHostException e) {
            host = uri.getHost();
        }

        for (int i = 0; i<blacklist.length; i++) {
	    if (HttpCookie.domainMatches(blacklist[i], host)) {
                return false;
            }
        }

        return CookiePolicy.ACCEPT_ORIGINAL_SERVER.shouldAccept(uri, cookie);
    }
}

当创建BlacklistCookiePolicy实例时,你需要传入一个string数组来表示你并不想要接收来自某些域的cookie。然后,设置BlacklistCookiePolicy 实例作为CookieManager的cookie策略。举个例子:

String[] list = new String[]{ ".example.com" };
CookieManager cm = new CookieManager(null, new BlacklistCookiePolicy(list));
CookieHandler.setDefault(cm);

此代码将会接收来自如下所列主机的cookie:

host.example.com
domain.example.com

然而,并不会接受来自如下主机的cookie:

example.com
example.org
myhost.example.org

CookieStore

CookieStore 是一个代表cookie存储区域的接口。CookieManager在每个HTTP response 时,会添加cookie到CookieStore 中,然后在每个HTTP request时,会从CookieStore中取出cookie。

你能实现此接口,并在CookieManager实例化时传给它。你不能在CookieManager实例化之后设置它的CookieStore。然而,你能通过调用CookieManager.getCookieStore()获得CookieStore引用。这样做非常有好处,因为它能让你利用默认内置内存中的CookieStore实现。

举个例子,你可能想要创建一个持久话的cookie store,来保存cookie以便他们即使在虚拟机重启了仍然能够被使用。你的实现可能会像是这样:

  1. 读入以前保存的全部cookie
  2. 在运行期间,读写cookie到内存中。
  3. 在退出前cookie被写出去(写到文件里或者。。。)

下面是一个不完整的cookie store的例子。此例展示了如何利用Java SE默认内置的的内存cookie store,并且如何来扩展此功能。

import java.net.*;
import java.util.*;

public class PersistentCookieStore implements CookieStore, Runnable {
    CookieStore store;

    public PersistentCookieStore() {
        // get the default in memory cookie store
        store = new CookieManager().getCookieStore();

        // todo: read in cookies from persistant storage
        // and add them store

        // add a shutdown hook to write out the in memory cookies
        Runtime.getRuntime().addShutdownHook(new Thread(this)); 
    }

    public void run() {
        // todo: write cookies in store to persistent storage
    }

    public void	add(URI uri, HttpCookie cookie) {
        store.add(uri, cookie);
    }

    public List<HttpCookie> get(URI uri) {
        return store.get(uri);
    }

    public List<HttpCookie> getCookies() {
        return store.getCookies();
    }
    
    public List<URI> getURIs() {
        return store.getURIs();
    }

    public boolean remove(URI uri, HttpCookie cookie) {
        return store.remove(uri, cookie);
    }

    public boolean removeAll()  {
        return store.removeAll();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值