首先创建Http连接池工具类:PoolingHttpClientConnectionUtils:
package com.epean.ops.utils;
import java.io.IOException;
import java.net.BindException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.*;
import com.epean.ops.exception.BaseAppException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
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.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 全局统一http请求控制(已采用连接池,且执行后关闭链接)
* 自己创建的httpclient 切记关闭 response 和 httpClient
*/
@Component
public class PoolingHttpClientConnectionUtils {
private final static Logger log = LoggerFactory.getLogger(PoolingHttpClientConnectionUtils.class);
public static PoolingHttpClientConnectionManager cm = null;
/**
* 初始化httpClient连接池
*/
static {
LayeredConnectionSocketFactory sslsf = null;
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
sslsf = new SSLConnectionSocketFactory(sslContext,new String[]{"TLSv1.2"},
null, new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
} catch (GeneralSecurityException e) {
log.info(e.getMessage(), e);
}
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
cm.setValidateAfterInactivity(1000);
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
}
/**
* 获取httpClient对象
* @return
*/
public CloseableHttpClient getHttpClient() {
RequestConfig.Builder builder = RequestConfig.custom();
builder.setConnectTimeout(60000).setConnectionRequestTimeout(60000).setSocketTimeout(60000);
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(builder.build())
.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
.setConnectionManager(cm)
.build();
return httpClient;
}
/**
* 获取httpClient返回信息字符串
* @param httpClient
* @param request
* @return
*/
public String readNet(CloseableHttpClient httpClient, HttpUriRequest request, HttpContext httpContext) throws BaseAppException {
CloseableHttpResponse response = null;
String content = null;
try {
response = httpClient.execute(request, httpContext);
HttpEntity entity = response.getEntity();
if (response.getStatusLine().getStatusCode() != 200) {
String entityStr = entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8);
String errorMsg = "readNet()返回码非200>>Code=" + response.getStatusLine().getStatusCode() + ",statusLine=" + response.getStatusLine()+",entityStr="+entityStr;
log.error(errorMsg);
return entityStr;
}
if (entity != null) {
content = EntityUtils.toString(entity, Consts.UTF_8);
}
} catch (UnsupportedOperationException e) {
log.error(e.getMessage(), e);
request.abort();
throw new BaseAppException("不被允许的操作异常:"+e.getMessage());
} catch (IOException e) {
log.error(e.getMessage(), e);
request.abort();
throw new BaseAppException("网络异常:"+e.getMessage());
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new BaseAppException("断开网络连接异常:"+e.getMessage());
}
}
}
return content;
}
public String http(CloseableHttpClient httpClient, HttpUriRequest request, HttpContext httpContext) throws BaseAppException {
CloseableHttpResponse response = null;
String content = null;
int retryTime = 3;
boolean needRetry = false;
String err;
do {
try {
needRetry = false;
response = httpClient.execute(request, httpContext);
HttpEntity entity = response.getEntity();
if (response.getStatusLine().getStatusCode() > 399) {
String entityStr = entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8);
String errorMsg = "statusLine=" + response.getStatusLine() + ",entityStr=" + entityStr;
log.error(errorMsg);
throw new BaseAppException(errorMsg);
}
if (entity != null) {
content = EntityUtils.toString(entity, Consts.UTF_8);//已经关闭了stream instream.close();
}
err = null;
} catch (UnsupportedOperationException e) {
log.error(e.getMessage(), e);
request.abort();
err = "不被允许的操作异常:" + e.getMessage();
} catch (IOException e) {
needRetry = true;
retryTime--;
log.error(e.getMessage(), e);
request.abort();
err = "网络异常:" + e.getMessage();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
log.error("断开网络连接异常:" + e.getMessage());
}
}
}
} while (needRetry && retryTime > 0);
if (StringUtils.isNotBlank(err)) {
throw new BaseAppException(err);
}
return content;
}
/**
* 获取重定向url
* @param httpClient
* @param request
* @return
*/
public String getRedirectsUrl(CloseableHttpClient httpClient, HttpUriRequest request, HttpContext httpContext) {
CloseableHttpResponse response = null;
String redirectsUrl = null;
try {
response = httpClient.execute(request, httpContext);
Header header = response.getFirstHeader("Location");
if(header != null) {
redirectsUrl = header.getValue();
log.info("joom 重定向地址:" + redirectsUrl);
}
} catch (UnsupportedOperationException e) {
log.error(e.getMessage(), e);
request.abort();
} catch (IOException e) {
log.error(e.getMessage(), e);
request.abort();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
return redirectsUrl;
}
}
分别使用get请求和put请求调用api:
package com.epean.ops.api.fyndiq;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.epean.ops.Constants;
import com.epean.ops.api.fyndiq.entity.ErrorResponse;
import com.epean.ops.api.fyndiq.entity.OrderResponse;
import com.epean.ops.exception.BaseAppException;
import com.epean.ops.utils.AssertUtils;
import com.epean.ops.utils.EncodeUtils;
import com.epean.ops.utils.PoolingHttpClientConnectionUtils;
import org.apache.commons.lang.StringUtils;
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.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @desc fyndiq订单Api
* @author chenp
* @date 2020-09-18
*/
@Component
public class FyndiqOrderApi {
private static final Logger log = LoggerFactory.getLogger(FyndiqOrderApi.class);
/**
* 获取订单接口路径
* @see ----https://merchantapi.fyndiq.com/
*/
public static final String orders_url = "https://merchants-api.fyndiq.se/api/v1/orders";
/**
*
* 平台比较特殊 无法按照订单修改时间拉取订单,只能按照状态拉取最新创建的订单
* @param state 订单状态
* @param loginUserName 登录账号
* @param token token
* @return
* @throws BaseAppException 接口异常
*/
public Map<String,Object> getOrders(String state, String loginUserName, String token,Integer page,Integer limit) throws BaseAppException {
Map<String,Object> resultMap = new HashMap<>(1);
StringBuilder param = new StringBuilder("?");
page = page == null ? 1 : page;
limit = limit == null ? 100 : limit;
param.append("page=").append(page).append("&");
param.append("limit=").append(limit).append("&");
if(StringUtils.isNotBlank(state)){
param.append("state=").append(state);
}
String url = orders_url + param.toString();
String entityStr = getResultString(loginUserName, token, url);
if(entityStr.contains(Constants.ERRORS)){
resultMap.put(Constants.ERRORS, JSONObject.parseObject(entityStr, ErrorResponse.class));
}else{
List<OrderResponse> orderResponses = JSONArray.parseArray(entityStr, OrderResponse.class);
resultMap.put(Constants.ORDERS,orderResponses);
}
return resultMap;
}
/**
* 标记订单已处理
* @param platOrderId 订单号
* @param loginUserName 登录账号
* @param token token
* @return
* @throws BaseAppException
*/
public ErrorResponse fulfillOrder(String loginUserName, String token,String platOrderId,String carrier_name,String tracking_number) throws BaseAppException{
AssertUtils.hasText(carrier_name,"物流名称不可为空");
AssertUtils.hasText(tracking_number,"跟赵不可为空");
Map<String,Object> resultMap = new HashMap<>(1);
String url = orders_url + "/"+ platOrderId + "/fulfill";
JSONObject jsonObject = new JSONObject();
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("carrier_name",carrier_name);
jsonObject1.put("tracking_number",tracking_number);
JSONArray jsonArray = new JSONArray();
jsonArray.add(jsonObject1);
jsonObject.put("tracking_information",jsonArray);
System.out.println(jsonObject.toJSONString());
String entityStr = putResultString(loginUserName, token, url,jsonObject.toJSONString());
return JSONObject.parseObject(entityStr, ErrorResponse.class);
}
/**
* 调用get请求
* @param loginUserName
* @param token
* @param url
* @return
* @throws BaseAppException
*/
private String getResultString(String loginUserName, String token, String url) throws BaseAppException {
PoolingHttpClientConnectionUtils poolingHttpClientConnectionUtils = new PoolingHttpClientConnectionUtils();
String headerParams = encodeHttpBasic(loginUserName,token);
Map<String,String> headers = new HashMap<>(1);
headers.put("Authorization",headerParams);
CloseableHttpClient httpClient = poolingHttpClientConnectionUtils.getHttpClient();
CloseableHttpResponse res=null;
HttpGet get = new HttpGet(url);
try {
if (headers != null) {
Set<String> keyset = headers.keySet();
for (String key : keyset) {
get.addHeader(key,headers.get(key));
}
}
RequestConfig.Builder configBuilder = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000);
get.setConfig(configBuilder.build());
res = httpClient.execute(get);
String entityStr = EntityUtils.toString(res.getEntity());
log.info("api接口返回:"+ entityStr);
return entityStr;
} catch (Exception e) {
log.info(e.getMessage());
throw new BaseAppException(e);
}finally {
close(res);
}
}
/**
* 调用put请求
* @param loginUserName clientid
* @param token token
* @param url url
* @param json 请求body
* @return
* @throws BaseAppException
*/
private String putResultString(String loginUserName, String token, String url,String json) throws BaseAppException {
PoolingHttpClientConnectionUtils poolingHttpClientConnectionUtils = new PoolingHttpClientConnectionUtils();
String headerParams = encodeHttpBasic(loginUserName,token);
Map<String,String> headers = new HashMap<>(1);
headers.put("Authorization",headerParams);
CloseableHttpResponse res=null;
CloseableHttpClient httpClient = poolingHttpClientConnectionUtils.getHttpClient();
HttpPut put = new HttpPut(url);
try {
if (headers != null) {
Set<String> keyset = headers.keySet();
for (String key : keyset) {
put.addHeader(key,headers.get(key));
}
}
// 组织请求参数
StringEntity stringEntity = new StringEntity(json, "utf-8");
put.setEntity(stringEntity);
RequestConfig.Builder configBuilder = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000);
put.setConfig(configBuilder.build());
res = httpClient.execute(put);
String entityStr = EntityUtils.toString(res.getEntity());
log.info("标记发货api接口返回:"+ entityStr);
return entityStr;
} catch (Exception e) {
log.info(e.getMessage());
throw new BaseAppException(e);
}finally {
close(res);
}
}
private void close( CloseableHttpResponse res){
if(res!=null){
try {
res.close();
} catch (IOException e) {
log.info(e.getMessage());
}
}
}
private String encodeHttpBasic(String loginUserName, String token) {
String encode = loginUserName + ":" + token;
return "Basic " + EncodeUtils.base64Encode(encode.getBytes());
}
}