默认spring-boot 微服务中 用feign来做服务间调用,是不会携带token传递的。为了能让服务间调用的时候带上token,需要进行配置,增强resTemplate
 

1、先实现请求拦截器

  1. /**
  2. * feign配置token
  3. */
  4. @Configuration
  5. public class FeignRequestInterceptor implements RequestInterceptor {
  6.  
  7. @Override
  8. public void apply(RequestTemplate requestTemplate) {
  9. // 这里可以添加feign请求的全局参数
  10. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  11. if (attributes == null || attributes.getRequest() == null) {
  12. return;
  13. }
  14. HttpServletRequest request = attributes.getRequest();
  15. requestTemplate.header("token", request.getHeader("token"));
  16. requestTemplate.header("feignClient", "ifaas-hotel-robot-platform");
  17.  
  18. }
  19. }
 

2.在@FeignClient接口里添加configuration = {FeignConfig.class}

  1. @FeignClientname="被调用的服务名", configuration={FeignRequestInterceptor .class})
由于feign的熔断器hystrix的隔离策略的原因,feign调用线程和主线程隔离了,请求上下文不共用,导致feign拦截器中 RequestContextHolder.getRequestAttributes()为空
 
原因:
此属性指示HystrixCommand.run()执行哪种隔离策略,是以下两种选择之一:
  • THREAD —它在单独的线程上执行,并发请求受线程池中线程数的限制
  • SEMAPHORE —它在调用线程上执行,并发请求受信号量限制
 

3、解决feign中RequestContextHolder.getRequestAttributes()为null方案有两种:

3.1、修改隔离策略:默认是 采用THREAD ,修改成SEMAPHORE 即可,但是不推荐这种做法,因为并发请求收到限制。

 

3.2、自定义feign的并发策略 继承HystrixConcurrencyStrategy,然后重写wrapCallable方法。如下:

  1. import com.netflix.hystrix.strategy.HystrixPlugins;
  2. import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.context.annotation.Primary;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.web.context.request.RequestAttributes;
  7. import org.springframework.web.context.request.RequestContextHolder;
  8.  
  9. import java.util.concurrent.Callable;
  10.  
  11. /**
  12. * Created by YangGuanRong
  13. * date: 2022/3/8
  14. */
  15. @Slf4j
  16. @Primary
  17. @Component
  18. public class CustomFeignHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
  19.  
  20. public CustomFeignHystrixConcurrencyStrategy() {
  21. try {
  22.  
  23. HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
  24.  
  25. } catch (Exception e) {
  26. log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
  27. }
  28. }
  29.  
  30. @Override
  31. public <T> Callable<T> wrapCallable(Callable<T> callable) {
  32. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  33. return new WrappedCallable<>(callable, requestAttributes);
  34. }
  35.  
  36. static class WrappedCallable<T> implements Callable<T> {
  37. private final Callable<T> target;
  38. private final RequestAttributes requestAttributes;
  39.  
  40. public WrappedCallable(Callable<T> target, RequestAttributes requestAttributes) {
  41. this.target = target;
  42. this.requestAttributes = requestAttributes;
  43. }
  44.  
  45. /**
  46. * feign opens the fuse (hystrix): feign.hystrix.enabled=ture, and uses the default signal isolation level,
  47. * The HttpServletRequest object is independent of each other in the parent thread and the child thread and is not shared.
  48. * So the HttpServletRequest data of the parent thread used in the child thread is null,
  49. * naturally it is impossible to obtain the token information of the request header In a multithreaded environment, call before the request, set the context before the call
  50. *
  51. * feign启用了hystrix,并且feign.hystrix.enabled=ture。采用了线程隔离策略。
  52. * HttpServletRequest 请求在对象在父线程和子线程中相互独立,且不共享
  53. * 所以父线程的 HttpServletRequest 在子线程中为空,
  54. * 所以通常 在多线程环境中,在请求调用之前设置上下文
  55. * @return T
  56. * @throws Exception Exception
  57. */
  58. @Override
  59. public T call() throws Exception {
  60. try {
  61. // Set true to share the parent thread's HttpServletRequest object setting
  62. RequestContextHolder.setRequestAttributes(requestAttributes, true);
  63. return target.call();
  64. } finally {
  65. RequestContextHolder.resetRequestAttributes();
  66. }
  67. }
  68. }
  69. }

