将Spring RequestAttributes(RequestContextHolder)传播给Feign配置bean?

时间:2018-08-29 15:39:13

标签: spring spring-cloud spring-cloud-feign feign

我正在使用Feign配置类,并使用诸如此类的注释进行声明;

@FeignClient(name = "${earfsdf}", configuration = FeignConf.class)

在这种情况下,FeignConf不是Spring @Configuration,它纯粹是使用上面的注释用于此Feign客户端的范围。在FeignConf中,我声明了一个RequestInterceptor bean;

@Bean
public RequestInterceptor requestInterceptor() {

Feign会正确拾取此消息,当我在Feign客户端上发出请求时会调用它。

但是,我希望这个RequestInterceptor bean能够访问Spring的“ RequestAttributes”,我正在尝试使用Spring的RequestContextHolder.getRequestAttributes()

获得它。

似乎当我从RequestInterceptor中调用此函数时,它返回null。有什么方法可以将RequestAttributes传播到Feign RequestInterceptor中以供使用?

谢谢!

1 个答案:

答案 0 :(得分:0)

因此,答案是使用HystrixCallableWrapper,它允许您包装通过Hystrix(我与Feign一起使用)执行的任务

Hystrix为Feign调用创建一个新线程。可调用包装器是在父线程上调用的,因此您可以获取所需的所有上下文,将其传递到新的可调用对象中,然后将上下文加载到在新线程上执行的可调用对象内。

public class ContextAwareCallableWrapper implements HystrixCallableWrapper {

  @Override
  public <T> Callable<T> wrapCallable(Callable<T> callable) {

    Context context = loadContextFromThisThread();

    return new ContextAwareCallable<>(callable, context);
  }

  public static class ContextAwareCallable<T> implements Callable<T> {

    private final Callable<T> callable;
    private Context context;

    ContextAwareCallable(Callable<T> callable, Context context) {
      this.callable = callable;
      this.context = context;
    }

    @Override
    public T call() throws Exception {

      try {
        loadContextIntoNewThread(context);
        return callable.call();
      } finally {
        resetContext();
      }
    }
  }
}