我试图通过线程使多个连接。
但是,每一个连接似乎重写其他的饼干,导致使用了错误的饼干的连接。
螺纹类的构造函数中:
manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
任何的方式来管理每线程或每类饼干?
新的失败尝试:
现在每个线程使用它自己的指标,但他们似乎仍然互相覆盖的cookie明智的。 有任何想法吗?
public class threadedCookieStore implements CookieStore, Runnable {
CookieStore[] store = new CookieStore[1000];
int index;
public threadedCookieStore(int new_index) {
index = new_index;
// get the default in memory cookie store
store[index] = 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[index].add(uri, cookie);
}
public List<HttpCookie> get(URI uri) {
return store[index].get(uri);
}
public List<HttpCookie> getCookies() {
return store[index].getCookies();
}
public List<URI> getURIs() {
return store[index].getURIs();
}
public boolean remove(URI uri, HttpCookie cookie) {
return store[index].remove(uri, cookie);
}
public boolean removeAll() {
return store[index].removeAll();
}
}
在类:
threadedCookieStore cookiestore = new threadedCookieStore(index);
manager = new CookieManager(cookiestore,CookiePolicy.ACCEPT_ALL);
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
Answer 1:
感谢大家。
我upvoted所有的答案,但什么都没有完整的解决方案。
由于google'ing这个问题导致这个页面在这里,我会发布了完整的解决方案,并接受我自己的答案:
如何:
1扩展CookieHandler
到SessionCookieManager
这是基于如何使用不同的Cookie使用HttpURLConnection类和CookieManager在Java中的每个连接 ,纳伟仕所描述的那样正确,并没有提供一个完整的解决方案寿。 因此,大多数/全部归功于他,我只是做了完整的HOWTO。 该SessionCookieManager是基于Java
的源代码http://docs.oracle.com/javase/7/docs/api/java/net/CookieManager.html
import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookiePolicy;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
public class SessionCookieManager extends CookieHandler
{
private CookiePolicy policyCallback;
public SessionCookieManager() {
this(null, null);
}
private final static SessionCookieManager ms_instance = new SessionCookieManager();
public static SessionCookieManager getInstance()
{
return ms_instance;
}
private final static ThreadLocal<CookieStore> ms_cookieJars = new ThreadLocal<CookieStore>() {
@Override
protected synchronized CookieStore initialValue() { return new InMemoryCookieStore(); }
};
public void clear()
{
getCookieStore().removeAll();
}
public SessionCookieManager(CookieStore store,
CookiePolicy cookiePolicy)
{
// use default cookie policy if not specify one
policyCallback = (cookiePolicy == null) ? CookiePolicy.ACCEPT_ALL //note that I changed it to ACCEPT_ALL
: cookiePolicy;
// if not specify CookieStore to use, use default one
}
public void setCookiePolicy(CookiePolicy cookiePolicy) {
if (cookiePolicy != null) policyCallback = cookiePolicy;
}
public CookieStore getCookieStore() {
return ms_cookieJars.get();
}
public Map<String, List<String>>
get(URI uri, Map<String, List<String>> requestHeaders)
throws IOException
{
// pre-condition check
if (uri == null || requestHeaders == null) {
throw new IllegalArgumentException("Argument is null");
}
Map<String, List<String>> cookieMap =
new java.util.HashMap<String, List<String>>();
// if there's no default CookieStore, no way for us to get any cookie
if (getCookieStore() == null)
return Collections.unmodifiableMap(cookieMap);
List<HttpCookie> cookies = new java.util.ArrayList<HttpCookie>();
for (HttpCookie cookie : getCookieStore().get(uri)) {
// apply path-matches rule (RFC 2965 sec. 3.3.4)
if (pathMatches(uri.getPath(), cookie.getPath())) {
cookies.add(cookie);
}
}
// apply sort rule (RFC 2965 sec. 3.3.4)
List<String> cookieHeader = sortByPath(cookies);
cookieMap.put("Cookie", cookieHeader);
return Collections.unmodifiableMap(cookieMap);
}
public void
put(URI uri, Map<String, List<String>> responseHeaders)
throws IOException
{
// pre-condition check
if (uri == null || responseHeaders == null) {
throw new IllegalArgumentException("Argument is null");
}
// if there's no default CookieStore, no need to remember any cookie
if (getCookieStore() == null)
return;
for (String headerKey : responseHeaders.keySet()) {
// RFC 2965 3.2.2, key must be 'Set-Cookie2'
// we also accept 'Set-Cookie' here for backward compatibility
if (headerKey == null
|| !(headerKey.equalsIgnoreCase("Set-Cookie2")
|| headerKey.equalsIgnoreCase("Set-Cookie")
)
)
{
continue;
}
for (String headerValue : responseHeaders.get(headerKey)) {
try {
List<HttpCookie> cookies = HttpCookie.parse(headerValue);
for (HttpCookie cookie : cookies) {
if (shouldAcceptInternal(uri, cookie)) {
getCookieStore().add(uri, cookie);
}
}
} catch (IllegalArgumentException e) {
// invalid set-cookie header string
// no-op
}
}
}
}
/* ---------------- Private operations -------------- */
// to determine whether or not accept this cookie
private boolean shouldAcceptInternal(URI uri, HttpCookie cookie) {
try {
return policyCallback.shouldAccept(uri, cookie);
} catch (Exception ignored) { // pretect against malicious callback
return false;
}
}
/*
* path-matches algorithm, as defined by RFC 2965
*/
private boolean pathMatches(String path, String pathToMatchWith) {
if (path == pathToMatchWith)
return true;
if (path == null || pathToMatchWith == null)
return false;
if (path.startsWith(pathToMatchWith))
return true;
return false;
}
/*
* sort cookies with respect to their path: those with more specific Path attributes
* precede those with less specific, as defined in RFC 2965 sec. 3.3.4
*/
private List<String> sortByPath(List<HttpCookie> cookies) {
Collections.sort(cookies, new CookiePathComparator());
List<String> cookieHeader = new java.util.ArrayList<String>();
for (HttpCookie cookie : cookies) {
// Netscape cookie spec and RFC 2965 have different format of Cookie
// header; RFC 2965 requires a leading $Version="1" string while Netscape
// does not.
// The workaround here is to add a $Version="1" string in advance
if (cookies.indexOf(cookie) == 0 && cookie.getVersion() > 0) {
cookieHeader.add("$Version=\"1\"");
}
cookieHeader.add(cookie.toString());
}
return cookieHeader;
}
static class CookiePathComparator implements Comparator<HttpCookie> {
public int compare(HttpCookie c1, HttpCookie c2) {
if (c1 == c2) return 0;
if (c1 == null) return -1;
if (c2 == null) return 1;
// path rule only applies to the cookies with same name
if (!c1.getName().equals(c2.getName())) return 0;
// those with more specific Path attributes precede those with less specific
if (c1.getPath().startsWith(c2.getPath()))
return -1;
else if (c2.getPath().startsWith(c1.getPath()))
return 1;
else
return 0;
}
}
}
请注意,在我的情况下,我改变了默认值CookiePolicy
到ACCEPT_ALL
2在全球范围内,运行任何线程之前,请致电:
CookieHandler.setDefault(SessionCookieManager.getInstance());
3当你的线程执行完毕,调用它里面:
SessionCookieManager.getInstance().clear();
再次:不是我的主意,只是把它在一起。 一切归功于Java
和https://stackoverflow.com/users/1442259/nivs
Answer 2:
谢谢,我试图用你的答案,但它是基于旧版本CookieManager的(也许就是为什么你不得不使用ACCEPT_ALL),并参考了包私人InMemoryCookieStore所以激发了我最终的解决方案。 一个ThreadLocal的CookieStore代理类:之前应该是很明显我们所有的人。
CookieHandler.setDefault(new CookieManager(new ThreadLocalCookieStore(), null));
同
import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;
public class ThreadLocalCookieStore implements CookieStore {
private final static ThreadLocal<CookieStore> ms_cookieJars = new ThreadLocal<CookieStore>() {
@Override
protected synchronized CookieStore initialValue() {
return (new CookieManager()).getCookieStore(); /*InMemoryCookieStore*/
}
};
@Override
public void add(URI uri, HttpCookie cookie) {
ms_cookieJars.get().add(uri, cookie);
}
@Override
public List<HttpCookie> get(URI uri) {
return ms_cookieJars.get().get(uri);
}
@Override
public List<HttpCookie> getCookies() {
return ms_cookieJars.get().getCookies();
}
@Override
public List<URI> getURIs() {
return ms_cookieJars.get().getURIs();
}
@Override
public boolean remove(URI uri, HttpCookie cookie) {
return ms_cookieJars.get().remove(uri, cookie);
}
@Override
public boolean removeAll() {
return ms_cookieJars.get().removeAll();
}
}
似乎是工作对我来说就像魅力
Answer 3:
你可以安装它管理的ThreadLocal CookieManager实例一的CookieHandler。
Answer 4:
在ThreadLocal
CookieStore
通过DavidBlackledge是海事组织最好的一段路要走。 对于内存的效率,我在这里提供一个简单实现定期着想CookieStore
所以你不必实例化一个整体CookieManager
为每个线程(假设你有不只是多了一些)。
/**
* @author lidor
* A simple implementation of CookieStore
*/
public class CookieJar implements CookieStore {
private Map<URI, List<HttpCookie>> jar;
private List<HttpCookie> freeCookies;
public CookieJar() {
jar = new HashMap<URI, List<HttpCookie>>();
freeCookies = new ArrayList<HttpCookie>();
}
@Override
public void add(URI uri, HttpCookie cookie) {
if (uri != null) {
if (!jar.containsKey(uri))
jar.put(uri, new ArrayList<HttpCookie>());
List<HttpCookie> cookies = jar.get(uri);
cookies.add(cookie);
} else {
freeCookies.add(cookie);
}
}
@Override
public List<HttpCookie> get(URI uri) {
Log.trace("CookieJar.get (" + this + ") called with URI " + uri + " (host=" + uri.getHost() + ")");
List<HttpCookie> liveCookies = new ArrayList<HttpCookie>();
if (jar.containsKey(uri)) {
for (HttpCookie cookie : jar.get(uri)) {
if (!cookie.hasExpired())
liveCookies.add(cookie);
}
}
for (HttpCookie cookie : getCookies()) {
if (cookie.getDomain().equals(uri.getHost()))
if (!liveCookies.contains(cookie))
liveCookies.add(cookie);
}
return Collections.unmodifiableList(liveCookies);
}
@Override
public List<HttpCookie> getCookies() {
List<HttpCookie> liveCookies = new ArrayList<HttpCookie>();
for (URI uri : jar.keySet())
for (HttpCookie cookie : jar.get(uri)) {
if (!cookie.hasExpired())
liveCookies.add(cookie);
}
for (HttpCookie cookie : freeCookies) {
if (!cookie.hasExpired())
liveCookies.add(cookie);
}
return Collections.unmodifiableList(liveCookies);
}
@Override
public List<URI> getURIs() {
return Collections.unmodifiableList(new ArrayList<URI>(jar.keySet()));
}
@Override
public boolean remove(URI uri, HttpCookie cookie) {
if (jar.containsKey(uri)) {
return jar.get(uri).remove(cookie);
} else {
return freeCookies.remove(cookie);
}
}
@Override
public boolean removeAll() {
boolean ret = (jar.size() > 0) || (freeCookies.size() > 0);
jar.clear();
freeCookies.clear();
return ret;
}
}
所以,如果你有这样的CookieJar,那么你可以改变ms_cookieJars
声明如下:
private final static ThreadLocal<CookieStore> ms_cookieJars = new ThreadLocal<CookieStore>() {
@Override
protected synchronized CookieStore initialValue() {
return new CookieJar();
}
};
Answer 5:
基于在这个线程的答案,我创建了另一个非常简单ThreadLocalCookieStore
实现,它推到GitHub上 (也提供了它作为Maven的依赖有):
public class ThreadLocalCookieStore implements CookieStore {
private final static ThreadLocal<CookieStore> stores = new ThreadLocal<CookieStore>() {
@Override protected synchronized CookieStore initialValue() {
return (new CookieManager()).getCookieStore(); //InMemoryCookieStore
}
};
@Override public void add(URI uri, HttpCookie cookie) { getStore().add(uri,cookie); }
@Override public List<HttpCookie> get(URI uri) { return getStore().get(uri); }
@Override public List<HttpCookie> getCookies() { return getStore().getCookies(); }
@Override public List<URI> getURIs() { return getStore().getURIs(); }
@Override public boolean remove(URI uri, HttpCookie cookie) { return getStore().remove(uri,cookie); }
@Override public boolean removeAll() { return getStore().removeAll(); }
@Override public int hashCode() { return getStore().hashCode(); }
protected CookieStore getStore() { return stores.get(); }
public void purgeStore() { stores.remove(); }
}
没有太多的代码就变得非常简单,设置cookie存储,与任何策略值,例如:
CookieHandler.setDefault(new java.net.CookieManager(
new ThreadLocalCookieStore(), CookiePolicy.ACCEPT_ALL));
此外,依赖设有一个小型sevlet @WebFilter
,以如果需要在多个请求的serlvet分开饼干店。
Answer 6:
您可以为饼干不同的路径。 因此,它不会被覆盖。
http://docs.oracle.com/javase/6/docs/api/java/net/HttpCookie.html#setPath%28java.lang.String%29
Answer 7:
怎么样一个ThreadLocal CookieManager? 同样的想法,因为一些其他的答案,但似乎需要更少的代码:
public class ThreadLocalCookies extends CookieManager {
private static CookiePolicy s_policy = null;
private static ThreadLocal<CookieManager> s_impl =
new ThreadLocal<CookieManager>() {
@Override protected CookieManager initialValue() {
if (null == s_policy) {
throw new IllegalStateException("Call install() first");
}
return new CookieManager(null, s_policy);
}
};
public static void install() {
install(CookiePolicy.ACCEPT_ALL);
}
public static void install(CookiePolicy policy) {
s_policy = policy;
CookieHandler.setDefault(new ThreadLocalCookies());
}
public static void clear() {
s_impl.set(new CookieManager(null, s_policy));
}
@Override
public Map<String, List<String>>
get(URI uri, Map<String, List<String>> requestHeaders)
throws IOException {
return s_impl.get().get(uri, requestHeaders);
}
@Override
public void put(URI uri, Map<String,List<String>> responseHeaders)
throws IOException {
s_impl.get().put(uri, responseHeaders);
}
}
文章来源: CookieManager for multiple threads