zoukankan      html  css  js  c++  java
  • HttpClient工具类

    依赖pom

    <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5</version>
    </dependency>

    工具类

    package com.hjf.boot.demo.boot_start;
    import java.io.IOException;
    import java.io.InterruptedIOException;
    import java.net.SocketTimeoutException;
    import java.net.UnknownHostException;
    import java.nio.charset.Charset;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLException;
    import javax.net.ssl.SSLHandshakeException;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpEntityEnclosingRequest;
    import org.apache.http.HttpRequest;
    import org.apache.http.NoHttpResponseException;
    import org.apache.http.ParseException;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpRequestRetryHandler;
    import org.apache.http.client.config.RequestConfig;
    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.protocol.HttpClientContext;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.config.SocketConfig;
    import org.apache.http.conn.ConnectTimeoutException;
    import org.apache.http.conn.routing.HttpRoute;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
    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.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.pool.PoolStats;
    import org.apache.http.protocol.HTTP;
    import org.apache.http.protocol.HttpContext;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    private final static int CONNECT_TIMEOUT = 4000;// 连接超时毫秒
    private final static int SOCKET_TIMEOUT = 10000;// 传输超时毫秒
    private final static int REQUESTCONNECT_TIMEOUT = 3000;// 获取请求超时毫秒
    private final static int CONNECT_TOTAL = 200;// 最大连接数
    private final static int CONNECT_ROUTE = 20;// 每个路由基础的连接数
    private final static String ENCODE_CHARSET = "utf-8";// 响应报文解码字符集
    private final static String RESP_CONTENT = "通信失败";
    private static PoolingHttpClientConnectionManager connManager = null;
    private static CloseableHttpClient httpClient = null;
    static {
    ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
    LayeredConnectionSocketFactory sslsf = createSSLConnSocketFactory();
    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
    .register("http", plainsf).register("https", sslsf).build();
    connManager = new PoolingHttpClientConnectionManager(registry);
    // 将最大连接数增加到200
    connManager.setMaxTotal(CONNECT_TOTAL );
    // 将每个路由基础的连接增加到20
    connManager.setDefaultMaxPerRoute(CONNECT_ROUTE );
    // 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建
    立
    connManager.setValidateAfterInactivity(30000);
    // 设置socket超时时间
    SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(SOCKET_TIMEOUT ).build();
    connManager.setDefaultSocketConfig(socketConfig);
    RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(REQUESTCONNECT_T
    IMEOUT )
    .setConnectTimeout(CONNECT_TIMEOUT ).setSocketTimeout(SOCKET_TIMEOUT ).build();
    HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
    public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
    if (executionCount >= 3) {// 如果已经重试了3次,就放弃
    return false;
    }
    if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试
    return true;
    }
    if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
    return false;
    }
    if (exception instanceof InterruptedIOException) {// 超时
    return true;
    }
    if (exception instanceof UnknownHostException) {// 目标服务器不可达
    return false;
    }
    if (exception instanceof ConnectTimeoutException) {// 连接被拒绝
    return false;
    }
    if (exception instanceof SSLException) {// ssl握手异常
    return false;
    }
    HttpClientContext clientContext = HttpClientContext.adapt(context);
    HttpRequest request = clientContext.getRequest();
    // 如果请求是幂等的,就再次尝试
    if (!(request instanceof HttpEntityEnclosingRequest)) {
    return true;
    }
    return false;
    }
    };
    httpClient = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(request
    Config)
    .setRetryHandler(httpRequestRetryHandler).build();
    if (connManager != null && connManager.getTotalStats() != null) {
    logger.info("now client pool " + connManager.getTotalStats().toString());
    }
    }
    /**
    * 发送HTTP_GET请求
    *
    * @see 1)该方法会自动关闭连接,释放资源
    * @see 2)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串
    * @see 3)请求参数含中文时,经测试可直接传入中文,HttpClient会自动编码发给Server,应用时应根据实际效果决
    定传入前是否转码
    * @see 4)该方法会自动获取到响应消息头中[Content-Type:text/html; charset=GBK]的charset值作为响应报文的
    解码字符集
    * @see 若响应消息头中无Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1作为响应报文的解码字符
    集
    * @param requestURL 请求地址(含参数)
    * @return 远程主机响应正文
    */
    public static String sendGetRequest(String reqURL, String param) {
    if (null != param) {
    reqURL += "?" + param;
    }
    String respContent = RESP_CONTENT ; // 响应内容
    // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET);
    HttpGet httpget = new HttpGet(reqURL);
    CloseableHttpResponse response = null;
    try {
    response = httpClient.execute(httpget, HttpClientContext.create()); // 执行GET请求
    HttpEntity entity = response.getEntity(); // 获取响应实体
    if (null != entity) {
    Charset respCharset = ContentType.getOrDefault(entity).getCharset();
    respContent = EntityUtils.toString(entity, respCharset);
    EntityUtils.consume(entity);
    }
    } catch (ConnectTimeoutException cte) {
    logger.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte);
    } catch (SocketTimeoutException ste) {
    logger.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste);
    } catch (ClientProtocolException cpe) {
    // 该异常通常是协议错误导致:比如构造HttpGet对象时传入协议不对(将'http'写成'htp')or响应内容不符合
    HTTP协议要求等
    logger.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe);
    } catch (ParseException pe) {
    logger.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe);
    } catch (IOException ioe) {
    // 该异常通常是网络原因引起的,如HTTP服务器未启动等
    logger.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe);
    } catch (Exception e) {
    logger.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e);
    } finally {
    try {
    if (response != null)
    response.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    if (httpget != null) {
    httpget.releaseConnection();
    }
    }
    return respContent;
    }
    public static String sendPostRequest(String reqURL, String param) {
    return sendPostRequest(reqURL, param, "");
    }
    /**
    * 发送HTTP_POST请求 type: 默认是表单请求,
    * @see 1)该方法允许自定义任何格式和内容的HTTP请求报文体
    * @see 2)该方法会自动关闭连接,释放资源
    * @see 3)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串
    * @see 4)请求参数含中文等特殊字符时,可直接传入本方法,并指明其编码字符集encodeCharset参数,方法内部会自
    动对其转码
    * @see 5)该方法在解码响应报文时所采用的编码,取自响应消息头中的[Content-Type:text/html; charset=GBK]的
    charset值
    * @see 若响应消息头中未指定Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1
    * @param reqURL 请求地址
    * @param reqData 请求参数,若有多个参数则应拼接为param11=value11&22=value22&33=value33的形式
    * @param encodeCharset 编码字符集,编码请求数据时用之,此参数为必填项(不能为""或null)
    * @return 远程主机响应正文
    */
    public static String sendPostRequest(String reqURL, String param, String type) {
    String result = RESP_CONTENT ;
    // 设置请求和传输超时时间
    HttpPost httpPost = new HttpPost(reqURL);
    // 这就有可能会导致服务端接收不到POST过去的参数,比如运行在Tomcat6.0.36中的Servlet,所以我们手工指定C
    ONTENT_TYPE头消息
    if (type != null && type.length() > 0) {
    httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json; charset=" + ENCODE_CHARSET );
    } else {
    httpPost.setHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=" + ENCO
    DE_CHARSET );
    }
    CloseableHttpResponse response = null;
    try {
    if (param != null) {
    StringEntity entity = new StringEntity(param, ENCODE_CHARSET );
    httpPost.setEntity(entity);
    }
    logger.info("开始执行请求:" + reqURL);
    // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET);
    response = httpClient.execute(httpPost, HttpClientContext.create());
    HttpEntity entity = response.getEntity();
    if (null != entity) {
    result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset());
    logger.info("执行请求完毕:" + result);
    EntityUtils.consume(entity);
    }
    } catch (ConnectTimeoutException cte) {
    logger.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte);
    } catch (SocketTimeoutException ste) {
    logger.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste);
    } catch (ClientProtocolException cpe) {
    logger.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe);
    } catch (ParseException pe) {
    logger.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe);
    } catch (IOException ioe) {
    logger.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe);
    } catch (Exception e) {
    logger.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e);
    } finally {
    try {
    if (response != null)
    response.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    if (httpPost != null) {
    httpPost.releaseConnection();
    }
    }
    return result;
    }
    //SSL的socket工厂创建
    private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
    SSLConnectionSocketFactory sslsf = null;
    // 创建TrustManager() 用于解决javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    X509TrustManager trustManager = new X509TrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() {
    return null;
    }
    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String authType) throws CertificateExce
    ption {
    // TODO Auto-generated method stub
    }
    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String authType) throws CertificateExce
    ption {
    // TODO Auto-generated method stub
    }
    };
    SSLContext sslContext;
    try {
    sslContext = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
    sslContext.init(null, new TrustManager[] {(TrustManager)trustManager}, null);
    // 创建SSLSocketFactory , // 不校验域名 ,取代以前验证规则
    sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    return sslsf;
    }
    public static Map<HttpRoute, PoolStats> getConnManagerStats() {
    if (connManager != null) {
    Set<HttpRoute> routeSet = connManager.getRoutes();
    if (routeSet != null && !routeSet.isEmpty()) {
    Map<HttpRoute, PoolStats> routeStatsMap = new HashMap<HttpRoute, PoolStats>();
    for (HttpRoute route : routeSet) {
    PoolStats stats = connManager.getStats(route);
    routeStatsMap.put(route, stats);
    }
    return routeStatsMap;
    }
    }
    return null;
    }
    public static PoolStats getConnManagerTotalStats() {
    if (connManager != null) {
    return connManager.getTotalStats();
    }
    return null;
    }
    /**
    * 关闭系统时关闭httpClient
    */
    public static void releaseHttpClient() {
    try {
    httpClient.close();
    } catch (IOException e) {
    logger.error("关闭httpClient异常" + e);
    } finally {
    if (connManager != null) {
    connManager.shutdown();
    }
    }
    }
    }
  • 相关阅读:
    Web API 强势入门指南
    毫秒必争,前端网页性能最佳实践
    Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap
    Windbg Extension NetExt 使用指南 【2】 ---- NetExt 的基本命令介绍
    Windbg Extension NetExt 使用指南 【1】 ---- NetExt 介绍
    WCF : 修复 Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service 问题
    透过WinDBG的视角看String
    Microsoft Azure Web Sites应用与实践【4】—— Microsoft Azure网站的“后门”
    企业IT管理员IE11升级指南【17】—— F12 开发者工具
    WCF : 如何将NetTcpBinding寄宿在IIS7上
  • 原文地址:https://www.cnblogs.com/winkey4986/p/6096504.html
Copyright © 2011-2022 走看看