用aop 拦截所有controller 的请求 生成全局traceId
@Pointcut("execution(* *.*.controller..*.*(..))")
public void cutOffPoint() {
}
@Before("cutOffPoint()")
public void doBefore(JoinPoint joinPoint)throws Throwable {
MDC.put("traceId", "生成全局traceid");
}
在logback.xml中配置
到此可以满足大部分的需求
需要注意的部分就是如果用到线程池需要特殊处理
可以参考
https://blog.csdn.net/yangcheng33/article/details/80796129
下面说下我的实现
项目中主要使用ThreadPoolTaskExecutor因此对他进行改造
复制public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor {
//内容为ThreadPoolTaskExecutor 类中的内容 我这里从新写了一下几个方法
initializeExecutor 方法中 super.execute(new MDCRunnable(decorated))
submitListenable方法中
ListenableFutureTask future =new ListenableFutureTask<>(new MDCCallable<>(task));
//住所有执行的方法都要改为MDCRunnable MDCCallable
}
MDCRunnable类 为
public class MDCRunnable implements Runnable {
private final Runnable runnable;
private transient final Map_cm = MDC.getCopyOfContextMap();
public MDCRunnable(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
if (_cm !=null) {
MDC.setContextMap(_cm);
}
try {
runnable.run();
}finally {
MDC.clear();
}}}
public class MDCCallable implements Callable {
private final Callablecallable;
private transient final Map_cm = MDC.getCopyOfContextMap();
public MDCCallable(Callable callable) {
this.callable = callable;
}
@Override
public V call()throws Exception {
if (_cm !=null) {
MDC.setContextMap(_cm);
}
try {
return callable.call();
}finally {
MDC.clear();
}}}
至此我们项目中就完美解决了traceId在本项目中传递
如果是在微服务中传递则 我们微服务之间的调用使用的restTemplate
所有增加一个拦截器
@Configuration
public class RestTemplateConfiguration {
@Bean
@LoadBalanced
public RestTemplateloadbalancedRestTemplate() {
SimpleClientHttpRequestFactory requestFactory =new SimpleClientHttpRequestFactory();
// 超时时间,单位毫秒
requestFactory.setConnectTimeout(3 *1000);
requestFactory.setReadTimeout(3 *60 *1000);
RestTemplate restTemplate =new RestTemplate(requestFactory);
restTemplate.getInterceptors().add(new TraceIdInterceptor());
return restTemplate;
}
public class TraceIdInterceptorimplements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponseintercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)throws IOException {
HttpHeaders headers = request.getHeaders();
traceId= MDC.get("traceId");
if(StringUtils.isNotBlank(traceId)){
headers.add("traceId",traceId);
}
return execution.execute(request,body);
}}}
然后在下游服务器写一个拦截器就可在request head中可以获取traceidl
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String traceId = request.getHeader("traceId");
至此就完成了所有的traceid 本项目 线程 项目之间 都可以用了