文档章节

HttpClient4.5使用

xlj44400
 xlj44400
发布于 2016/07/13 18:41
字数 1306
阅读 782
收藏 4

HttpClient简介

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient支持的功能如下:

  • 支持Http0.9、Http1.0和Http1.1协议。
  • 实现了Http全部的方法(GET,POST,PUT,HEAD 等)。
  • 支持HTTPS协议。
  • 支持代理服务器。
  • 提供安全认证方案。
  • 提供连接池以便重用连接。
  • 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
  • 在http1.0和http1.1中利用KeepAlive保持长连接。

以前是commons-httpclient,后面被Apache HttpComponents取代,目前版本4.5.x,我们现在用的就是4.5版本

HttpClient连接池使用

为什么要用Http连接池:

1、降低延迟:如果不采用连接池,每次连接发起Http请求的时候都会重新建立TCP连接(经历3次握手),用完就会关闭连接(4次挥手),如果采用连接池则减少了这部分时间损耗

2、支持更大的并发:如果不采用连接池,每次连接都会打开一个端口,在大并发的情况下系统的端口资源很快就会被用完,导致无法建立新的连接
  • 默认http协议:
private static final Charset CHAR_SET = Charset.forName("utf-8");
private static PoolingHttpClientConnectionManager cm;

	public void init() {
		cm = new PoolingHttpClientConnectionManager();
		cm.setMaxTotal(50);
		cm.setDefaultConnectionConfig(ConnectionConfig.custom()
				.setCharset(CHAR_SET).build());
		SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(30000)
				.setSoReuseAddress(true).build();
		cm.setDefaultSocketConfig(socketConfig);
		// HttpProtocolParams.setContentCharset(httpParams, "UTF-8");
		// HttpClientParams.setCookiePolicy(httpParams, "ignoreCookies");
		// HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
		// HttpConnectionParams.setSoTimeout(httpParams, 30000);
		httpClient = HttpClientBuilder.create().setConnectionManager(cm)
				.build();
	}

	public CloseableHttpClient getHttpClient() {
		int timeout=2;
		RequestConfig config = RequestConfig.custom()
				.setConnectTimeout(timeout * 1000) //设置连接超时时间,单位毫秒
				//.setConnectionRequestTimeout(timeout * 1000) //设置从connect Manager获取Connection 超时时间,单位毫秒
				.setSocketTimeout(timeout * 1000).build(); //请求获取数据的超时时间,单位毫秒
		CloseableHttpClient _httpClient = HttpClients.custom()
				.setConnectionManager(cm).setDefaultRequestConfig(config)
				.build();
		if(cm!=null&&cm.getTotalStats()!=null) { //打印连接池的状态		
			LOGGER.info("now client pool {}",cm.getTotalStats().toString());
		}
		return _httpClient;
	}

	public String post(String url, Map<String, String> params) {
		HttpPost post = new HttpPost(url);
		String resp = null;
		try {
			if(params != null){
				List<NameValuePair> nvps = new ArrayList<NameValuePair>();
				for (Map.Entry<String, String> param : params.entrySet()) {
					nvps.add(new BasicNameValuePair(param.getKey(), param.getValue()));
				}
				post.setEntity(new UrlEncodedFormEntity(nvps, CHAR_SET));
			}
			
			try {
				HttpResponse response = httpClient.execute(post);
				InputStream input = response.getEntity().getContent();
				resp = IOUtils.toString(input);
			} catch (ClientProtocolException e) {
				LOGGER.error(e.getMessage(), e);
			} catch (IOException e) {
				LOGGER.error(e.getMessage(), e);
			} catch (Exception e) {
				LOGGER.error(e.getMessage(), e);
			}
		} finally {
			if (post != null)
				post.releaseConnection();
		}
		return resp;
	}
  • https协议:
public class HttpConnectionManager {

    PoolingHttpClientConnectionManager cm = null;
    
    public void init() {
        LayeredConnectionSocketFactory sslsf = null;
        try {
            sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("https", sslsf)
                .register("http", new PlainConnectionSocketFactory())
                .build();
        cm =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        cm.setMaxTotal(200);
        cm.setDefaultMaxPerRoute(20);
    }

    public CloseableHttpClient getHttpClient() {       
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                .build();          
        
        /*
        //如果不采用连接池就是这种方式获取连接
        CloseableHttpClient httpClient = HttpClients.createDefault();
        */
        return httpClient;
    }
}
  • httpClient使用
catch (Exception e) {
            logger.error("ufile send error e:",e);
            try {
                if (resEntity != null && resEntity.getContent() != null) {
                    resEntity.getContent().close();
                }
            } catch (IllegalStateException | IOException e1) {
                logger.error("ufile send error e1:",e1);
            } finally {
                if (getMethod!=null) {
                    getMethod.releaseConnection();
                }
                /*if (httpClient!=null) { //连接池使用的时候不能关闭连接,否则下次使用会抛异常 java.lang.IllegalStateException: Connection pool shut down
                    try {
                        httpClient.close();
                    } catch (IOException e2) {
                        logger.error("ufile httpclient close error e2:",e2);
                    }
                }*/
            }
        }
  • 连接池使用注意事项:
    1. 连接池中连接都是在发起请求的时候建立,并且都是长连接
    
