上篇说了当前端访问微服务网关,借助ZuulFilter过滤器来过滤所有请求,获取request,判断cookie是否有身份短令牌,request的header中是否有Jwt令牌,redis中是否有Jwt令牌。但是这个数据传递只能是前端访问微服务时,网关进行过滤,在微服务访问微服务时,则没有数据向下传递。

所以我们使用Fegin拦截器来做微服务之间的数据下沉,数据传递。

因为在每个微服务使用Fegin远程调用时都会使用,所以写在了common包下。


import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;/** Fegin远程调用拦截器*/
public class FeignClientInterceptor implements RequestInterceptor {/*** 每次远程调用都会走这个方法* @param requestTemplate*/@Overridepublic void apply(RequestTemplate requestTemplate) {//的到requst中Header数据ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if(requestAttributes!=null){HttpServletRequest request = requestAttributes.getRequest();//取出header中的Jwt令牌Enumeration<String> headerNames = request.getHeaderNames();if(headerNames!=null){while(headerNames.hasMoreElements()){String headerName = headerNames.nextElement();String headerValue = request.getHeader(headerName);//向下传递requestTemplate.header(headerName,headerValue);}}}}}

可以从代码中看到,implements RequestInterceptor每个微服务远程调用都会走下面的实现方法,在apply()方法中,我们获取当前的request中Header中所有数据,然后用requestTemplate.header(headerName,headerValue) 将所有数据下沉。

所以在使用fegin远程调用时是可以这样利用fegin拦截器进行数据下沉的,但是在使用别的方法远程调用微服务时这个拦截器是不会处理的。

比如说,当我们使用的是restTemplate进行远程调用时,

