HttpURLConnection和CookieManager是否应自动处理会话cookie?

29

我有一个Java应用程序(JDK 1.7.0_13),正在使用java.net.HttpURLConnection连接到一些基于servlet的服务进行会话管理。我试图弄清楚如何使用java.net.CookieManager跟踪会话cookie。阅读文档,我得出结论,使用CookieHandler.setDefault(new CookieManager())安装CookieManager应自动执行cookie管理。然而,对同一URL进行多个请求似乎没有保留cookie。我是否必须手动从响应中提取cookie并自己在请求中重新发送它们,还是CookieManager会自动执行此操作?如果CookieManager不这样做,那么它有什么价值呢?

为了测试这些东西,我有一个Servlet,每次浏览器访问URL时都可以成功递增计数器。 Safari、FireFox和Chrome都可以正常工作...但是,我无法从独立的Java应用程序中使其工作。

下面是一个非常简单的测试程序,以说明我希望它可以简单地工作。它在启动时安装了CookieManager,然后随着在控制台上键入URL,重复调用fetch(String urlString)方法。

package com.brilliant.experimental;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpFetcher {  
    public static void fetch(String urlString) {
        try {
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            InputStream in = conn.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            int status = conn.getResponseCode();
            System.out.println("Status = " + status);
            String key;
            System.out.println("Headers-------start-----");
            for (int i = 1; (key = conn.getHeaderFieldKey(i)) != null; i++) {
                System.out.println(key + ":" + conn.getHeaderField(i));
            }
            System.out.println("Headers-------end-----");
            System.out.println("Content-------start-----");
            String inputLine;
            while ((inputLine = reader.readLine()) != null) {
                System.out.println(inputLine);
            }
            System.out.println("Content-------end-----");
            in.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public static void main(String[] args) {
        CookieHandler.setDefault(new CookieManager());

        for (int i = 0; i < args.length; i++) {
            fetch(args[i]);
        }

        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader reader = new BufferedReader(isr);
        String prompt = "> ";
        String urlString;
        try {
            for (System.out.print(prompt);
                    (urlString = reader.readLine()) != null; 
                    System.out.print(prompt)) 
            {
                fetch(urlString);
            }
        } catch (IOException ioe) {
            System.out.println(ioe);
        }
    }

}

从这个应用程序中调用我的servlet,清楚地会从服务器获取一个会话cookie。但是,再次调用会得到一个新的会话cookie。

> http://localhost:8080/brilliant/TestServlet
Status = 200
Headers-------start-----
Server:Resin/4.0.34
Cache-Control:private
Set-Cookie:JSESSIONID=aaaMp0uKke4gp9_-nUuZt; path=/
Content-Length:19
Date:Wed, 13 Feb 2013 18:02:31 GMT
Headers-------end-----
Content-------start-----
Session count is 0
Content-------end-----
> http://localhost:8080/brilliant/TestServlet
Status = 200
Headers-------start-----
Server:Resin/4.0.34
Cache-Control:private
Set-Cookie:JSESSIONID=aaaZ-oPaC1I9WdEDoUuZt; path=/
Content-Length:19
Date:Wed, 13 Feb 2013 18:02:33 GMT
Headers-------end-----
Content-------start-----
Session count is 0
Content-------end-----

总之,为了让CookieManager自动工作,我需要做些其他的事情吗?还是我必须手动从响应中提取cookie,并将其重新发送请求?


请转到https://dev59.com/4mct5IYBdhLWcg3wF5tF#32001630。最佳解决方案已经出现。 - hgg
1个回答

63
我运行了你的代码并替换了这个。
CookieHandler.setDefault(new CookieManager()); 

CookieHandler.setDefault( new CookieManager( null, CookiePolicy.ACCEPT_ALL ) );

它有效!


1
谢谢。运作得非常出色。当然,现在知道了答案,文档也很容易找到。;-) - Chuck
1
这是一个比通常能找到的更好、更紧凑的答案。谢谢! - Panayotis
1
这个操作会自动将Cookies添加到CookieStore吗?还是每次都需要写cookieManager.getCookieStore().add(uri,hc);? 其中的hc是一个HttpCookie Object - Mathews Mathai
1
这仅在第一次运行时有效...当我重新启动应用程序时,它会给我一个错误BasicNetwork.performRequest:意外的响应代码401...请帮忙! - Vivek Bhardwaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接