1. MAVEN 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
2. 获取代码
// ServletServerHttpRequest request
TraceContext traceContext = (TraceContext) request.getServletRequest().getAttribute(TraceContext.class.getName());
String traceId = traceContext.traceIdString();
// HttpServletRequest request
TraceContext traceContext = (TraceContext) request.getAttribute(TraceContext.class.getName());
String traceId = traceContext.traceIdString();
3. 为何可以如此获取?
// brave.servlet.TracingFilter
...
...
public final class TracingFilter implements Filter {
final ServletRuntime servlet = ServletRuntime.get();
final CurrentTraceContext currentTraceContext;
final HttpServerHandler<HttpServerRequest, HttpServerResponse> handler;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = this.servlet.httpServletResponse(response);
TraceContext context = (TraceContext)request.getAttribute(TraceContext.class.getName());
if (context != null) {
CurrentTraceContext.Scope scope = this.currentTraceContext.maybeScope(context);
try {
chain.doFilter(request, response);
} finally {
scope.close();
}
} else {
Span span = this.handler.handleReceive(new HttpServletRequestWrapper(req));
request.setAttribute(SpanCustomizer.class.getName(), span.customizer());
// 赋值 traceId
request.setAttribute(TraceContext.class.getName(), span.context());
...
...
}
}
}
4. 实际项目中使用
package com.zxguan.springcloud2.user.config;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@Order(0)
@RestControllerAdvice
public class ApiResponseAdvice implements ResponseBodyAdvice {
/**
* 判断需要处理的情况
*
* @param methodParameter
* @param selectedHttpMessageConverter
*
* @return boolean true: false:
*/
@Override
public boolean supports(MethodParameter methodParameter, Class selectedHttpMessageConverter) {
//
return false;
}
/**
* 消息体返回前处理
*
* @param body 返回的消息体
* @param methodParameter 响应类型
* @param mediaType 请求的响应 contentType
* @param selectedHttpMessageConverter 执行序列化的转换器
* @param request
* @param response
*
* @return Object 返回的消息体
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class selectedHttpMessageConverter, ServerHttpRequest request, ServerHttpResponse response) {
// 此处可以统一添加 traceId 到响应中
return null;
}
}
在这里插入代码片
5. 日志中打印 traceId
// 借助 MDC 机制, 实现 traceId 的打印
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{X-B3-TraceId:-}</pattern>
6. 特别注意
MDC traceId
设置, 可以通过自定义过滤器提前到过滤器级别,但需要注意 过滤器顺序
,自定义过滤器需排在 brave.servlet.TracingFilter
之后