HttpClient

本文主要大致介绍HttpClient(基于HttpClient 4.5)及如何使用,附HttpUtil工具类。

 一、HttpClient使用流程

  1、创建HttpClient对象

  2、创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

  3、如果需要发送请求参数,可调用HttpGetsetParams方法来添加请求参数;对于HttpPost对象而言,可调用setEntity(HttpEntity entity)方法来设置请求参数。

  4、调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse对象。

  5、调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

  6、释放连接。无论执行方法是否成功,都必须释放连接

  二、介绍

  1、GET,HEAD, POST, PUT, DELETE, TRACE and OPTIONS.对应的HttpClient中的类型分别为HttpGet,HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace, and HttpOptions.

  2、响应头,设置和获取响应头:

        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
        response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");
        response.addHeader("Set-Cookie", "c2=b; path="/", c3=c; domain="localhost"");
        HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie"));
        while (it.hasNext()) {
            HeaderElement elem = it.nextElement();
            System.out.println(elem.getName() + " = " + elem.getValue());
            NameValuePair[] params = elem.getParameters();
            for (int i = 0; i < params.length; i++) {
                System.out.println(" " + params[i]);
            }
        }

  3、HTTP entity

  HTTP消息可以携带与请求或响应相关联的内容实体(entity)。对应请求报文中的请求主体和响应报文中的响应正文。

请求报文构成 请求报文由请求行(请求方式,URI和HTTP版本),请求头空行(CR+LF,回车符+换行符),请求数据主体构成。
响应报文构成 响应报文由状态行(HTTP版本,状态码,原因),响应头空行响应正文构成。


  根据内容的来源,HttpClient区分了三种实体:

    1)streamed:内容以流的方式接收

    2)self-contained:内容在内存中,或者通过独立于连接或其他实体的方式获取。self-contained实体通常是可重复的。这种类型的实体将主要用于封装HTTP请求的实体。

    3)wrapping:内容是从另一个实体获得的

  可重复的实体:意思是它的内容可以读取一次或多次,仅存在于self-contained实体类型,如ByteArrayEntity or StringEntity

   API:

    HttpEntity#getContent() 返回java.io.InputStream

    HttpEntity#getContentType()、HttpEntity#getContentType() 获取响应的Content-Type、Content-Length响应头。

  4、确保释放资源

    httpClient、response及获取的流式的内容等都需要在finally块中进行close。

  5、获取返回内容

    推荐的使用实体内容的方法是使用它的HttpEntity#getContent()或HttpEntity#writeTo(OutputStream)方法。HttpClient还提供了EntityUtils类,它公开了几个静态方法,以便更容易地从实体中读取内容或信息。而不是读java.io。通过使用这个类中的方法,可以直接在astring / byte数组中检索整个内容体。但是,强烈建议不要使用EntityUtils,除非响应实体来自受信任的HTTP服务器,并且已知其长度有限。

        ...
        // http客户端
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // get请求
        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            String content;
            if (entity != null) {
                long len = entity.getContentLength();
                if (len != -1 && len < 2048) {
                    content = EntityUtils.toString(entity);
                } else {
                    // Stream content out
                    InputStream instream = entity.getContent();
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(instream, "UTF-8"));
                        char[] buffer = new char[4096];
                        int length;
                        StringBuilder sb = new StringBuilder();
                        while ((length = br.read(buffer)) > 0) {
                            sb.append(new String(buffer, 0, length));
                        }
                        content = sb.toString();
                    } finally {
                        instream.close();
                    }
                }
                resultMap.put("content", content);
            }
        }
...            

  在一些情况下需要从entity中多次读取content,这时entity content需要缓存在内存或磁盘中。最简单方法是使用BufferedHttpEntity类包装原始实体,将原始实体的内容读入到内存缓冲区。

    HttpEntity entity = response.getEntity();
            if (entity != null) {
                entity=new BufferedHttpEntity(entity);
    }

  6、写入entity content

    HttpClient提供了几个类,可用于通过HTTP连接高效地传输内容。这些类的实例可以与封装请求(如POST和PUT)的实体相关联,以便将实体内容封装到传出HTTP请求中。HttpClient为最常见的数据容器提供了几个类,比如字符串、字节数组、输入流和文件:StringEntity、ByteArrayEntity、InputStreamEntity和FileEntity。

   1)HTML forms

    对应的Content-Type:application/x-www-form-urlencoded 

