springweb添加traceId

上面要求添加 traceId,需求很简单。
唯一的难点是,jakarta.servlet.http.HttpServletRequest 不支持直接 put 请求头。
所以需要创建一个可修改的对象,包装请求。
另外,由于我们应用还使用了 openFeign ,需要将 traceId 传递进去。
PS: 老大非要把appName用做traceId前缀,无语~

过滤器

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** 追踪id过滤器**/
@WebFilter(urlPatterns = "/*")
@Component
@Slf4j
public class TraceIdFilter extends HttpFilter {@Value("${spring.application.name:appName}")private String appName;@Overridepublic void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {try {// 添加 HeaderString traceId = request.getHeader(HConst.TRACE_ID);// 已存在则放行if (StringUtils.isNotBlank(traceId)) {// 放入日志MDC.put(HConst.TRACE_ID, traceId);response.setHeader(HConst.TRACE_ID,traceId);chain.doFilter(request, response);} else {// 不存在则自生成traceId = appName + "-" + UUIDGenerator.getUUID();log.info("appGenerator traceId : {}",traceId);// 推入请求MutableHttpServletRequest muRequest = new MutableHttpServletRequest(request);response.setHeader(HConst.TRACE_ID,traceId);muRequest.putHeader(HConst.TRACE_ID, traceId);// 放入日志MDC.put(HConst.TRACE_ID, traceId);chain.doFilter(muRequest, response);}} catch (Exception e) {log.error("TRACE_id异常:", e);throw new RuntimeException("TRACE_id异常");}}
}

可修改的请求适配器

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;import java.util.*;/*** 可修改的请求对象**/
public final class MutableHttpServletRequest extends HttpServletRequestWrapper {/*** 保持自定义头、值*/private final Map<String, String> customHeaders;public MutableHttpServletRequest(HttpServletRequest request){super(request);this.customHeaders = new HashMap<>();}public void putHeader(String name, String value){this.customHeaders.put(name, value);}@Overridepublic String getHeader(String name) {// 检查String headerValue = customHeaders.get(name);if (headerValue != null){return headerValue;}// 返回原头return ((HttpServletRequest) getRequest()).getHeader(name);}@Overridepublic Enumeration<String> getHeaderNames() {// 创建自定义头容器Set<String> set = new HashSet<String>(customHeaders.keySet());// 添加头@SuppressWarnings("unchecked")Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames();while (e.hasMoreElements()) {// 复制到新容器String n = e.nextElement();set.add(n);}// 重新构建并返回return Collections.enumeration(set);}}

调用了 openFeign,将 traceId 传入代码

@Slf4j
@Component
public class CipherInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {try {// 添加traceIdaddTraceId(template);byte[] body = template.body();String bodyStr = new String(body, StandardCharsets.UTF_8);// 打印请求消息log.info("feign-request-path: {}", template.path());log.info("feign-request-bodyStr : {}", bodyStr);} catch (Exception e) {log.error("CipherInterceptor error :", e);}}/*** 添加请求头* @param template 请求对象*/private static void addTraceId(RequestTemplate template) {Map<String, Collection<String>> headers = template.headers();String traceId = ServletUtil.getHeader(HConst.TRACE_ID);if (StringUtils.isBlank(traceId)) {traceId = "feign-" + UUIDGenerator.getUUID();}headers.put(HConst.TRACE_ID, Collections.singletonList(traceId));log.info("feign-request-headers: {}", headers);}}

其它代码

从请求上下文中获取请求头方法,生成 UUID
    public static String getHeader(String name){// 获取请求头信息ServletRequestAttributes requestAttributes =(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequest request = null;if (requestAttributes != null) {request = requestAttributes.getRequest();return request.getHeader(name);}return null;}public static String getUUID() {String s = UUID.randomUUID().toString();return s.replaceAll("-", "");}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/39194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3开发过程中遇到的一些问题记录

问题&#xff1a; vue3在使用 defineProps、defineEmits、defineExpose 时不需要import&#xff0c;但是 eslint会报错error defineProps is not defined no-undef 解决方法&#xff1a; 安装 vue-eslint-parser 插件&#xff0c;在 .eslintrc.js 文件中添加配置 parser: vue-e…

python中的json库常见使用总结

一、数据加载 1、json.loads() 接受一个包含JSON数据的字符串作为参数&#xff0c;从字符串中加载JSON数据。 import json json_string {"name":"Alice","age":30,"is_student":false,"hobbies":["reading",&…

计算机网络期末复习6(武夷学院版)略看

第6章 应用层 应用层是TCP/IP协议栈的最高层&#xff0c;直接面向用户&#xff0c;为各种网络应用提供服务。以下是一些典型的应用层协议的基本概念和主要使用的端口。 1. HTTP&#xff08;HyperText Transfer Protocol&#xff09; 基本概念&#xff1a;用于万维网上的数据…

Windows 组策略编辑器怎么打开,这两种方法你必须知道

组策略编辑器&#xff08;Group Policy Editor, 简称 GPEdit.msc&#xff09;是 Windows 操作系统中一个强大的工具&#xff0c;主要用于管理和配置系统设置、安全选项、用户权限等&#xff0c;尤其适用于企业环境中批量部署和管理策略。 尽管家庭版 Windows&#xff08;如 Win…

Flink分区和窗口操作

分区&#xff08;Partitioning&#xff09;与分组&#xff08;Grouping&#xff09;: 分区&#xff1a; 将数据流划分为多个子流&#xff0c;每个子流由一个或多个子任务处理。通过 keyBy 操作实现&#xff0c;根据键对数据进行分区。数据具体去往哪个分区&#xff0c;是通过…

解锁Memcached的Key长度极限:深入探索与实践

&#x1f511; 解锁Memcached的Key长度极限&#xff1a;深入探索与实践 Memcached是一种广泛使用的高性能分布式内存缓存系统&#xff0c;它通过减少数据库的读取次数来提高应用程序的性能。在Memcached中&#xff0c;每个缓存项都通过一个唯一的key来标识。然而&#xff0c;对…

秋招Java后端开发冲刺——并发篇1(线程与进程、多线程)

一、进程 1. 进程 进程是程序的一次动态执行过程&#xff0c;是操作系统资源分配的基本单位。 2. 进程和线程的区别 特性进程线程定义独立运行的程序实例&#xff0c;资源分配的基本单位进程中的一个执行单元&#xff0c;CPU调度的基本单位资源进程拥有独立的内存空间和资源线…

ubuntu安装miniconda、jupyer、ros2

miniconda: 类似于虚拟机 ,可以安装不同版本的python jupyer: python执行、调试命令工具 1.下载安装文件 wget https://repo.anaconda.com/miniconda/Miniconda3-py310_23.5.2-0-Linux-x86_64.sh 2.安装minconda bash https://repo.anaconda.com/miniconda/Miniconda3-py…

傅雷家书思维导图的制作方法,分享制作技巧和软件!

在浩如烟海的书海中&#xff0c;《傅雷家书》以其独特的视角和深厚的情感&#xff0c;成为了无数读者心中的经典。那么&#xff0c;如何将这部饱含父爱的书信集转化为清晰易懂的思维导图呢&#xff1f;本文将为您详细解读傅雷家书思维导图的制作技巧&#xff0c;并推荐几款实用…

能自动铲屎的养猫救星?带你了解热门爆款智能猫砂盆的真实体验!

在谈论猫咪的日常生活时&#xff0c;我和朋友最经常聊的话题就是在各种各样的紧急情况下如何狼狈地赶回去给猫咪铲屎&#xff0c;毕竟猫砂盆里的屎但凡停留那么几小时&#xff0c;就要开始发臭了&#xff0c;一下班回去实在受不了那个味道&#xff0c;每次下班在家门口都想带个…

gemma2 vllm和ollama推理部署;openai接口调用、requests调用

参考: https://huggingface.co/google/gemma-2-9b https://ai.google.dev/gemma/docs/model_card_2?hl=zh-cn https://huggingface.co/blog/gemma2 发布了两个型号9B\27B 支持上下文长度有点短:4096 1、 ollama推理部署 升级ollama: curl -fsSL https://ollama.com/…

AVL许可证与版权保护

在数字化时代&#xff0c;知识产权保护成为企业发展的重要保障。AVL许可证与版权保护的关系密不可分&#xff0c;共同为企业筑起坚实的防线。本文将深入探讨AVL许可证在版权保护中的重要性、作用以及最佳实践&#xff0c;帮助企业更好地维护自身知识产权。 一、AVL许可证在版权…

高三才考试努力,请记住这些个学习方法,助你华丽逆袭

站在人生的十字路口&#xff0c;高三是整个人生中重要的转折点&#xff0c;这一年的学习成果直接影响我们未来的人生走向。站在我们求学生涯的高度上&#xff0c;高三也是特殊的一年&#xff0c;因为我们要用一整年的时间去复习旧知识。   如果你到了高三改意识到自己需要努力…

AMSA-UNet | 基于自注意力的多尺度 U-Net 提升图像去模糊性能

前言 传统的单尺度U-Net在去模糊过程中常常会导致空间信息的丢失,这影响了去模糊的准确性。此外,由于卷积方法在捕捉长距离依赖方面的局限性,恢复图像的质量下降。为了解决上述问题,提出了一种基于自注意力的非对称多尺度U-Net(AMSA-UNet)来提高去模糊方法在准确性和计算…

修改Springboot项目名称

修改Springboot项目名称 1. 整体描述2. 具体步骤2.1 修改module名称2.2 修改程序包名2.3 mybatis/mybatis-plus配置修改2.4 logback文件2.5 yml配置2.6 Application启动类2.7 其他 3. 总结 1. 整体描述 开发过程中&#xff0c;经常遇到新来个项目&#xff0c;需要一份初始代码…

【前端】HTML+CSS复习记录【5】

文章目录 前言一、padding、margin、border&#xff08;边框边距&#xff09;二、样式优先级三、var&#xff08;使用 CSS 变量更改多个元素样式&#xff09;四、media quary&#xff08;媒体查询&#xff09;系列文章目录 前言 长时间未使用HTML编程&#xff0c;前端知识感觉…

去中心化革命:探索区块链技术的前沿

随着信息技术的飞速发展&#xff0c;区块链技术作为一种新兴的去中心化解决方案&#xff0c;正逐渐改变着我们的经济、社会和技术格局。本文将从区块链的基本原理、当前的应用实例以及未来的发展趋势三个方面&#xff0c;深入探讨区块链技术在革命性变革中的角色和影响。 1. 区…

构建工程化:建立平台化工程体系

一、功能描述 工程化体系主要是解决能够统一进行打包的问题&#xff0c;故需要对整体进行描述 1.1、子项目描述 1.1.1、配置管理 对于每一个子项目而言&#xff0c;需要有专门的配置管理目录&#xff0c;目录的建议组建方式为conf/defalut和conf/local&#xff0c;其中defa…

TypeScript中,如何利用数组生成一个联合类型

本文由 ChatMoney团队出品 在开发中我们常常会遇到这样一个问题&#xff0c;代码如下&#xff1a; const arr ["a","b","c","d","e","f","g","h","i","j","k&quo…

利用区块链技术实现返利App的透明化追溯

利用区块链技术实现返利App的透明化追溯 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何利用区块链技术实现返利App的透明化追溯&#xff0c…