由于最近公司在对接银行项目,所以我研究了一下关于httpclient的一下基本用法,我这里使用的是httpclient链接池的方式进行的
首先先设置基本参数
private static CloseableHttpClient httpClient;
private final static Object syncLock = new Object();
private static final Logger LOGGER = LoggerFactory.getLogger(HTTPUtils.class);
/**
* 最大连接数
*/
private static int MAX_CONNECTION_NUM = 400;
/**
* 单路由最大连接数
*/
private static int DEFAULT_MAX_PER_ROUTE = 50;
/**
* 目标主机最大连接数
*/
private static int MAX_PER_ROUTE = 100;
/**
* 向服务器请求超时时间
*/
private static int SERVER_REQUEST_TIME_OUT = 10000;
/**
* 服务端响应超时时间设置(单位:毫秒)
*/
private static int SERVER_RESPONSE_TIME_OUT = 10000;
private static final String CHARSET = "utf-8";// 编码设置
2.创建Httpclient链接对象
/**
* 创建httpClient对象
*
* @param hostname
* @param port
* @return
*/
private static CloseableHttpClient createHttpClient(String hostname, int port) {
// SSLContext sslContext = createIgnoreVerifySSL();
// 设置协议http和https对应的处理socket链接工厂的对象
ConnectionSocketFactory socketFactory = PlainConnectionSocketFactory.getSocketFactory();
// LayeredConnectionSocketFactory connectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", socketFactory)
.register("https", trustAllHttpsCert()).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
// 将最大连接数添加
cm.setMaxTotal(MAX_CONNECTION_NUM);
// 将每一个路由基础的连接添加
cm.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
HttpHost httpHost = new HttpHost(hostname, port);
// 将目标主机的最大连接数添加
cm.setMaxPerRoute(new HttpRoute(httpHost), MAX_PER_ROUTE);
HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= 5) {// 假设已经重试了5次,就放弃
return false;
}
if (exception instanceof NoHttpResponseException) {// 假设server丢掉了连接。那么就重试
LOGGER.error("NoHttpResponseException: server丢掉了连接");
// logRepositoryService.error("假设server丢掉了连接。那么就重试", exception.getMessage());
return true;
}
if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
LOGGER.error("SSLHandshakeException: 不要重试SSL握手异常");
// logRepositoryService.error("不要重试SSL握手异常", exception.getMessage());
return false;
}
if (exception instanceof InterruptedIOException) {// 超时
LOGGER.error("InterruptedIOException:超时");
// logRepositoryService.error("超时", exception.getMessage());
return false;
}
if (exception instanceof UnknownHostException) {// 目标server不可达
LOGGER.error("UnknownHostException: 目标server不可达");
// logRepositoryService.error("目标server不可达", exception.getMessage());
return false;
}
if (exception instanceof ConnectTimeoutException) {// 连接被拒绝
LOGGER.error("ConnectTimeoutException: 连接被拒绝");
// logRepositoryService.error("连接被拒绝", exception.getMessage());
return false;
}
if (exception instanceof SSLException) {// SSL握手异常
// logRepositoryService.error("SSL握手异常", exception.getMessage());
LOGGER.error("SSLException: SSL握手异常");
return false;
}
HttpClientContext clientContext = HttpClientContext
.adapt(context);
HttpRequest request = clientContext.getRequest();
if (!(request instanceof HttpEntityEnclosingRequest)) {
return true;
}
return false;
}
};
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.setRetryHandler(httpRequestRetryHandler).build();
return httpClient;
}
3.获取Httpclient
/**
* 获取httpclient
*
* @param url
* @return
*/
public static CloseableHttpClient getHttpClient(String url) {
String hostname = url.split("/")[2];
int port = 80;
if (hostname.contains(":")) {
String[] arr = hostname.split(":");
hostname = arr[0];
port = Integer.parseInt(arr[1]);
}
if (httpClient == null) {
synchronized (syncLock) {
if (httpClient == null) {
httpClient = createHttpClient(hostname, port);
}
}
}
return httpClient;
}
4.创建httpclient之前需要忽略https的证书验证
/**
* https忽略证书验证
*
* @return
*/
public static SSLConnectionSocketFactory trustAllHttpsCert() {
SSLConnectionSocketFactory socketFactory = null;
TrustManager[] trustManagers = new TrustManager[1];
TrustManager tm = new miTM();
trustManagers[0] = tm;
SSLContext sc = null;
try {
sc = SSLContext.getInstance("TLS");//sc = SSLContext.getInstance("TLS")
sc.init(null, trustManagers, null);
socketFactory = new SSLConnectionSocketFactory(sc, NoopHostnameVerifier.INSTANCE);
//HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return socketFactory;
}
static class miTM implements TrustManager, X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
//don't check
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
//don't check
}
}
5.设置请求头相关信息,由于httpclient相当于是客户端,所以我们请求需要设置提交服务器的请求头,这里我设置了xml、json、和一般表单方式的请求头
/**
* 设置基本信息,相应头,请求时间, 超时时间等...
* <p>
* 配置xml格式
*
* @param httpRequestBase httpRequestBase
*/
private static void configXml(HttpRequestBase httpRequestBase) {
httpRequestBase.setHeader("Content-type", (new StringBuilder()).append("application/xml; charset=")
.append(CHARSET).toString());
// httpRequestBase.setHeader("Accept", new StringBuffer("text/xml;charset=").append(CHARSET).toString());
httpRequestBase.setHeader("Cache-Control", "no-cache");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(SERVER_REQUEST_TIME_OUT)
.setConnectTimeout(SERVER_REQUEST_TIME_OUT).setSocketTimeout(SERVER_RESPONSE_TIME_OUT).build();
httpRequestBase.setConfig(requestConfig);
}
/**
* 设置基本信息,相应头,请求时间, 超时时间等...
* contentType为x-www-form-urlencoded
* <p>
* 配置默认格式
*
* @param httpRequestBase httpRequestBase
*/
private static void configNomal(HttpRequestBase httpRequestBase) {
httpRequestBase.setHeader("Content-type", (new StringBuilder().append("application/x-www-form-urlencoded; charset="))
.append(CHARSET).toString());
httpRequestBase.setHeader("Cache-Control", "no-cache");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(SERVER_REQUEST_TIME_OUT)
.setConnectTimeout(SERVER_REQUEST_TIME_OUT).setSocketTimeout(SERVER_RESPONSE_TIME_OUT).build();
httpRequestBase.setConfig(requestConfig);
}
/**
* json格式提交
* <p>
* 设置基本信息,相应头,请求时间, 超时时间等...
*
* @param httpRequestBase httpRequestBase
*/
private static void configJson(HttpRequestBase httpRequestBase) {
httpRequestBase.setHeader("Content-type", (new StringBuilder()).append("application/json; charset=")
.append(CHARSET).toString());
// httpRequestBase.setHeader("Accept", new StringBuffer("text/xml;charset=").append(CHARSET).toString());
httpRequestBase.setHeader("Cache-Control", "no-cache");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(SERVER_REQUEST_TIME_OUT)
.setConnectTimeout(SERVER_REQUEST_TIME_OUT).setSocketTimeout(SERVER_RESPONSE_TIME_OUT).build();
httpRequestBase.setConfig(requestConfig);
}
6.发起get请求
/**
* get请求
*
* @param url 请求地址
* @return 放回参数
* @throws Exception 异常
*/
public static String doGet(String url) throws Exception {
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = null;
try {
response = getHttpClient(url).execute(httpGet);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("请求失败" + response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity();
if (entity == null) {
return "";
}
return EntityUtils.toString(entity,"UTF-8");
} finally {
if (response != null) {
response.close();
}
}
}
7.提交POST请求(xml、json参数形式都可以传入)
/**
* post请求提交String类型参数
*
* @param url 请求地址
* @param params 请求参数
* @param contentType 请求参数类型
* @return 请求返回参数
*/
public static String doPostByString(String url, String params, String contentType) throws Exception {
HttpPost httpPost = new HttpPost(url);
// 判断请求参数类型为JSON还是XML,不同的类型需要设置不同的Content—type
if (contentType.equals("xml") || contentType.equals("XML")) {// xml方式
configXml(httpPost);
} else if (contentType.equals("json") || contentType.equals("JSON")) {// json方式
configXml(httpPost);
} else { // 这里默认的为默认提交方式即表单提交
configNomal(httpPost);
}
CloseableHttpResponse response = null;
String result = "";
try {
if (StringUtils.isNotBlank(params)) {// 判断是否有参数
StringEntity entity = new StringEntity(params, "UTF-8");
httpPost.setEntity(entity);
}
response = getHttpClient(url).execute(httpPost);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
return "";
}
HttpEntity responseEntity = response.getEntity();
result = EntityUtils.toString(responseEntity, "UTF-8");
} finally {
if (response != null) {
response.close();
}
}
return result;
}
8.文件上传
/**
* 利用Httpclient上传文件
* @param url 地址
* @param map 参数
* @param file 文件
* @return 返回信息
* @throws Exception 异常
*/
public static String doPostUplodeFile(String url, Map<String, Object> map, File file) throws Exception {
if (StringUtils.isBlank(url) || map == null || map.isEmpty()) {
return "";
}
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse response = null;
try {
List<BasicNameValuePair> params = new ArrayList<>();
MultipartEntity entity = new MultipartEntity();
for (String key : map.keySet()) {
entity.addPart(key, new StringBody((String) map.get(key), Charset.forName("UTF-8")));
}
entity.addPart("param3", new FileBody(file));
httpPost.setEntity(entity);
response = getHttpClient(url).execute(httpPost);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("请求失败" + response.getStatusLine().getStatusCode());
}
HttpEntity resEntity = response.getEntity();
return null == resEntity ? "" : EntityUtils.toString(resEntity, CHARSET);
} finally {
if (response != null) {
response.close();
}
}
}