使用Feign,模块之间调用传递参数HttpServletRequest request拿不到值问题
问题描述:
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请求中的值。