Fegin拦截器解决各微服务之间数据下沉
上篇说了当前端访问微服务网关,借助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拦截器解决各微服务之间数据下沉相关推荐
- 微服务之间数据同步的思考
周末无聊,来一篇服务之间数据同步的博客吧(主要讲注意的问题).具体什么业务场景就不举例了. ps:纯属个人瞎说,有错误.不足请大侠指出.嗯,开始说正事了. 业务流程 主要业务流程如下: #mermai ...
- 从0到1学SpringCloud——08 通过fegin实现微服务之间请求调用
目录 一.前言 1.关于Fegin 2.注意事项 3.POM依赖 二.编码实现 1.启动类 2.创建openfeign接口 3.Controller代码 4.回调工厂 三.文件配置 1.Feign接口 ...
- spring cloud微服务之间调用Feign
微服务之间调用Feign 1.在调用方添加feign依赖: <dependency><groupId>org.springframework.cloud</groupId ...
- springcloudalibaba架构(31):SpringCloud实现用户信息在微服务之间传递(Feign和Dubbo)
文章目录 前言 第一节 微服务间用户信息传递问题 第二节 解决思路 第三节 实践操作(基于Feign) 1. 调用链路说明 2. shop-common改造 3. 开启注解 4. 启动服务器测试 第四 ...
- 微博中微服务缓存_微服务之间调用超时的设置治理
原标题:微服务之间调用超时的设置治理 作者 | 奇正 微服务是⼀种分布式架构,系统内各部分(服务)被部署为单独的应用程序,并通过某种远程访问协议进⾏通讯.分布式应⽤的挑战之⼀就是如何管理远程服务的可用 ...
- SpringCloud 各个微服务之间会话共享以及Feign调用会话共享
目录 1.会话共享应用背景 2.SpringCloud各个微服务 (SpringBoot)应用之间会话共享 2.1.启动类或者Redis配置类加入Redis会话共享注解 2.2.配置Redis基本配置 ...
- 微服务之间的最佳调用方式
上一篇:3600万中国人在抖音"上清华" 0.2T架构师学习资料干货分享 茉莉花,别名:茉莉,拉丁文名:Jasminum sambac (L.) Ait,木犀科.素馨属直立或攀援灌 ...
- JHipster技术栈定制 - 基于UAA的微服务之间安全调用
本文通过代码实例演示如何通过UAA实现微服务之间的安全调用. uaa: 身份认证服务,同时也作为被调用的资源服务.服务端口9999. microservice1: 调用uaa的消费者服务,服务端口80 ...
- mysql 间接引用_微服务之间安全调用 by UAA
本文通过代码实例演示如何通过UAA实现微服务之间的安全调用. uaa: 身份认证服务,同时也作为被调用的资源服务.服务端口9999. microservice1: 调用uaa的消费者服务,服务端口80 ...
最新文章
- 攻下《JavaScript高级程序设计》——第二章 在HTML中使用JavaScript
- Windows下的磁盘管理(二)
- [转]:xmake插件开发之色彩高亮显示
- firebug中html显示为灰色的原因总结
- HikariCP-史上最快速的连接池
- python的os模块使用_Python之os模块的常见用法
- 更改sql-2008sa密码
- mysql启动失败2005_数据库2005服务启动不了
- 记一次Mysql数据库Kill完之后启动不起来的解决方案
- matlab2c使用c++实现matlab函数系列教程-unique函数
- 【数据分析认知课(一):数据分析思维观】——读后感
- 2022年圣诞节外贸出口热门清单 外贸进出口商品查询 贸易动力
- python如何对两个矩阵进行拼接_Python:合并两个numpy矩阵的实现
- 脱星摘帽刺激 ST板块表现出众
- 为什么每个团队中,总有猪队友?
- 如何免费添加QQ空间的音乐
- 李开复:渗透与价值——2012年的中国移动互联网
- 中国高速铁路发展对交通方式转变的影响与二氧化碳减排潜力研究
- dpdk中文-使用openwrt-SDK编译DPDK
- 94、厂房和仓库的耐火等级
热门文章
- throw和throws的使用
- mysql ip to int_ip网段转换程序(把ip地址转换成相对就的整数)
- Linux单独编译设备树,迅为IMX6Q开发板-非设备树内核-单独编译内核驱动
- mysql1846错误_远程连接MySQL报错ERROR 2003解决办法
- linux数据库怎么import,mysqlimport
- php 写一个大富翁游戏,C++大富翁代码 现在要设计一个类似“大富翁”的游戏:有一条由20个格子组成的 联合开发网 - pudn.com...
- dicom虚拟打印服务器,DICOM打印服务器软件
- android获取子线程id,Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
- 华为系统10.0是鸿蒙吗,暂时忘记鸿蒙!华为EMUI 10.0发布时间确认:这才是主角...
- php mysql 统计_PHP和MySQL实现优化统计每天数据