• AsyncHttpClient使用


    github地址:AsyncHttpClient

    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.*;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.Future;
    
    /**
     * Created by yhzh on 2016/9/19.
     */
    public class MlsAsyncHttpClient {
        private AsyncHttpClient client;
    
        private static class HttpClientHolder{
            private static MlsAsyncHttpClient httpClient=new MlsAsyncHttpClient();
        }
    
        private MlsAsyncHttpClient(){
            AsyncHttpClientConfig.Builder configBuilder=new AsyncHttpClientConfig.Builder();
            configBuilder.setMaxConnections(2);
            /*使用默认值:
            configBuilder.setConnectTimeout(3000);
            configBuilder.setReadTimeout(5000);*/
            configBuilder.setRequestTimeout(60000);
            this.client=new AsyncHttpClient(configBuilder.build());
        }
    
        public static MlsAsyncHttpClient getAsyncHttpClient(){
            return HttpClientHolder.httpClient;
        }
    
        public Future<Response> get(String url) {
            return this.client.prepareGet(url).execute();
        }
    
        public void get(String url, AsyncHandler resHandler) {
            this.client.prepareGet(url).execute(resHandler);
        }
    
        public Future<Response> post(String url) {
            return this.client.preparePost(url).execute();
        }
    
        public void post(String url,AsyncHandler resHandler) {
            this.client.preparePost(url).execute(resHandler);
        }
    
        private Request buildRequest(String url, Map<String,String> paramsMap){
            RequestBuilder requestBuilder = new RequestBuilder();
            if(paramsMap != null && paramsMap.size() > 0) {
                Set<Map.Entry<String, String>> entrySet = paramsMap.entrySet();
                Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
                while(iterator.hasNext()) {
                    Map.Entry<String, String> 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);
    
            return requestBuilder.build();
        }
    
        public Future<Response> post(String url, Map<String,String> paramsMap) {
            Request req=this.buildRequest(url,paramsMap);
    
            return this.client.executeRequest(req);
        }
    
        public void post(String url, Map<String,String> paramsMap, AsyncHandler resHandler) {
            Request req=this.buildRequest(url,paramsMap);
    
            this.client.executeRequest(req,resHandler);
            //this.client.preparePost(url).execute(responseHandler);
        }
    }

    测试代码

    @Test
        public void testSelectLoanResultOfLoanResultsOfZgController() throws InterruptedException {
            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",new AsyncHandler() {
                private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                boolean done=false;
                @Override
                public STATE onStatusReceived(HttpResponseStatus status) throws Exception {
                    int statusCode = status.getStatusCode();
                    if (statusCode >= 500) {
                        return STATE.ABORT;
                    }
                    return STATE.CONTINUE;
                }
    
                @Override
                public STATE onHeadersReceived(HttpResponseHeaders httpResponseHeaders) throws Exception {
                    FluentCaseInsensitiveStringsMap str=httpResponseHeaders.getHeaders();
                    return STATE.CONTINUE;
                }
    
                @Override
                public STATE onBodyPartReceived(HttpResponseBodyPart httpResponseBodyPart) throws Exception {
                    bytes.write(httpResponseBodyPart.getBodyPartBytes());
                    return STATE.CONTINUE;
                }
    
                @Override
                public Object onCompleted() throws Exception {
                    String str=bytes.toString("utf-8");
                    System.out.println("get baidu:");
                    completionLatch.countDown();
                    return null;
                }
    
                @Override
                public void onThrowable(Throwable t){
                    if(!done){
                        completionLatch.countDown();
                        done=true;
                    }
                    System.out.println("get exception:"+t.getMessage());
                }
            });
    
            Map<String,String> m=new HashMap<String,String>();
            m.put("lrid","-1");
            MlsAsyncHttpClient.getAsyncHttpClient().post("http://127.0.0.1:8080/assetmgmt/ploanouter/repayplan",m,new AsyncCompletionHandler() {
                boolean done=false;
                @Override
                public Object onCompleted(Response response) throws Exception {
                    String str=response.getResponseBody();
                    String name=Thread.currentThread().getName();
                    boolean daemon=Thread.currentThread().isDaemon();
                    System.out.println("post baidu:");
                    completionLatch.countDown();
                    return null;
                }
    
                @Override
                public void onThrowable(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);

    什么东西还是明确的好,各种参数都要经过调试才能确定

    参考文章:

    1. java之httpClient 3.x、AsyncHttpClient1.9.x使用总结

    2. Async Http Client:异步HTTP和WebSocket客户端

  • 相关阅读:
    模板方法设计模式(未完待续)
    适配器模式
    g2o:一种图优化的C++框架
    U14.04 teamviewer install
    小教训
    卡2-SLAM
    Odometry的发布和发布odom到base_link的tf变换
    #pragma once
    友元
    Ubuntu 14.04 安装配置强大的星际译王(stardict)词典
  • 原文地址:https://www.cnblogs.com/yhzh/p/5889681.html
Copyright © 2020-2023  润新知