最近项目有用到ssl的httpClient,原项目不支持,所以查资料实现了一下
httpClient官方文档:http://hc.apache.org/
实现参考:https://blog.csdn.net/zhuwukai/article/details/78644484
Http协议的历史演变和设计思想: https://www.oschina.net/news/76365/http-introduce
采用版本是httpclient4.4.1
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.4.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.1</version> </dependency>
代码
package com.yao.purchasing.common.util; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; 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.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.TrustStrategy; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import com.alibaba.druid.support.json.JSONUtils; import com.yao.purchasing.common.enumerate.ReturnCode; import com.yao.purchasing.common.exception.PmsBizException; import java.io.IOException; import java.io.UnsupportedEncodingException; 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.*; import javax.xml.ws.http.HTTPException; /** * 九州通HttpClientJZTT * * @author wuqi * */ public class HttpClientUtilJZT { private static Logger logger = Logger.getLogger(HttpClientUtil.class); private static PoolingHttpClientConnectionManager connectionManager = null; private static HttpClientBuilder httpBuilder = null; private static RequestConfig requestConfig = null; private static SSLContextBuilder builder = null; private static SSLConnectionSocketFactory sslsf = null; private static CloseableHttpClient httpClient = null; private static int MAXCONNECTION = 100; private static int DEFAULTMAXCONNECTION = 20; static { // 设置http的状态参数 requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000) .setConnectionRequestTimeout(15000).build(); builder = new SSLContextBuilder(); // 全部信任 不做SSL身份鉴定 try { builder.loadTrustMaterial(null, new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { return true; } }); sslsf = new SSLConnectionSocketFactory(builder.build(), new String[] { "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE); Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", new PlainConnectionSocketFactory()).register("https", sslsf).build(); connectionManager = new PoolingHttpClientConnectionManager(registry); connectionManager.setMaxTotal(MAXCONNECTION); connectionManager.setDefaultMaxPerRoute(DEFAULTMAXCONNECTION); httpBuilder = HttpClients.custom(); httpBuilder.setConnectionManager(connectionManager); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } } // 创建单例httpclient public static CloseableHttpClient getConnection() { if (httpClient == null) { synchronized (HttpClientUtilJZT.class) { if (httpClient == null) { httpClient = httpBuilder.setSSLSocketFactory(sslsf).build(); } } } return httpClient; } public static HttpUriRequest getRequestMethod(Map<String, Object> map, String url, String method, Header header) { List<NameValuePair> params = new ArrayList<NameValuePair>(); Set<Map.Entry<String, Object>> entrySet = map.entrySet(); for (Map.Entry<String, Object> e : entrySet) { String name = e.getKey(); Object value = e.getValue(); if (value instanceof String) { NameValuePair pair = new BasicNameValuePair(name, (String) value); params.add(pair); } if (value instanceof List) { String valueList = JSONUtils.toJSONString(value); NameValuePair pair = new BasicNameValuePair(name, valueList); params.add(pair); } } HttpUriRequest reqMethod = null; if ("post".equals(method)) { reqMethod = RequestBuilder.post().setUri(url).addHeader(header) .addParameters(params.toArray(new BasicNameValuePair[params.size()])).setConfig(requestConfig) .build(); } else if ("get".equals(method)) { reqMethod = RequestBuilder.get().setUri(url).addHeader(header) .addParameters(params.toArray(new BasicNameValuePair[params.size()])).setConfig(requestConfig) .build(); } return reqMethod; } public static String doGet(String url, Map<String, Object> map) throws PmsBizException { HttpUriRequest request = getRequestMethod(map, url, "get", null); return doExecute(url, request); } public static String doPost(String url, Map<String, Object> map) throws PmsBizException { HttpUriRequest request = getRequestMethod(map, url, "post", null); return doExecute(url, request); } public static String doPost(String url, Header header, Map<String, Object> map) throws PmsBizException { HttpUriRequest request = getRequestMethod(map, url, "post", header); return doExecute(url, request); } public static String doPost(String url, String jsonStr) throws PmsBizException { HttpPost request = new HttpPost(url); request.addHeader(HTTP.CONTENT_TYPE, "application/json"); StringEntity entity = new StringEntity(jsonStr,"utf-8"); request.setEntity(entity); return doExecute(url, request); } public static String doExecute(String url, HttpUriRequest request) throws PmsBizException { CloseableHttpClient client = getConnection(); CloseableHttpResponse response = null; try { // logger.info("request:" + map); response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); String responseMsg = EntityUtils.toString(entity, "utf-8"); logger.info("response:" + responseMsg); return responseMsg; } else { logger.error("response httpCode:" + response.getStatusLine().getStatusCode()); throw new PmsBizException(ReturnCode.THIRD_API_INVOKE_ERR, EntityUtils.toString(response.getEntity(), "utf-8")); } } catch (ClientProtocolException e) { logger.error("doPost error", e); } catch (IOException e) { logger.error("doPost error", e); } finally { if (response != null) { try { response.close();// 释放链接 } catch (IOException e) { logger.error("Httpresponse.close error", e); } } } return null; } public static void main(String args[]) throws IOException { // HttpUriRequest request = getCode(); // HttpUriRequest request = getToken(); // HttpUriRequest request = getTest(); HttpUriRequest request = postTest(); HttpClient client = getConnection(); HttpResponse response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); String message = EntityUtils.toString(entity, "utf-8"); System.out.println(message); } else { System.out.println("请求失败"); HttpEntity entity = response.getEntity(); String message = EntityUtils.toString(entity, "utf-8"); System.out.println(message); } }
}
httpclient传输的两种方式
API地址:http://hc.apache.org/httpcomponents-core-4.4.x/httpcore/apidocs/index.html
Entity:
BasicHttpEntity:基础的Entity,传输字节流
ByteArrayEntity:传输字节数组的Entity
EntityTemplate:
FileEntity:传输文件的Entity
InputStreamEntity:传输字节流的Entity
SerializableEntity:传输可序列化对象的Entity
StringEntity:传输String字符串的Entity
Enity在Servlet接收时都是用request.getInputSteam()获取,然后实例化成各种相应的Entity;可以看到
//发送 HttpPost request = new HttpPost(url); request.addHeader(HTTP.CONTENT_TYPE, "application/json"); StringEntity entity = new StringEntity(jsonStr,"utf-8"); request.setEntity(entity); response = client.execute(request); //接受 public void doFilter(ServletRequest request, ServletResponse response, FilterChain arg2) throws IOException, ServletException { BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream())); String line = null; StringBuilder sb = new StringBuilder(); while((line = br.readLine())!=null){ sb.append(line); } System.out.println(sb); }
Parameters:传输key-value参数
以BasicNameValuePair的数组传输,限制是只支持key-value都为String字符串类型。下面是部分代码,具体看最上面的例子
//发送 reqMethod = RequestBuilder.post().setUri(url).addHeader(header) .addParameters(params.toArray(new BasicNameValuePair[params.size()])).setConfig(requestConfig) .build();
response = client.execute(request);
//接受
for(String key:request.getParameterMap().keySet()) {
System.out.println(request.getParameter(key));
}
两种方式建议用Entity,Parameters限制太大满足不了大部分需求,我原本是用Parameters的,但是后面涉及json嵌套,只有兼容Entity,采用StringEntity实现了