报错信息:
    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拦截器,在拦截器中完成传递参数,拦截器代码如下:

    1. import feign.RequestInterceptor;
    2. import feign.RequestTemplate;
    3. import org.apache.commons.lang3.StringUtils;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.context.annotation.Configuration;
    6. import javax.servlet.http.HttpServletRequest;
    7. /**
    8. * feign调用传递workspaceId请求头
    9. */
    10. @Configuration
    11. public class FeignWorkspaceInterceptor implements RequestInterceptor {
    12. @Autowired
    13. private HttpServletRequest httpServletRequest;
    14. /**
    15. * 设置header传递,将当前服务的header信息传递到下游服务
    16. */
    17. @Override
    18. public void apply(RequestTemplate template) {
    19. String workspaceId = httpServletRequest.getHeader("workspaceId");
    20. if (StringUtils.isNotBlank(workspaceId)) {
    21. template.header("workspaceId", workspaceId);
    22. }
    23. }
    24. }

    如果是通过多线程调用OpenFeign的话,将获取不到HttpServletRequest对象,可以通过设置子线程共享解决,在多线程调用OpenFeign之前增加一行:RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(),true);,但是如果多线程内业务代码执行时间较长,这时HttpServletRequest生命周期已结束,对象已经被销毁,就算设置了子线程共享也获取不到了。
    要解决获取不到HttpServletRequest对象的问题,办法只有一个,就是不依赖HttpServletRequest对象!因为这个对象会随着请求生命周期结束被销毁。

    • 在请求进入的时候将需要传递的参数存储在ThreadLocal
    • RequestInterceptor拦截器中通过ThreadLocal获取需要传递的参数值
    • 在多线程执行之前将ThreadLocal值赋值到子线程