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 中正常工作了。如果还有其他问题,欢迎继续交流。

相关推荐
nanxun88630 分钟前
记一次诡异的 Docker 容器"串包"故障排查
java
Pedantic37 分钟前
SwiftUI 手势笔记
前端·后端
金銀銅鐵1 小时前
[Python] 从《千字文》中随机挑选汉字
后端·python
用户1563068103513 小时前
Day01 | Java 基础(Java SE)
java
飘尘3 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
浏览器工程师5 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
行者全栈架构师5 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
Chenyiax5 小时前
从一次请求看懂 OkHttp:架构、调度与连接管理
后端
爱勇宝5 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
AskHarries6 小时前
工具失败时怎么办:重试、回滚、人工确认和风险提示
后端·程序员