java 在工作线程上使用@RequestScoped类

r7s23pms  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(153)

我正在创建一个日志系统,其中所有由特定请求生成的日志都存储在一个请求范围内的对象中,并随后记录在一个ContainerResponseFilter上。因此,与每个请求有许多日志不同,我将只有一个包含有关该特定请求的所有信息的日志。
如何存储日志:

@RequestScoped
class Logs {
    private List<Log> logs;
    ...
}

如何添加日志:

@Inject
Logs logs;

...

private void myFunction(){
    logs.add(new Log(...));
}

如何在ContainerResponseFilter中编写它们:

@Inject
Logs logs;

@Inject
Logger logger;

@Override
public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) {
    logger.log(logs.entries());
}

如何启动async代码:

Uni.createFrom().item(myItem)
                .emitOn(Infrastructure.getDefaultWorkerPool())
                .subscribe().with(this::myFunc)

我遇到的问题是一个请求启动了一个在工作线程上运行的异步Uni。由于它不在请求的同一线程上,我有两个问题:

  • ContainerResponseFilter可能在Uni之前完成执行,这意味着在Uni中执行的任何日志都将丢失。
  • 由于@RequestScoped上下文似乎是线程本地的,因此在Uni中执行的日志被放置在一个完全独立的结构上。

通过让ContainerResponseFilter启动一个在前面提到的异步uni之后运行的Uni,我设法解决了第一个问题,但没有解决第二个问题。
对于如何解决最后一个问题,有什么建议吗?当运行在工作线程或任何其他与请求本身异步的上下文上时,我可以立即单独记录日志。

hs1ihplo

hs1ihplo1#

如果你真的需要在过滤器中以异步方式完成一些事情(我承认我不确定你是否会这样做),那么你应该使用Quarkus的ServerResponseFilter,它允许你返回Uni作为响应类型。
他是一个典型的例子:

public class UniResponseFilter {

    @ServerResponseFilter
    Uni<Void> filter() {
        return Uni.createFrom().nullItem();
    }
}

您可以在这里找到更多信息。

相关问题