异步httpclient---HttpAsyncClient的使用
来源:互联网 发布:js 数字比大小 编辑:程序博客网 时间:2024/05/18 12:04
这两天研究了一下异步的httpclient ---- httpAsyncClient
原来使用httpclient都是同步的,如果项目中有大量的httpclient的话,可能会造成阻塞,如果使用异步请求的话可以避免这些问题
可以用在调用第三方接口或者不需要知道请求返回结果的场景下
于是写了一个工具类来封装了同步异步httpclient
github地址:https://github.com/a63881763/HttpAsyncClientUtils
1.首先需要在pom中添加需要的jar
<properties> <!-- log4j日志包版本号 --> <slf4j.version>1.7.25</slf4j.version> <log4j.version>2.8.2</log4j.version> </properties> <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.6</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.3.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpasyncclient</artifactId> <version>4.1.3</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j --> <!--用log4j接管commons-logging--> <!-- log配置:Log4j2 + Slf4j --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <!-- 桥接:告诉Slf4j使用Log4j2 --> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <!-- 桥接:告诉commons logging使用Log4j2 --> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jcl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.39</version> </dependency> </dependencies>
import org.apache.http.Consts;import org.apache.http.HttpHost;import org.apache.http.auth.AuthSchemeProvider;import org.apache.http.auth.AuthScope;import org.apache.http.auth.MalformedChallengeException;import org.apache.http.auth.UsernamePasswordCredentials;import org.apache.http.client.CredentialsProvider;import org.apache.http.client.config.AuthSchemes;import org.apache.http.client.config.RequestConfig;import org.apache.http.config.ConnectionConfig;import org.apache.http.config.Lookup;import org.apache.http.config.Registry;import org.apache.http.config.RegistryBuilder;import org.apache.http.conn.ssl.SSLContexts;import org.apache.http.impl.auth.*;import org.apache.http.impl.client.BasicCookieStore;import org.apache.http.impl.client.BasicCredentialsProvider;import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;import org.apache.http.impl.nio.client.HttpAsyncClients;import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;import org.apache.http.impl.nio.reactor.IOReactorConfig;import org.apache.http.nio.conn.NoopIOSessionStrategy;import org.apache.http.nio.conn.SchemeIOSessionStrategy;import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;import org.apache.http.nio.reactor.ConnectingIOReactor;import org.apache.http.nio.reactor.IOReactorException;import javax.net.ssl.SSLContext;import java.nio.charset.CodingErrorAction;import java.security.KeyManagementException;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.UnrecoverableKeyException;/** * 异步的HTTP请求对象,可设置代理 */public class HttpAsyncClient { private static int socketTimeout = 1000;// 设置等待数据超时时间5秒钟 根据业务调整 private static int connectTimeout = 2000;// 连接超时 private static int poolSize = 3000;// 连接池最大连接数 private static int maxPerRoute = 1500;// 每个主机的并发最多只有1500 // http代理相关参数 private String host = ""; private int port = 0; private String username = ""; private String password = ""; // 异步httpclient private CloseableHttpAsyncClient asyncHttpClient; // 异步加代理的httpclient private CloseableHttpAsyncClient proxyAsyncHttpClient; public HttpAsyncClient() { try { this.asyncHttpClient = createAsyncClient(false); this.proxyAsyncHttpClient = createAsyncClient(true); } catch (Exception e) { e.printStackTrace(); } } public CloseableHttpAsyncClient createAsyncClient(boolean proxy) throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, MalformedChallengeException, IOReactorException { RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(connectTimeout) .setSocketTimeout(socketTimeout).build(); SSLContext sslcontext = SSLContexts.createDefault(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials( username, password); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, credentials); // 设置协议http和https对应的处理socket链接工厂的对象 Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder .<SchemeIOSessionStrategy> create() .register("http", NoopIOSessionStrategy.INSTANCE) .register("https", new SSLIOSessionStrategy(sslcontext)) .build(); // 配置io线程 IOReactorConfig ioReactorConfig = IOReactorConfig.custom() .setIoThreadCount(Runtime.getRuntime().availableProcessors()) .build(); // 设置连接池大小 ConnectingIOReactor ioReactor; ioReactor = new DefaultConnectingIOReactor(ioReactorConfig); PoolingNHttpClientConnectionManager conMgr = new PoolingNHttpClientConnectionManager( ioReactor, null, sessionStrategyRegistry, null); if (poolSize > 0) { conMgr.setMaxTotal(poolSize); } if (maxPerRoute > 0) { conMgr.setDefaultMaxPerRoute(maxPerRoute); } else { conMgr.setDefaultMaxPerRoute(10); } ConnectionConfig connectionConfig = ConnectionConfig.custom() .setMalformedInputAction(CodingErrorAction.IGNORE) .setUnmappableInputAction(CodingErrorAction.IGNORE) .setCharset(Consts.UTF_8).build(); Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder .<AuthSchemeProvider> create() .register(AuthSchemes.BASIC, new BasicSchemeFactory()) .register(AuthSchemes.DIGEST, new DigestSchemeFactory()) .register(AuthSchemes.NTLM, new NTLMSchemeFactory()) .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()) .register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()) .build(); conMgr.setDefaultConnectionConfig(connectionConfig); if (proxy) { return HttpAsyncClients.custom().setConnectionManager(conMgr) .setDefaultCredentialsProvider(credentialsProvider) .setDefaultAuthSchemeRegistry(authSchemeRegistry) .setProxy(new HttpHost(host, port)) .setDefaultCookieStore(new BasicCookieStore()) .setDefaultRequestConfig(requestConfig).build(); } else { return HttpAsyncClients.custom().setConnectionManager(conMgr) .setDefaultCredentialsProvider(credentialsProvider) .setDefaultAuthSchemeRegistry(authSchemeRegistry) .setDefaultCookieStore(new BasicCookieStore()).build(); } } public CloseableHttpAsyncClient getAsyncHttpClient() { return asyncHttpClient; } public CloseableHttpAsyncClient getProxyAsyncHttpClient() { return proxyAsyncHttpClient; }}
3.httpclient的工厂类
/** * * httpclient 工厂类 * */public class HttpClientFactory { private static HttpAsyncClient httpAsyncClient = new HttpAsyncClient(); private static HttpSyncClient httpSyncClient = new HttpSyncClient(); private HttpClientFactory() { } private static HttpClientFactory httpClientFactory = new HttpClientFactory(); public static HttpClientFactory getInstance() { return httpClientFactory; } public HttpAsyncClient getHttpAsyncClientPool() { return httpAsyncClient; } public HttpSyncClient getHttpSyncClientPool() { return httpSyncClient; }}
4.httpclient的util
2017.11.22
发现每次异步连接回调成功后,连接总是延迟很久关,查了不少资料,发现httpAsyncClient默认是长连接,所以在不需要长连接的时候记得要把请求头中的connection设成false
/** * * http client 业务逻辑处理类 * */public class HttpClientUtil { private static Logger LOG = LoggerFactory .getLogger(HttpClientUtil.class); private static String utf8Charset = "utf-8"; /** * 向指定的url发送一次post请求,参数是List<NameValuePair> * @param baseUrl 请求地址 * @param list 请求参数,格式是List<NameValuePair> * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static String httpSyncPost(String baseUrl,List<BasicNameValuePair> list) { CloseableHttpClient httpClient = HttpClientFactory.getInstance().getHttpSyncClientPool().getHttpClient(); HttpPost httpPost = new HttpPost(baseUrl); //Parameters LOG.warn("==== Parameters ======" +list); CloseableHttpResponse response = null; try { httpPost.setEntity(new UrlEncodedFormEntity(list)); response = httpClient.execute(httpPost); LOG.warn("========HttpResponseProxy:========"+response.getStatusLine()); HttpEntity entity = response.getEntity(); String result = null; if(entity != null){ result = EntityUtils.toString(entity, "UTF-8"); LOG.warn("========Response=======" +result); } EntityUtils.consume(entity); return result; } catch (Exception e) { e.printStackTrace(); }finally { if(response != null){ try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 向指定的url发送一次post请求,参数是字符串 * @param baseUrl 请求地址 * @param postString 请求参数,格式是json.toString() * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestBody接收参数 */ public static String httpSyncPost(String baseUrl, String postString) { CloseableHttpClient httpClient = HttpClientFactory.getInstance().getHttpSyncClientPool().getHttpClient(); HttpPost httpPost = new HttpPost(baseUrl); //parameters LOG.warn("==== Parameters ======" +postString); CloseableHttpResponse response = null; try { if(postString == null || "".equals(postString)){ throw new Exception("missing post String"); } StringEntity stringEntity = new StringEntity(postString.toString(), utf8Charset); stringEntity.setContentEncoding("UTF-8"); stringEntity.setContentType("application/json"); httpPost.setEntity(stringEntity); response = httpClient.execute(httpPost); LOG.warn("========HttpResponseProxy:========"+response.getStatusLine()); HttpEntity entity = response.getEntity(); String result = null; if(entity != null){ result = EntityUtils.toString(entity, "UTF-8"); LOG.warn("========Response=======" +result); } EntityUtils.consume(entity); return result; } catch (Exception e) { e.printStackTrace(); }finally { if(response != null){ try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 向指定的url发送一次get请求,参数是List<NameValuePair> * @param baseUrl 请求地址 * @param list 请求参数,格式是List<NameValuePair> * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static String httpSyncGet(String baseUrl, List<BasicNameValuePair> list) { CloseableHttpClient httpClient = HttpClientFactory.getInstance().getHttpSyncClientPool().getHttpClient(); HttpGet httpGet = new HttpGet(baseUrl); //Parameters LOG.warn("==== Parameters ======" +list); CloseableHttpResponse response = null; try { if(list != null){ String getUrl = EntityUtils .toString(new UrlEncodedFormEntity(list)); httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + getUrl)); } else{ httpGet.setURI(new URI(httpGet.getURI().toString())); } response = httpClient.execute(httpGet); LOG.warn("========HttpResponseProxy:========"+response.getStatusLine()); HttpEntity entity = response.getEntity(); String result = null; if(entity != null){ result = EntityUtils.toString(entity, "UTF-8"); LOG.warn("========Response=======" +result); } EntityUtils.consume(entity); return result; } catch (Exception e) { e.printStackTrace(); }finally { if(response != null){ try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 向指定的url发送一次get请求,参数是字符串 * @param baseUrl 请求地址 * @param urlParams 请求参数,格式是String * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static String httpSyncGet(String baseUrl,String urlParams) { CloseableHttpClient httpClient = HttpClientFactory.getInstance().getHttpSyncClientPool().getHttpClient(); HttpGet httpGet = new HttpGet(baseUrl); //Parameters LOG.warn("==== Parameters ======" +urlParams); CloseableHttpResponse response = null; try { if (null != urlParams || "".equals(urlParams)) { httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + urlParams)); } else{ httpGet.setURI(new URI(httpGet.getURI().toString())); } response = httpClient.execute(httpGet); LOG.warn("========HttpResponseProxy:========"+response.getStatusLine()); HttpEntity entity = response.getEntity(); String result = null; if(entity != null){ result = EntityUtils.toString(entity, "UTF-8"); LOG.warn("========Response=======" +result); } EntityUtils.consume(entity); return result; } catch (Exception e) { e.printStackTrace(); }finally { if(response != null){ try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 向指定的url发送一次get请求,参数是字符串 * @param baseUrl 请求地址 * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static String httpSyncGet(String baseUrl) { CloseableHttpClient httpClient = HttpClientFactory.getInstance().getHttpSyncClientPool().getHttpClient(); HttpGet httpGet = new HttpGet(baseUrl); CloseableHttpResponse response = null; try { httpGet.setURI(new URI(httpGet.getURI().toString())); response = httpClient.execute(httpGet); LOG.warn("========HttpResponseProxy:========"+response.getStatusLine()); HttpEntity entity = response.getEntity(); String result = null; if(entity != null){ result = EntityUtils.toString(entity, "UTF-8"); LOG.warn("========Response=======" +result); } EntityUtils.consume(entity); return result; } catch (Exception e) { e.printStackTrace(); }finally { if(response != null){ try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 向指定的url发送一次异步post请求,参数是字符串 * @param baseUrl 请求地址 * @param postString 请求参数,格式是json.toString() * @param urlParams 请求参数,格式是String * @param callback 回调方法,格式是FutureCallback * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static void httpAsyncPost(String baseUrl,String postString, String urlParams,FutureCallback callback) throws Exception { if (baseUrl == null || "".equals(baseUrl)) { LOG.warn("we don't have base url, check config"); throw new Exception("missing base url"); } CloseableHttpAsyncClient hc = HttpClientFactory.getInstance().getHttpAsyncClientPool() .getAsyncHttpClient(); try { hc.start(); HttpPost httpPost = new HttpPost(baseUrl); httpPost.setHeader("Connection","close"); if (null != postString) { LOG.debug("exeAsyncReq post postBody={}", postString); StringEntity entity = new StringEntity(postString.toString(), utf8Charset); entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); } if (null != urlParams) { httpPost.setURI(new URI(httpPost.getURI().toString() + "?" + urlParams)); } LOG.warn("exeAsyncReq getparams:" + httpPost.getURI()); hc.execute(httpPost, callback); } catch (Exception e) { e.printStackTrace(); } } /** * 向指定的url发送一次异步post请求,参数是字符串 * @param baseUrl 请求地址 * @param urlParams 请求参数,格式是List<BasicNameValuePair> * @param callback 回调方法,格式是FutureCallback * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static void httpAsyncPost(String baseUrl, List<BasicNameValuePair> postBody, List<BasicNameValuePair> urlParams, FutureCallback callback ) throws Exception { if (baseUrl == null || "".equals(baseUrl)) { LOG.warn("we don't have base url, check config"); throw new Exception("missing base url"); } try { CloseableHttpAsyncClient hc = HttpClientFactory.getInstance().getHttpAsyncClientPool() .getAsyncHttpClient(); hc.start(); HttpPost httpPost = new HttpPost(baseUrl); httpPost.setHeader("Connection","close"); if (null != postBody) { LOG.debug("exeAsyncReq post postBody={}", postBody); UrlEncodedFormEntity entity = new UrlEncodedFormEntity( postBody, "UTF-8"); httpPost.setEntity(entity); } if (null != urlParams) { String getUrl = EntityUtils .toString(new UrlEncodedFormEntity(urlParams)); httpPost.setURI(new URI(httpPost.getURI().toString() + "?" + getUrl)); } LOG.warn("exeAsyncReq getparams:" + httpPost.getURI()); hc.execute(httpPost, callback); } catch (Exception e) { e.printStackTrace(); } } /** * 向指定的url发送一次异步get请求,参数是String * @param baseUrl 请求地址 * @param urlParams 请求参数,格式是String * @param callback 回调方法,格式是FutureCallback * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static void httpAsyncGet(String baseUrl,String urlParams,FutureCallback callback) throws Exception { if (baseUrl == null || "".equals(baseUrl)) { LOG.warn("we don't have base url, check config"); throw new Exception("missing base url"); } CloseableHttpAsyncClient hc = HttpClientFactory.getInstance().getHttpAsyncClientPool() .getAsyncHttpClient(); try { hc.start(); HttpGet httpGet = new HttpGet(baseUrl); httpGet.setHeader("Connection","close"); if (null != urlParams || "".equals(urlParams)) { httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + urlParams)); } else{ httpGet.setURI(new URI(httpGet.getURI().toString())); } LOG.warn("exeAsyncReq getparams:" + httpGet.getURI()); hc.execute(httpGet, callback); } catch (Exception e) { e.printStackTrace(); } } /** * 向指定的url发送一次异步get请求,参数是List<BasicNameValuePair> * @param baseUrl 请求地址 * @param urlParams 请求参数,格式是List<BasicNameValuePair> * @param callback 回调方法,格式是FutureCallback * @return 返回结果,请求失败时返回null * @apiNote http接口处用 @RequestParam接收参数 */ public static void httpAsyncGet(String baseUrl, List<BasicNameValuePair> urlParams, FutureCallback callback) throws Exception { if (baseUrl == null || "".equals(baseUrl)) { LOG.warn("we don't have base url, check config"); throw new Exception("missing base url"); } try { CloseableHttpAsyncClient hc = HttpClientFactory.getInstance().getHttpAsyncClientPool() .getAsyncHttpClient(); hc.start(); HttpPost httpGet = new HttpPost(baseUrl); httpGet.setHeader("Connection","close"); if (null != urlParams) { String getUrl = EntityUtils .toString(new UrlEncodedFormEntity(urlParams)); httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + getUrl)); } LOG.warn("exeAsyncReq getparams:" + httpGet.getURI()); hc.execute(httpGet, callback); } catch (Exception e) { e.printStackTrace(); } }}
工具类种有8种同步异步的post和get请求,通过不同的参数获得结果
本文章参考了http://blog.csdn.net/angjunqiang/article/details/55259170
阅读全文
0 0
- 异步httpclient---HttpAsyncClient的使用
- 异步httpclient(httpasyncclient)的使用与总结
- 异步HttpAsyncClient框架的学习和使用
- HttpAsyncClient (异步http 请求)的连接池使用
- 使用异步HTTP提升客户端性能(HttpAsyncClient)
- 使用异步HTTP提升客户端性能(HttpAsyncClient)
- HttpAsyncClient的连接池使用
- HttpAsyncClient使用中碰到的问题
- Java的异步HttpClient
- Java的异步HttpClient
- Java的异步HttpClient
- Java利用httpasyncclient进行异步HTTP请求
- Java利用httpasyncclient进行异步HTTP请求
- apache httpcompontens之HttpAsyncClient使用
- 使用第三方框架实现异步的HttpClient
- C# 中HttpClient的使用中同步异步问题
- Netty,HttpAsyncClient和阻塞I/O(Httpclient)比较
- 使用异步HttpClient框架提交数据
- Qt creator工程项目移植时因环境变换造成qmake错误的解决方案 1.问题描述:移植从他机上的qt工程项目,打开时提示: Qt Creator找到了一个由其他开发环境创建的设置文件,或许
- 洛谷P2904 [USACO08MAR]跨河River Crossing
- springmvc不进入Controller导致404
- java集合分析(8):AbstractSequentialList
- Java图案绘制
- 异步httpclient---HttpAsyncClient的使用
- elasticsearch 6.0安装手册
- MySQL Galera Cluster 快速删除大表
- ros总线舵机机械臂串口协议源码
- 一例Unable to determine composite primary key ordering for type错误的解决
- RabbitMQ入门教程(三):Hello World
- 回调函数实例
- Codeforces Round #447 (Div. 2) B. Ralph And His Magic Field(数论,组合数学)
- 配置QSslConfiguration让客户端程序跳过本地SSL验证