feign服务中调用,传递token的更多相关文章

  1. SpringCloud初体验:三、Feign 服务间调用(FeignClient)、负载均衡(Ribbon)、容错/降级处理(Hystrix)

    FeignOpenFeign Feign是一种声明式.模板化的HTTP客户端. 看了解释过后,可以理解为他是一种 客户端 配置实现的策略,它实现 服务间调用(FeignClient).负载均衡(Rib ...

  2. Spring Cloud Feign 服务消费调用(三)

    序言 Spring Cloud Netflix的微服务都是以HTTP接口的形式暴露的,所以可以用Apache的HttpClient或Spring的RestTemplate去调用 而Feign是一个使用 ...

  3. 在Delphi开发的服务中调用指定应用程序

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://fxh7622.blog.51cto.com/63841/529033 在很多时候 ...

  4. Spring Cloud OAuth2.0 微服务中配置 Jwt Token 签名/验证

    关于 Jwt Token 的签名与安全性前面已经做了几篇介绍,在 IdentityServer4 中定义了 Jwt Token 与 Reference Token 两种验证方式(https://www ...

  5. 代码书写C++ 中调用传递与指针传递根本区别

    从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变.而引用是一个别名,它在逻辑上不是独立的,它的存在具有依 ...

  6. 【多线程】java多线程Completablefuture 详解【在spring cloud微服务之间调用,防止接口超时的应用】【未完成】

    参考地址:https://www.jianshu.com/p/6f3ee90ab7d3 示例: public static void main(String[] args) throws Interr ...

  7. DELPHI编写服务程序总结(在系统服务和桌面程序之间共享内存,在服务中使用COM组件)

    DELPHI编写服务程序总结 一.服务程序和桌面程序的区别 Windows 2000/XP/2003等支持一种叫做“系统服务程序”的进程,系统服务和桌面程序的区别是:系统服务不用登陆系统即可运行:系统 ...

  8. Spring Cloud中Feign如何统一设置验证token

    代码地址:https://github.com/hbbliyong/springcloud.git 原理是通过每个微服务请求之前都从认证服务获取认证之后的token,然后将token放入到请求头中带过 ...

  9. SpringCloud系列——Feign 服务调用

    前言 前面我们已经实现了服务的注册与发现(请戳:SpringCloud系列——Eureka 服务注册与发现),并且在注册中心注册了一个服务myspringboot,本文记录多个服务之间使用Feign调 ...

随机推荐

  1. 线程池之 newSingleThreadExecutor 介绍

    package com.aaa.threaddemo; import java.text.DateFormatSymbols; import java.util.concurrent.Executor ...

  2. 如何在pyqt中使用 QStyle 重绘 QSlider

    前言 使用 qss 可以很方便地改变 QSlider 的样式,但是有些情况下 qss 无法满足我们的需求.比如下图所示样式: 如果直接使用 qss 将 handle 的内圆设置为透明背景,会看到 ha ...

  3. ApacheCN Kali Linux 译文集 20211020 更新

    Kali Linux 秘籍 中文版 第一章 安装和启动Kali 第二章 定制 Kali Linux 第三章 高级测试环境 第四章 信息收集 第五章 漏洞评估 第六章 漏洞利用 第七章 权限提升 第八章 ...

  4. JSP response.setCharacterEncoding与response.setContentType的区别

    问题描述 昨天在参考别人的项目时,发现页面引用js,css等文件总是乱码,后来才发现是MIME类型统一设置为text/html,并且仅仅编码设置了浏览器端的解析编码.另外,可以先通过文本编辑器(如no ...

  5. Redis的最常被问到知识点总结 (转)

    1.什么是redis? Redis 是一个基于内存的高性能key-value数据库. 2.Reids的特点 Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库 ...

  6. linux .h文件

    转载请注明来源:https://www.cnblogs.com/hookjc/ c++ #include <sys/types.h>   #include <unistd.h> ...

  7. Python property动态属性

    from datetime import datetime, date class User: def __init__(self, name, birthday): self.name = name ...

  8. 搭建golang开发环境(1.14之后版本)

    Go语言1.14版本之后推荐使用go modules管理依赖,也不再需要把代码写在GOPATH目录下. 下载地址 Go官网下载地址:https://golang.org/dl/ Go官方镜像站(推荐) ...

  9. python语法_1基础语法概述

    http://www.runoob.com/python3 章节:教程.基础语法.数据类型.解释器.注释.运算符. 大纲 查看python版本 实现第一个python3.x程序,hello world ...

  10. Solution -「SDOI 2016」「洛谷 P4076」墙上的句子

    \(\mathcal{Description}\)   Link.   (概括得说不清话了还是去看原题吧 qwq. \(\mathcal{Solution}\)   首先剔除回文串--它们一定对答案产 ...