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

如何在Quarkus中实现类似Spring ResponseBodyAdvice的自定义响应封装?

在Quarkus中实现全局响应封装(类似Spring ResponseBodyAdvice)

Quarkus中没有直接对应Spring ResponseBodyAdvice的组件,但可以通过JAX-RS标准的ContainerResponseFilter实现全局统一响应封装,效果和你在Spring中的实现一致,同时能覆盖成功响应的包装逻辑。以下是具体实现步骤:

1. 定义统一响应体结构

先对齐Spring代码中的Response和ResponseUtil,统一响应格式:

public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    private PageMeta meta; // 分页元数据,按需使用

    // 构造方法、getter/setter省略
}

public class PageMeta {
    private long totalElements;
    private int totalPages;
    private int currentPage;
    private int pageSize;

    // 构造方法、getter/setter省略
}

public class ResponseUtil {
    // 普通响应构建
    public static <T> ApiResponse<T> build(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("success");
        response.setData(data);
        return response;
    }

    // 分页响应构建
    public static <T> ApiResponse<T> buildWithMeta(Page<T> page) {
        ApiResponse<T> response = build(page.getContent());
        PageMeta meta = new PageMeta();
        meta.setTotalElements(page.getTotalElements());
        meta.setTotalPages(page.getTotalPages());
        meta.setCurrentPage(page.getNumber() + 1); // Quarkus Page索引从0开始,转成前端常用的从1计数
        meta.setPageSize(page.getSize());
        response.setMeta(meta);
        return response;
    }
}

2. 实现全局响应过滤器

通过ContainerResponseFilter拦截所有响应,复刻Spring中的逻辑:

import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Provider;
import jakarta.json.bind.JsonbBuilder;
import java.util.Arrays;
import java.util.List;

@Provider
@Priority(1000) // 设置优先级,确保在Quarkus默认过滤器前执行
public class ResponseWrapperFilter implements ContainerResponseFilter {

    private static final List<String> IGNORED_URIS = Arrays.asList("swagger", "v2/api-docs", "v3/api-docs", "actuator");

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        String path = requestContext.getUriInfo().getPath();
        Object body = responseContext.getEntity();

        // 跳过特定URI或已封装的响应
        if (IGNORED_URIS.stream().anyMatch(path::contains) || body instanceof ApiResponse) {
            return;
        }

        // 处理分页响应
        if (body instanceof Page<?>) {
            responseContext.setEntity(ResponseUtil.buildWithMeta((Page<?>) body));
        }
        // 处理String类型:手动序列化为JSON,避免返回纯文本
        else if (body instanceof String) {
            ApiResponse<String> wrapped = ResponseUtil.build((String) body);
            String json = JsonbBuilder.create().toJson(wrapped);
            responseContext.setEntity(json);
            responseContext.getHeaders().putSingle("Content-Type", MediaType.APPLICATION_JSON);
        }
        // 处理其他普通响应
        else {
            responseContext.setEntity(ResponseUtil.build(body));
        }
    }
}

3. 关键注意事项

  • @Priority注解:数值越小优先级越高,设置为1000能确保过滤器在Quarkus默认的响应处理逻辑前执行。
  • String类型特殊处理:JAX-RS对String的默认行为是直接返回文本,所以需要手动转成JSON并修改响应头,保证前端拿到标准JSON格式。
  • 忽略URI逻辑:和Spring实现一致,跳过Swagger、Actuator等不需要封装的接口。

补充:WriterInterceptor方案(序列化阶段处理)

如果需要在响应体序列化前做细粒度控制,可使用WriterInterceptor,适合聚焦序列化环节的场景:

import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.ext.WriterInterceptor;
import jakarta.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;

@Provider
public class ResponseWriterInterceptor implements WriterInterceptor {
    @Override
    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
        Object body = context.getEntity();
        if (!(body instanceof ApiResponse)) {
            ApiResponse<?> wrapped = ResponseUtil.build(body);
            context.setEntity(wrapped);
        }
        context.proceed();
    }
}

不过ContainerResponseFilter更适合全局响应封装场景,能更早拦截响应,处理逻辑更全面。

内容的提问来源于stack exchange,提问作者Mete Alpaslan KATIRCIOGLU

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:27:06