new DefaultHttpClient过时处理建议和HTTP调用后关闭流处理

最近写新的调用代码时候,发现项目中new DefaultHttpClient()实例过期很久了,翻了翻另一个生产项目调用端的代码也是如此,于是查阅了些资料,用新版本代码替换了手上项目的代码并且正常测试完、生产上也正常运行完,算是一次补习,特记录下替换过程和调用完后的处理。

1:来看下原来的调用代码,也是最常用的(httpclient版本超过4.2.6):(仅限于引用org.apache.httpcomponents的调用方式)

  项目原先用的4.3.1,过了4.2.6就已经过时了,过时代码下面我会标注。  

复制代码
       HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("调用地址");
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        formparams.add(new BasicNameValuePair("参数队列头部", 调用参数));
        System.out.println("==== 提交参数 ======" +formparams);
        UrlEncodedFormEntity uefEntity;
        try {
            uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
            httppost.setEntity(uefEntity);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if(entity!=null){
                String results=EntityUtils.toString(entity, "UTF-8");
                System.out.println("接口返回值="+results);
            }
         EntityUtils.consume(entity);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭连接,释放资源
            httpclient.getConnectionManager().shutdown();
        }
复制代码

  

  从4.2.6版本后,原作用类就出现了过时标识注明,看了maven仓更新时间2013-09-04是4.2.6和4.3同时发布的。

 

2:下面看下DefaultHttpClient的源码:(追溯源码)

 

复制代码
 * @since 4.0
  *
  * @deprecated (4.3) use {@link HttpClientBuilder}.
  */
 @ThreadSafe
 @Deprecated
 public class DefaultHttpClient extends AbstractHttpClient {
 
     /**
      * Creates a new HTTP client from parameters and a connection manager.
      *
      * @param params    the parameters
      * @param conman    the connection manager
      */
     public DefaultHttpClient(
             final ClientConnectionManager conman,
             final HttpParams params) {
         super(conman, params);
     }
复制代码

  看得出来为什么过时了还能用,DefaultHttpClient 继承了 AbstractHttpClient,AbstractHttpClient 继承了CloseableHttpClient。

  ”Creates a new HTTP client from parameters and a connection manager“ ,创建一个HTTP管理连接的一个”动作“类。

  ”* @deprecated (4.3) use {@link HttpClientBuilder}.“ ,说明从4.3版本后使用httpclientBuilder新的类,类httpclientBuilder的头部介绍:

  ”* Please note that some settings used by this class can be mutually exclusive and may not apply when building {@link CloseableHttpClient}“,翻译过来是和CloseableHttpClient有互斥性,看到有hostname,ssl安全证书加载这些就知道是中后期才会运行到的,都是在外部封装类运行提交的参数后内部运行的。

  

  这是调式模式下,图中可以看到参数会传递到httpClientBuilder中处理。

  

  综合资料和httpClientBuilder的作用写下新的调用代码(HttpClientBuilder里CloseableHttpClient的build方法):

复制代码
private static final CloseableHttpClient httpClient;
    static {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
        httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
    }

    public static void TestHttpPost(String url, String jsonData) {
        HttpPost httpPost = new HttpPost("调用地址");
        // 拼接参数
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        list.add(new BasicNameValuePair("参数队列头部", 调用参数));
        System.out.println("==== 提交参数 ======" + list);
        CloseableHttpResponse response = null;
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(list));
            response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                httpPost.abort();
                throw new RuntimeException("HttpClient,error status code :" + statusCode);
            }
            System.out.println("========HttpResponseProxy:========" + statusCode);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                System.out.println("========接口返回=======" + result);
            }
            EntityUtils.consume(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
 
复制代码

 

  看AbstractHttpClient 继承了CloseableHttpClient的CloseableHttpClient:

  @ThreadSafe //线程安全
  public abstract class CloseableHttpClient implements HttpClient, Closeable

  不难看出实现了httpclient,那么调用方法有了,还实现了关闭流,说明调用完毕后会做关闭处理。CloseableHttpResponse也替换了原来的HttpResponse ,使用CloseableHttpClient的新版本代码:

 

复制代码
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(”调用地址“);        
        //拼接参数
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        list.add(new BasicNameValuePair("参数队列头部", 调用参数));
        System.out.println("==== 提交参数 ======" +list);
        CloseableHttpResponse response  = null;
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(list));
            response = httpClient.execute(httpPost);
            System.out.println("========HttpResponseProxy:========"+response.getStatusLine());
            HttpEntity entity = response.getEntity();
            if(entity != null){
                String result = EntityUtils.toString(entity, "UTF-8");
                System.out.println("========接口返回=======" +result);
            }
            EntityUtils.consume(entity);
            //httpClient.getConnectionManager().shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(httpClient != null){
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
复制代码

 

   

3:旧版本调用完处理和新版本调用完处理:

  先看旧版本的关闭方法,

  httpclient.getConnectionManager().shutdown();

  只要httpclient开启后,BasicClientConnectionManager里的托管连接connManager初始化,其中shutdown开启 = false,运行完调用shutdown方法变 = true。

  Response接收httpEntity返回参数时,EntityUtils.consume(entity);关闭参数流操作。

  总结:连接动作关闭,接收参数流关闭。

复制代码
public static void consume(final HttpEntity entity) throws IOException {
        if (entity == null) {
            return;
        }
        if (entity.isStreaming()) {
            final InputStream instream = entity.getContent();
            if (instream != null) {
                instream.close();
            }
        }
    }
复制代码

 

  新方法调用后关闭方法,

  httpClient.close();

  新方法是开启了CloseableHttpClient后,PoolingHttpClientConnectionManager赋值CloseableHttpClient 对象并初始化,shutdown为开启状态。

  httpClient.getConnectionManager().shutdown(); 和 httpClient.close(); 都是关闭调用功能,因为实现类都impl实现了Closeable关闭流操作,所以在client端调用哪个方法都是可以关闭的,只是有些方法被注明过时了,用新方法不用担心出现@Deprecated标记。

 

4:总结:

  因为每次调用的不同,不及时关闭在大请求量下就需要谨慎设计代码的安全性了。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值