You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Micronaut HttpServerFilter响应处理顺序反转问题咨询

问题:Micronaut响应式过滤器中响应处理逻辑顺序反转的原因

我刚接触反应式编程,目前在Micronaut服务器中创建两个HttpServerFilter用于处理响应,简化代码示例如下:

FirstFilter

@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()));
                });
    }
}

SecondFilter

@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方法执行顺序正确,但反应式流中的响应映射逻辑执行顺序反转。我的需求是先通过响应体(ServiceHttpResponse)设置响应状态,再设置格式化后的响应体,但因顺序反转导致状态信息丢失,多次测试多过滤器场景均出现该顺序反转问题,请问该现象的原因是什么?


原因分析

这是由Micronaut过滤器的洋葱执行模型结合反应式流的回调时机导致的:

  1. 请求阶段的执行顺序:
    过滤器的getOrder()决定了请求传递的优先级——FirstFilter的FIRST.before()优先级更高,请求先进入它的doFilter方法,打印日志后调用chain.proceed(request)将请求传递给SecondFilter,后者执行自身doFilter后再把请求传递到后端处理器。

  2. 响应阶段的回调顺序:
    Publishers.then(publisher, callback)的作用是:当上游publisher(即chain.proceed(request)返回的响应流)完成时,执行传入的回调逻辑。而响应流是从后端处理器反向返回的——先回到最内层的SecondFilter,触发它的then回调;之后才回到外层的FirstFilter,触发它的then回调,这就是日志中响应处理顺序反转的核心原因。

  3. 状态丢失的直接诱因:
    你的需求是先设置响应状态再格式化响应体,但当前回调顺序是先执行SecondFilter的格式化逻辑——此时响应体被替换为格式化后的内容,原ServiceHttpResponse实例已不存在;后续FirstFilter尝试从响应体中获取ServiceHttpResponse时无法拿到,自然无法完成状态设置。


内容的提问来源于stack exchange,提问作者Mateusz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:52:47