 //注入restTemplate@Bean@LoadBalanced//开启客户端负载均衡public RestTemplate restTemplate(){return new RestTemplate(new OkHttp3ClientHttpRequestFactory());}
 //rest远程获取数据ResponseEntity<Map> forEntity = restTemplate.getForEntity(dataUrl, Map.class);

此时进行数据下沉需要进行数据处理,借助request中header的HttpEntity进行数据存储,数据传递。

比如

private AuthToken applyToken(String clientId, String clientSecret, String username, String password) {//获取认证服务 的微服务实例ServiceInstance serviceInstance = loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH);if (serviceInstance == null) {LOGGER.error("choose an auth instance fail");ExceptionCast.cast(AuthCode.AUTH_LOGIN_AUTHSERVER_NOTFOUND);}//  http://IP:port/URI uri = serviceInstance.getUri();String authUrl = uri + "/auth/oauth/token";//HttpEntity//bodyLinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<>();body.add("grant_type","password");body.add("username",username);body.add("password",password);//headersLinkedMultiValueMap<String, String> header = new LinkedMultiValueMap<>();header.add("Authorization",getHttpBasic(clientId,clientSecret));HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, header);//设置restTemplate远程调用时,对400,401错误不报错,正确返回数据restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){@Overridepublic void handleError(ClientHttpResponse response) throws IOException {if(response.getRawStatusCode()!=400&&response.getRawStatusCode()!=401){super.handleError(response);}}});//申请令牌的信息Map map = null;try {ResponseEntity<Map> bodyMap = restTemplate.exchange(authUrl, HttpMethod.POST, httpEntity, Map.class);map = bodyMap.getBody();} catch (RestClientException e) {e.printStackTrace();LOGGER.error("request oauth_token_password error: {}",e.getMessage());e.printStackTrace();ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);}if(map == null ||map.get("access_token") == null ||map.get("refresh_token") == null ||map.get("jti") == null){//确定用户名 或者 密码错误异常抛出if(map!=null){String error_description = (String) map.get("error_description");if(error_description.indexOf("UserDetailsService returned null")>=0){ExceptionCast.cast(AuthCode.AUTH_ACCOUNT_NOTEXISTS);}else if(error_description.indexOf("坏的凭证")>=0){ExceptionCast.cast(AuthCode.AUTH_CREDENTIAL_ERROR);}}//jti是jwt令牌的唯一标识作为用户身份令牌ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);}AuthToken authToken = new AuthToken();//访问令牌(jwt)String jwt_token = (String) map.get("access_token");//刷新令牌(jwt)String refresh_token = (String) map.get("refresh_token");//jti,作为用户的身份标识String access_token = (String) map.get("jti");authToken.setJwt_token(jwt_token);authToken.setAccess_token(access_token);authToken.setRefresh_token(refresh_token);return authToken;}

Fegin拦截器解决各微服务之间数据下沉相关推荐

  1. 微服务之间数据同步的思考

    周末无聊,来一篇服务之间数据同步的博客吧(主要讲注意的问题).具体什么业务场景就不举例了. ps:纯属个人瞎说,有错误.不足请大侠指出.嗯,开始说正事了. 业务流程 主要业务流程如下: #mermai ...

  2. 从0到1学SpringCloud——08 通过fegin实现微服务之间请求调用

    目录 一.前言 1.关于Fegin 2.注意事项 3.POM依赖 二.编码实现 1.启动类 2.创建openfeign接口 3.Controller代码 4.回调工厂 三.文件配置 1.Feign接口 ...

  3. spring cloud微服务之间调用Feign

    微服务之间调用Feign 1.在调用方添加feign依赖: <dependency><groupId>org.springframework.cloud</groupId ...

  4. springcloudalibaba架构(31):SpringCloud实现用户信息在微服务之间传递(Feign和Dubbo)

    文章目录 前言 第一节 微服务间用户信息传递问题 第二节 解决思路 第三节 实践操作(基于Feign) 1. 调用链路说明 2. shop-common改造 3. 开启注解 4. 启动服务器测试 第四 ...

  5. 微博中微服务缓存_微服务之间调用超时的设置治理

    原标题:微服务之间调用超时的设置治理 作者 | 奇正 微服务是⼀种分布式架构,系统内各部分(服务)被部署为单独的应用程序,并通过某种远程访问协议进⾏通讯.分布式应⽤的挑战之⼀就是如何管理远程服务的可用 ...

  6. SpringCloud 各个微服务之间会话共享以及Feign调用会话共享

    目录 1.会话共享应用背景 2.SpringCloud各个微服务 (SpringBoot)应用之间会话共享 2.1.启动类或者Redis配置类加入Redis会话共享注解 2.2.配置Redis基本配置 ...

  7. 微服务之间的最佳调用方式

    上一篇:3600万中国人在抖音"上清华" 0.2T架构师学习资料干货分享 茉莉花,别名:茉莉,拉丁文名:Jasminum sambac (L.) Ait,木犀科.素馨属直立或攀援灌 ...

  8. JHipster技术栈定制 - 基于UAA的微服务之间安全调用

    本文通过代码实例演示如何通过UAA实现微服务之间的安全调用. uaa: 身份认证服务,同时也作为被调用的资源服务.服务端口9999. microservice1: 调用uaa的消费者服务,服务端口80 ...

  9. mysql 间接引用_微服务之间安全调用 by UAA

    本文通过代码实例演示如何通过UAA实现微服务之间的安全调用. uaa: 身份认证服务,同时也作为被调用的资源服务.服务端口9999. microservice1: 调用uaa的消费者服务,服务端口80 ...

最新文章

  1. 攻下《JavaScript高级程序设计》——第二章 在HTML中使用JavaScript
  2. Windows下的磁盘管理(二)
  3. [转]:xmake插件开发之色彩高亮显示
  4. firebug中html显示为灰色的原因总结
  5. HikariCP-史上最快速的连接池
  6. python的os模块使用_Python之os模块的常见用法
  7. 更改sql-2008sa密码
  8. mysql启动失败2005_数据库2005服务启动不了
  9. 记一次Mysql数据库Kill完之后启动不起来的解决方案
  10. matlab2c使用c++实现matlab函数系列教程-unique函数
  11. 【数据分析认知课(一):数据分析思维观】——读后感
  12. 2022年圣诞节外贸出口热门清单 外贸进出口商品查询 贸易动力
  13. python如何对两个矩阵进行拼接_Python:合并两个numpy矩阵的实现
  14. 脱星摘帽刺激 ST板块表现出众
  15. 为什么每个团队中,总有猪队友?
  16. 如何免费添加QQ空间的音乐
  17. 李开复:渗透与价值——2012年的中国移动互联网
  18. 中国高速铁路发展对交通方式转变的影响与二氧化碳减排潜力研究
  19. dpdk中文-使用openwrt-SDK编译DPDK
  20. 94、厂房和仓库的耐火等级

热门文章

  1. throw和throws的使用
  2. mysql ip to int_ip网段转换程序(把ip地址转换成相对就的整数)
  3. Linux单独编译设备树,迅为IMX6Q开发板-非设备树内核-单独编译内核驱动
  4. mysql1846错误_远程连接MySQL报错ERROR 2003解决办法
  5. linux数据库怎么import,mysqlimport
  6. php 写一个大富翁游戏,C++大富翁代码 现在要设计一个类似“大富翁”的游戏:有一条由20个格子组成的 联合开发网 - pudn.com...
  7. dicom虚拟打印服务器,DICOM打印服务器软件
  8. android获取子线程id,Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
  9. 华为系统10.0是鸿蒙吗,暂时忘记鸿蒙!华为EMUI 10.0发布时间确认:这才是主角...
  10. php mysql 统计_PHP和MySQL实现优化统计每天数据