Spring Boot 3 tlog 适配

文章目录

    • 项目背景
    • [✅ 解决方案:重写 TLog 核心类适配 Spring Boot 3.5.13](#✅ 解决方案:重写 TLog 核心类适配 Spring Boot 3.5.13)
      • [1️⃣ 添加 TLog 依赖](#1️⃣ 添加 TLog 依赖)
      • [2️⃣ 创建适配 Jakarta Servlet 的 `TLogWebCommon`](#2️⃣ 创建适配 Jakarta Servlet 的 TLogWebCommon)
      • [3️⃣ 创建适配 Jakarta Servlet 的 `TLogFilter`](#3️⃣ 创建适配 Jakarta Servlet 的 TLogFilter)
      • [4️⃣ 注册 Filter](#4️⃣ 注册 Filter)
      • [5️⃣ 修改日志配置文件(Logback 示例)](#5️⃣ 修改日志配置文件(Logback 示例))
    • [📝 关键配置说明](#📝 关键配置说明)
      • [1️⃣ 日志格式中的变量](#1️⃣ 日志格式中的变量)
      • [2️⃣ 可选配置(`application.yml`)](#2️⃣ 可选配置(application.yml))
    • [⚠️ 注意事项](#⚠️ 注意事项)

项目背景

在 Spring Boot 3.5.13 中直接接入 TLog 会遇到问题,因为 TLog 的最新版本(如 1.5.2)是基于 javax.servlet 包名构建的,而 Spring Boot 3.x 使用的是 jakarta.servlet 包名,两者不兼容 。

不过,这个问题已经有成熟的解决方案,可以通过重写 TLog 的核心类来适配 Jakarta EE 规范 。


✅ 解决方案:重写 TLog 核心类适配 Spring Boot 3.5.13

1️⃣ 添加 TLog 依赖

xml 复制代码
<dependency>
    <groupId>com.yomahub</groupId>
    <artifactId>tlog-all-spring-boot-starter</artifactId>
    <version>1.5.2</version>
</dependency>

2️⃣ 创建适配 Jakarta Servlet 的 TLogWebCommon

java 复制代码
package com.yourproject.tlog.adapter;

import com.yomahub.tlog.context.TLogContext;
import com.yomahub.tlog.core.rpc.TLogLabelBean;
import com.yomahub.tlog.core.rpc.TLogRPCHandler;
import com.yomahub.tlog.web.TLogWebCommon;
import jakarta.servlet.http.HttpServletRequest;

public class JakartaTLogWebCommon extends TLogRPCHandler {

    private static volatile JakartaTLogWebCommon instance;

    public static JakartaTLogWebCommon loadInstance() {
        if (instance == null) {
            synchronized (JakartaTLogWebCommon.class) {
                if (instance == null) {
                    instance = new JakartaTLogWebCommon();
                }
            }
        }
        return instance;
    }

    public void preHandle(HttpServletRequest request) {
        String traceId = request.getHeader(TLogWebCommon.TLOG_TRACE_KEY);
        String spanId = request.getHeader(TLogWebCommon.TLOG_SPANID_KEY);
        String preIvkApp = request.getHeader(TLogWebCommon.PRE_IVK_APP_KEY);
        String preIvkHost = request.getHeader(TLogWebCommon.PRE_IVK_APP_HOST);
        String preIp = request.getHeader(TLogWebCommon.PRE_IP_KEY);

        TLogLabelBean labelBean = new TLogLabelBean(preIvkApp, preIvkHost, preIp, traceId, spanId);
        processProviderSide(labelBean);
    }

    public void afterCompletion() {
        TLogContext.remove();
    }
}

3️⃣ 创建适配 Jakarta Servlet 的 TLogFilter

java 复制代码
package com.yourproject.tlog.adapter;

import com.yomahub.tlog.context.TLogContext;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JakartaTLogFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;

            try {
                JakartaTLogWebCommon.loadInstance().preHandle(httpRequest);

                String traceId = TLogContext.getTraceId();
                if (traceId != null) {
                    httpResponse.setHeader("X-Trace-Id", traceId);
                }

                chain.doFilter(request, response);
            } finally {
                JakartaTLogWebCommon.loadInstance().afterCompletion();
            }
        } else {
            chain.doFilter(request, response);
        }
    }
}

4️⃣ 注册 Filter

java 复制代码
package com.yourproject.config;

import com.yourproject.tlog.adapter.JakartaTLogFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

@Configuration
public class TLogConfig {

    @Bean
    public FilterRegistrationBean<JakartaTLogFilter> tlogFilter() {
        FilterRegistrationBean<JakartaTLogFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new JakartaTLogFilter());
        registration.addUrlPatterns("/*");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        registration.setName("jakartaTLogFilter");
        return registration;
    }
}

5️⃣ 修改日志配置文件(Logback 示例)

logback-spring.xml 中,使用 TLog 提供的 AspectLogbackEncoder

xml 复制代码
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{spanId}] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

📝 关键配置说明

1️⃣ 日志格式中的变量

变量 说明
%X{traceId} 全局链路 ID(整个请求链路唯一)
%X{spanId} 调用跨度 ID(标识当前调用层级)

2️⃣ 可选配置(application.yml

yaml 复制代码
tlog:
  enable-invoke-time-print: true   # 打印调用耗时

⚠️ 注意事项

问题 解决方法
TLog 与 Spring Boot 3.x 不直接兼容 使用上述适配类,将 javax.servlet 替换为 jakarta.servlet
TraceId 不显示 检查 logback-spring.xml 中的 encoder 是否为 AspectLogbackEncoder
异步线程中 TraceId 丢失 使用 TLogInheritableTask 包装任务,或 TLogThreadPoolExecutor
Feign 调用不传递 TraceId TLog 已内置支持 ,确保引入 tlog-all-spring-boot-starter 即可

按上述步骤配置后,TLog 就能在 Spring Boot 3.5.13 中正常工作了。如果还有其他问题,欢迎继续交流。

相关推荐
落苜蓿蓝22 分钟前
Java 循环中对象复用导致属性覆盖?从 JVM 内存模型讲解原因
java·jvm·python
weixin_4407841126 分钟前
Android基础知识汇总
android·java·android studio
布鲁飞丝27 分钟前
从零实现富文本编辑器#-浏览器选区与编辑器选区模型同步
java·前端·编辑器
天丁o38 分钟前
Spring Boot + MyBatis Plus 考勤日报统计报表:打卡记录聚合、异常分类和明细下钻 Demo
spring boot·mybatis plus·企业数字化·考勤系统·报表统计
jun_bai1 小时前
使用java安全的移动文件
java
caishenzhibiao1 小时前
市场同步系统 同花顺期货通指标
java·c语言·c#
Devin~Y1 小时前
从本地生活电商到 AI RAG:互联网大厂 Java 面试场景完整实战
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
米码收割机1 小时前
SA508-3钢回火焊道焊接温度场数值模拟(模拟图+论文)
spring boot·express·宠物
520拼好饭被践踏1 小时前
JAVA+Agent学习day25
java·开发语言·学习
大黄说说1 小时前
Java 并发大坑:volatile、synchronized、Lock 三者如何选择?
java·开发语言