java 为什么micronaut会以相反的顺序拦截请求

ecbunoof  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(141)

我对React式世界很陌生,现在我正试图创建两个HttpServerFilters,它们将Map用micronaut编写的服务器中的响应。为了提出我的问题,我准备了简化的代码片段:

@Filter("/**")
public class FirstFilter implements HttpServerFilter {

    @Override
    public int getOrder(){
        return ServerFilterPhase.FIRST.before();
    }

    @Override
    public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
        System.out.println("Returning publisher in FirstFilter!");
        return Publishers.then(
                chain.proceed(request),
                mutableHttpResponse -> {
                    System.out.println("Mapping response in first filter!");
                    mutableHttpResponse.getBody(ServiceHttpResponse.class)
                            .ifPresent(resp -> mutableHttpResponse.status(resp.getStatus()));
                });
    }
}
@Filter("/**")
public class SecondFilter implements HttpServerFilter {

    @Override
    public int getOrder(){
        return ServerFilterPhase.FIRST.after();
    }

    @Override
    public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
        System.out.println("Returning publisher in SecondFilter!");
        return Publishers.then(
                chain.proceed(request),
                mutableHttpResponse -> {
                    System.out.println("Mapping response in second filter!");
                    mutableHttpResponse.getBody(ServiceHttpResponse.class)
                            .ifPresent(resp -> mutableHttpResponse.body(resp.format()));
                });
    }
}

执行请求后的日志如下:

Returning publisher in FirstFilter!
Returning publisher in SecondFilter!
Mapping response in second filter!
Mapping response in first filter!

从日志中我可以看到,doFilter方法是按正确的顺序调用的,但是React流中Map响应的方法是按相反的顺序调用的。
在我的示例中,我尝试首先使用当前响应主体(ServiceHttpResponse)中的信息设置响应状态,然后设置一个新的格式化主体,但由于这些主体以相反的顺序执行,因此首先设置新主体,有关响应状态的信息丢失。
是什么导致了这种行为?我测试了它使用2个以上的过滤器和顺序总是颠倒,所以它不是随机的。

gwo2fgha

gwo2fgha1#

正如Jon Skeet所提到的,这是一个过滤器链。在这个链中,你的所有过滤器都按照给定的顺序排列。当链到达末端时,实际的控制器被调用。同样的过滤器链以相反的顺序被处理。

@Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
        // This happens before the controller gets invoked
        System.out.println("Returning publisher in SecondFilter!");
        return Publishers.then(
                chain.proceed(request),
                mutableHttpResponse -> {
                    // this happens after the controller has been invokes. That's why you have the http response available.
                    System.out.println("Mapping response in second filter!");
                    mutableHttpResponse.getBody(ServiceHttpResponse.class)
                            .ifPresent(resp -> mutableHttpResponse.body(resp.format()));
        });
}

下面的图片说明了这个模式。它不是Micronaut所做的1:1,但它应该给予你一个印象,事情是如何工作的。

图片来源:https://www.informit.com/articles/article.aspx?p=1398619&seqNum=3

相关问题