List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("param1", "value1"));
formparams.add(new BasicNameValuePair("param2", "value2"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);

    UrlEncodedFormEntity实例将使用所谓的URL编码来对参数和进行编码:param1=value1&param2=value2

   2)Content chunking (内容分块)

     对应的Content-Type:application/octet-stream?(不确定)

    用在服务器生成的消息无法确定消息大小,而进行分块加载

StringEntity entity = new StringEntity("important message",
ContentType.create("plain/text", Consts.UTF_8));
entity.setChunked(true);
HttpPost httppost = new HttpPost("http://localhost/acrtion.do");
httppost.setEntity(entity);

  7、重试处理器

 HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                if (executionCount >= 5) {
                    // Do not retry if over max retry count
                    return false;
                }
                return false;
            }

        };
        CloseableHttpClient httpclient = HttpClients.custom()
                .setRetryHandler(myRetryHandler)
                .build();

  8、SSL/TLS

    HttpClient利用SSLConnectionSocketFactory来创建SSL连接。SSLConnectionSocketFactory允许高度定制。它可以将javax.net.ssl.SSLContext的实例作为参数,并使用它创建自定义配置的SSL连接

KeyStore myTrustStore = <...>
SSLContext sslContext = SSLContexts.custom()
    .loadTrustMaterial(myTrustStore)
    .build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();

  9、Hostname verification

    除了在SSL/TLS协议级别上执行的信任验证和客户端身份验证之外,一旦建立了连接,HttpClient还可以选择性地验证目标主机名是否与存储在服务器的X.509证书中的名称相匹配。这种验证可以为服务器信任材料的真实性提供额外的保证。hostnameverifier接口代表了一种验证主机名的策略。

    重要提示:不应将hostnameverification与SSL信任验证混淆。

    HttpClient附带两个javax.net.ssl.HostnameVerifier实现。

    1)DefaultHostnameVerifier:主机名必须与证书指定的任何替代名称匹配,如果没有替代名称,则提供证书主体的最特定CN

    2)NoopHostnameVerifier:这个主机名验证器实际上关闭了主机名验证。它接受任何有效的、与目标主机匹配的SSL会话。

    每个默认的HttpClient使用DefaultHostnameVerifier实现。如果需要,可以指定不同的主机名验证器实现,如使用NoopHostnameVerifier:

SSLContext sslContext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
    sslContext,
    NoopHostnameVerifier.INSTANCE);

   10、HTTP execution context 执行上下文

    最初,HTTP被设计成一种无状态的、面向响应请求的协议。然而,现实世界中的应用程序通常需要能够通过几个逻辑相关的请求-响应交换来持久化状态信息。为了使应用程序能够维护一个处理状态,HttpClient允许在一个特定的执行上下文中执行HTTP请求,即HTTP上下文。如果在连续的请求之间重用相同的上下文,则多个逻辑相关的请求可以参与逻辑会话。HTTP上下文的功能类似于java.util.Map。它只是一个任意命名值的集合。应用程序可以在请求执行之前填充上下文属性,或者在执行完成后检查上下文。

    HttpContext:可能包含任意对象,因此在多个线程之间共享是不安全的。建议每个执行线程维护自己的上下文。

    在HTTP请求执行过程中,HttpClient将以下属性添加到执行上下文

HttpConnection 实例表示到目标服务器的实际连接
HttpHost 表示连接目标的实例
HttpRoute 表示完整连接路由的实例
HttpRequest 实例表示实际的HTTP请求。执行上下文中的最后一个HttpRequest对象始终表示消息发送到目标服务器时的状态。对于默认的HTTP/1.0和HTTP/1.1,使用相对请求uri。但是,如果以非隧道模式通过代理发送请求,则URI将是绝对的。
HttpResponse 实例表示实际的HTTP响应
RequestConfig 表示实际请求配置的对象。
   

   示例:

  

CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            // Create a local instance of cookie store
            CookieStore cookieStore = new BasicCookieStore();

            // Create local HTTP context
            HttpClientContext localContext = HttpClientContext.create();
            // Bind custom cookie store to the local context
            localContext.setCookieStore(cookieStore);

            HttpGet httpget = new HttpGet("http://httpbin.org/cookies");
            System.out.println("Executing request " + httpget.getRequestLine());

            // Pass local context as a parameter
            CloseableHttpResponse response = httpclient.execute(httpget, localContext);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                List<Cookie> cookies = cookieStore.getCookies();
                for (int i = 0; i < cookies.size(); i++) {
                    System.out.println("Local cookie: " + cookies.get(i));
                }
                EntityUtils.consume(response.getEntity());
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }

  11、设置超时时间

            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .build();
            httpPost.setConfig(requestConfig);    

   12、中止请求:httpget.abort();

   13、验证用户身份的请求

 CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope("httpbin.org", 80),
                new UsernamePasswordCredentials("user", "passwd"));
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultCredentialsProvider(credsProvider)
                .build();
    ...

  14、设置代理

            HttpHost target = new HttpHost("httpbin.org", 443, "https");// 目标请求地址
            HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");// 客户端代理
            RequestConfig config = RequestConfig.custom()
                    .setProxy(proxy)
                    .build();
            HttpGet request = new HttpGet("/");
            request.setConfig(config);
            CloseableHttpResponse response = httpclient.execute(target, request);    

  15、通过身份验证代理在安全连接隧道上执行HTTP请求

CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope("localhost", 8888),
                new UsernamePasswordCredentials("squid", "squid"));
        credsProvider.setCredentials(
                new AuthScope("httpbin.org", 80),
                new UsernamePasswordCredentials("user", "passwd"));
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultCredentialsProvider(credsProvider).build();
        try {
            HttpHost target = new HttpHost("httpbin.org", 80, "http");
            HttpHost proxy = new HttpHost("localhost", 8888);
            RequestConfig config = RequestConfig.custom()
                .setProxy(proxy)
                .build();
            HttpGet httpget = new HttpGet("/basic-auth/user/passwd");
            httpget.setConfig(config);
            CloseableHttpResponse response = httpclient.execute(target, httpget);
            try {
                System.out.println(EntityUtils.toString(response.getEntity()));
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }

  16、使用块编码(chunk)来发送请求实体

        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httppost = new HttpPost("http://httpbin.org/post");

            File file = new File("filePath");

            InputStreamEntity reqEntity = new InputStreamEntity(
                    new FileInputStream(file), -1, ContentType.APPLICATION_OCTET_STREAM);
            reqEntity.setChunked(true);
            // It may be more appropriate to use FileEntity class in this particular
            // instance but we are using a more generic InputStreamEntity to demonstrate
            // the capability to stream out data from any arbitrary source
            //
            // FileEntity entity = new FileEntity(file, "binary/octet-stream");

            httppost.setEntity(reqEntity);

            System.out.println("Executing request: " + httppost.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity()));
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }

  17、使用HttpClient执行基于表单的登录

BasicCookieStore cookieStore = new BasicCookieStore();
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultCookieStore(cookieStore)
                .build();
        try {
            HttpGet httpget = new HttpGet("https://someportal/");
            CloseableHttpResponse response1 = httpclient.execute(httpget);
            try {
                HttpEntity entity = response1.getEntity();

                System.out.println("Login form get: " + response1.getStatusLine());
                EntityUtils.consume(entity);

                System.out.println("Initial set of cookies:");
                List<Cookie> cookies = cookieStore.getCookies();
                if (cookies.isEmpty()) {
                    System.out.println("None");
                } else {
                    for (int i = 0; i < cookies.size(); i++) {
                        System.out.println("- " + cookies.get(i).toString());
                    }
                }
            } finally {
                response1.close();
            }

            HttpUriRequest login = RequestBuilder.post()
                    .setUri(new URI("https://someportal/"))
                    .addParameter("IDToken1", "username")
                    .addParameter("IDToken2", "password")
                    .build();
            CloseableHttpResponse response2 = httpclient.execute(login);
            try {
                HttpEntity entity = response2.getEntity();

                System.out.println("Login form get: " + response2.getStatusLine());
                EntityUtils.consume(entity);

                System.out.println("Post logon cookies:");
                List<Cookie> cookies = cookieStore.getCookies();
                if (cookies.isEmpty()) {
                    System.out.println("None");
                } else {
                    for (int i = 0; i < cookies.size(); i++) {
                        System.out.println("- " + cookies.get(i).toString());
                    }
                }
            } finally {
                response2.close();
            }
        } finally {
            httpclient.close();
        }

  18、多个工作线程执行HTTP请求

