Java怎么在CompletableFuture中实现日志记录

1.首先利用aop为所有请求入口添加requestid。

@Aspect@Componentpublic class LoggingAspect {    /**     * AOP注解的Controller类方法必须为 public 或 protect ,千万不能用private!!!!!!!!否则会@Autowired注入的service会报空指针异常。     * 私有方法和字段不属于Spring上下文中的bean属性。     */    @Around("@annotation(org.springframework.web.bind.annotation.GetMapping) || " +            "@annotation(org.springframework.web.bind.annotation.PostMapping) || " +            "@annotation(org.springframework.web.bind.annotation.PutMapping) || " +            "@annotation(org.springframework.web.bind.annotation.DeleteMapping)")    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {        // 在logback-spring.xml里对应%X{requestId}        MDC.put("requestId", UUID.randomUUID().toString().substring(0, 13));  // Add request ID to MDC        try {            return joinPoint.proceed(); // Execute method        } finally {            MDC.remove("requestId");  // Remove request ID from MDC        }    }}

登录后复制

2.定义一下 logback-spring.xml ,引入 requestId 来进行链路记录,关键代码是 %X{requestId}

                                                                    debug                                    ${CONSOLE_LOG_PATTERN}                        UTF-8                                        ${LOG_FILE_PATH}/debug.log                     %d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n            UTF-8                                                ${LOG_FILE_PATH}/debug-%d{yyyy-MM-dd}.%i.log                                        100MB                                    15                        1GB                                    debug            ACCEPT            DENY                            ${LOG_FILE_PATH}/info.log                    %d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n            UTF-8                            ${LOG_FILE_PATH}/info-%d{yyyy-MM-dd}.%i.log                            100MB                        15                                    info            ACCEPT            DENY                            ${LOG_FILE_PATH}/warn.log                    %d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n            UTF-8                             ${LOG_FILE_PATH}/warn-%d{yyyy-MM-dd}.%i.log                            100MB                        15                                    warn            ACCEPT            DENY                            ${LOG_FILE_PATH}/error.log                            %d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n            UTF-8                            ${LOG_FILE_PATH}/error-%d{yyyy-MM-dd}.%i.log                            100MB                        15                                    ERROR            ACCEPT            DENY                                                                                                                                    

登录后复制

2.定义一个`复杂`业务流程,来看看日志的实力

private final ExecutorService executorService = Executors.newFixedThreadPool(4);@GetMapping("saveUser")    public String saveUser() {    log.info("进入了saveUser");    // 异步    CompletableFuture.runAsync(()-> b(), executorService);    log.info("退出了saveUser");    return "Ok";}private void b() {    log.info("进入了b");}

登录后复制

日志如下,可以看到异步线程的requestId丢失了,21dbaad3-3158 这个就是requestId,这种情况下我们需要自定义线程类来保存MDC的上下文

2023-04-19 11:51:59.309 21dbaad3-3158  INFO 23044 — [p-nio-80-exec-1] c.h.m.api.CompletableFutureApi           : 进入了saveUser2023-04-19 11:51:59.312 21dbaad3-3158  INFO 23044 — [p-nio-80-exec-1] c.h.m.api.CompletableFutureApi           : 退出了saveUser2023-04-19 11:51:59.312   INFO 23044 — [pool-1-thread-1] c.h.m.api.CompletableFutureApi           : 进入了b

3.定义线程实现类,并且在构造函数中存储MDC的上下文

立即学习“Java免费学习笔记(深入)”;

public static class MdcTaskWrapper implements Runnable {    private final Runnable task;    private final Map contextMap;    public MdcTaskWrapper(Runnable task) {        this.task = task;        this.contextMap = MDC.getCopyOfContextMap();    }    @Override    public void run() {        if (contextMap != null) {            MDC.setContextMap(contextMap);        }        try {            task.run();        } finally {            MDC.clear();        }    }}

登录后复制

4.接下来再改写一下runAsync的使用方式,我们用MdcTaskWrapper来进行线程操作,这个线程类是包含mdc上下文的

@GetMapping("saveUser")public String saveUser() {    log.info("进入了saveUser");    // 异步    CompletableFuture.runAsync(this::b, command -> executorService.execute(new MdcTaskWrapper(command)));    log.info("退出了saveUser");    return "Ok";}private void b() {    log.info("进入了b");}

登录后复制

可以看到,requestId:4ab037ab-92cb,异步线程能够拿到MDC的上下文,并且成功记录链路日志

2023-04-19 11:58:27.581 4ab037ab-92cb  INFO 6816 — [p-nio-80-exec-5] c.h.m.api.CompletableFutureApi           : 进入了saveUser
2023-04-19 11:58:27.582 4ab037ab-92cb  INFO 6816 — [p-nio-80-exec-5] c.h.m.api.CompletableFutureApi           : 退出了saveUser
2023-04-19 11:58:27.582 4ab037ab-92cb  INFO 6816 — [pool-1-thread-1] c.h.m.api.CompletableFutureApi    

以上就是Java怎么在CompletableFuture中实现日志记录的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2626175.html

(0)
上一篇 2025年3月7日 00:50:13
下一篇 2025年2月18日 10:40:53

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Java如何实现优雅的参数校验

    一、引子 要对方法的参数进行校验,最简单暴力的写法是这个样子:     public static void utilA(String a,BigDecimal b){        if (StringUtils.isEmpty(a)){…

    2025年3月7日
    200
  • Java之SpringBoot怎么实现基本增删改查

    根据上图所示,idea中我们有7个比较重要的模块需要建立 (1)controller包:如果学习过或者对SpringMVC有所了解的小伙伴,肯定知道,controller是控制层,相当于我们的接收浏览器信息并响应发送相关信息的地方,具体的还…

    2025年3月7日 编程技术
    200
  • Java SpringMVC数据响应实例分析

    1)页面跳转   直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转。  返回带有前缀的字符串: 转发:   forward:/WEB-INF/views/index.jsp 重定向:   redirect:/index…

    2025年3月7日
    200
  • Java反射怎么定义和使用

    定义 在java程序运行期间动态获取和操作类、方法、属性等元素的能力被称为java反射。它使得我们可以在程序运行时获取一个类的信息,并对其进行操作,这极大地扩展了java语言的灵活性和可扩展性。 在Java中,每个类都有一个对应的Class…

    编程技术 2025年3月7日
    200
  • Java Agent怎么用

    Java Agent 技术简介 java agent 直译为 java 代理,也常常被称为 java 探针技术。 Java Agent 这种技术是在 JDK1.5 引入的,可以在运行时动态修改 Java 字节码。Java 中的类编译后形成字…

    2025年3月7日 编程技术
    200
  • Java Spring怎么实现定时任务

    java实现定时任务 jdk自带的库中,有两种方式可以实现定时任务,一种是timer,另一种是scheduledthreadpoolexecutor。 Timer+TimerTask 创建一个Timer就创建了一个线程,可以用来调度Time…

    2025年3月7日
    200
  • Java 中的异构系统集成和数据集成技术

    随着大数据和云计算技术的发展,企业和组织面临着多种异构系统的集成和数据交换的挑战。在这个背景下,java 的异构系统集成和数据集成技术得到了广泛的应用和发展。本文将从异构系统集成和数据集成的概念、java 中异构系统集成和数据集成的原理和应…

    编程技术 2025年3月7日
    200
  • Java 中的移动支付和金融科技技术

    随着人们生活方式和消费习惯的变化,移动支付和金融科技在全球范围内正在迅速发展。作为一种新兴的支付方式,移动支付已经成为了人们生活中不可或缺的一部分。java 作为一种强大的编程语言,在移动支付和金融科技领域也有着重要的作用。 移动支付的核心…

    编程技术 2025年3月7日
    200
  • Java 中的区块链和数字货币技术

    区块链和数字货币技术是如今最热门的技术之一,文章将对java中的区块链和数字货币技术进行探讨。 区块链是一个由多个块组成的链式结构网络,每个块存储着许多交易信息。 在Java中,区块链可以通过使用Spring Boot和Web3J等框架来实…

    编程技术 2025年3月7日
    200
  • Java语言中的微信小程序开发介绍

    微信小程序是一种轻量级的应用程序,可以在微信平台上运行,不需要下载安装,方便快捷。java语言作为一种广泛应用于企业级应用开发的语言,也可以用于微信小程序的开发。 在Java语言中,可以使用Spring Boot框架和第三方工具包来开发微信…

    编程技术 2025年3月7日
    200

发表回复

登录后才能评论