【Java:Apache HttpClient】HttpRequestUtils

正式参加工作一年了,记录一下开发接口使用的Http工具类 

依赖引入:
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.22</version>
    <optional>true</optional>
</dependency>
package com.google.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.google.common.constants.CharSetConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
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.config.Registry;
import org.apache.http.config.RegistryBuilder;
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.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.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Http请求工具类
 *
 * @author wk
 * update time 20190815 14:00
 */
@Slf4j
public class HttpRequestUtils {

    private static final Charset CHARSET_UTF8 = Charset.forName(CharSetConstants.UTF_8);
    private static final Charset CHARSET_GBK = Charset.forName(CharSetConstants.GBK);

    private static PoolingHttpClientConnectionManager cm = null;

    static {
        LayeredConnectionSocketFactory sslsf = null;
        try {
            sslsf = new SSLConnectionSocketFactory(createIgnoreVerifySSL());
        } catch (NoSuchAlgorithmException e) {
            log.error("创建SSL连接失败");
            e.printStackTrace();
        } catch (KeyManagementException e) {
            log.error("创建SSL连接失败");
            e.printStackTrace();
        }
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslsf)
                .register("http", new PlainConnectionSocketFactory())
                .build();
        cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        cm.setMaxTotal(200);
        cm.setDefaultMaxPerRoute(20);
    }

    private static CloseableHttpClient getHttpClient() {
        return HttpClients.custom().setConnectionManager(cm).build();
    }

    /**
     * 绕过证书方式实现ssl请求
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("SSLv3");
        // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sc.init(null, new TrustManager[]{trustManager}, null);
        return sc;
    }

    /**
     * 判断字符集
     *
     * @param charsetFlag
     * @return
     */
    private static Charset judgeCharSet(String charsetFlag) {
        if (CharSetConstants.UTF_8.equals(charsetFlag)) {
            return CHARSET_UTF8;
        } else if (CharSetConstants.GBK.equals(charsetFlag)) {
            return CHARSET_GBK;
        }
        return null;
    }

    /**
     * @param timeout        设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。
     * @param connectTimeout 设置连接超时时间,单位毫秒。
     * @param socketTimeout  请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。
     * @return
     */
    private static RequestConfig getRequestConfig(int timeout, int connectTimeout, int socketTimeout) {
        return RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(timeout)
                .setSocketTimeout(socketTimeout).build();
    }

    /**
     * 关闭流
     *
     * @param res
     */
    private static void closeStream(CloseableHttpResponse res) {
        if (res != null) {
            try {
                EntityUtils.consume(res.getEntity());
                res.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * return HttpResult
     *
     * @param httpResponse
     * @param charset
     * @return
     * @throws IOException
     */
    private static HttpResult getHttpResult(CloseableHttpResponse httpResponse, Charset charset) throws IOException {
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        if (httpResponse.getEntity() != null) {
            return new HttpResult(statusCode,
                    EntityUtils.toString(httpResponse.getEntity(), charset));
        } else {
            return new HttpResult(statusCode, "");
        }
    }

    /**
     * 无参get请求
     *
     * @param url
     * @return
     */
    public static HttpResult doGet(String url, JSONObject jsonData) {
        CloseableHttpClient closeableHttpClient = HttpRequestUtils.getHttpClient();
        CloseableHttpResponse httpResponse = null;
        try {

            String params = "";
            if (jsonData != null && !jsonData.isEmpty()) {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                Set<Map.Entry<String, Object>> set = jsonData.entrySet();
                for (Map.Entry<String, Object> entry : set) {
                    String key = entry.getKey();
                    String value = entry.getValue().toString();
                    nameValuePairs.add(new BasicNameValuePair(key, value));
                }
                params = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs, CHARSET_GBK));
            }

            HttpGet get = new HttpGet(url + params);
            get.setConfig(getRequestConfig(5000, 5000, 20000));
            httpResponse = closeableHttpClient.execute(get);
            return getHttpResult(httpResponse, CHARSET_UTF8);
        } catch (IOException e) {
            log.error("httpclient请求失败", e);
            e.printStackTrace();
            return null;
        } finally {
            closeStream(httpResponse);
        }
    }

    /**
     * doGetSSL请求
     *
     * @param url
     * @param jsonData
     * @return
     */
    public static HttpResult doGetSSL(String url, JSONObject jsonData) {

        CloseableHttpResponse httpResponse = null;
        CloseableHttpClient httpClient = getHttpClient();
        try {
            String params = "";
            if (jsonData != null && !jsonData.isEmpty()) {
                List<NameValuePair> nameValuePairs = new ArrayList<>();
                Set<Map.Entry<String, Object>> set = jsonData.entrySet();
                for (Map.Entry<String, Object> entry : set) {
                    String key = entry.getKey();
                    String value = entry.getValue().toString();
                    nameValuePairs.add(new BasicNameValuePair(key, value));
                }
                params = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs, CharSetConstants.UTF_8));
            }
            url = url + "?" + params;
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(getRequestConfig(5000, 5000, 20000));
            httpResponse = httpClient.execute(httpGet);
            return getHttpResult(httpResponse, CHARSET_UTF8);
        } catch (IOException e) {
            log.error("httpclient请求失败", e);
            e.printStackTrace();
            return null;
        } finally {
            closeStream(httpResponse);
        }
    }

    /**
     * 参数为字符串比如json串
     *
     * @param url
     * @param str
     * @param charsetFlag
     * @return
     */
    public static HttpResult doPost(String url, String str, String charsetFlag) {
        CloseableHttpClient httpClient = HttpRequestUtils.getHttpClient();
        CloseableHttpResponse httpResponse = null;
        Charset charset = judgeCharSet(charsetFlag);
        try {
            HttpPost post = new HttpPost(url);
            StringEntity se = new StringEntity(str, charset);
            post.setEntity(se);
            httpResponse = httpClient.execute(post);
            return getHttpResult(httpResponse, charset);
        } catch (IOException e) {
            log.error("httpclient请求失败", e);
            e.printStackTrace();
            return null;
        } finally {
            closeStream(httpResponse);
        }
    }

    /**
     * doPost请求,参数UrlEncodedFormEntity
     *
     * @param url
     * @param map
     * @return
     */
    public static HttpResult doPost(String url, Map<String, Object> map) {
        CloseableHttpResponse httpResponse = null;
        try {
            CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            if (map != null) {
                List<NameValuePair> params = new ArrayList<>();
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, CHARSET_UTF8);
                httpPost.setConfig(getRequestConfig(5000, 5000, 20000));
                httpPost.setEntity(formEntity);
            }
            httpResponse = closeableHttpClient.execute(httpPost);
            return getHttpResult(httpResponse, CHARSET_UTF8);
        } catch (Exception e) {
            log.error("httpclient请求失败", e);
            e.printStackTrace();
            return null;
        } finally {
            closeStream(httpResponse);
        }
    }

    /**
     * JSONObject json
     *
     * @param url
     * @param str
     * @return
     */
    public static HttpResult doPost(String url, String str) {
        CloseableHttpClient httpClient = HttpRequestUtils.getHttpClient();
        CloseableHttpResponse httpResponse = null;
        try {
            HttpPost post = new HttpPost(url);
            StringEntity stringEntity = new StringEntity(str, ContentType.create("application/xml", CharSetConstants.UTF_8));
            post.setEntity(stringEntity);
            post.setConfig(getRequestConfig(5000, 5000, 20000));
            httpResponse = httpClient.execute(post);
            return getHttpResult(httpResponse, CHARSET_UTF8);
        } catch (IOException e) {
            log.error("httpclient请求失败", e);
        } finally {
            closeStream(httpResponse);
        }
        return null;
    }

    public static HttpResult doPost(String url, JSONObject json) {
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        CloseableHttpResponse httpResponse = null;
        HttpPost post = new HttpPost(url);
        try {
            String data = json.toString();
            StringEntity stringEntity = new StringEntity(data, ContentType.create("text/plain", CharSetConstants.UTF_8));
            post.setEntity(stringEntity);
            post.setConfig(getRequestConfig(5000, 5000, 20000));
            httpResponse = closeableHttpClient.execute(post);
            return getHttpResult(httpResponse, CHARSET_UTF8);
        } catch (Exception e) {
            log.error("httpclient请求失败", e);
            e.printStackTrace();
            return null;
        } finally {
            closeStream(httpResponse);
        }
    }

    public static HttpResult soapPost(String url, String str) {
        CloseableHttpClient httpClient = HttpRequestUtils.getHttpClient();
        CloseableHttpResponse httpResponse = null;
        try {
            HttpPost post = new HttpPost(url);
            StringEntity stringEntity = new StringEntity(str, ContentType.create("text/xml", CharSetConstants.UTF_8));
            post.setEntity(stringEntity);
            post.setConfig(getRequestConfig(5000, 5000, 20000));
            httpResponse = httpClient.execute(post);
            return getHttpResult(httpResponse, CHARSET_UTF8);
        } catch (IOException e) {
            log.error("httpclient请求失败", e);
            e.printStackTrace();
            return null;
        } finally {
            closeStream(httpResponse);
        }
    }


}
/**
 * @author wk
 */