// Create an HttpClient with the ThreadSafeClientConnManager.
        // This connection manager must be used if more than one thread will
        // be using the HttpClient.
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);

        CloseableHttpClient httpclient = HttpClients.custom()
                .setConnectionManager(cm)
                .build();
        try {
            // create an array of URIs to perform GETs on
            String[] urisToGet = {
                "http://hc.apache.org/",
                "http://hc.apache.org/httpcomponents-core-ga/",
                "http://hc.apache.org/httpcomponents-client-ga/",
            };

            // create a thread for each URI
            GetThread[] threads = new GetThread[urisToGet.length];
            for (int i = 0; i < threads.length; i++) {
                HttpGet httpget = new HttpGet(urisToGet[i]);
                threads[i] = new GetThread(httpclient, httpget, i + 1);
            }
            // start the threads
            for (int j = 0; j < threads.length; j++) {
                threads[j].start();
            }
            // join the threads
            for (int j = 0; j < threads.length; j++) {
                threads[j].join();
            }
        } finally {
            httpclient.close();
        }

  /**
     * A thread that performs a GET.
     */
    static class GetThread extends Thread {

        private final CloseableHttpClient httpClient;
        private final HttpContext context;
        private final HttpGet httpget;
        private final int id;

        public GetThread(CloseableHttpClient httpClient, HttpGet httpget, int id) {
            this.httpClient = httpClient;
            this.context = new BasicHttpContext();
            this.httpget = httpget;
            this.id = id;
        }
        /**
         * Executes the GetMethod and prints some status information.
         */
        @Override
        public void run() {
            try {
                System.out.println(id + " - about to get something from " + httpget.getURI());
                CloseableHttpResponse response = httpClient.execute(httpget, context);
                try {
                    System.out.println(id + " - get executed");
                    // get the response body as an array of bytes
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        byte[] bytes = EntityUtils.toByteArray(entity);
                        System.out.println(id + " - " + bytes.length + " bytes read");
                    }
                } finally {
                    response.close();
                }
            } catch (Exception e) {
                System.out.println(id + " - error: " + e);
            }
        }
    }

   19、执行包含多部分编码实体的请求

            HttpPost httppost = new HttpPost("http://localhost:8080" +
                    "/servlets-examples/servlet/RequestInfoExample");

            FileBody bin = new FileBody(new File("filePath"));
            StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);

            HttpEntity reqEntity = MultipartEntityBuilder.create()
                    .addPart("bin", bin)
                    .addPart("comment", comment)
                    .build();
            httppost.setEntity(reqEntity);    

  三、使用:

  1、jar包依赖

        <!--httpClient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
        </dependency>

  2、HttpClientUtil工具类

import org.apache.http.HttpEntity;
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.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Http工具类
 *
 * @author yangyongjie
 * @date 2020/3/26
 * @desc
 */
