httpclient 用法

package com.kdniao.logisticsfront.common.util.http;

import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class HttpTest implements InitializingBean {
    protected static final Logger logger = LoggerFactory.getLogger("remote.digest");
    protected String appName;
    protected CloseableHttpClient httpClient;
    protected String contentType = "application/x-www-form-urlencoded; charset=UTF-8";
    protected Map<String, String> headerMap;
    protected String hostname;
    protected int readTimeout = 5000;
    protected int connectionTimeout = 5000;
    protected int maxTotalConnection = 5000;
    protected int retryCount = 0;
    protected String senderType;
    protected int validateAfterInactivityTime = 60000;
    private int maxPerRoute = 500;
    @Override
    public void afterPropertiesSet()throws Exception{
        //创建http连接池
        SSLContextBuilder builder = new SSLContextBuilder();
        //忽略SSL协议
        builder.loadTrustMaterial(null, (chain,authType)->{return true;});
        /* (chain,authType)->{return true;}  lambda 表达式方式
        builder.loadTrustMaterial(null, new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType){
                return true;
            }
        });

        builder.loadTrustMaterial(null, (chain,authType)->{return true;});
        上面两端代码含义一致
        */

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
        //注册访问协议相关的Socket工厂
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", sslsf).build();
        //HttpConnection 工厂:配置写请求/解析响应处理器
        ManagedHttpClientConnectionFactory connFactory = new ManagedHttpClientConnectionFactory(DefaultHttpRequestWriterFactory.INSTANCE, DefaultHttpResponseParserFactory.INSTANCE);
        //DNS 解析器
        DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
        //连接池
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, connFactory, dnsResolver);
        //默认为Socket配置   // TcpNoDelay是否立即发送数据,设置为true会关闭Socket缓冲,默认为false
        SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
        manager.setDefaultSocketConfig(socketConfig);


        manager.setMaxTotal(maxTotalConnection); //设置整个连接池的最大连接数
        manager.setDefaultMaxPerRoute(maxPerRoute);//每个路由的最大连接数
        manager.setValidateAfterInactivity(validateAfterInactivityTime);  //在从连接池获取连接时,连接不活跃多长时间后需要进行一次验证,默认为2s
        //默认请求配置
        RequestConfig defaulRequestConfig = RequestConfig.custom()
                .setConnectTimeout(connectionTimeout) //设置连接超时时间
                .setSocketTimeout(readTimeout)  //设置等待数据超时时间,5s
                .setConnectionRequestTimeout(connectionTimeout)
                .build();

        httpClient = HttpClients.custom()
                .setConnectionManager(manager)
                .setConnectionManagerShared(false)//连接池不是共享模式
                .evictIdleConnections(60, TimeUnit.SECONDS)  //定期回收空闲连接
                .evictExpiredConnections() // 定期回收过期连接
                .setConnectionTimeToLive(60, TimeUnit.SECONDS)//连接存活时间,如果不设置,则根据长连接信息决定
                .setDefaultRequestConfig(defaulRequestConfig)//设置默认请求配置
                .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)//连接重用策略,即是否能keepAlive
                .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)//长连接配置,即获取长连接生产多长时间
                .setRetryHandler((exception, executionCount, context)->{
                    //设置重试 lambda 表达式方式
                    if(executionCount>2){
                        return false;
                    }
                    if(exception instanceof NoHttpResponseException){
                        logger.warn("NoHttpResponseException on"+executionCount+"call");
                        return true;
                    }
                    return false;
                })
                .build();
        //jvm 虚拟机关闭时执行 关闭http线程池
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * http 请求
     * @param path url 请求路径
     * @param paramMap get 请求参数
     * @param body post 请求参数   字符串类型
     * @param method 请求方式 post get
     * @param formMap post请求参数  map类型
     * @return
     */
    public String send(String path, Map<String, String> paramMap, String body, String method, Map<String, String> formMap) {
        // HttpClients 创建连接步骤
        //1.使用帮助类HttpClients创建CloseableHttpClient对象. 
        //2. 基于要发送的HTTP请求类型创建HttpGet或者HttpPost实例. 
        //3. 使用addHeader方法添加请求头部,诸如User-Agent, Accept-Encoding等参数. 
        //4. 对于POST请求,创建NameValuePair列表,并添加所有的表单参数.然后把它填充进HttpPost实体. 
        //5. 通过执行此HttpGet或者HttpPost请求获取CloseableHttpResponse实例 
        //6. 从此CloseableHttpResponse实例中获取状态码,错误信息,以及响应页面等等. 
        //7. 最后关闭HttpClient资源.


        //1、通过线程池创建CloseableHttpClient对象 httpClient
        HttpRequestBase request = null;
        URIBuilder uriBuilder = null;
        try {
            uriBuilder = new URIBuilder(hostname); //hostname 配置文件配置的默认url
        } catch (URISyntaxException urise) {
            System.out.println("url语法错误:" + urise);
        }

        if (!StringUtils.isEmpty(path)) {
            uriBuilder.setPath(path);
        }

        if (!CollectionUtils.isEmpty(paramMap)) {
            //设置请求参数  例子:url&use=1
            for (String paramName : paramMap.keySet()) {
                uriBuilder.addParameter(paramName, paramMap.get(paramName));
            }
        }
        String url = uriBuilder.toString();
        try {
            if (HttpGet.METHOD_NAME.equals(method)) {
                HttpGet httpGet = new HttpGet(url);
                request = httpGet;
            } else if (HttpPost.METHOD_NAME.equals(method)) {
                HttpPost httpPost = new HttpPost(url);
                if (StringUtils.isEmpty(body) && null != formMap) {
                    List<NameValuePair> paramList = new ArrayList<>();
                    for (String key : formMap.keySet()) {
                        paramList.add(new BasicNameValuePair(key, formMap.get(key)));
                    }
                    //通过list形式来添加参数
                    httpPost.setEntity(new UrlEncodedFormEntity(paramList, "utf-8"));
                } else {
                    //通过string形式传参
                    httpPost.setEntity(new StringEntity(body, ContentType.create(contentType)));
                }
                request = httpPost;
            } else {
                System.out.println("不支持的http method[" + method + "]");
            }
            //设置表头
            if (!CollectionUtils.isEmpty(headerMap)) {
                for (String headerName : headerMap.keySet()) {
                    request.addHeader(headerName, headerMap.get(headerName));
                }
            }
        } catch (Exception e1) {
            System.out.println("Unsupported  http exception:"+ e1);
        }
        String responseString = null;
        try {
            //创建连接
            CloseableHttpResponse response = httpClient.execute(request);
            //返回结果
            responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            //ioe = e ;
            System.out.println("http invoke exception:" + e.getMessage());
        }  finally {
            //链接并没有关闭  只是将链接还给连接池
            request.releaseConnection();
            //程序终止
            request.abort();
           /* DefaultDigestLogBuilder logBuilder = new DefaultDigestLogBuilder();
            logBuilder.setRequestId(cxt != null ? cxt.getRequestId() : null);
            logBuilder.setAppName(appName);
            logBuilder.setStartTime(new Date(startTime));
            logBuilder.setUri(url);
            logBuilder.setLocalIp(SystemUtils.hostInfo.getHostAddress());
            //logBuilder.setRemoteIp(RpcContext.getContext().getRemoteAddressString());
            // 只有系统不可用导致的错误为调用失败
            logBuilder.setSuccess(success);
            logBuilder.setError(ioe == null ? null : GatewayErrors.invoke3thFailed.message(ioe.getMessage()));
            logBuilder.setParameters(new Object[]{method, paramMap, body,formMap});
            logBuilder.setResult(responseString);
            logBuilder.setElapseTime(endTime - startTime);*/
        }
        //返回结果
        return responseString;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值