微服务参数透传实现

news2025/1/18 20:11:52

说明:在微服务架构中,用户身份经网关验证后,我们可以将用户信息,如ID加入到请求头上。后面的微服务中,可以设置一个拦截器,拦截请求,获取请求头上的用户ID,加入到ThreadLocal中。

最重要的是,在当前微服务发起请求,调用其他微服务时,需要将发出去的请求再进行拦截,把本地线程池中的用户ID再次放入到请求头中,这样就实现了用户信息在微服务中的流转,称为参数透传。本文介绍,上述参数透传的实现。

在这里插入图片描述

在微服务系统中,一般都会有一个共同模块,是所有微服务共同引用的模块,比如模块名为Base、Util、Feign-API,我们可以把参数透传的拦截器写在这个模块里面,这样其他微服务就不用再写拦截器的配置类了。

比如,我当前的这个系统,Feign-API模块是所有微服务共同引用的。里面写了一些共同的DTO对象,以及Feign-Client类对象;

在这里插入图片描述

实现

第一步:创建ThreadLocal类

在FeignAPI模块中,创建一个本地线程池对象,用于存储当前用户的ID;

/**
 * 本地线程池
 */
public class TokenThreadLocal {
    
    private static final ThreadLocal<Long> THREAD_LOCAL= new ThreadLocal<>();

    /**
     * 设置
     * @param tokenId
     */
    public static void set(Long tokenId){
        THREAD_LOCAL.set(tokenId);
    }

    /**
     * 获取
     * @return
     */
    public static Long get(){
        return THREAD_LOCAL.get();
    }

    /**
     * 移除
     */
    public static void remove(){
        THREAD_LOCAL.remove();
    }
}

第二步:创建MVC拦截器

在FeignAPI模块中,创建MVC拦截器(HandlerInterceptor),拦截路径为所有路径;

package com.hzy.interceptor;

import com.hzy.config.TokenThreadLocal;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 接收请求拦截器
 */
public class AuthorizationInterceptor implements HandlerInterceptor {

    /**
     * 收到请求会执行的方法
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        // 获取请求头中的用户ID
        String id = request.getHeader("authorization");

        // 判断用户ID是否为空
        if (id != null && id != ""){
            // 将字符串转换为Long类型
            long l = Long.parseLong(id);
            
            // 将用户ID存入ThreadLocal中
            TokenThreadLocal.set(l);
        }else {
            responseHandler(response);
            return false;
        }

        // 放行
        return true;
    }

    /**
     * 请求返回客户端之前会执行的方法
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 请求到客户端之后会执行的方法
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        TokenThreadLocal.remove();
    }

    /**
     * 用户尚未登录的返回信息
     * @param response
     * @return
     * @throws IOException
     */
    private boolean responseHandler(HttpServletResponse response) throws IOException {
        // 设置响应状态码 401 如果用户未登录 状态码都返回401
        response.setStatus(HttpStatus.UNAUTHORIZED.value());

        // 响应的数据类型和编码格式
        response.setContentType("application/json;charset=UTF-8");

        // 提示信息
        response.getWriter().write("用户未登录");

        return false;
    }
}

拦截器配置类,设置为所有路径请求都拦截;

import com.hzy.interceptor.AuthorizationInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 接收请求拦截器配置类
 */
public class MVCInterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthorizationInterceptor())
                .addPathPatterns("/**");
    }
}

第三步:创建Feign拦截器

创建Feign的拦截器(RequestInterceptor),该拦截器用于拦截当前微服务发出去的请求,代码内容写把当前本地线程池的用户ID再次放入到请求头中,传给下游微服务解析;

import com.hzy.config.TokenThreadLocal;
import feign.RequestInterceptor;
import feign.RequestTemplate;

/**
 * 发送请求拦截器
 */
public class AuthorizationRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 从本地线程池中获取用户ID,放入请求头中
        requestTemplate.header("authorization",TokenThreadLocal.get().toString());
    }
}

测试

测试订单服务,生成订单中,会调用库存服务,查询库存信息。在MVC、Feign拦截器、调用库存服务行分别打断点,发送请求,查看执行过程;

在这里插入图片描述

请求通过网关,先被订单服务的MCV拦截器拦截到,可以看到当前用户的ID是2,说明网关的默认过滤器起作用了,放行……

