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

在Quarkus与Eclipse MicroProfile中复用REST API的@Header定义

解决方案

一、复用@Header配置数组

有两种实用方式可以避免重复编写分页相关的@Header配置:

1. 定义常量数组

先创建一个常量类,把分页响应头的OpenAPI配置封装成静态数组,后续直接引用即可:

public class OpenApiConstants {
    public static final Header[] PAGE_RESPONSE_HEADERS = {
        new Header()
            .name("X-Total-Count")
            .description("总对象数")
            .schema(new Schema().type(SchemaType.INTEGER)),
        new Header()
            .name("X-Offset")
            .description("当前偏移量")
            .schema(new Schema().type(SchemaType.INTEGER)),
        new Header()
            .name("X-Limit")
            .description("当前限制值")
            .schema(new Schema().type(SchemaType.INTEGER))
    };
}

在接口方法的@APIResponse中直接使用这个常量数组:

@GET
@APIResponse(
    responseCode = "200",
    description = "分页结果",
    headers = OpenApiConstants.PAGE_RESPONSE_HEADERS
)
public List<Item> getItems(@QueryParam("offset") int offset, @QueryParam("limit") int limit) {
    // 业务逻辑实现
}

后续如果要调整头的命名或描述,只需要修改常量数组,所有引用的地方都会自动同步。

2. 自定义组合注解

利用Java的注解组合特性,创建一个包含所有分页头配置的自定义注解,替代重复的@Header数组:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@APIResponse(
    responseCode = "200",
    headers = {
        @Header(name = "X-Total-Count", description = "总对象数", schema = @Schema(type = SchemaType.INTEGER)),
        @Header(name = "X-Offset", description = "当前偏移量", schema = @Schema(type = SchemaType.INTEGER)),
        @Header(name = "X-Limit", description = "当前限制值", schema = @Schema(type = SchemaType.INTEGER))
    }
)
public @interface PageableApiResponse {}

之后在接口方法上只需标记这个自定义注解即可:

@GET
@PageableApiResponse
public List<Item> getItems(@QueryParam("offset") int offset, @QueryParam("limit") int limit) {
    // 业务逻辑实现
}

这种方式更简洁,后期调整配置时只需要修改自定义注解的内容。

二、Quarkus中用响应头返回分页信息的标准化处理

如果不想在每个方法上手动配置OpenAPI注解,更高效的方案是通过JAX-RS ContainerResponseFilter统一处理分页响应头,无需重复代码:

  1. 先定义一个分页结果载体类,用来封装数据列表和分页元数据:
public class PageResult<T> {
    private List<T> data;
    private long totalCount;
    private int offset;
    private int limit;

    // 构造器、getter/setter方法
}
  1. 实现ContainerResponseFilter,拦截返回PageResult的响应,自动添加分页头并替换响应体为数据列表:
@Provider
public class PageResponseFilter implements ContainerResponseFilter {
    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        Object entity = responseContext.getEntity();
        if (entity instanceof PageResult<?>) {
            PageResult<?> pageResult = (PageResult<?>) entity;
            // 添加分页响应头
            responseContext.getHeaders().add("X-Total-Count", pageResult.getTotalCount());
            responseContext.getHeaders().add("X-Offset", pageResult.getOffset());
            responseContext.getHeaders().add("X-Limit", pageResult.getLimit());
            // 将响应体替换为实际数据列表,避免返回整个PageResult对象
            responseContext.setEntity(pageResult.getData());
        }
    }
}
  1. 接口方法直接返回PageResult,过滤器会自动处理响应头和响应体:
@GET
public PageResult<Item> getItems(@QueryParam("offset") int offset, @QueryParam("limit") int limit) {
    List<Item> items = // 从数据源获取分页数据
    long totalCount = // 查询总记录数
    return new PageResult<>(items, totalCount, offset, limit);
}

这种方式是Quarkus社区常用的实践,既符合RESTful设计(用响应头传递元数据),又能保证所有分页接口的格式统一。如果后续需要调整头的命名规则,只需修改过滤器中的头名称即可。

内容的提问来源于stack exchange,提问作者mitch-lbw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:43:23