public class HttpResult {

    /**
     * 响应的状态码
     */
    private int code;

    /**
     * 响应的响应体
     */
    private String body;

    public HttpResult(int statusCode, String string) {
        this.code = statusCode;
        this.body = string;
    }

    public HttpResult() {

    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}
package com.google.common.constants;

/**
 * @author wk
 * @Description:
 * @date 2019/8/13 17:37
 **/
public class CharSetConstants {

    public static final String UTF_8 = "UTF-8";

    public static final String GBK = "GBK";
}
 public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
//该方法已过时(依然可以使用),改用上述方式实现SSL请求
            SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            return HttpClients.custom().setSSLSocketFactory(sslFactory).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

工作中遇到的问题:

1.乱码问题,在使用StringEntity这个类时,StringEntity(String string, String charset) 用到了这个构造方法,但是传入的utf-8时,通过debug发现,传递的参数依然乱码。询问大佬后,说是这个方法是有bug的,必须这样写

new StringEntity(data, ContentType.create("application/json", "utf-8"));

2.连续请求一个接口,报错Exception in thread "main" java.lang.IllegalStateException: Connection pool shut down

把这块代码删除就好了
if (closeableHttpClient != null) {
    try {
        closeableHttpClient.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3.(http工具类没有加closeStream这个方法,目前还没有进行验证是否是这个原因)

netstat -ano|find /i /c "TIME_WAIT" 

生产服务器(windows),服务报这个错误,导致服务卡顿,甚至崩溃,所有的http请求均失败。

No buffer space available (maximum connections reached?): connectNo buffer space available (maximum connections reached?): connect

4.java.net.SocketException: Connection reset

   请求银行接口(测试环境),经常报这个错误,在本地运行服务很少报这个错,没找出原因,也可能是Tomcat配置的问题


参照链接:

https://www.cnblogs.com/chinaifae/articles/10443047.html

 

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Apache HttpClientApache基金会开发的一个用于创建和发送HTTP请求的Java库。它可以通过Maven来管理和使用。在pom.xml文件中,可以添加如下依赖来使用HttpClient: ``` <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> ``` 其中,groupId是"org.apache.httpcomponents",artifactId是"httpclient",version是"4.5.13"(版本可能会有变化)。 ### 回答2: Apache HttpClient pom是指Apache HttpClient目中的pom.xml文件。pom.xml是Apache Maven目的核心文件,它定义了目的基本信息、依赖关系以及构建的配置。 在Apache HttpClient pom中,我们可以看到一些重要的配置。首先是目的基本信息,如groupId、artifactId和version,它们用于唯一标识一个目。这些信息在构建和部署过程中非常重要,它们定义了目的身份和版本。 其次,Apache HttpClient pom中定义了目的依赖关系。这些依赖描述了目所依赖的其他库或框架,以及它们的版本。这些依赖是构建和运行Apache HttpClient所必需的,它们被自动下载并添加到目的classpath中。 此外,Apache HttpClient pom还包含了构建和打包目的配置。这些配置描述了如何编译源代码、生成文档以及打包可执行文件。例如,它指定了编译器的版本、源代码目录和输出目录等。 对于开发人员来说,Apache HttpClient pom是非常重要的。它提供了一种统一的方式来管理目的依赖,并自动处理构建和部署过程中的许多细节。通过简单地编辑pom.xml文件,开发人员可以添加、移除或更新目的依赖,而无需手动下载和配置这些库。 总之,Apache HttpClient pom是Apache HttpClient目中用于管理依赖关系和构建配置的核心文件。它定义了目的基本信息、依赖关系以及构建的配置,为开发人员提供了方便的构建和部署方法。 ### 回答3: Apache HttpClient是一个开源的Java库,用于实现HTTP和HTTP/2客户端。它提供了各种功能,如发送HTTP请求、处理HTTP响应、处理cookie、进行连接管理和认证等。 pom是Apache Maven目的配置文件,用于描述目的依赖关系。在pom.xml文件中,我们可以指定Apache HttpClient作为目的依赖。通过在pom.xml中添加以下代码,我们可以引入Apache HttpClient依赖: ``` <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> </dependencies> ``` 这段代码的意思是,我们使用的是org.apache.httpcomponents组织下的httpclient库,版本号为4.5.13。当我们构建或运行目时,Maven将自动下载并导入所需的Apache HttpClient库。 通过在pom.xml中添加Apache HttpClient依赖,我们就可以在目中使用它提供的HTTP客户端功能。例如,我们可以创建一个HttpClient对象,发送GET或POST请求,获取服务器的响应等等。 总结来说,Apache HttpClient pom指的是在Apache Maven目中,通过配置pom.xml文件来引入Apache HttpClient库的依赖。这样一来,我们就可以在目中使用Apache HttpClient来实现HTTP和HTTP/2的客户端功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值