微服务参数透传实现

这篇具有很好参考价值的文章主要介绍了微服务参数透传实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

微服务参数透传实现,微服务,架构,SpringBoot

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

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

微服务参数透传实现,微服务,架构,SpringBoot

实现

第一步:创建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拦截器、调用库存服务行分别打断点,发送请求,查看执行过程;

微服务参数透传实现,微服务,架构,SpringBoot

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

微服务参数透传实现,微服务,架构,SpringBoot

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

微服务参数透传实现,微服务,架构,SpringBoot

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

微服务参数透传实现,微服务,架构,SpringBoot

请求又来到了MVC拦截器,注意哦,这里不是订单服务,是库存服务的拦截器;

微服务参数透传实现,微服务,架构,SpringBoot

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

总结

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

  • 两个拦截器所依赖的是本地线程池,所以如果微服务发出的是异步消息(如MQ),就行不通(参考:使用Feign出现空指针异常);

  • 拦截器是写在共同模块中的,所以参数得以流转的前提是当前微服务引用了共同模块文章来源地址https://www.toymoban.com/news/detail-664904.html

到了这里,关于微服务参数透传实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《黑马头条》SpringBoot+SpringCloud+ Nacos等企业级微服务架构项目

    各位爷,完整项目gitee如下,求star heima-leadnews-master: 《黑马头条》项目采用的是SpringBoot+springcloud当下最流行的微服务为项目架构,配合spring cloud alibaba nacos作为项目的注册和配置中心。新课程采用快速开发的模式,主要解决真实企业开发的一些应用场景。详情请看博客:htt

    2024年02月15日
    浏览(46)
  • 黑马头条 SpringBoot+SpringCloud+ Nacos等企业级微服务架构项目

    各位爷,完整项目gitee如下,求star heima-leadnews-master: 《黑马头条》项目采用的是SpringBoot+springcloud当下最流行的微服务为项目架构,配合spring cloud alibaba nacos作为项目的注册和配置中心。新课程采用快速开发的模式,主要解决真实企业开发的一些应用场景。详情请看博客:htt

    2024年02月08日
    浏览(55)
  • 【Spring Boot】SpringBoot参数验证以及实现原理

    参数验证很重要,是平时开发环节中不可少的一部分,但是我想很多后端同事会偷懒,干脆不做,这样很可能给系统的稳定性和安全性带来严重的危害。 那么在Spring Boot应用中如何做好参数校验工作呢,本文提供了小技巧以及验证实现原理,你知道几个呢? Spring Boot 提供了内

    2023年04月16日
    浏览(52)
  • 基于SpringBoot+Dubbo构建的电商平台-微服务架构、商城、电商、微服务、高并发、kafka、Elasticsearc+源代码+文档说明

    项目基于springboot2.1.6.RELEASE+Dubbo2.7.3 来构建微服务。 业务模块划分,尽量贴合互联网公司的架构体系。所以,除了业务本身的复杂度不是很高之外,整体的架构基本和实际架构相差无几。 但实际上,真实的生产级的项目由于用户量以及业务的复杂度,会变得非常复杂。 所以

    2024年02月20日
    浏览(50)
  • springboot第54集:思维导图后端知识点微服务分布式架构周刊

    InnoDB和Myisam是MySQL数据库中两种非常流行的存储引擎,主要存在四大区别: 事务支持能力不同:InnoDB支持ACID事务。所以可以处理高级别的数据完整性和可靠性。而MyISAM不支持事务,所以MyISAM在处理需要高度数据完整性的操作时不如InnoDB可靠。 锁定机制不同:InnoDB使用行级别

    2024年02月20日
    浏览(46)
  • 7.13 在SpringBoot中 正确使用Validation实现参数效验

    先说下 Spring Validation 参数校验,它是前后端分离项目SpringBoot后端Controller层必做的工作之一,目的是防止非法调用, Java JSR303 定义了校验标准 validation-api ,但没有实现, Hibernate validation 是规范的实现,另外还增加了一些 constraints 注解,最后 Spring Validation 对 Hibernate validati

    2024年02月09日
    浏览(43)
  • springboot第55集:思维导图Sharding-JDBC,事务,微服务分布式架构周刊

    事务定义 在数据库管理系统中,事务是单个逻辑或工作单元,有时由多个操作组成,在数据库中以一致模式完成的逻辑处理称为事务。一个例子是从一个银行账户转账到另一个账户:完整的交易需要减去从一个账户转账的金额,然后将相同的金额添加到另一个账户。 事务特

    2024年02月19日
    浏览(42)
  • 如何实现 Java SpringBoot 自动验证入参数据的有效性

    Java SpringBoot 通过javax.validation.constraints下的注解,实现入参数据自动验证 如果碰到 @NotEmpty 否则不生效,注意看下 @RequestBody 前面是否加上了 @Valid Validation常用注解汇总 Constraint 详细信息 @Null 被注释的元素必须为 null @NotNull 被注释的元素必须不为 null @NotBlank 被注释的元素不能

    2023年04月13日
    浏览(44)
  • 毕设常用云平台OneNET对接测试TCP方式透传实现

    在OneNet用网络调试助手实现数据上传跟命令下发 登录onenet云台: 登录地址:https://open.iot.10086.cn/ 完成账号注册之后登录,选择右上角控制台, 控制台版本分新版版本和旧版版本,二者数据不互通,我这里选择旧版本。 如果进入到新版界面可以切换到旧版本进行。切换到旧版

    2024年02月04日
    浏览(31)
  • 使用STM32 在实现温湿度LCD显示并蓝牙透传

    通过温湿度传感器将值传到LCD1602,并实时通过蓝牙透传到手机。 LCD1602 是一种工业字符型液晶,能够同时显示16x02即32字符 (16列两行) DHT11  DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 HC-01 蓝牙模块。 关于以上这三个模块的使用和详细介绍

    2024年02月17日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包