报错信息: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请求头*/@Configurationpublic class FeignWorkspaceInterceptor implements RequestInterceptor {@Autowiredprivate HttpServletRequest httpServletRequest;/*** 设置header传递,将当前服务的header信息传递到下游服务*/@Overridepublic 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值赋值到子线程
