我有一个调用十几个其他服务的服务。@StreamListener
这使用控制器类中的 a从 Kafka 主题中读取。出于可追溯性的目的,来自 Kafka 消息的相同标头(原始请求 ID)也需要转发到所有其他服务
传统上,使用@PostMapping("/path")
orGetMapping
会生成一个请求上下文,并且可以从任何地方访问标头,并且只要我需要进行外部调用RequestContextHolder.currentRequestAttributes()
,我只需将HttpHeaders
对象传递给RequestEntity
但是在 a 中StreamListener
,不会生成请求上下文并尝试RequestContextHolder
在异常中访问结果
这是我尝试做的一个例子,它导致了一个异常:
public class Controller {
@Autowired Service1 service1
@Autowired Service2 service2
@StreamListener("stream")
public void processMessage(Model model) {
service1.execute(model);
service2.execute(model);
}
}
public class Service {
RestTemplate restTemplate;
public void execute(Model model){
// Do some stuff
HttpHeaders httpHeaders = RequestContextHolder.currentRequestAttributes().someCodeToGetHttpHeaders();
HttpEntity<Model> request = new HttpEntity(model, httpHeaders);
restTemplate.exchange(url, HttpMethod.POST, request, String.class);
}
}
我目前的解决方法是将 a 更改StreamListener
为 aPostMapping
并有另一个PostMapping
调用它,以便可以生成请求上下文。另一种选择是使用 aThreadLocal
但它看起来就像 janky
我知道@Headers MessageHeaders
用于访问流标头的注释,但是,如果不将标头向下传递给每个服务,这将无法轻松访问,并且会影响许多单元测试
理想情况下,我需要一种方法来创建我自己的请求上下文(或任何适当的术语),以便有一个地方来存储请求范围的对象(the HttpHeader
)或另一种线程安全的方式,以便在不添加请求参数的情况下将请求标头向下传递到堆栈至service.execute