工作中经常遇到要发送https请求情况,一般都有自己的工具包,很多过时的方法都被打了@Deprecated这个鬼东西,导致代码上面总是出现那个又大又粗的黑线,看着都头疼
我写这篇文章的时候,最新的版本是4.5.2
org.apache.httpcomponents
httpclient
4.5.2
X509TrustManager:用来读取公钥做验证加密数据传输的。如何导出公钥请参考“
http://blog.csdn.net/mzh1992/article/details/53887321
HostnameVerifier:就好理解多了,从字面上就能看出来,是用来验证host的
X509TrustManager:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* Created by mazhenhua on 2016/12/23.
*/
public class MyX509TrustManager implements X509TrustManager {
private Certificate cert = null;
public MyX509TrustManager() {
try {
FileInputStream fis = new FileInputStream(
"C:\\Users\\mazhenhua\\Desktop\\cert\\test.cer");
BufferedInputStream bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
cert = cf.generateCertificate(bis);
System.out.println(cert.toString());
}
bis.close();
} catch (Exception e) {
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Deprecated
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
for (X509Certificate cert : chain) {
if (cert.toString().equals(this.cert.toString()))
return;
}
throw new CertificateException("certificate is illegal");
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] { (X509Certificate) cert };
}
}
HostnameVerifier:
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
/**
* Created by mazhenhua on 2016/12/23.
*/
public class MyVerifyHostname implements HostnameVerifier {
@Override
public boolean verify(String arg0, SSLSession arg1) {
if (arg0.equals("127.0.0.1") || arg0.equals("mazhenhua.com"))
return true;
else
return false;
}
}
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.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
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.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.BufferedHttpEntity;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Created by mazhenhua on 2016/12/23.
*/
public class HttpClientPool {
private String host;
private String cookie;
private String path;
private int port;
private SSLContext sslContext;
private X509TrustManager tm;
private HttpClient httpClient;
private Registry registry;
private ConnectionSocketFactory plainSF;
private LayeredConnectionSocketFactory sslSF;
int maxPerRoute = 15; // 每个路由允许活跃连接数
int maxTotal = 100; // 所有路由总连接数上限
int maxLineLength = 0; // 每一个请求行的最大行长度(坑已踩)
int connectionRequestTimeout = 1000000000; // 向连接池申请连接超时,单位:毫秒
int connectTimeout = 6000; // 建立连接超时,单位:毫秒
int socketTimeout = 10000; // 等待数据超时,单位:毫秒
public HttpClientPool(String host, String cookie, String path, int port)
throws Exception {
this.host = host;
this.cookie = cookie;
this.path = path;
this.port = port;
sslContext = SSLContext.getInstance("TLS");
tm = new MyX509TrustManager(); // 那个读取公钥的实现类
sslContext.init(null, new TrustManager[] { tm },
new java.security.SecureRandom());
/* 不使用连接次
httpClient = HttpClients.custom()
.setSSLHostnameVerifier(new MyVerifyHostname())
.setSSLContext(sslContext).build();*/
/** 以下是连接池区域 具体的参数,可以根据情况自己调整**/
sslSF = new SSLConnectionSocketFactory(sslContext, new MyVerifyHostname()); // 验证host的那个
RegistryBuilder registryBuilder = RegistryBuilder
. create();
plainSF = new PlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
registryBuilder.register("https", sslSF);
registry = registryBuilder.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
registry);
connManager.setDefaultMaxPerRoute(maxPerRoute);
connManager.setMaxTotal(maxTotal);
ConnectionConfig connConfig = ConnectionConfig
.custom()
.setMessageConstraints(
MessageConstraints.custom().setMaxLineLength(maxLineLength).build()).build();
connManager.setDefaultConnectionConfig(connConfig);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(connectionRequestTimeout)
.setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();
httpClient = HttpClients.custom().setConnectionManager(connManager)
.setDefaultRequestConfig(requestConfig).build();
}
public String sendPost(String localPath, String filename)
throws URISyntaxException, ClientProtocolException, IOException {
URI uri = new URIBuilder().setScheme("https").setHost(host)
.setPath(path).setParameter("filename", filename).setPort(port)
.build();
HttpPost httpPost = new HttpPost(uri);
/**这个部分是支持带上传的*/
FileEntity fileEntity = new FileEntity(new File(localPath));
//fileEntity.setChunked(true);
//httpPost.setEntity(fileEntity);
httpPost.addHeader("Cookie", cookie);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(20000).build();//设置请求和传输超时时间
httpPost.setConfig(requestConfig);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
httpEntity = new BufferedHttpEntity(httpEntity);
String resultString = EntityUtils.toString(httpEntity);
return resultString;
}
public static void main(String[] args) {
try {
HttpClientPool test = new HttpClientPool(
"127.0.0.1",
null,
"/post/index.htm", 8443);
String resultString = test.sendPost(null, null);
System.out.println(resultString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面这个类中httpClient连接池支持发送http和https两种,发请求的时候不用再关心到底是https还是http