首页 > 其他分享 >Feign远程调用的问题

Feign远程调用的问题

时间:2022-12-07 17:07:52浏览次数:37  
标签:Feign 调用 confirmVo 请求 RequestContextHolder requestAttributes 远程


1. Feign远程调用丢失请求头问题

问题:使用feign远程调用会创建一个新request,会丢失请求头。

解决:加上feign远程调用的请求拦截器。使用拦截器apply方法应用拦截器,使用 RequestContextHolder拿到之前请求数据并加上请求头。

new request -> 远程调用拦截器 -> 远程调用

@Configuration
public class GuliFeignConfig {

@Bean("requestInterceptor")
public RequestInterceptor requestInterceptor() {

RequestInterceptor requestInterceptor = new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
//1、使用RequestContextHolder拿到刚进来的请求数据
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

if (requestAttributes != null) {
//老请求
HttpServletRequest request = requestAttributes.getRequest();

if (request != null) {
//2、同步请求头的数据(主要是cookie)
//把老请求的cookie值放到新请求上来,进行一个同步
String cookie = request.getHeader("Cookie");
template.header("Cookie", cookie);
}
}
}
};

return requestInterceptor;
}
}

2. Feign异步调用丢失请求头问题

//解决Feign异步调用丢失请求头问题

//主线程获取当前线程请求头信息
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

//子线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);
@Override
public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {

//构建OrderConfirmVo
OrderConfirmVo confirmVo = new OrderConfirmVo();

//获取当前用户登录的信息
MemberRespVo memberResponseVo = LoginUserInterceptor.loginUser.get();

//TODO :获取当前线程请求头信息(解决Feign异步调用丢失请求头问题)
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

//开启第一个异步任务
CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {

//每一个线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);

//1、远程查询所有的收获地址列表
List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());
confirmVo.setMemberAddressVos(address);
}, threadPoolExecutor);

//开启第二个异步任务
CompletableFuture<Void> cartInfoFuture = CompletableFuture.runAsync(() -> {

//每一个线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);

//2、远程查询购物车所有选中的购物项
List<OrderItemVo> currentCartItems = cartFeignService.getCurrentCartItems();
confirmVo.setItems(currentCartItems);
//feign在远程调用之前要构造请求,调用很多的拦截器
}, threadPoolExecutor).thenRunAsync(() -> {
List<OrderItemVo> items = confirmVo.getItems();
//获取全部商品的id
List<Long> skuIds = items.stream()
.map((itemVo -> itemVo.getSkuId()))
.collect(Collectors.toList());

//远程查询商品库存信息
R skuHasStock = wmsFeignService.getSkuHasStock(skuIds);
List<SkuStockVo> skuStockVos = skuHasStock.getData("data", new TypeReference<List<SkuStockVo>>() {});

if (skuStockVos != null && skuStockVos.size() > 0) {
//将skuStockVos集合转换为map
Map<Long, Boolean> skuHasStockMap = skuStockVos.stream().collect(Collectors.toMap(SkuStockVo::getSkuId, SkuStockVo::getHasStock));
confirmVo.setStocks(skuHasStockMap);
}
},threadPoolExecutor);

//3、查询用户积分
Integer integration = memberResponseVo.getIntegration();
confirmVo.setIntegration(integration);

//4、价格数据自动计算

//TODO 5、防重令牌(防止表单重复提交)
//为用户设置一个token,三十分钟过期时间(存在redis)
String token = UUID.randomUUID().toString().replace("-", "");
redisTemplate.opsForValue().set(USER_ORDER_TOKEN_PREFIX+memberResponseVo.getId(),token,30, TimeUnit.MINUTES);
confirmVo.setOrderToken(token);


CompletableFuture.allOf(addressFuture,cartInfoFuture).get();

return confirmVo;
}

标签:Feign,调用,confirmVo,请求,RequestContextHolder,requestAttributes,远程
From: https://blog.51cto.com/u_15905340/5919701

相关文章

  • 服务器远程端口怎么修改
    服务器远程端口怎么修改​修改Windows系统实例默认远程端口​以WindowsServer2012为例介绍如何修改Windows系统实例默认远程端口。​远程连接进入服务器后修改注册表子项P......
  • .net js 调用后端方法 取div元素
    js调用后端方法:varres="<%=checkOpenInitial()%>";https://blog.csdn.net/qq_27480007/article/details/127251935页面初始化加载就调用的js方法:window.onload=......
  • golang编译为dll与调用dll简单样例
    ==前置准备==1、golang版本:1.182、安装MinGW(我的环境本身已经安装好了,没有验证不安装是否可以生成) ==编译为DLL==【代码样例】packagemainimport"C"//export......
  • 为什么Git远程仓库中要配置公钥?
    最近在使用阿里云效平台代码管理,首次使用新建仓库,使用SSH时需要配置公钥。之前也在GitHub、Gitee上配置过,每次都能正常使用,也没有思考过为什么要配置公钥。这次记录一下其......
  • 还在用Feign?推荐一款微服务间调用神器,跟SpringCloud绝配
     简介:大家好,我是枫哥,......
  • Java通过JNA方式调用DLL(动态链接库)
    Java通过JNA方式调用DLL(动态链接库)1.JNA简单介绍先说JNI(JavaNativeInterface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进......
  • gitee建立远程仓库
    1.   新建仓库2.    (1),若本地已经写有代码,则:1,初始化:   2,暂存:   3,提交到本地:   4,本地和远程仓库建立联系......
  • rsync—远程同步
    一、rsync1.1rsync简介(1)rsync是一款开源的、快速的、多功能的、可实现全量及增量的本地或远程数据同步备份的优秀工具。并且可以不进行改变原有数据的属性信息,实现数据的......
  • Spring Cloud - Feign
    JAVA项目中如何实现接口调用?1)HttpclientHttpClient是ApacheJakartaCommon下的子项目,用来提供高效的、最新的、功能丰富的支持Http协议的客户端编程工具包,并且它......
  • SpringCloud-负载均衡和通信(Ribbon、Feign)
    1.Ribbon:负载均衡(基于客户端)1.1负载均衡以及RibbonRibbon是什么?SpringCloudRibbon是基于NetflixRibbon实现的一套客户端负载均衡的工具。简单的说,Ribbon是......