@Component
public class HttpUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtil.class);
private static final ObjectMapper MAPPER = new ObjectMapper();
private final String success = "success";
private final String fail = "fail";
static {
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
@Autowired
private AcHttpClient acHttpClient;
@Resource(name = "extLogAndMetricExecutor")
private ThreadPoolTaskExecutor extLogAndMetricExecutor;
@Autowired
private LogExtService logExtService;
/**
* get请求,返回泛型类,默认超时时间,失败返回null
*/
public <T, R> T get(String uri, R request, Map<String, String> headers, TypeToken<T> typeToken) {
return doGet(uri, request, headers, typeToken.getType(), acHttpClient.getConnectionTimeout(), acHttpClient.getSoTimeout());
}
/**
* get请求,返回泛型类,定制超时时间,失败返回null
*/
public <T, R> T get(String uri, R request, Map<String, String> headers, TypeToken<T> typeToken, int soTimeOut) {
return doGet(uri, request, headers, typeToken.getType(), acHttpClient.getConnectionTimeout(), soTimeOut);
}
/**
* get请求,返回普通类,默认超时时间,失败返回null
*/
public <T, R> T get(String uri, R request, Map<String, String> headers, Class<T> returnClass) {
return doGet(uri, request, headers, returnClass, acHttpClient.getConnectionTimeout(), acHttpClient.getSoTimeout());
}
/**
* get请求,返回普通类,定制超时时间,失败返回null
*/
public <T, R> T get(String uri, R request, Map<String, String> headers, Class<T> returnClass, int soTimeout) {
return doGet(uri, request, headers, returnClass, acHttpClient.getConnectionTimeout(), soTimeout);
}
/**
* post-json请求,返回泛型类,默认超时时间,失败返回null
*/
public <T, R> T postJson(String uri, R request, Map<String, String> headers, TypeToken<T> typeToken) {
return doPostJson(uri, request, headers, typeToken.getType(), acHttpClient.getConnectionTimeout(), acHttpClient.getSoTimeout());
}
/**
* post-json请求,返回泛型类,定制超时时间,失败返回null
*/
public <T, R> T postJson(String uri, R request, Map<String, String> headers, TypeToken<T> typeToken, int soTimeOut) {
return doPostJson(uri, request, headers, typeToken.getType(), acHttpClient.getConnectionTimeout(), soTimeOut);
}
/**
* post-json请求,返回普通类,默认超时时间,失败返回null
*/
public <T, R> T postJson(String uri, R request, Map<String, String> headers, Class<T> returnClass) {
return doPostJson(uri, request, headers, returnClass, acHttpClient.getConnectionTimeout(), acHttpClient.getSoTimeout());
}
/**
* post-json请求,返回普通类,定制超时时间,失败返回null
*/
public <T, R> T postJson(String uri, R request, Map<String, String> headers, Class<T> returnClass, int soTimeout) {
return doPostJson(uri, request, headers, returnClass, acHttpClient.getConnectionTimeout(), soTimeout);
}
/**
* post-form请求, 返回泛型类,默认超时时间,失败返回null
*/
public <T, R> T postForm(String uri, R request, Map<String, String> headers, TypeToken<T> typeToken) {
return doPostForm(uri, request, headers, typeToken.getType(), acHttpClient.getConnectionTimeout(), acHttpClient.getSoTimeout());
}
/**
* post-form请求, 返回泛型类, 定制超时时间,失败返回null
*/
public <T, R> T postForm(String uri, R request, Map<String, String> headers, TypeToken<T> typeToken, int soTimeOut) {
return doPostForm(uri, request, headers, typeToken.getType(), acHttpClient.getConnectionTimeout(), soTimeOut);
}
/**
* post-form请求,返回普通类,默认超时时间,失败返回null
*/
public <T, R> T postForm(String uri, R request, Map<String, String> headers, Class<T> returnClass) {
return doPostForm(uri, request, headers, returnClass, acHttpClient.getConnectionTimeout(), acHttpClient.getSoTimeout());
}
/**
* post-form请求,返回普通类,定制超时时间,失败返回null
*/
public <T, R> T postForm(String uri, R request, Map<String, String> headers, Class<T> returnClass, int soTimeout) {
return doPostForm(uri, request, headers, returnClass, acHttpClient.getConnectionTimeout(), soTimeout);
}
private <T, R> T doPostJson(String uri, R request, Map<String, String> headers, Type returnType, int connectTimeout, int soTimeout) {
//记录起始时间
Long beginTime = System.currentTimeMillis();
RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(soTimeout).build();
HttpPost httpPost = new HttpPost(uri);
httpPost.setConfig(config);
CloseableHttpResponse httpResponse = null;
String requestString = JsonUtils.objectToJsonString(request);
String responseString = null;
String result = success;
try {
if (request != null) {
StringEntity entity = this.getStringEntity(requestString, StandardCharsets.UTF_8);
httpPost.setEntity(entity);
}
if (headers != null) {
for (final Map.Entry<String, String> stringStringEntry : headers.entrySet()) {
httpPost.addHeader(stringStringEntry.getKey(), stringStringEntry.getValue());
}
}
httpResponse = acHttpClient.getHttpClient().execute(httpPost);
if (httpResponse != null) {
SimpleHttpResponse simpleHttpResponse = getSimpleHttpResponse(httpResponse);
responseString = simpleHttpResponse.getEntityString();
if (String.class.equals(returnType)) {
return (T)responseString;
}
return JsonUtils.stringToTypeOfT(responseString, returnType);
}
return null;
} catch (Exception e) {
LOGGER.error(LogChain.text("do post json fail."), e);
responseString = String.format("调用%s服务出现异常%s", uri, e.getMessage());
result = fail;
return null;
} finally {
if (httpResponse != null) {
try {
httpResponse.close();
} catch (Exception e) {
LOGGER.error(LogChain.text("http close fail."), e);
}
}
httpPost.releaseConnection();
//统计接口耗时
Long endTime = System.currentTimeMillis();
Long cost = endTime - beginTime;
try {
String requestStr = StringUtils.substring(requestString, 0, 4000);
String responseStr = StringUtils.substring(responseString, 0, 4000);
asyncExtLogAndMetric(uri, CommonConstant.HttpMethod.POST, requestStr, responseStr, cost, result);
} catch (TaskRejectedException ex) {
LOGGER.warn(LogChain.text("执行外部服务调用切面,线程池执行异常,记录日志与发送Grafana指标失败。"), ex);
}
}
}
private <T, R> T doPostForm(String uri, R request, Map<String, String> headers, Type returnType, int connectTimeout, int soTimeout) {
//记录起始时间
Long beginTime = System.currentTimeMillis();
RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(soTimeout).build();
HttpPost httpPost = new HttpPost(uri);
httpPost.setConfig(config);
CloseableHttpResponse httpResponse = null;
String responseString = null;
String result = success;
try {
if (!CollectionUtils.isEmpty(headers)) {
for (final Map.Entry<String, String> entry : headers.entrySet()) {
httpPost.addHeader(entry.getKey(), entry.getValue());
}
}
Map<String, String> bodies = request != null ? MAPPER.convertValue(request, new TypeReference<Map<String, String>>() {
}) : null;
if (!CollectionUtils.isEmpty(bodies)) {
List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
for (final Map.Entry<String, String> entry : bodies.entrySet()) {
BasicNameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue());
parameters.add(pair);
}
StringEntity myEntity = new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8);
httpPost.setEntity(myEntity);
}
httpResponse = acHttpClient.getHttpClient().execute(httpPost);
if (httpResponse != null) {
SimpleHttpResponse simpleHttpResponse = getSimpleHttpResponse(httpResponse);
responseString = simpleHttpResponse.getEntityString();
if (String.class.equals(returnType)) {
return (T)responseString;
}
return JsonUtils.stringToTypeOfT(responseString, returnType);
}
return null;
} catch (Exception e) {
LOGGER.error(LogChain.text("do post form fail."), e);
responseString = String.format("调用%s服务出现异常%s", uri, e.getMessage());
result = fail;
return null;
} finally {
if (httpResponse != null) {
try {
httpResponse.close();
} catch (Exception e) {
LOGGER.error(LogChain.text("http close fail."), e);
}
}
httpPost.releaseConnection();
//统计接口耗时
Long endTime = System.currentTimeMillis();
Long cost = endTime - beginTime;
try {
String requestStr = StringUtils.substring(JsonUtils.objectToJsonString(request), 0, 4000);
String responseStr = StringUtils.substring(responseString, 0, 4000);
asyncExtLogAndMetric(uri, CommonConstant.HttpMethod.FORM, requestStr, responseStr, cost, result);
} catch (TaskRejectedException ex) {
LOGGER.warn(LogChain.text("执行外部服务调用切面,线程池执行异常,记录日志与发送Grafana指标失败。"), ex);
}
}
}
private <T, R> T doGet(String uri, R request, Map<String, String> headers, Type returnType, int connectTimeout, int soTimeout) {
//记录起始时间
Long beginTime = System.currentTimeMillis();
RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(soTimeout).build();
Map<String, String> params = request != null ? MAPPER.convertValue(request, new TypeReference<Map<String, String>>() {
}) : null;
String url = uri;
if (!CollectionUtils.isEmpty(params)) {
List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
for (final Map.Entry<String, String> entry : params.entrySet()) {
BasicNameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue());
parameters.add(pair);
}
url = uri + "?" + URLEncodedUtils.format(parameters, StandardCharsets.UTF_8);
}
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(config);
CloseableHttpResponse httpResponse = null;
String responseString = null;
String result = success;
try {
if (!CollectionUtils.isEmpty(headers)) {
for (final Map.Entry<String, String> entry : headers.entrySet()) {
httpGet.addHeader(entry.getKey(), entry.getValue());
}
}
httpResponse = acHttpClient.getHttpClient().execute(httpGet);
if (httpResponse != null) {
SimpleHttpResponse simpleHttpResponse = getSimpleHttpResponse(httpResponse);
responseString = simpleHttpResponse.getEntityString();
if (String.class.equals(returnType)) {
return (T)responseString;
}
return JsonUtils.stringToTypeOfT(responseString, returnType);
}
return null;
} catch (Exception e) {
LOGGER.error(LogChain.text("do get fail."), e);
responseString = String.format("调用%s服务出现异常%s", uri, e.getMessage());
result = fail;
return null;
} finally {
if (httpResponse != null) {
try {
httpResponse.close();
} catch (Exception e) {
LOGGER.error(LogChain.text("http close fail."), e);
}
}
httpGet.releaseConnection();
//统计接口耗时
Long endTime = System.currentTimeMillis();
Long cost = endTime - beginTime;
try {
String requestStr = StringUtils.substring(JsonUtils.objectToJsonString(request), 0, 4000);
String responseStr = StringUtils.substring(responseString, 0, 4000);
asyncExtLogAndMetric(uri, CommonConstant.HttpMethod.GET, requestStr, responseStr, cost, result);
} catch (TaskRejectedException ex) {
LOGGER.warn(LogChain.text("执行外部服务调用切面,线程池执行异常,记录日志与发送Grafana指标失败。"), ex);
}
}
}
private StringEntity getStringEntity(String content, Charset charset) throws UnsupportedEncodingException {
StringEntity entity;
if (charset != null) {
entity = new StringEntity(content, charset);
entity.setContentType("application/json;charset=" + charset.displayName());
} else {
entity = new StringEntity(content);
entity.setContentType("application/json");
}
return entity;
}
private SimpleHttpResponse getSimpleHttpResponse(HttpResponse httpResponse) throws IOException {
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
String reasonPhrase = statusLine.getReasonPhrase();
HttpEntity httpEntity = httpResponse.getEntity();
String entityString = EntityUtils.toString(httpEntity);
return new SimpleHttpResponse(statusCode, reasonPhrase, entityString);
}
/**
* 异步记录日志并发送Grafana指标
*
* @param api api
* @param requestStr 请求字符串
* @param responseStr 返回字符串
* @param cost 耗时
*/
private void asyncExtLogAndMetric(String api, String method, String requestStr, String responseStr, Long cost, String result) {
extLogAndMetricExecutor.execute(Objects.requireNonNull(TtlRunnable.get(() -> {
//记录时间
Date current = new Date();
//1. 记日志
try {
LogExtPo logeExtPo =
new LogExtPo(null, ContextHolder.getTraceId(), api, method, requestStr, responseStr, cost.intValue(), current);
logExtService.insertLog(logeExtPo);
} catch (Exception e) {
LOGGER.warn(LogChain.text("执行外部服务调用切面,异步打印日志失败"), e);
}
//2. 打Metric
try {
//如需展示接口平均耗时,需要使用直方图类型指标
GlobalMetric.histogram(MetricTagsConst.METRIC_INVOKE_EXTERNAL).value(cost).tag(MetricTagsConst.METRIC_TAG_NAME, api)
.tag(MetricTagsConst.METRIC_TAG_RESULT, result).go();
} catch (Exception e) {
LOGGER.warn(LogChain.text("执行外部服务调用切面,异步发送Grafana指标失败"), e);
}
})));
}
}这个和刚才的两个有什么区别
最新发布