问题描述:
spring boot 项目,多模块之间使用Feign调用,请求方的request对象在传递的过程中丢失,服务方request对象中没有相应值。
初始状态:
feign接口
@PostMapping("/xxxx")
@ApiOperation(value = "xxxx", notes = xxxx")
RestResult<JSONObject> testFeign() throws Exception;
实现:
@PostMapping("/xxxx")
@ApiOperation(value = "xxxx", notes = xxxx")
@Transactional(rollbackFor = Exception.class)
public RestResult<JSONObject> testFeign(@Autowired HttpServletRequest request) throws Exception{
}
调用:
feignClient.testFeign();
结果:
request中没有请求头中没有相应数据。
解决过程:
尝试修改参数注解,在feign接口中增加参数。依然拿不到。
解决方案:
修改feign配置
public class NativeFeignConfig { @Bean public RequestInterceptor getRequestInterceptor() { return new RequestInterceptor() { @Override public void apply(RequestTemplate requestTemplate) { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpServletRequest req = servletRequestAttributes.getRequest(); Map<String, Collection<String>> headerMap = new HashMap(); //获取你需要传递的头信息 String userId = req.getHeader(SessionConst.KEY_USER_ID); String userName = req.getHeader(SessionConst.KEY_USER_NAME); String token = req.getHeader(SessionConst.KEY_TOKEN); String systemRole = req.getHeader(SessionConst.KEY_USER_SYSTEMROLE_ID); headerMap.put(SessionConst.KEY_USER_ID, Arrays.asList(userId)); headerMap.put(SessionConst.KEY_USER_NAME, Arrays.asList(userName)); headerMap.put(SessionConst.KEY_TOKEN, Arrays.asList(token)); headerMap.put(SessionConst.KEY_USER_SYSTEMROLE_ID, Arrays.asList(systemRole)); //feign请求时,便可携带上该信息 requestTemplate.headers(headerMap); } }; } }
注:创建一个自定义的hystrix 线程策略, 将servletRequestAttributes传入新线程中,并赋给RequestContextHolder: public class MyHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { @Override public <T> Callable<T> wrapCallable(Callable<T> callable){ ServletRequestAttributes servletRequestAttributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return new Callable<T>() { @Override public T call() throws Exception { try { if (null != servletRequestAttributes) { RequestContextHolder.setRequestAttributes(servletRequestAttributes); } return callable.call(); }finally { RequestContextHolder.resetRequestAttributes(); } } }; } }
@Configuration public class HystrixConfig { @PostConstruct public void init(){ HystrixPlugins.getInstance().registerConcurrencyStrategy( new MyHystrixConcurrencyStrategy() ); } }
在feign接口类中的注解上增加 :configuration= NativeFeignConfig.class
@FeignClient(value = "xxxx",configuration= NativeFeignConfig.class)
问题原因:
开启hystrix后,feign请求,会运行在hystrix管理的另一线程下。也就是说从请求方模块发送到服务方的请求参数可以正常传递,但是HttpServletRequest request对象并没有正常传递,从一个线程到另一个线程中时,request并没有跟随一起。需要手工组装request请求中的值。