Spring Boot项目调用外部接口,大部分使用RestTemplate调用,本文主要解决RestTemplate调用第三方接口时怎么无侵入实现动态header增加和请求日志输出
以下直接上代码:
<hr/>
import com.google.common.base.Charsets;
import com.mycompany.projectname.common.constant.AppCons;
import com.mycompany.projectname.context.LoginInfoHolder;
import com.mycompany.projectname.util.ApigatewayUtil;
import mycompany.projectname.util.FastJsonUtils;
import mycompany.projectname.util.Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.URI;
import java.net.URLDecoder;
/**
* RestTempate请求拦截器
* Created by author on 2018/11/17.
*/
@Slf4j
@Component
public class ApiLoggerInterceptor implements ClientHttpRequestInterceptor {
private final String apiHost = "api.mycompay.com";
private final String aServicePath = "/a-service/v1";
private final String bServicePath = "/b-service/1.0";
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
traceRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
traceResponse(request, response);
return response;
}
private void traceRequest(HttpRequest request, byte[] body) throws IOException {
log.info("===========================request begin================================================");
addCommonHeader(request);
log.info("URI :{} {}", request.getMethod(), URLDecoder.decode(request.getURI().toString(), Charsets.UTF_8.name()));
log.info("Headers : {}", request.getHeaders());
log.info("Request body: {}", new String(body, Charsets.UTF_8));
log.info("===========================request end==================================================");
}
private void addCommonHeader(HttpRequest request) {
URI uri = request.getURI();
HttpHeaders headers = request.getHeaders();
if(uri.getHost().indexOf(apiHost) > -1) {//apigateway调用,需要签名信息
headers.setAll(ApigatewayUtil.generateApiGatewayHeader(uri));
}
if(uri.getPath().startsWith(aServicePath)) {//组装a service特殊要求的header
headers.add("appCode", System.getProperty("appCode"));
headers.add("appSecret", System.getProperty("appSecret"));
} else if(uri.getPath().startsWith(aServicePath)) {//b service需要的特殊header
headers.add("X-TENANT", LoginInfoHolder.tenantId());
}
}
private void traceResponse(HttpRequest request, ClientHttpResponse response) throws IOException {
String respContent = Utils.readInputStream(response.getBody());
log.info("============================response begin==========================================");
log.info("Response Status : {} {}", response.getStatusCode(), response.getStatusText());
log.info("Headers : {}", response.getHeaders());
if(request.getURI().getPath().startsWith("/c-service/1.0/dblist/")) {
respContent = FastJsonUtils.toJsonString(FastJsonUtils.parse(respContent), (object, name, value) -> {
if (name.equalsIgnoreCase("dbPassword")) {
//false表示指定字段将被排除在外
return false;
}
return true;
});
}
log.info("Response body : {}{}", StringUtils.substring(respContent,0, AppCons.LENGTH_OF_API_LOG),
respContent.length() > AppCons.LENGTH_OF_API_LOG ? "...略" : "");
log.info("=======================response end=================================================");
}
}