public class HttpClientUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);

    /**
     * http get 请求
     *
     * @param url
     * @return
     */
    public static Map<String, Object> doGet(String url) {
        HashMap<String, Object> resultMap = new HashMap<String, Object>(8);
        resultMap.put("isOk", "ok");
        // http客户端
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // get请求
        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            String content;
            if (entity != null) {
                long len = entity.getContentLength();
                if (len != -1 && len < 2048) {
                    content = EntityUtils.toString(entity);
                } else {
                    // Stream content out
                    InputStream instream = entity.getContent();
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
                        char[] buffer = new char[4096];
                        int length;
                        StringBuilder sb = new StringBuilder();
                        while ((length = br.read(buffer)) > 0) {
                            sb.append(new String(buffer, 0, length));
                        }
                        content = sb.toString();
                    } finally {
                        instream.close();
                    }
                }
                resultMap.put("content", content);
            }
        } catch (IOException e) {
            LOGGER.error("关闭response异常" + e.getMessage(), e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    LOGGER.error("关闭response异常" + e.getMessage(), e);
                }
            }
            try {
                httpclient.close();
            } catch (IOException e) {
                LOGGER.error("httpclient close exceprion:" + e.getMessage(), e);
            }
        }
        return resultMap;
    }

    /**
     * http post 请求
     *
     * @param url
     * @param param
     * @return
     */
    public static Map<String, Object> doPost(String url, Map<String, String> param) {
        HashMap<String, Object> resultMap = new HashMap<String, Object>(8);
        resultMap.put("isOk", "ok");
        CloseableHttpClient httpclient = HttpClients.custom().build();
        try {
            HttpPost httpPost = new HttpPost(url);
            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .build();
            httpPost.setConfig(requestConfig);

            LOGGER.info("Executing request {}", httpPost.getRequestLine());
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            if (param != null) {
                for (Map.Entry<String, String> entry : param.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            }
            httpPost.addHeader("Accept-Encoding", "gzip,deflate");
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                LOGGER.info("response statusLine:{}", response.getStatusLine());
                resultMap.put("status", response.getStatusLine().getStatusCode());
                String content = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                resultMap.put("content", content);
                LOGGER.info("CONTENT={}", content);
                // and ensure it is fully consumed
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } catch (Exception e) {
            LOGGER.error(url + "request exception:" + e.getMessage(), e);
            resultMap.put("isOk", "no");
            return resultMap;
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                LOGGER.error("httpclient close exceprion:" + e.getMessage(), e);
            }
        }
        return resultMap;
    }

    /**
     * 忽略证书验证的https post请求
     *
     * @param url
     * @param param
     * @return
     */
    public static Map<String, Object> doSSLPost(String url, Map<String, String> param) {
        HashMap<String, Object> resultMap = new HashMap<String, Object>(8);
        resultMap.put("isOk", "ok");

        CloseableHttpClient httpclient;
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                // 忽略所有证书验证
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            LOGGER.error("sslcontext error" + e.getMessage(), e);
            resultMap.put("isOk", "no");
            return resultMap;
        }
        // 忽略主机名验证
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE);
        httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
            HttpPost httpPost = new HttpPost(url);
            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .build();
            httpPost.setConfig(requestConfig);

            LOGGER.info("Executing request {}", httpPost.getRequestLine());
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            if (param != null) {
                for (Map.Entry<String, String> entry : param.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            }
            httpPost.addHeader("Accept-Encoding", "gzip,deflate");
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                LOGGER.info("response statusLine:{}", response.getStatusLine());
                resultMap.put("status", response.getStatusLine().getStatusCode());
                String content = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                resultMap.put("content", content);
                LOGGER.info("CONTENT={}", content);
                // and ensure it is fully consumed
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } catch (Exception e) {
            LOGGER.error(url + "request exception:" + e.getMessage(), e);
            resultMap.put("isOk", "no");
            return resultMap;
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                LOGGER.error("httpclient close exceprion:" + e.getMessage(), e);
            }
        }
        return resultMap;
    }
    
}

 2

