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();
    }
    }
    }
    }
  • 相关阅读:
    二叉树(前序,中序,后序遍历)查找
    插入查找
    归并排序
    解密Spring AOP 之AspectJ与动态代理基础知识
    常用的sql
    python 集合方法
    python 字典
    python 列表方法
    python 序列类型
    fake_useragent
  • 原文地址:https://www.cnblogs.com/winkey4986/p/6096504.html
Copyright © 2011-2022 走看看