或许你早已经了解过cookies,但是或许你还不知道怎样在Java应用程序中利用cookies的优势.这篇文章可以引导你深入理解cookies,并且告诉你怎样设置一个cookie handler来使 HTTP URL 网络连接使用到这些cookie.
Java SE 提供了一个主要的类来实现这一功能,java.net.CookieHandler
还有一些其他的辅助类和接口:java.net.CookieManager,java.net.CookiePolicy,java.net.CookieStore,
和java.net.HttpCookie.
描述cookies的性质,解释cookies是怎样被用到sessions中的
Http 的状态管理机制,指定了一种方法。这种方法可以 利用 Http
的 requests
和 responses
创建具有状态的 session
.
通常来说,Http 请求 或者 返回,两两之间应该是相互独立的。然而,状态管理机制(the state management mechanism),可以使 客户端(clients) 和 服务器(servers)可以通过把这些信息放进一个上下文变量中来实现状态信息的交换,这种方式被称作 Session
.这些被用来创建 和维护session
的状态信息被称作 cookie
.
一个Cookie是一个数据片段,它可以被存储在浏览器的缓存中.如果你访问过一个网站,并且再次访问它的时候,这些cookie数据就可以用来识别你是一个“回头客”,说明你之前访问过该网站。Cookies
使状态信息的存在成为可能,例如在线的购物车,可以将信息存储起来。一个Cookie可以短期存在,为单个web页面的session维持信息,因此 除非你关闭浏览器,否则一个cookie可以长期存在,维持信息 一个星期或者一年。
描述当你访问一个页面的时候 一个cookie handler 是如何被调用的,并且告诉你 如何设置一个 cookie handler
Http 状态的管理是通过Java SE中的java.net.CookieHandler
这个类来实现的。
一个CookieHandler
对象提供了一个回调机制,这些回调机制提供给 Http 状态管理一些规则。而这些规则是在Http protocol Handler 内部实现的。
URLs 使用 HTTP 作为协议,new URL("http://example.com")
新建一个URLs对象来作为例子,这个会使用HTTP protocol handler.这个 HTTP protocol handler回调 CookieHanlder
对象的方法,如果CookieHandler
中有设置的话,就可以进行状态管理。
CookieHandler
是一个抽象类,它有两对相互对应的方法。
第一对:getDefault()
和setDefault(cookieHandler)
方法
这对方法是静态的
第二对:put(uri,responseHeader)
和get(uri,requestHeaders)
这对方法是抽象方法
这两个方法分别用在指定的URI的 response 和 request header 中,这两个方法是抽象方法,凡是实现了CookieHandler
的,都需要提供内部实现。
java.net.CookieManger
提供了一个构造方法的方式来实现CookieHandler
对状态的管理。这种方式对大多数人来说,已经足够了。CookieManger
通过policy来划分存储的cookies,通过policy可以实现接收和拒绝cookies。
CookieManger
通过java.net.CookieStore
和java.net.CookiePolicy
参数来进行初始化。
以下的代码用来展示如何创建 并且设置一个 system-wide CookieManager (系统通用的CookieManager/默认的CookieManager)
java.net.CookieManager cm = new java.net.CookieManager();
java.net.CookieHandler.setDefault(cm);
第一行代码通过调用 默认的CookieManager的构造函数来创建了一个实例
第二行通过调用CookieHandler
静态方法setDefault
来设置一个system-wide handler.
默认情况下 CookieManager
的构造函数,通过默认的 cookie store 和 accept policy.
CookieStore 指明了任何已经接收了的HTTP cookies的存放位置,如果在构造函数中没有指明,CookieManager
实例就会使用 in-memory 的CookieStore来实现。 这种实现方式,不是持久化的 只有在Java虚拟机存活的时候存在。如果用户需要一个持久化的CookieStore
必须要进行自己的自定义。
CookieManager
使用的默认的cookie policy 是CookiePolicy.ACCEPT_ORIGINAL_SERVER
,这种policy只接收对应服务器的cookie.所以,服务器反回的response中Set-Cookie
选项中必须要有domain
属性,而且这个domain
属性的值必须和请求的url中host相匹配。
想了解更多关于这方面的信息可以参照java.net.HttpCookie.domainMatches
如果用户需要使用不同的policy的话,必须要实现CookiePolicy
接口,然后通过构造方法传递进去,或者通过一个已经创建的CookieManager
的setCookiePolicy(cookiePolicy)
方法。
CookieManager 有两个方面可以进行自定义,CookiePolicy
和 CookieStore
为了使用方便,CooliePolicy
定义了一下几个 预定义的规则用来接收cookies:
implementing
这个shouldAccept
方法来定义自己接收Cookie的规则。然后通过CookieManager
的多参数构造函数将自定义的CookiePolicy
传递进去,或者通过调用setCookiePolicy(cookiePolicy)
方法来改变已经存在的cookie Manager.以下就是一个拒绝接收domain在黑名单中列表中的例子,这个需要在CookiePolicy.ACCEPT_ORIGINAL_SERVER
之前调用。
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; iif (HttpCookie.domainMatches(blacklist[i], host)) {
return false;
}
}
return CookiePolicy.ACCEPT_ORIGINAL_SERVER.shouldAccept(uri, cookie);
}
}
当你创建一个 BlacklistCookiePolicy
的实例,你可以传递一个 String array 用来表示一些你不想接受cookie 的domain.
然后你将这个BlacklistCookiePolicy
的实例作为CookieManager
的cookie policy 设置进去,举例来说:
String[] list = new String[]{ ".example.com" };
CookieManager cm = new CookieManager(null, new BlacklistCookiePolicy(list));
CookieHandler.setDefault(cm);
以上的示例代码就不会接收以下hosts的cookie:
host.example.com
domain.example.com
然而,示例代码会接收来自以下hosts的cookie:
example.com
example.org
myhost.example.org
CookieStore
作为一个接口,它表示了一个用来存储cookies的地方。CookieManager
都会把这些cookies添加到CookieStore
中.CookieManager
都会从CookieStore
中获取cookies.你可以通过 implements CookieStore
接口来实现自己的CookieStore,然后在CookieManger
创建的时候,将自己的CookieStore传递进去,不能在CookieManger
已经被创建之后,来设置 CookieStore。 但是,你可以通过调用CookieManager.getCookieStore()
方法获取cookie Store的引用。这种实现CookieStore
接口的做法非常实用,因为这个可以你可以借用 Java SE 提供的默认的 内存中的CookieStore
的实现,然后自己完善CookieStore的功能。
举例来说,你或许想创建一个 持久的 cookie store ,能够在Java虚拟机重启后依然生效的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 get(URI uri) {
return store.get(uri);
}
public List getCookies() {
return store.getCookies();
}
public List getURIs() {
return store.getURIs();
}
public boolean remove(URI uri, HttpCookie cookie) {
return store.remove(uri, cookie);
}
public boolean removeAll() {
return store.removeAll();
}
}
原文链接