package com.yang.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 〈一句话功能简述〉
 * 〈功能详细描述〉
 *
 * @author 17090889
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class HttpClientTemplate {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientTemplate.class);

    private static HttpClient httpClient;

    static {
        httpClient = HttpClients.createDefault();
    }

    /**
     * 执行get请求
     *
     * @param uri
     * @return
     */
    public static Map<String, Object> executeGet(String uri) {
        HttpGet httpGet = new HttpGet(uri);
        Map<String, Object> resultMap = new HashMap<String, Object>(4);
        try {
            resultMap = httpClient.execute(httpGet, new ResponseHandler<Map<String, Object>>() {
                public Map<String, Object> handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
                    HttpEntity httpEntity = httpResponse.getEntity();
                    String result = EntityUtils.toString(httpEntity, Charset.forName("utf-8"));
                    return JSON.parseObject(result);
                }
            });
        } catch (Exception e) {
            LOGGER.error("执行get请求异常" + e.getMessage(), e);
            return null;
        }
        return resultMap;
    }

    /**
     * 执行post请求
     *
     * @param uri
     * @return
     */
    public static Map<String, Object> executePost(String uri, JSONObject jsonObject) {
        HttpPost httpPost = new HttpPost(uri);
        StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        Map<String, Object> resultMap = new HashMap<String, Object>(4);
        try {
            resultMap = httpClient.execute(httpPost, new ResponseHandler<Map<String, Object>>() {
                public Map<String, Object> handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
                    HttpEntity httpEntity = httpResponse.getEntity();
                    String result = EntityUtils.toString(httpEntity, Charset.forName("utf-8"));
                    return JSON.parseObject(result);
                }
            });
        } catch (IOException e) {
            LOGGER.error("执行post请求异常" + e.getMessage(), e);
            return null;
        }
        return resultMap;
    }

    public static void main(String[] args) {
        MDC.put("threadId", UUID.randomUUID().toString().replaceAll("-", ""));
        // 没有数据再调用接口查询
        String uri = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + "&appId=" + "wxe0e11acdb6dbccbb" + "&secret=" + "7dfb67f45b79292e3b0b969b2590a06b";
        Map<String, Object> resultMap = HttpClientTemplate.executeGet(uri);
        LOGGER.info("getAccessToken-resultMap={}", resultMap);
        String errcode = String.valueOf(resultMap.get("errcode"));
        String accessToken = String.valueOf(resultMap.get("access_token"));
        String expiresIn = String.valueOf(resultMap.get("expires_in"));

        // 写死一个行业,其他,41

        if (accessToken == null) {
            return;
        }
        String uri2 = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=" + accessToken;
        JSONObject jsonObject = new JSONObject(4);
        jsonObject.put("industry_id1", 1);
        jsonObject.put("industry_id2", "41");
        Map<String, Object> resultMap2 = HttpClientTemplate.executePost(uri2, jsonObject);
        String errcode2 = String.valueOf(resultMap2.get("errcode"));
        MDC.remove("threadId");
    }
}

  四、官方示例

/*
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.http.examples.client;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;

import javax.net.ssl.SSLContext;

import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
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.protocol.HttpClientContext;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.MessageConstraints;
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.HttpConnectionFactory;
import org.apache.http.conn.ManagedHttpClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultHttpResponseParser;
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.io.HttpMessageParser;
import org.apache.http.io.HttpMessageParserFactory;
import org.apache.http.io.HttpMessageWriterFactory;
import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicLineParser;
import org.apache.http.message.LineParser;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EntityUtils;

/**
 * This example demonstrates how to customize and configure the most common aspects
 * of HTTP request execution and connection management.
 */
public class ClientConfiguration {

    public final static void main(String[] args) throws Exception {

        // Use custom message parser / writer to customize the way HTTP
        // messages are parsed from and written out to the data stream.
        HttpMessageParserFactory<HttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {

            @Override
            public HttpMessageParser<HttpResponse> create(
                SessionInputBuffer buffer, MessageConstraints constraints) {
                LineParser lineParser = new BasicLineParser() {

                    @Override
                    public Header parseHeader(final CharArrayBuffer buffer) {
                        try {
                            return super.parseHeader(buffer);
                        } catch (ParseException ex) {
                            return new BasicHeader(buffer.toString(), null);
                        }
                    }

                };
                return new DefaultHttpResponseParser(
                    buffer, lineParser, DefaultHttpResponseFactory.INSTANCE, constraints) {

                    @Override
                    protected boolean reject(final CharArrayBuffer line, int count) {
                        // try to ignore all garbage preceding a status line infinitely
                        return false;
                    }

                };
            }

        };
        HttpMessageWriterFactory<HttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();

        // Use a custom connection factory to customize the process of
        // initialization of outgoing HTTP connections. Beside standard connection
        // configuration parameters HTTP connection factory can define message
        // parser / writer routines to be employed by individual connections.
        HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
                requestWriterFactory, responseParserFactory);

        // Client HTTP connection objects when fully initialized can be bound to
        // an arbitrary network socket. The process of network socket initialization,
        // its connection to a remote address and binding to a local one is controlled
        // by a connection socket factory.

        // SSL context for secure connections can be created either based on
        // system or application specific properties.
        SSLContext sslcontext = SSLContexts.createSystemDefault();

        // Create a registry of custom connection socket factories for supported
        // protocol schemes.
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register("https", new SSLConnectionSocketFactory(sslcontext))
            .build();

