HttpClient4.1.1到4.2升级timeout等参数设定的问题

  HttpClient是不错的http工具,可是每次升级api都变化很大,可能是4.x版本时间太短还不够稳定吧。今天在升级的时候遇到了一个问题。http请求设定的超时时间没有用了。之前获取httpclient实例的工具类如下

01 import org.apache.http.conn.ClientConnectionManager;
02 import org.apache.http.conn.params.ConnManagerParams;
03 import org.apache.http.conn.params.ConnPerRouteBean;
04 import org.apache.http.conn.scheme.PlainSocketFactory;
05 import org.apache.http.conn.scheme.Scheme;
06 import org.apache.http.conn.scheme.SchemeRegistry;
07 import org.apache.http.conn.ssl.SSLSocketFactory;
08 import org.apache.http.impl.client.DefaultHttpClient;
09 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
10 import org.apache.http.params.BasicHttpParams;
11 import org.apache.http.params.HttpConnectionParams;
12 import org.apache.http.params.HttpParams;
13  
14 public class HttpConnectionManager {
15  
16     private static HttpParams httpParams;
17     private static ClientConnectionManager connectionManager;
18  
19     /**
20      * 最大连接数
21      */
22     public final static int MAX_TOTAL_CONNECTIONS = 800;
23     /**
24      * 获取连接的最大等待时间
25      */
26     public final static int WAIT_TIMEOUT = 60000;
27     /**
28      * 每个路由最大连接数
29      */
30     public final static int MAX_ROUTE_CONNECTIONS = 400;
31     /**
32      * 连接超时时间
33      */
34     public final static int CONNECT_TIMEOUT = 30000;
35     /**
36      * 读取超时时间
37      */
38     public final static int READ_TIMEOUT = 30000;
39  
40     static {
41         httpParams = new BasicHttpParams();
42         // 设置最大连接数
43  
44         ConnManagerParams.setMaxTotalConnections(httpParams,
45                 MAX_TOTAL_CONNECTIONS);
46         // 设置获取连接的最大等待时间
47         ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT);
48         // 设置每个路由最大连接数
49         ConnPerRouteBean connPerRoute = new ConnPerRouteBean(
50                 MAX_ROUTE_CONNECTIONS);
51         ConnManagerParams.setMaxConnectionsPerRoute(httpParams, connPerRoute);
52         // 设置连接超时时间
53         HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
54         // 设置读取超时时间
55         HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT);
56  
57         SchemeRegistry registry = new SchemeRegistry();
58         registry.register(new Scheme("http", PlainSocketFactory
59                 .getSocketFactory(), 80));
60         registry.register(new Scheme("https", SSLSocketFactory
61                 .getSocketFactory(), 443));
62  
63         connectionManager = new ThreadSafeClientConnManager(httpParams,
64                 registry);
65     }
66  
67     public static DefaultHttpClient getHttpClient() {
68         return new DefaultHttpClient(connectionManager, httpParams);
69     }
70  
71     public static void shutdown() {
72         connectionManager.shutdown();
73     }
74  
75 }

很简单的一个类,初始化一些设置,然后提供一个getHttpClient方法,这里设定httpParam使用的是DefaultHttpClient的构造方法。很简单。

但是到了4.2~~~~。这个构造方法没有了。。xd,不再可以直接传递httpParams进去设定。

所以。。

 

1 HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
2 HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT);

 

根本就不管用。。。HttpConnectionParams的两个方法如下

 

01 public static void setConnectionTimeout(final HttpParams params, int timeout) {
02     if (params == null) {
03         throw new IllegalArgumentException("HTTP parameters may not be null");
04     }
05     params.setIntParameter
06         (CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);
07 }
08 public static void setSoTimeout(final HttpParams params, int timeout) {
09     if (params == null) {
10         throw new IllegalArgumentException("HTTP parameters may not be null");
11     }
12     params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);
13  
14 }

就是给传进来的httpParams设定两个参数而已。那这两个set方法对应的get方法在哪里调用呢。。我们看代码。
 
观察 httpclient.execute(httpget)方法,跳到AbstractHttpClient的execute方法,代码如下

 

