报错信息:Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!
在使用OpenFeign
进行远程调用的时候一般需要将请求头参数传递给下游服务,这时需要通过HttpServletRequest
获取请求头参数,一般是通过实现RequestInterceptor
接口增加Feign拦截器,在拦截器中完成传递参数,拦截器代码如下:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletRequest;
/**
* feign调用传递workspaceId请求头
*/
@Configuration
public class FeignWorkspaceInterceptor implements RequestInterceptor {
@Autowired
private HttpServletRequest httpServletRequest;
/**
* 设置header传递,将当前服务的header信息传递到下游服务
*/
@Override
public void apply(RequestTemplate template) {
String workspaceId = httpServletRequest.getHeader("workspaceId");
if (StringUtils.isNotBlank(workspaceId)) {
template.header("workspaceId", workspaceId);
}
}
}
如果是通过多线程调用OpenFeign
的话,将获取不到HttpServletRequest
对象,可以通过设置子线程共享解决,在多线程调用OpenFeign
之前增加一行:RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(),true);
,但是如果多线程内业务代码执行时间较长,这时HttpServletRequest
生命周期已结束,对象已经被销毁,就算设置了子线程共享也获取不到了。
要解决获取不到HttpServletRequest
对象的问题,办法只有一个,就是不依赖HttpServletRequest
对象!因为这个对象会随着请求生命周期结束被销毁。
- 在请求进入的时候将需要传递的参数存储在
ThreadLocal
中 - 在
RequestInterceptor
拦截器中通过ThreadLocal
获取需要传递的参数值 - 在多线程执行之前将ThreadLocal值赋值到子线程