        // Use custom DNS resolver to override the system DNS resolution.
        DnsResolver dnsResolver = new SystemDefaultDnsResolver() {

            @Override
            public InetAddress[] resolve(final String host) throws UnknownHostException {
                if (host.equalsIgnoreCase("myhost")) {
                    return new InetAddress[] { InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) };
                } else {
                    return super.resolve(host);
                }
            }

        };

        // Create a connection manager with custom configuration.
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
                socketFactoryRegistry, connFactory, dnsResolver);

        // Create socket configuration
        SocketConfig socketConfig = SocketConfig.custom()
            .setTcpNoDelay(true)
            .build();
        // Configure the connection manager to use socket configuration either
        // by default or for a specific host.
        connManager.setDefaultSocketConfig(socketConfig);
        connManager.setSocketConfig(new HttpHost("somehost", 80), socketConfig);
        // Validate connections after 1 sec of inactivity
        connManager.setValidateAfterInactivity(1000);

        // Create message constraints
        MessageConstraints messageConstraints = MessageConstraints.custom()
            .setMaxHeaderCount(200)
            .setMaxLineLength(2000)
            .build();
        // Create connection configuration
        ConnectionConfig connectionConfig = ConnectionConfig.custom()
            .setMalformedInputAction(CodingErrorAction.IGNORE)
            .setUnmappableInputAction(CodingErrorAction.IGNORE)
            .setCharset(Consts.UTF_8)
            .setMessageConstraints(messageConstraints)
            .build();
        // Configure the connection manager to use connection configuration either
        // by default or for a specific host.
        connManager.setDefaultConnectionConfig(connectionConfig);
        connManager.setConnectionConfig(new HttpHost("somehost", 80), ConnectionConfig.DEFAULT);

        // Configure total max or per route limits for persistent connections
        // that can be kept in the pool or leased by the connection manager.
        connManager.setMaxTotal(100);
        connManager.setDefaultMaxPerRoute(10);
        connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 20);

        // Use custom cookie store if necessary.
        CookieStore cookieStore = new BasicCookieStore();
        // Use custom credentials provider if necessary.
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // Create global request configuration
        RequestConfig defaultRequestConfig = RequestConfig.custom()
            .setCookieSpec(CookieSpecs.DEFAULT)
            .setExpectContinueEnabled(true)
            .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
            .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
            .build();

        // Create an HttpClient with the given custom dependencies and configuration.
        CloseableHttpClient httpclient = HttpClients.custom()
            .setConnectionManager(connManager)
            .setDefaultCookieStore(cookieStore)
            .setDefaultCredentialsProvider(credentialsProvider)
            .setProxy(new HttpHost("myproxy", 8080))
            .setDefaultRequestConfig(defaultRequestConfig)
            .build();

        try {
            HttpGet httpget = new HttpGet("http://httpbin.org/get");
            // Request configuration can be overridden at the request level.
            // They will take precedence over the one set at the client level.
            RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
                .setSocketTimeout(5000)
                .setConnectTimeout(5000)
                .setConnectionRequestTimeout(5000)
                .setProxy(new HttpHost("myotherproxy", 8080))
                .build();
            httpget.setConfig(requestConfig);

            // Execution context can be customized locally.
            HttpClientContext context = HttpClientContext.create();
            // Contextual attributes set the local context level will take
            // precedence over those set at the client level.
            context.setCookieStore(cookieStore);
            context.setCredentialsProvider(credentialsProvider);

            System.out.println("executing request " + httpget.getURI());
            CloseableHttpResponse response = httpclient.execute(httpget, context);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity()));
                System.out.println("----------------------------------------");

                // Once the request has been executed the local context can
                // be used to examine updated state and various objects affected
                // by the request execution.

                // Last executed request
                context.getRequest();
                // Execution route
                context.getHttpRoute();
                // Target auth state
                context.getTargetAuthState();
                // Proxy auth state
                context.getProxyAuthState();
                // Cookie origin
                context.getCookieOrigin();
                // Cookie spec used
                context.getCookieSpec();
                // User security token
                context.getUserToken();

            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}

END

原文地址:https://www.cnblogs.com/yangyongjie/p/12575879.html