不会为每个请求添加独一无二的id?轻松改造spring项目,Java视频课资源

2019-10-23 10:45:10.917 INFO 1146 — [nio-8080-exec-1] c.e.demo.controller.TestController : this is hello 1

2019-10-23 10:45:10.917 INFO 1146 — [nio-8080-exec-1] c.e.demo.controller.TestController : this is hello 2

2019-10-23 10:45:10.917 INFO 1146 — [nio-8080-exec-1] c.e.demo.controller.TestController : this is hello 3

从这个日志中,我们根本无法区分单独的请求。如果同一时间有2到3个请求过来的话,那么你还能分得清哪个对哪个么?所以这就是今天要改造的地方。

改造思路

====

其实要改造的话其实很简单,我们可以在每个controller入口处,生成唯一的uuid,并传递下去。这样的话缺点就是对代码干扰太大,每个方法都要多加一个参数。

那么我们能不能把这个参数存在一个统一的地方,需要打印日志的时候,直接去取呢?大家应该可以想到了,用ThreadLocal类。其实到这儿思路已经对了,不过日志框架也想到了这个问题,他们已经封装好了现成的功能,就是日志框架中的MDC

1.首先将日志的id添加进MDC中

@Component

public class TraceIdInterceptor extends HandlerInterceptorAdapter {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String traceId = getTraceId(request); MDC.put(“traceId”, traceId);

//将traceId添加进响应头

response.addHeader(“traceId”,traceId);

return true;

}

private String getTraceId(HttpServletRequest request){

return String.format(“%s - %s”,request.getRequestURI(), UUID.randomUUID());

}

}

@Component

public class GlobalWebMvcConfigurer implements WebMvcConfigurer {

@Autowired

private TraceIdInterceptor traceIdInterceptor;

@Override

/*

traceId 拦截器需要在最开始执行

*/

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(traceIdInterceptor).order(0);

}

}

我们使用一下Spring的拦截器功能。在请求开始之前,将请求id添加进MDC。

2.修改日志的配置文件

新建一个logback-spring.xml文件添加如下内容

<?xml version="1.0" encoding="UTF-8"?>

<property name=“LOG_PATTERN”

value=“%d{yyyy-MM-dd} %d{HH:mm:ss.SSS} [%-5level] [%X{traceId}] [%thread] %logger{36} %F.%L %msg%n”>

${LOG_PATTERN}

INFO

在日志的格式LOG_PATTERN中,添加%X{traceId} ,这样日志在打印的时候便会去MDC中取出traceid,放在这儿。现在我们可以看看效果。

2019-10-23 11:02:46.649 [INFO ] [/hello - 79ec561a-ef5e-4dc5-91cc-b2143fa3dbd3] [http-nio-8080-exec-1] c.e.demo.controller.TestController TestController.java.18 this is hello 1

2019-10-23 11:02:46.649 [INFO ] [/hello - 79ec561a-ef5e-4dc5-91cc-b2143fa3dbd3] [http-nio-8080-exec-1] c.e.demo.controller.TestController TestController.java.19 this is hello 2

2019-10-23 11:02:46.650 [INFO ] [/hello - 79ec561a-ef5e-4dc5-91cc-b2143fa3dbd3] [http-nio-8080-exec-1] c.e.demo.controller.TestController TestController.java.20 this is hello 3

2019-10-23 11:02:47.612 [INFO ] [/hello - 2ac7450f-40f5-441c-8e10-9b937c006484] [http-nio-8080-exec-2] c.e.demo.controller.TestController TestController.java.18 this is hello 1

2019-10-23 11:02:47.612 [INFO ] [/hello - 2ac7450f-40f5-441c-8e10-9b937c006484] [http-nio-8080-exec-2] c.e.demo.controller.TestController TestController.java.19 this is hello 2

2019-10-23 11:02:47.612 [INFO ] [/hello - 2ac7450f-40f5-441c-8e10-9b937c006484] [http-nio-8080-exec-2] c.e.demo.controller.TestController TestController.java.20 this is hello 3

可以看到,两个请求通过traceId可以很清楚的区分开了。这样我们在排查问题的时候,可以通过响应头里面的traceId,直接查找到相关日志,非常方便。

进阶版traceId

==========

之前说过traceId的实现思路是通过ThreadLocal来实现的。使用ThreadLocal有一个前提就是一个请求进来始终是一个线程在处理。如果用到spring中的异步方法,traceId就会失效了。

我们可以做个实验

//编写一个service类

public class Service { @Async public void run(){ log.info(“this is service run!”);

}}//在hello方法中调用service的run方法@GetMapping(“hello”)

public String hello(){ log.info(“this is hello 1”);

log.info(“this is hello 2”);

log.info(“this is hello 3”);

service.run(); return “hello”;

}

可以看的打印出来的日志

2019-10-23 11:12:23.265 [INFO ] [/hello - 96b31833-e8e6-46c5-8459-d423309d1488] [http-nio-8080-exec-1] c.e.demo.controller.TestController TestController.java.22 this is hello 1

2019-10-23 11:12:23.266 [INFO ] [/hello - 96b31833-e8e6-46c5-8459-d423309d1488] [http-nio-8080-exec-1] c.e.demo.controller.TestController TestController.java.23 this is hello 2

2019-10-23 11:12:23.267 [INFO ] [/hello - 96b31833-e8e6-46c5-8459-d423309d1488] [http-nio-8080-exec-1] c.e.demo.controller.TestController TestController.java.24 this is hello 3

2019-10-23 11:12:23.278 [INFO ] [] [task-1] com.example.demo.controller.Service Service.java.17 this is service run!

其实也很简单,只要对异步线程池跑的对象稍作封装即可。

@EnableAsync

@Configuration

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述
后续会持续更新**

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-Z1u9n1PZ-1711999727347)]

最后

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-cVW13dlc-1711999727348)]

  • 23
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值