    2. HttpResponse input.close();作用就是将用完的连接释放,下次请求可以复用,这里特别注意的是,如果不使用in.close();而仅仅使用httpClient.close();结果就是连接会被关闭,并且不能被复用,这样就失去了采用连接池的意义。
    
    3. 连接池释放连接的时候,并不会直接对TCP连接的状态有任何改变,只是维护了两个Set,leased和avaliabled,leased代表被占用的连接集合,avaliabled代表可用的连接的集合,释放连接的时候仅仅是将连接从leased中remove掉了,并把连接放到avaliabled集合中
    

打印的状态:

INFO c.m.p.u.h.HttpClientUtils[72] - now client pool [leased: 0; pending: 0; available: 0; max: 50]

leased :the number of persistent connections tracked by the connection manager currently being used to execute requests.  
  
available :the number idle persistent connections.  
  
pending : the number of connection requests being blocked awaiting a free connection.  
  
max: the maximum number of allowed persistent connections.  

HttpClient 4.5超时设置

4.5版本中,这两个参数的设置都抽象到了RequestConfig中,由相应的Builder构建,具体的例子如下:

CloseableHttpClient httpclient = HttpClients.createDefault();  
HttpGet httpGet = new HttpGet("http://stackoverflow.com/");  
RequestConfig requestConfig = RequestConfig.custom()  
      .setConnectTimeout(5000).setConnectionRequestTimeout(1000)  
      .setSocketTimeout(5000).build();  
httpGet.setConfig(requestConfig);  
CloseableHttpResponse response = httpclient.execute(httpGet);  
System.out.println("得到的结果:" + response.getStatusLine());//得到请求结果  
HttpEntity entity = response.getEntity();//得到请求回来的数据
  • setConnectTimeout:设置连接超时时间,单位毫秒。ConnectTimeoutException
  • setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。ConnectionPoolTimeout
  • setSocketTimeout:请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。SocketTimeoutException
  • 上面3个时间4.5版本默认是-1,就是不限,如果不设置就会一直等待

© 著作权归作者所有

共有 人打赏支持
xlj44400
粉丝 1
博文 3
码字总数 3826
作品 0
高级程序员
私信 提问
httpclient4.5请求重试

大家好,我用httpclient4.5设置请求重试的时候,怎么也设置不行,谁能贴一段能用的代码呀,谢谢!httpclient各种版本都不一样,真是坑.....

银粟
2016/01/19
1K
3
问下httpclient怎么能对服务端进行断点调试

我是用httpclient4.5写的客户端和服务端进行交互,但是客户端的statusCode老是报500,估计是服务端代码出错了,但是不知道怎么能通过运行客户端代码对服务端进行断点调试有没有会的啊。或者有...

冬夜的星空
2017/08/05
59
1
httpclient跳过https请求的验证

一、因为在使用https发送请求的时候会涉及,验证方式。但是这种方式在使用的时候很不方便。特别是在请求外部接口的时候,所以这我写了一个跳过验证的方式。(供参考) 二、加入包,这里用的是...

小不点丶
2017/07/12
0
0
HttpClient4.5 上传文件失败

@JFinal 你好,想跟你请教个问题: 我使用httpclient上传附件的时候报Separation boundary was not specified 下面是方法方法的代码

简洛-默
2015/11/05
2K
3
有关于httpclient4.5进行CA证书认证

鄙人做了个小项目,在eclipse搭建了一个客户端项目和一个服务端项目,客户端将文件流和印章图片流上传至服务端,服务端将印章盖在文件后化为流返回到客户端,客户端再输出到本地,功能是做出...

冬夜的星空
2017/07/31
104
5

没有更多内容

加载失败,请刷新页面

加载更多

80后阿里P10,“关老板”如何带着MaxCompute一路升级?

我是个幸运的人。虽然幸运不能被复制,但是眼光和努力可以。 关涛/关老板,80后的阿里P10,阿里巴巴通用计算平台负责人,阿里巴巴计算平台研究员。12年职场人生,微软和阿里的选择。 关涛的花...

阿里云官方博客
18分钟前
0
0
开源软件和开源模式面临的生存危机

开源模式可能正面临一场危机。越来越多的开源软件和平台被大型云计算服务商融入自家的云服务体系,并以此获利颇丰,但并不支付费用,也没有对开源社区做出相应的回馈。而实际上,大部分开源软...

Linux就该这么学
18分钟前
0
0
统一服务消息返回错误:{"errcode":40165,"errmsg":"invalid weapp pagepath hint: [bsAWua0201ge30]"}

{"errcode":40165,"errmsg":"invalid weapp pagepath hint: [bsAWua0201ge30]"} 原因:pagepath参数为所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar), 以前配置的是:m...

tianma3798
20分钟前
0
0
ElasticSearch实战:Linux日志对接Kibana

本文由云+社区发表 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTFul web接口。ElasticSearch是用Java开发的,并作为Apache许可条款下...

腾讯云加社区
23分钟前
0
0
FeignClient超时配置

1前沿 使用Feign调用接口分两层,ribbon的调用和hystrix的调用,所以ribbon的超时时间和Hystrix的超时时间的结合就是Feign的超时时间 1.1ribbon配置 ribbon: OkToRetryOnAllOperations: f...

lovelan1314
26分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部