API:API
1.X和2.X差别很大,我用的1.X中的最新版 1.9.39。
这是一个异步请求的工具,越简单越好,不喜欢再结合netty使用。AsyncHttpClient底层使用java线程池
this.applicationThreadPool = Executors.newCachedThreadPool(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "AsyncHttpClient-Callback");
t.setDaemon(true);
return t;
}
});
这样的线程池最大线程数没有限制(Integer.MAX_VALUE),就知道开开开线程,在某种情况下会很容易搞垮我们的系统,所以在下面的单例类中做了限制
configBuilder.setMaxConnections(2);
限制提交的数量。可以看出线程池中的线程是daemon的,当所有非daemon线程退出后jvm将退出!!!
写了个单例类,供参考
import com.ning.http.client.*;importjava.util.Iterator;importjava.util.Map;importjava.util.Set;importjava.util.concurrent.Future;/*** Created by yhzh on 2016/9/19.*/
public classMlsAsyncHttpClient {privateAsyncHttpClient client;private static classHttpClientHolder{private static MlsAsyncHttpClient httpClient=newMlsAsyncHttpClient();
}privateMlsAsyncHttpClient(){
AsyncHttpClientConfig.Builder configBuilder=newAsyncHttpClientConfig.Builder();
configBuilder.setMaxConnections(2);/*使用默认值:
configBuilder.setConnectTimeout(3000);
configBuilder.setReadTimeout(5000);*/configBuilder.setRequestTimeout(60000);this.client=newAsyncHttpClient(configBuilder.build());
}public staticMlsAsyncHttpClient getAsyncHttpClient(){returnHttpClientHolder.httpClient;
}public Futureget(String url) {return this.client.prepareGet(url).execute();
}public voidget(String url, AsyncHandler resHandler) {this.client.prepareGet(url).execute(resHandler);
}public Futurepost(String url) {return this.client.preparePost(url).execute();
}public voidpost(String url,AsyncHandler resHandler) {this.client.preparePost(url).execute(resHandler);
}private Request buildRequest(String url, MapparamsMap){
RequestBuilder requestBuilder= newRequestBuilder();if(paramsMap != null && paramsMap.size() > 0) {
Set> entrySet =paramsMap.entrySet();
Iterator> iterator =entrySet.iterator();while(iterator.hasNext()) {
Map.Entry entry =iterator.next();if(entry.getKey() != null) {
requestBuilder.addFormParam(entry.getKey(), entry.getValue());
}
}
}//添加RequestHeader,key
requestBuilder.addHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
requestBuilder.setMethod("POST");
requestBuilder.setUrl(url);returnrequestBuilder.build();
}public Future post(String url, MapparamsMap) {
Request req=this.buildRequest(url,paramsMap);return this.client.executeRequest(req);
}public void post(String url, MapparamsMap, AsyncHandler resHandler) {
Request req=this.buildRequest(url,paramsMap);this.client.executeRequest(req,resHandler);//this.client.preparePost(url).execute(responseHandler);
}
}
测试代码
@Testpublic void testSelectLoanResultOfLoanResultsOfZgController() throwsInterruptedException {
CountDownLatch completionLatch= new CountDownLatch(2);//com.ning.http.client.providers.netty.NettyAsyncHttpProvider
MlsAsyncHttpClient.getAsyncHttpClient().get("http://127.0.0.1:8081/assetmgmt/ploanouter/repayplan?lrid=0",newAsyncHandler() {private ByteArrayOutputStream bytes = newByteArrayOutputStream();boolean done=false;
@Overridepublic STATE onStatusReceived(HttpResponseStatus status) throwsException {int statusCode =status.getStatusCode();if (statusCode >= 500) {returnSTATE.ABORT;
}returnSTATE.CONTINUE;
}
@Overridepublic STATE onHeadersReceived(HttpResponseHeaders httpResponseHeaders) throwsException {
FluentCaseInsensitiveStringsMap str=httpResponseHeaders.getHeaders();returnSTATE.CONTINUE;
}
@Overridepublic STATE onBodyPartReceived(HttpResponseBodyPart httpResponseBodyPart) throwsException {
bytes.write(httpResponseBodyPart.getBodyPartBytes());returnSTATE.CONTINUE;
}
@Overridepublic Object onCompleted() throwsException {
String str=bytes.toString("utf-8");
System.out.println("get baidu:");
completionLatch.countDown();return null;
}
@Overridepublic voidonThrowable(Throwable t){if(!done){
completionLatch.countDown();
done=true;
}
System.out.println("get exception:"+t.getMessage());
}
});
Map m=new HashMap();
m.put("lrid","-1");
MlsAsyncHttpClient.getAsyncHttpClient().post("http://127.0.0.1:8080/assetmgmt/ploanouter/repayplan",m,newAsyncCompletionHandler() {boolean done=false;
@Overridepublic Object onCompleted(Response response) throwsException {
String str=response.getResponseBody();
String name=Thread.currentThread().getName();boolean daemon=Thread.currentThread().isDaemon();
System.out.println("post baidu:");
completionLatch.countDown();return null;
}
@Overridepublic voidonThrowable(Throwable t){if(!done){
completionLatch.countDown();
done=true;
}
System.out.println("post exception:"+t.getMessage());
}
});
completionLatch.await();
System.out.println("异步请求结束!!!");
}
正如一开始所说(当所有非daemon线程退出后jvm将退出),所以我加了个CountDownLatch,在每个请求可以结束的地方
completionLatch.countDown();
最后
completionLatch.await();
完成退出。
其实如果允许请求无限等待,这样还是有可能导致程序阻塞在await这,可以使用
await(long timeout, TimeUnit unit)
设置时间等待,这个时候请求的响应可能会丢失(参数设置等问题),所以我设置了等待响应的时间
configBuilder.setRequestTimeout(60000);
什么东西还是明确的好,各种参数都要经过调试才能确定
参考文章: