提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、Trace filter 实现1、请求入口 MDC 注入2、异步场景 MDC 传递二、Filter 注册三、Sensitive utilsExample ID Card maskerSensitiveUtils四、ClassicConverter 实现五、backlog 配置前言Filter 添加日志MDC变量使用ClassicConverter 实现日志脱敏全链路追踪通过 MDC 透传 traceId、userId 等全局标识串联单次请求的所有日志定位问题更高效全局脱敏日志输出前统一拦截自动对手机号、身份证、银行卡、密码等敏感字段打码一、Trace filter 实现1、请求入口 MDC 注入importcom.ft.mall.common.util.StringUtil;importjakarta.servlet.FilterChain;importjakarta.servlet.ServletException;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importorg.slf4j.MDC;importorg.springframework.web.filter.OncePerRequestFilter;importjava.io.IOException;importjava.util.UUID;publicclassTraceFilterextendsOncePerRequestFilter{privatestaticfinalStringTRACE_IDtraceId;privatestaticfinalStringUSER_IDuserId;OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{try{StringtraceIdrequest.getHeader(X-Trace-Id);StringuserIdrequest.getHeader(X-User-Id);if(StringUtil.isEmptyStringAfterTrim(traceId)){traceIdUUID.randomUUID().toString();}if(StringUtil.isEmptyStringAfterTrim(userId)){traceIdanonymous;}MDC.put(TRACE_ID,traceId);MDC.put(USER_ID,userId);filterChain.doFilter(request,response);}finally{MDC.remove(TRACE_ID);MDC.remove(USER_ID);}}}2、异步场景 MDC 传递需通过TaskDecorator装饰线程池透传 MDC 上下文importorg.slf4j.MDC;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.task.TaskDecorator;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;importjava.util.Map;importjava.util.concurrent.Executor;ConfigurationpublicclassThreadPoolConfig{Bean(asyncExecutor)publicExecutorasyncExecutor(){ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);executor.setThreadNamePrefix(async-);// 配置MDC上下文传递装饰器executor.setTaskDecorator(newMdcTaskDecorator());executor.initialize();returnexecutor;}/** * MDC上下文传递装饰器 */staticclassMdcTaskDecoratorimplementsTaskDecorator{OverridepublicRunnabledecorate(Runnablerunnable){// 父线程拷贝MDC上下文MapString,StringcontextMapMDC.getCopyOfContextMap();return()-{try{// 子线程设置MDCif(contextMap!null){MDC.setContextMap(contextMap);}runnable.run();}finally{MDC.clear();}};}}}二、Filter 注册importcom.ft.mall.common.web.filter.RepeatableReadFilter;importjakarta.servlet.Filter;importorg.springframework.boot.web.servlet.FilterRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.Ordered;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{/** * 注册可重复读请求体过滤器 * * p拦截所有路径优先级最高确保在 Spring 拦截器和其他 Filter 之前包装请求。 * * return Filter 注册 Bean */BeanpublicFilterRegistrationBeanFilterrepeatableReadFilter(){FilterRegistrationBeanFilterregistrationnewFilterRegistrationBean();registration.setFilter(newTraceFilter());registration.addUrlPatterns(/*);registration.setOrder(Ordered.HIGHEST_PRECEDENCE1);registration.setName(traceFilter);returnregistration;}}三、Sensitive utilsExample ID Card maskerimportjava.util.Set;importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassIdCardMasker{// ---------- 身份证 ----------// 18位6位地区 8位日期 3位顺序 校验位(0-9/X)/** 手机号字段名集合大小写不敏感统一存小写 */publicstaticfinalSetStringMOBILE_KEYSSet.of(id_card,sdcard,cardId,省份证);/** 身份证正则1[3-9] 开头 9 位数字 *//* *(?![0-9Xx]) *[1-9]\d{5} // 6位地区 *(?:19|20)\d{2} // 年份 1900-2099 *(?:0[1-9]|1[0-2]) // 月份 01-12 *(?:0[1-9]|[12]\d|3[01]) // 日期 01-31 *\d{3} // 顺序码 *[\dXx] // 校验位 *(?![0-9Xx]) */privatestaticfinalStringID_CARD_REGEX[1-9]\\d{5}(?:19|20)\\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx];/** 字段名 alternation从 Set 动态构建 */privatestaticfinalStringKEY_ALTMaskerUtils.buildKeyAlternation();privatestaticfinalPatternID_CARD_PATTERNPattern.compile((\(?:KEY_ALT)\\\s*:\\s*\)((?![0-9])ID_CARD_REGEX(?![0-9Xx]))\// KV: mobile13800138000 / mobile:13800138000|((?:KEY_ALT)\\s*[:]\\s*)((?![0-9])ID_CARD_REGEX(?![0-9Xx]))// 全文裸匹配带边界防止从长数字中截取|((?![0-9])ID_CARD_REGEX(?![0-9Xx])),Pattern.CASE_INSENSITIVE);/** 脱敏保留前 6 后 4 */privatestaticfinalintPREFIX6;privatestaticfinalintSUFFIX4;/** * 统一入口支持全文、JSON、KV */publicstaticStringmask(Stringtext){if(textnull||text.isEmpty()){returntext;}MatchermID_CARD_PATTERN.matcher(text);StringBuildersbnewStringBuilder(text.length());while(m.find()){Stringreplacement;if(m.group(2)!null){replacementm.group(1)maskIdCard(m.group(2))\;}elseif(m.group(4)!null){replacementm.group(3)maskIdCard(m.group(4));}else{replacementmaskIdCard(m.group(5));}m.appendReplacement(sb,Matcher.quoteReplacement(replacement));}m.appendTail(sb);returnsb.toString();}privatestaticStringmaskIdCard(StringidCard){if(idCardnull||idCard.length()PREFIXSUFFIX){returnidCard;}StringBuildersbnewStringBuilder(idCard.length());sb.append(idCard,0,PREFIX);sb.append(*.repeat(idCard.length()-SUFFIX-PREFIX));sb.append(idCard,idCard.length()-SUFFIX,idCard.length());returnsb.toString();}}SensitiveUtilsimportcom.ft.mall.common.util.sensitive.IdCardMasker;importcom.ft.mall.common.util.sensitive.MobileMasker;/** * 敏感信息脱敏工具类 */publicclassSensitiveUtils{publicstaticStringconvert(StringlogMsg){if(StringUtil.isEmptyStringAfterTrim(logMsg)){returnlogMsg;}logMsgIdCardMasker.mask(logMsg);returnlogMsg;}}四、ClassicConverter 实现importch.qos.logback.classic.pattern.ClassicConverter;importch.qos.logback.classic.spi.ILoggingEvent;importcom.ft.mall.common.util.SensitiveUtils;publicclassSensitiveLogConverterextendsClassicConverter{OverridepublicStringconvert(ILoggingEventevent){returnconvertStr(event.getFormattedMessage());}publicStringconvertStr(StringlogMsg){returnSensitiveUtils.convert(logMsg);}}五、backlog 配置?xml version1.0 encodingUTF-8?configurationscantruescanPeriod60 seconds!-- 日志基础配置 --propertynameLOG_PATHvalue./logs/propertynameAPP_NAMEvaluespringboot-demo/!-- 注册自定义脱敏转换器conversionWord为日志格式中使用的关键字 --conversionRuleconversionWordsensitiveMsgconverterClasscom.example.config.SensitiveMessageConverter/!-- 控制台输出包含MDC链路信息 脱敏后日志 --appendernameCONSOLEclassch.qos.logback.core.ConsoleAppenderencoderpattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{userId}] %-5level %logger{50} - %sensitiveMsg%n/patterncharsetUTF-8/charset/encoder/appender!-- 文件输出按天滚动 --appendernameFILEclassch.qos.logback.core.rolling.RollingFileAppenderfile${LOG_PATH}/${APP_NAME}.log/filerollingPolicyclassch.qos.logback.core.rolling.TimeBasedRollingPolicyfileNamePattern${LOG_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log/fileNamePatternmaxHistory30/maxHistory/rollingPolicyencoderpattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{userId}] %-5level %logger{50} - %sensitiveMsg%n/patterncharsetUTF-8/charset/encoder/appender!-- 根日志级别 --rootlevelINFOappender-refrefCONSOLE/appender-refrefFILE//root/configuration
企业数字化 ERP 产品动态
相关推荐
Skia ARM Chromebook GLES 交叉编译资产(chromebook_arm_gles)完整指南 图形学 【免费下载链接】skia Skia is a complete 2D graphic library for drawing Text, Geometries, and Images. See documentation for contribution instructions. 项目地址: https://gitcode.com/gh_mirrors/ski/skia 点击查看 免费下载 本篇技术指南聚焦于 … · 2026/9/24 9:33:09
自部署开源知识库Outline:成本、部署与团队协作实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 9:33:09
ADS 2023实战:433MHz低噪声放大器设计流程 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 9:33:09
2026年AI办公智能体Work Agent品类全解读 最近不少职场人都有类似的感知:之前使用AI工具,大多只能得到一段文字回复,想要产出一份完整的项目材料,还得手动把内容复制出来,调整格式、补充数据、对接不同工具处理后续环节,整个过程依然要耗费不少时间… · 2026/9/24 10:09:31
I2C总线从物理层到多主仲裁:开漏输出、上拉电阻与波形调试实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:09:25
电力监控网络安全态势感知架构设计与实战落地指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:09:25
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44