httpclient保持会话登录

1.连接池原理(待续)

2.httpclient连接池如何保证连接交回至连接池管理器

    2.1 方式一

HttpResponse response = (httpMethod);  
HttpEntity entity = response.getEntity();  
//这两段代码返回的entity是HttpEntity的实现类BasicManagedEntity。此时与本次请求关联的连接尚未归还至连接管理器。需要调用以下两条语句:  
InputStream instream = entity.getContent();//获得响应具体内容  
//处理响应:代码省略  
instream.close();//关闭输入流同时会将连接交回至连接处理器  

     2.2 方式二使用默认的响应处理器BasicResponseHandler

httpClient Jar包中提供BasicResponseHandler。如果返回的类型能确定需要解码为String类型的话,推荐使用该响应处理器。  
该处理器解码http连接响应字节流为String类型,对返回码>=300的响应进行了异常封装,并能够保证连接交还给连接池管理器。  
该处理器将字节解码为字符的过程依次如下:  
1)如果响应http报文Head部分由指定的charset,则使用该charset进行解码,否则进行下一步。例如使用UTF-8解码以下响应:DEBUG org.apache.http.headers - $amp;  
2)如果响应报文未执行charset,则使用传入EntityUntils.toString()时指定的charset进行解码。否则进行下一步  
3)使用ISO-8859-1进行解码。  

3.实现连接池(待续)

4.遇到的问题

    4.1 连接池阻塞,频繁的报以下错误信息

pooling post() method executing IOException:java.net.SocketTimeoutException: Read timed out  
java.net.SocketTimeoutException: Read timed out  
        at java.net.SocketInputStream.socketRead0(Native Method)  
        at java.net.SocketInputStream.read(SocketInputStream.java:129)  
        at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136)  
        at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:152)  
        at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:270)  
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)  
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)  
        at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260)  
        at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:161)  
        at sun.reflect.GeneratedMethodAccessor96.invoke(Unknown Source)  
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
        at java.lang.reflect.Method.invoke(Method.java:597)  
        at org.apache.http.impl.conn.CPoolProxy.invoke(CPoolProxy.java:138)  
        at com.sun.proxy.$Proxy43.receiveResponseHeader(Unknown Source)  
        at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271)  
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)  
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:254)  
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)  
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)  
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)  
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)  
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72)  
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:214)  
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:160)  
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:136)  

 上述问题主要问题是连接池中httpclient连接在遇到异常情况下未正常关闭导致,出问题时候连接池关于回收httpclient连接的代码如下:

private ResponseHandler<String> responseHandler = new ResponseHandler<String>() {  
    public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {  
        int status = response.getStatusLine().getStatusCode();  
        if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {  
            HttpEntity entity = response.getEntity();  
              
            Charset charset = ContentType.getOrDefault(entity).getCharset();  
            if (charset == null) {  
                charset = Charset.forName("UTF-8");  
            }  
            return entity != null ? EntityUtils.toString(entity, charset) : null;  
        } else {  
                            //注意这里没有告诉连接池要回收连接  
            throw new ClientProtocolException("Unexpected response status: " + status);  
        }  
};  

 修改后的代码如下:

private ResponseHandler<String> responseHandler = new ResponseHandler<String>() {  
    public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {  
  
        final StatusLine statusLine = response.getStatusLine();  
        final HttpEntity entity = response.getEntity();  
        if (statusLine.getStatusCode() >= HttpStatus.SC_MULTIPLE_CHOICES||statusLine.getStatusCode()<HttpStatus.SC_OK) {  
            //主动回收httpclient连接  
        EntityUtils.consume(entity);  
            throw new HttpResponseException(statusLine.getStatusCode(),  
                    statusLine.getReasonPhrase());  
        }  
        Charset charset = ContentType.getOrDefault(entity).getCharset();  
        if (charset == null) {  
            charset = Charset.forName("UTF-8");  
        }  
        return entity != null ? EntityUtils.toString(entity, charset) : null;  
    }  
};  

相关推荐