01 public final HttpResponse execute(HttpHost target, HttpRequest request,
02                                   HttpContext context)
03     throws IOException, ClientProtocolException {
04  
05     if (request == null) {
06         throw new IllegalArgumentException
07             ("Request must not be null.");
08     }
09     // a null target may be acceptable, this depends on the route planner
10     // a null context is acceptable, default context created below
11  
12     HttpContext execContext = null;
13     RequestDirector director = null;
14     HttpRoutePlanner routePlanner = null;
15     ConnectionBackoffStrategy connectionBackoffStrategy = null;
16     BackoffManager backoffManager = null;
17  
18     // Initialize the request execution context making copies of
19     // all shared objects that are potentially threading unsafe.
20     synchronized (this) {
21  
22         HttpContext defaultContext = createHttpContext();
23         if (context == null) {
24             execContext = defaultContext;
25         } else {
26             execContext = new DefaultedHttpContext(context, defaultContext);
27         }
28         // Create a director for this request
29         director = createClientRequestDirector(
30                 getRequestExecutor(),
31                 getConnectionManager(),
32                 getConnectionReuseStrategy(),
33                 getConnectionKeepAliveStrategy(),
34                 getRoutePlanner(),
35                 getProtocolProcessor(),
36                 getHttpRequestRetryHandler(),
37                 getRedirectStrategy(),
38                 getTargetAuthenticationStrategy(),
39                 getProxyAuthenticationStrategy(),
40                 getUserTokenHandler(),
41                 determineParams(request));
42         routePlanner = getRoutePlanner();
43         connectionBackoffStrategy = getConnectionBackoffStrategy();
44         backoffManager = getBackoffManager();
45     }

看41行的方法

01     protected HttpParams determineParams(HttpRequest req) {
02         return new ClientParamsStack
03             (null, getParams(), req.getParams(), null);
04     }
05 //还有getParams()
06     public synchronized final HttpParams getParams() {
07         if (defaultParams == null) {
08             defaultParams = createHttpParams();
09         }
10         return defaultParams;
11     }

发现了吧。。httpclient的request参数,是这么初始化的,但是你根本就没给他传递过来httpParams,所以defaultParams是null,自己创建了一个。。我们看timeout的获取代码,在DefaultRequestDirector#execute 方法中,太长了,我就贴关键代码

 

1 long timeout = HttpClientParams.getConnectionManagerTimeout(params);
2 try {
3      managedConn = connRequest.getConnection(timeout, TimeUnit.MILLISECONDS);
4 } catch(InterruptedException interrupted) {
5      InterruptedIOException iox = new InterruptedIOException();
6      iox.initCause(interrupted);
7      throw iox;
8 }

哦。原来之前在工具类中设定的timeout参数是这么获取的。看看getConnectionManagerTimeout干啥了。相关代码

 

1 public static int getConnectionTimeout(final HttpParams params) {
2     if (params == null) {
3         throw new IllegalArgumentException("HTTP parameters may not be null");
4     }
5     return params.getIntParameter
6         (CoreConnectionPNames.CONNECTION_TIMEOUT, 0);
7 }

坑爹啊。传过来的params是刚才httpclient自己创建的。你去获得参数。当然是为空。。然后设定为0了。。所以timeout根本就不管用。。。

所以说。。在工具类里面设定HttpConnectionParams根本就不管用,因为你给httpParams设定的参数,httpclient根本就没接收到,最后的解决办法很简单,自己设定下httpParams好了。。修改后的代码

 

01 import org.apache.http.conn.scheme.PlainSocketFactory;
02 import org.apache.http.conn.scheme.Scheme;
03 import org.apache.http.conn.scheme.SchemeRegistry;
04 import org.apache.http.conn.ssl.SSLSocketFactory;
05 import org.apache.http.impl.client.DefaultHttpClient;
06 import org.apache.http.impl.conn.PoolingClientConnectionManager;
07 import org.apache.http.params.BasicHttpParams;
08 import org.apache.http.params.CoreConnectionPNames;
09 import org.apache.http.params.CoreProtocolPNames;
10 import org.apache.http.params.HttpParams;
11  
12 public class HttpConnectionManager {
13  
14     private static HttpParams httpParams;
15     private static PoolingClientConnectionManager cm;
16  
17     /**
18      * 最大连接数
19      */
20     public final static int MAX_TOTAL_CONNECTIONS = 200;
21     /**
22      * 每个路由最大连接数
23      */
24     public final static int MAX_ROUTE_CONNECTIONS = 20;
25     /**
26      * 连接超时时间
27      */
28     public final static int CONNECT_TIMEOUT = 30000;
29     /**
30      * 读取超时时间
31      */
32     public final static int READ_TIMEOUT = 30000;
33  
34     static {
35         httpParams = new BasicHttpParams();
36         // 连接请求超时
37         httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
38                 CONNECT_TIMEOUT);
39         // 数据读取超时
40         httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, READ_TIMEOUT);
41         // 编码
42         httpParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,
43                 "UTF-8");
44         SchemeRegistry schemeRegistry = new SchemeRegistry();
45         schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory
46                 .getSocketFactory()));
47         schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory
48                 .getSocketFactory()));
49         cm = new PoolingClientConnectionManager(schemeRegistry);
50         // Increase max total connection to 200
51         cm.setMaxTotal(MAX_TOTAL_CONNECTIONS);
52         // Increase default max connection per route to 20
53         cm.setDefaultMaxPerRoute(MAX_ROUTE_CONNECTIONS);
54     }
55  
56     public static DefaultHttpClient getHttpClient() {
57         DefaultHttpClient httpClient = new DefaultHttpClient(cm);
58         httpClient.setParams(httpParams);
59         return httpClient;
60     }
61  
62     public static void shutdown() {
63         cm.shutdown();
64     }
65  
66     public static PoolingClientConnectionManager getConnectionManager() {
67         return cm;
68     }
69  
70 }


over了。。真是蛋疼啊。

 

ps:实际想想,既然没有了直接设定httpParams的地方,那应该提供方法了吧,还是我自己的思路有问题。。对httpclient了解不够深。。

参考:

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html

http://blog.csdn.net/shootyou/article/details/6415248

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值