在这里插入图片描述

然后,断点来到订单服务的,调用库存服务这里,放行,查看发出去的请求会不会被拦截住;

在这里插入图片描述

断点被Feign拦截器(RequestInterceptor)拦住,将参数放入到请求头中;

在这里插入图片描述

这样,就实现了用户参数在微服务系统中的流转。

总结

使用一前一后两个拦截器,对微服务接受请求前,发送请求前分别进行拦截,实现参数透传。但是需要注意以下两点:

  • 两个拦截器所依赖的是本地线程池,所以如果微服务发出的是异步消息(如MQ),就行不通(参考:http://t.csdn.cn/wWsb7);

  • 拦截器是写在共同模块中的,所以参数得以流转的前提是当前微服务引用了共同模块

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

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

相关文章

Spring【学习记录一】

Spring内容解释 早期的Spring仅指代Spring Framework&#xff0c;后来基于Spring Framework孵化出大量的项目&#xff0c;Spring的含义变成了指代Spring家族 Spring Framework是Spring家族所有成员的基础&#xff0c;想要学透Spring&#xff0c;就必须要掌握Spring Framework…

电脑提示concrt140.dll丢失或找不到怎么恢复

现在系统在安装的时候为了简化包体会将一些组件给删除了&#xff0c;这样会造成在运行某些程序的时候&#xff0c;出现组件丢失的提示。例如concrt140.dll丢失&#xff0c;如果不及时处理&#xff0c;会导致系统中不少程序无法正常使用&#xff0c;那么要如何处理这个问题呢&am…

SpringBoot案例-员工管理-删除员工

查看页面原型&#xff0c;明确需求 页面原型 有批量删除和删除单个数据 需求 查看接口文档 接口文档的链接如下&#xff1a; 【腾讯文档】SpringBoot案例所需文档 https://docs.qq.com/doc/DUkRiTWVaUmFVck9N 思路分析 删除单个数据&#xff0c;将要删除的员工信息的id传…

消息中间件主要作用

首先我们想一下&#xff0c;两个公司之间如果有互相调用接口的业务需求&#xff0c;如果没有引入中间件技术&#xff0c;是怎么实现的呢&#xff1f; 用户发起请求给系统A&#xff0c;系统A接到请求直接调用系统B&#xff0c;系统B返回结果后&#xff0c;系统A才能返回结果给用…

YOLOv5、YOLOv8改进:S2注意力机制

目录 1.简介 2.YOLOv5改进 2.1增加以下S2-MLPv2.yaml文件 2.2common.py配置 2.3yolo.py配置 1.简介 S2-MLPv2注意力机制 最近&#xff0c;出现了基于 MLP 的视觉主干。与 CNN 和视觉Transformer相比&#xff0c;基于 MLP 的视觉架构具有较少的归纳偏差&#xff0c;在图像识…

线代强化第四章

下面正式开始公式的证明&#xff1a; B改变了矩阵的秩&#xff0c;所以他是不满秩的。 就是说一个矩阵如果左边乘上一个列满秩的&#xff0c;它的秩不会改变 一个矩阵如果右边乘上一个行满秩的&#xff0c;它的秩不会改变 PROVE: 等于主对角线或副对角线上分块阵的秩的和 当两…

Three.js 实现模型材质局部辉光效果和解决辉光影响场景背景图显示的问题

1.Three.js 实现模型材质局部辉光效果 2.解决辉光效果影响场景背景图显示的问题 相关API的使用&#xff1a; 1. EffectComposer&#xff08;渲染后处理的通用框架&#xff0c;用于将多个渲染通道&#xff08;pass&#xff09;组合在一起创建特定的视觉效果&#xff09; 2. …

【100天精通python】Day36:GUI界面编程_Tkinter高级功能操作和示例

目录 专栏导读 一、GUI 高级功能 1 自定义主题和样式 2 实现拖放功能 3 多线程和异步编程 二、实战项目 1. 待办事项应用 2. 图像查看器 3. 文本编辑器 4 添加动画和过渡效果 5 多界面和多线程示例 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_358…

前端-初始化Vue3+TypeScript

如果使用如下命令初始化项目&#xff0c;项目很干净&#xff0c;很适合了解项目的各个结构。 npm init vitelatest如果使用如下命令初始化项目&#xff0c;是可以选择你需要的组件 npm init vuelatest

Docker 容器数据卷

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied 解决办法&#xff1a;在挂载目录后多加一个--privilegedtrue参数即可 如果是CentOS7安全模块会比之前系统版本加强&#xff0c;不安全的会先禁止&#xff0c;所以目录挂载的情况被默认为不安全的行…

你家的wifi安全么?

在移动互联网已经相当普及的今天&#xff0c;家用Wifi已经成为居家必备设备了&#xff0c;但你有没有考虑过这样一个问题&#xff0c;“我家的Wifi安全么&#xff0c;有没有可能被别人蹭网&#xff0c;或者被黑客登录进来&#xff0c;窃取数据&#xff1f;”下面就结合目前主流…

Bryntum Scheduler Pro 5.5.1 Crack

BRYNTUM 调度程序专业版,专业的日程安排小部件 Bryntum Scheduler Pro 5.5.1 一个专业有大脑的调度UI组件。Scheduler Pro 可帮助您安排任务&#xff0c;同时考虑资源和任务的可用性。 连接您的任务 让 Scheduler Pro 处理剩下的事情。它将根据您定义的链接安排您的任务并遵守任…

3D echarts在vue中的使用

注意&#xff1a;高度问题要如此设置即可解决 参考1 参考2

由于找不到d3dx9_43.dll无法继续执行代码怎么解决

我们在安装PS&#xff0c;吃鸡等软件跟游戏的时候&#xff0c;有可能安装完之后出现以下问题&#xff08;特别是win7或者win8系统&#xff09; 错误&#xff1a; 打开PS或者吃鸡等游戏的时候出现这个错误&#xff1a;无法启动此程序&#xff0c;因为计算机中丢失d3dx9_43.dll。…

如何让多线程步调一致?

前几天老板突然匆匆忙忙的过来说对账系统最近越来越慢了&#xff0c;能不能快速优化一下&#xff1f;我了解了对账系统的业务后&#xff0c;发现还是挺简单的&#xff0c;用户通过在线商城下单&#xff0c;会生成电子订单&#xff0c;保存在订单库。之后物流会生成派送单给用户…

免费写真软件让你畅享写真之旅

佳媛: 嗨&#xff0c;妙纯&#xff0c;听说你喜欢拍摄写真照&#xff0c;那你有什么简单的写真照制作方式推荐吗&#xff1f; 妙纯&#xff1a;当然&#xff0c;现在有很多古装写真软件&#xff0c;你可以利用这些软件来制作写真照片哦。 佳媛: 哦&#xff1f;那拍古装写真软…

Apache JMeter

下载 Apache JMeter 并安装 java链接 打开 apache-jmeter-5.4.1\bin 找到jmeter.bat 双击打开 或者 ApacheJMeter.jar 双击打开 设置中文 找到 options 》choose Language 》chinese 新建 计划 创建线程组 添加Http请求 配置元件添加请求头参数&#xff08;content-type&…

LVS - DR

LVS-DR 数据流向 客户端发送请求到 Director Server&#xff08;负载均衡器&#xff09;&#xff0c;请求的数据报文&#xff08;源 IP 是 CIP,目标 IP 是 VIP&#xff09;到达内核空间。Director Server 和 Real Server 在同一个网络中&#xff0c;数据通过二层数据链路层来传…

miniconda克隆arcpy

arcpy环境克隆 前言尝试思考到此结束 前言 最近遇到了一些问题&#xff0c;需要用到arcpy来处理一些东西&#xff0c;但众所周知&#xff0c;arcgis的arcpy是python 2.0的&#xff0c;我不是很喜欢&#xff1b;所以我安装了arcgis pro 2.8&#xff0c;我发现这也是个坑&#x…

Redis高可用:主从复制详解

目录 1.什么是主从复制&#xff1f; 2.优势 3.主从复制的原理 4.全量复制和增量复制 4.1 全量复制 4.2 增量复制 5.相关问题总结 5.1 当主服务器不进行持久化时复制的安全性 5.2 为什么主从全量复制使用RDB而不使用AOF&#xff1f; 5.3 为什么还有无磁盘复制模式&#xff…