Java使用HttpClient发送Https请求,并解决证书失效问题

阿帕奇的开源项目。用于Http通信。

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

HttpClient工具类

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
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.HttpDelete;
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.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

@Slf4j
public class HttpRequestClient {

    /**
     * 向指定URL发送GET方法的请求
     * @param url 发送请求的URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
            // 打开和URL之间的连接
            HttpsURLConnection connection = (HttpsURLConnection) realUrl.openConnection();
            // 设置通用的请求属性
            connection.setSSLSocketFactory(sc.getSocketFactory());
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            log.info("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送post请求
     * @param url  路径
     * @param jsonObject  参数(json类型)
     * @param encoding 编码格式
     * @return
     * @throws IOException
     */
    public static String sendPost(String url, JSONObject jsonObject, String encoding) throws ParseException, IOException{
        String body = "";
        //创建httpclient对象
        CloseableHttpClient client = HttpClients.createDefault();
        //创建post方式请求对象
        HttpPost httpPost = new HttpPost(url);
        //装填参数
        StringEntity s = new StringEntity(jsonObject.toString(), "utf-8");
        s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
        //设置参数到请求对象中
        httpPost.setEntity(s);
        log.info("请求地址:"+url);
        //设置header信息
        //指定报文头【Content-type】、【User-Agent】
        httpPost.setHeader("Content-type", "application/json");
        httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        Object token = jsonObject.get("token");
        if (token != null) {
            httpPost.setHeader("token", (String)token);
        }

        //执行请求操作,并拿到结果(同步阻塞)
        CloseableHttpResponse response = client.execute(httpPost);
        //获取结果实体
        org.apache.http.HttpEntity entity = response.getEntity();
        if (entity != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString( entity, encoding);
        }
        EntityUtils.consume( entity);
        //释放链接
        response.close();
        return body;
    }

    /**
     * 发送delete请求
     */
    public static String doDelete(String url, String authorization) {

        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpDelete httpDelete = new HttpDelete(url);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000).setConnectionRequestTimeout(35000).setSocketTimeout(60000).build();
        httpDelete.setConfig(requestConfig);
        httpDelete.setHeader("Content-type", "application/json");
        httpDelete.setHeader("DataEncoding", "UTF-8");
        httpDelete.setHeader("Authorization", authorization);

        CloseableHttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(httpDelete);
            HttpEntity entity = httpResponse.getEntity();
            String result = EntityUtils.toString(entity);
            return result;
        }  catch (Exception e) {
            log.error("刪除請求調用失敗", e );
        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 发送post请求
     *
     * @param url     路径
     * @param jsonStr 参数(json类型)
     * @return
     * @throws IOException
     */
    public static String sendPostWithToken(String url, String jsonStr, String token) throws ParseException, IOException {
        String body = "";
        //创建httpclient对象
//        CloseableHttpClient client = HttpClients.createDefault();
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(2000) // 设置连接超时时间,单位毫秒
                .setConnectionRequestTimeout(1000)
                .setSocketTimeout(5000) // 请求获取数据的超时时间,单位毫秒
                .build();
        HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                return false;
            }
        };
        SSLConnectionSocketFactory scsf = null;
        try {
            scsf = new SSLConnectionSocketFactory(
                    SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(),
                    NoopHostnameVerifier.INSTANCE);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (KeyManagementException e) {
            throw new RuntimeException(e);
        } catch (KeyStoreException e) {
            throw new RuntimeException(e);
        }

        try (CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(scsf)
        .setDefaultRequestConfig(requestConfig)
                .setRetryHandler(myRetryHandler)
                .build()) {
            //创建post方式请求对象
            HttpPost httpPost = new HttpPost(url);
            //装填参数
            StringEntity s = new StringEntity(jsonStr, "utf-8");
            s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            //设置参数到请求对象中
            httpPost.setEntity(s);
            log.info("请求地址:" + url);
            //设置header信息
            //指定报文头【Content-type】、【User-Agent】
            httpPost.setHeader("Content-type", "application/json");
            httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            if (!StringUtils.isEmpty(token)) {
                httpPost.setHeader("token", token);
            }
            //执行请求操作,并拿到结果(同步阻塞)
            CloseableHttpResponse response = client.execute(httpPost);
            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            //释放链接
            response.close();
        }
        return body;
    }

    private static class TrustAnyTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
}

1.client
org.apache.http.client. HttpClient
接口。
CloseableHttpClient org.apache.http.impl.client.HttpClients. createDefault()
此方法可以拿到HttpClient对象。它是线程安全的。

2.request
org.apache.http. HttpRequest
接口。实现类有HttpGet、HttpPost等。
org.apache.http.client.methods. HttpUriRequest
继承了HttpRequest接口的接口。
void org.apache.http.message.AbstractHttpMessage. addHeader(String name, String value)
添加请求的头部信息。
org.apache.http.client.methods. HttpGet
代表HttpGet请求。
org.apache.http.client.methods. HttpPost
代表HttpPost请求。
2.1 get请求
org.apache.http.client.methods.HttpGet. HttpGet(String uri)
HttpGet请求的构造函数。
2.2 post请求
org.apache.http.client.methods.HttpPost. HttpPost(String uri)
HttpPost请求的构造函数。
org.apache.http.entity.StringEntity. StringEntity(String string)
http报文body的格式是字符串。用于构造json、xml类post请求。

3.设置参数
Builder org.apache.http.client.config.RequestConfig. custom()
拿到builder。
Builder org.apache.http.client.config.RequestConfig.Builder. setSocketTimeout(int socketTimeout)
设置socket链接超时。
Builder org.apache.http.client.config.RequestConfig.Builder. setConnectionTimeout(int connectionRequestTimeout)
设置http连接超时。socket超时是http超时的充分不必要条件。
Builder org.apache.http.client.config.RequestConfig.Builder. setConnectionRequestTimeout(int connectionRequestTimeout)
设置请求发出前的超时时间。适用于用连接池,连接池占满的情况。
RequestConfig org.apache.http.client.config.RequestConfig.Builder. build()
至此拿到了RequestConfig 对象。
void org.apache.http.client.methods.HttpRequestBase. setConfig( RequestConfigconfig)
设置连接超时等在内的参数。RequestConfig对象的生成见下行。

RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(2000).build();

4.execute
CloseableHttpResponse org.apache.http.impl.client.CloseableHttpClient. execute(HttpUriRequest request)
执行请求并返回结果,是同步函数,需要等待。

5.response
org.apache.http.client.methods. CloseableHttpResponse
接口。
StatusLine org.apache.http.HttpResponse. getStatusLine()
获取状态栏。
HttpEntity org.apache.http.HttpResponse. getEntity()
获取消息实体。
InputStream org.apache.http.HttpEntity. getContent()
获取内容。如果是文本数据,通常这样来拿。

Scanner scanner = new Scanner(instream, "utf-8");

void org.apache.http.util.EntityUtils.consume(HttpEntity entity)
调用HttpEntity.getContent()就得到了InputStream,此方法用于把流消费完,然后关掉这个InputStream。

6. 常见问题
中文乱码.
需要 header 加入 Content-Type: text/plain; charset=UTF-8.
代码为:

httpPost.setEntity(new StringEntity(content, ContentType.create("text/plain", Charset.forName("UTF-8"))));

猜你喜欢

转载自blog.csdn.net/weixin_45336946/article/details/128115179