兩種Java Http客戶端 httpclient4.3 +RestTemplate

  • apache httclient模式(4.3版本)
public class HttpClientUtils {

    public static final int connTimeout=10000;
    public static final int readTimeout=10000;
    public static final String charset="UTF-8";
    private static HttpClient client = null;
    private static Logger log = LoggerFactory.getLogger(HttpClientUtils.class);

    //配置連接池
    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(128);
        cm.setDefaultMaxPerRoute(128);
        client = HttpClients.custom().setConnectionManager(cm).build();
    }

    public static String postMutiPartFormData(String url, Map<String, String> params) throws Exception {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-type","multipart/form-data; charset=utf-8");
        return postMultipartFormData(url, params, headers, connTimeout, readTimeout);
    }

    public static String postParameters(String url, Map<String, String> params) throws ConnectTimeoutException,
            SocketTimeoutException, Exception {
        return postForm(url, params, null, connTimeout, readTimeout);
    }

    public static String postParameters(String url, Map<String, String> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
            SocketTimeoutException, Exception {
        return postForm(url, params, null, connTimeout, readTimeout);
    }

    public static String get(String url) throws Exception {
        return get(url, charset, null, null);
    }

    public static String get(String url, String charset) throws Exception {
        return get(url, charset, connTimeout, readTimeout);
    }

    /**
     * 發送一個 Post 請求, 使用指定的字符集編碼.
     * 支撐普通表單請求
     * @param url
     * @param body RequestBody
     * @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3
     * @param charset 編碼
     * @param connTimeout 建立鏈接超時時間,毫秒.
     * @param readTimeout 響應超時時間,毫秒.
     * @return ResponseBody, 使用指定的字符集編碼.
     * @throws ConnectTimeoutException 建立鏈接超時異常
     * @throws SocketTimeoutException  響應超時
     * @throws Exception
     */
    public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
            throws ConnectTimeoutException, SocketTimeoutException, Exception {
        HttpClient client = null;
        HttpPost post = new HttpPost(url);
        String result = "";
        try {
            if (StringUtils.isNotBlank(body)) {
                HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
                post.setEntity(entity);
            }
            // 設置參數
            Builder customReqConf = RequestConfig.custom();
            if (connTimeout != null) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            if (readTimeout != null) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            post.setConfig(customReqConf.build());

            HttpResponse res;
            if (url.startsWith("https")) {
                // 執行 Https 請求.
                client = createSSLInsecureClient();
                res = client.execute(post);
            } else {
                // 執行 Http 請求.
                client = HttpClientUtils.client;
                res = client.execute(post);
            }
            result = EntityUtils.toString(res.getEntity(), charset);
        } finally {
            post.releaseConnection();
            if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
        }
        return result;
    }

    // 支持multipart/form-data 或 application/json請求,mimetype類型,需要在headers中指定
    public static String postMultipartFormData(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws Exception {
        HttpClient client = null;
        HttpPost post = new HttpPost(url);
        try {
            if (params != null && !params.isEmpty()) {
                MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
                multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
                Set<Map.Entry<String, String>> entrySet = params.entrySet();
                for (Map.Entry<String, String> entry : entrySet) {
                    // 設置ContentType.APPLICATION_JSON 用於支撐utf-8編碼
                    multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue(), ContentType.APPLICATION_JSON);
                }
                HttpEntity reqEntity = multipartEntityBuilder.build();
                post.setEntity(reqEntity);

            }

            if (headers != null && !headers.isEmpty()) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    post.addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 設置參數
            Builder customReqConf = RequestConfig.custom();
            if (connTimeout != null) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            if (readTimeout != null) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            post.setConfig(customReqConf.build());
            HttpResponse res = null;
            if (url.startsWith("https")) {
                // 執行 Https 請求.
                client = createSSLInsecureClient();
                res = client.execute(post);
            } else {
                // 執行 Http 請求.
                client = HttpClientUtils.client;
                res = client.execute(post);
            }
            return EntityUtils.toString(res.getEntity(), "UTF-8");
        } finally {
            post.releaseConnection();
            if (url.startsWith("https") && client != null
                    && client instanceof CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
        }
    }

    /**
     * 提交form表單
     * 普通form表單請求
     * @param url
     * @param params
     * @param connTimeout
     * @param readTimeout
     * @return
     * @throws ConnectTimeoutException
     * @throws SocketTimeoutException
     * @throws Exception
     */
    public static String postForm(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
            SocketTimeoutException, Exception {

        HttpClient client = null;
        HttpPost post = new HttpPost(url);
        try {
            if (params != null && !params.isEmpty()) {
                List<NameValuePair> formParams = new ArrayList<NameValuePair>();
                Set<Map.Entry<String, String>> entrySet = params.entrySet();
                for (Map.Entry<String, String> entry : entrySet) {
                    formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
                post.setEntity(entity);
            }

            if (headers != null && !headers.isEmpty()) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    post.addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 設置參數
            Builder customReqConf = RequestConfig.custom();
            if (connTimeout != null) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            if (readTimeout != null) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            post.setConfig(customReqConf.build());
            HttpResponse res = null;
            if (url.startsWith("https")) {
                // 執行 Https 請求.
                client = createSSLInsecureClient();
                res = client.execute(post);
            } else {
                // 執行 Http 請求.
                client = HttpClientUtils.client;
                res = client.execute(post);
            }
            return EntityUtils.toString(res.getEntity(), "UTF-8");
        } finally {
            post.releaseConnection();
            if (url.startsWith("https") && client != null
                    && client instanceof CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
        }
    }

    
    /**
     * 發送一個 GET 請求
     *
     * @param url
     * @param charset
     * @param connTimeout  建立鏈接超時時間,毫秒.
     * @param readTimeout  響應超時時間,毫秒.
     * @return
     * @throws ConnectTimeoutException   建立鏈接超時
     * @throws SocketTimeoutException   響應超時
     * @throws Exception
     */
    public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
            throws ConnectTimeoutException,SocketTimeoutException, Exception {

        HttpClient client = null;
        HttpGet get = new HttpGet(url);
        String result = "";
        try {
            // 設置參數
            Builder customReqConf = RequestConfig.custom();
            if (connTimeout != null) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            if (readTimeout != null) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            get.setConfig(customReqConf.build());

            HttpResponse res = null;

            if (url.startsWith("https")) {
                // 執行 Https 請求.
                client = createSSLInsecureClient();
                res = client.execute(get);
            } else {
                // 執行 Http 請求.
                client = HttpClientUtils.client;
                res = client.execute(get);
            }

            result = EntityUtils.toString(res.getEntity(), charset);
        } finally {
            get.releaseConnection();
            if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
        }
        return result;
    }

    /**
     * 從 response 裏獲取 charset
     *
     * @param ressponse
     * @return
     */
    @SuppressWarnings("unused")
    private static String getCharsetFromResponse(HttpResponse ressponse) {
        // Content-Type:text/html; charset=GBK
        if (ressponse.getEntity() != null  && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {
            String contentType = ressponse.getEntity().getContentType().getValue();
            if (contentType.contains("charset=")) {
                return contentType.substring(contentType.indexOf("charset=") + 8);
            }
        }
        return null;
    }

    /**
     * 創建 SSL連接
     * @return
     * @throws GeneralSecurityException
     */
    private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
        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, new X509HostnameVerifier() {

                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }

                @Override
                public void verify(String host, SSLSocket ssl)
                        throws IOException {
                }

                @Override
                public void verify(String host, X509Certificate cert)
                        throws SSLException {
                }

                @Override
                public void verify(String host, String[] cns,
                                   String[] subjectAlts) throws SSLException {
                }

            });

            return HttpClients.custom().setSSLSocketFactory(sslsf).build();

        } catch (GeneralSecurityException e) {
            throw e;
        }
    }
  • Spring RestTemplate模式
/**
 * RestTemplate請求類封裝
 */
public class RestClientUtil {

    private RestClientUtil() {}

    private static RestTemplate restClient;

    static {
        restClient = RestTemplateConfiguration.restTemplate();
    }

    public static RestTemplate getRestTemplate() {
        return restClient;
    }

    public static JSONObject getRequestForData(String url, Map<String, Object> params) {
        JSONObject resJson = restClient.getForObject(url, JSONObject.class, params);
        return resJson;
    }

    /**
     * 表單請求
     * @return
     */
    public static JSONObject postFormData(String url, Map<String, Object> params) {
        JSONObject body = new JSONObject();
        // 請求
        HttpHeaders headers = new HttpHeaders();
        //組裝參數
        MultiValueMap<String, Object> reqParams = new LinkedMultiValueMap<String, Object>();
        Set<Map.Entry<String, Object>> entrySet = params.entrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
            reqParams.add(entry.getKey(), entry.getValue());
        }
        org.springframework.http.HttpEntity<MultiValueMap<String, Object>> entity =
                new org.springframework.http.HttpEntity<MultiValueMap<String, Object>>(reqParams, headers);
        ResponseEntity<JSONObject> upstreamRes = restClient.exchange(url, HttpMethod.POST, entity, JSONObject.class);
        return upstreamRes.getBody();

    }

    public static JSONObject postForApplicationJson(String url, Map<String, Object> params) {
        return restClient.postForObject(url, params,
                JSONObject.class);
    }

    /**
     * 配置類:內部靜態類
     */
    static class RestTemplateConfiguration {

        /**
         * 單例創建restTemplate
         * @return
         */
        private static RestTemplate restTemplate() {
            RestTemplate restTemplate = new RestTemplate();
            // request連接池工廠類
            restTemplate.setRequestFactory(clientHttpRequestFactory());
            // 使用 utf-8 編碼集的 conver 替換默認的 conver(默認的 string conver 的編碼集爲"ISO-8859-1")
            List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
            Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
            while (iterator.hasNext()) {
                HttpMessageConverter<?> converter = iterator.next();
                if (converter instanceof StringHttpMessageConverter) {
                    iterator.remove();
                }
            }
            messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
            return restTemplate;
        }

        // 連接池等參數配置
        private static HttpClient httpClient() {

            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", SSLConnectionSocketFactory.getSocketFactory())
                    .build();
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
            connectionManager.setMaxTotal(1000);
            connectionManager.setDefaultMaxPerRoute(20);
            // 時間單位爲millseconds
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(10000) //服務器返回數據(response)的時間,超過拋出read timeout
                    .setConnectTimeout(10000) //連接上服務器(握手成功)的時間,超出拋出connect timeout
                    .setConnectionRequestTimeout(10000)//從連接池中獲取連接的超時時間,超時間未拿到可用連接,會拋出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                    .build();
            return HttpClientBuilder.create()
                    .setDefaultRequestConfig(requestConfig)
                    .setConnectionManager(connectionManager)
                    .build();
        }

        private static ClientHttpRequestFactory clientHttpRequestFactory() {
            HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());
            return clientHttpRequestFactory;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章