1.debug Feign远程 2. 3.远程调用实际是new 了一个新的RequestTemplate,并没有把之前请求的header给设置进去 4. 5.可以通过拦截器,拦截请求,然后在给请求设置上,原请求的header信息即可
图解:
解决:
@Configuration public class FeignConfig { @Bean public RequestInterceptor requestInterceptor(){ return new RequestInterceptor() { @Override public void apply(RequestTemplate requestTemplate) { //1.RequestContextHolder拿到当前请求的数据,相当与拿到controller入参的HttpServletRequest ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); //老请求 HttpServletRequest request = requestAttributes.getRequest(); //2.同步请求头信息->cookie String cookie = request.getHeader("Cookie"); requestTemplate.header("Cookie",cookie); } }; } }还是上面的服务,只是改成异步调用
@Override public OrderConfirmVo confirmOrder() { OrderConfirmVo orderConfirmVo=new OrderConfirmVo(); //当前登录的用户 MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get(); //1.异步任务1 - 远程查询所有的收货地址列表 CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> { List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId()); orderConfirmVo.setMemberAddressVos(address); }, threadPoolExecutor); //2.异步任务2 - 远程查询购物车所有选中的购物项 CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> { List<OrderItemVo> currentCartItems = cartFeignService.getCurrentCartItems(); orderConfirmVo.setItems(currentCartItems); }, threadPoolExecutor); //feign在远程调用之前要构造请求,调用很多的拦截器 try { //等待所有任务完成 CompletableFuture.allOf(voidCompletableFuture,voidCompletableFuture1).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } //3.查询用户积分 Integer integration = memberResponseVo.getIntegration(); orderConfirmVo.setIntegration(integration); //4.其他数据自动计算 return orderConfirmVo; }改为了异步,发现之前的FeignConfig配置类在获取ServletRequestAttributes时,获取不到了 原因:旧请求是在线程A上,当使用异步时,是新开了一条线程去执行,新开的线程自然没有线程A的各种属性以及数据
图解:
解决:将旧线程中的属性RequestAttributes,设置到新线程中即可
@Override public OrderConfirmVo confirmOrder() { OrderConfirmVo orderConfirmVo=new OrderConfirmVo(); //当前登录的用户 MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get(); //解决:-------------------------------------- //获取旧线程的RequestAttributes //RequestContextHolder底层使用的是ThreadLocal RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); //1.异步任务1 - 远程查询所有的收货地址列表 CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> { //解决:-------------------------------------- //将旧线程中的RequestAttributes,设置到线程中的RequestContextHolder里 RequestContextHolder.setRequestAttributes(requestAttributes); List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId()); orderConfirmVo.setMemberAddressVos(address); }, threadPoolExecutor); //2.异步任务2 - 远程查询购物车所有选中的购物项 CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> { //解决:-------------------------------------- //将旧线程中的RequestAttributes,设置到线程中的RequestContextHolder里 RequestContextHolder.setRequestAttributes(requestAttributes); List<OrderItemVo> currentCartItems = cartFeignService.getCurrentCartItems(); orderConfirmVo.setItems(currentCartItems); }, threadPoolExecutor); //feign在远程调用之前要构造请求,调用很多的拦截器 try { //等待所有任务完成 CompletableFuture.allOf(voidCompletableFuture,voidCompletableFuture1).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } //3.查询用户积分 Integer integration = memberResponseVo.getIntegration(); orderConfirmVo.setIntegration(integration); //4.其他数据自动计算 return orderConfirmVo; }配置类加个非空判断即可
@Configuration public class FeignConfig { @Bean public RequestInterceptor requestInterceptor(){ return new RequestInterceptor() { @Override public void apply(RequestTemplate requestTemplate) { //1.RequestContextHolder拿到当前请求的数据,相当与拿到controller入参的HttpServletRequest ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (requestAttributes!=null){ //老请求 HttpServletRequest request = requestAttributes.getRequest(); if (request!=null){ //2.同步请求头信息->cookie String cookie = request.getHeader("Cookie"); requestTemplate.header("Cookie",cookie); } } } }; } }再次测试: ok,解决
