Java Spring Boot中Swagger UI按类型分组Header输入参数实现问询
我用Java Spring Boot开发微服务,控制器通过Header接收30个输入参数,但不想在Swagger UI里展示全部参数。需求如下:
- 要么把参数按类型分组并显示分组标题
- 要么提供下拉框按类型筛选展示对应参数(包含公共参数)
- 禁止编写多个控制器方法
预期分组展示效果
(FieldName) Type: Value
Heading: These 3 attributes are required for type Carrier
(FieldName) United_Count: 20
(FieldName) AmericanAir_Count: 30
(FieldName) Delta_Count: 30Heading: These 3 attributes are required for type Model
(FieldName) Boeing_Count: 20
(FieldName) Jet_Count: 30
(FieldName) United_Count: 30 (common for two types)
预期下拉筛选效果
UI中提供下拉框Type By: Carrier, Model,选择不同选项展示对应参数:
- 选择"Carrier"时:
United: 20
AmericanAir: 30
Delta: 30 - 选择"Model"时:
Boeing: 20
Jet: 30
United: 30 (common for two types)
可以实现,无需拆分控制器方法,利用Spring Doc(替代Swagger2的主流方案)的注解特性即可完成,以下是两种方案的具体实现:
方案一:参数分组展示
通过@Parameter注解的group属性给参数分类,配合@Operation的参数配置添加分组标题,实现参数按类型分组展示。
实现步骤
- 定义分组常量复用:
public interface ParamGroups { String CARRIER = "Carrier类型必填参数"; String MODEL = "Model类型必填参数"; String COMMON = "公共参数"; }
- 控制器方法中给Header参数标注分组:
@RestController @RequestMapping("/api/flight") public class FlightController { @Operation(summary = "获取航班统计数据", parameters = { @Parameter(name = "分组说明", description = ParamGroups.CARRIER, hidden = false), @Parameter(ref = "#/components/parameters/United_Count"), @Parameter(ref = "#/components/parameters/AmericanAir_Count"), @Parameter(ref = "#/components/parameters/Delta_Count"), @Parameter(name = "分组说明", description = ParamGroups.MODEL, hidden = false), @Parameter(ref = "#/components/parameters/Boeing_Count"), @Parameter(ref = "#/components/parameters/Jet_Count") }) @GetMapping("/stats") public ResponseEntity<Map<String, Integer>> getStats( // Carrier组参数 @RequestHeader("United_Count") @Parameter(groups = {ParamGroups.CARRIER, ParamGroups.COMMON}, description = "联合航空数量") Integer unitedCount, @RequestHeader("AmericanAir_Count") @Parameter(group = ParamGroups.CARRIER, description = "美航数量") Integer americanAirCount, @RequestHeader("Delta_Count") @Parameter(group = ParamGroups.CARRIER, description = "达美航空数量") Integer deltaCount, // Model组参数 @RequestHeader("Boeing_Count") @Parameter(group = ParamGroups.MODEL, description = "波音机型数量") Integer boeingCount, @RequestHeader("Jet_Count") @Parameter(group = ParamGroups.MODEL, description = "喷气式机型数量") Integer jetCount ) { // 业务逻辑实现 Map<String, Integer> stats = new HashMap<>(); stats.put("United_Count", unitedCount); stats.put("AmericanAir_Count", americanAirCount); stats.put("Delta_Count", deltaCount); stats.put("Boeing_Count", boeingCount); stats.put("Jet_Count", jetCount); return ResponseEntity.ok(stats); } }
- Spring Doc配置中注册组件参数:
@Configuration public class SpringDocConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .components(new Components() .addParameters("United_Count", new Parameter().in("header").name("United_Count").schema(new IntegerSchema()).description("联合航空数量")) .addParameters("AmericanAir_Count", new Parameter().in("header").name("AmericanAir_Count").schema(new IntegerSchema()).description("美航数量")) .addParameters("Delta_Count", new Parameter().in("header").name("Delta_Count").schema(new IntegerSchema()).description("达美航空数量")) .addParameters("Boeing_Count", new Parameter().in("header").name("Boeing_Count").schema(new IntegerSchema()).description("波音机型数量")) .addParameters("Jet_Count", new Parameter().in("header").name("Jet_Count").schema(new IntegerSchema()).description("喷气式机型数量")) ) .info(new Info().title("航班统计API").version("v1")); } }
启动服务后,Swagger UI会按分组展示参数,分组标题通过@Operation中的参数说明体现。
方案二:下拉筛选(基于OpenAPI的oneOf特性)
通过定义不同的参数Schema,结合oneOf实现动态参数筛选,Swagger UI会自动生成下拉框,选择后展示对应组的参数(包含公共参数)。
实现步骤
- Spring Doc配置中定义参数Schema组:
@Configuration public class SpringDocConfig { @Bean public OpenAPI customOpenAPI() { // 公共参数 Parameter unitedCountParam = new Parameter().in("header").name("United_Count").schema(new IntegerSchema()).description("公共参数:联合航空数量"); // Carrier组参数Schema Schema carrierSchema = new ObjectSchema() .addProperty("AmericanAir_Count", new IntegerSchema().description("美航数量")) .addProperty("Delta_Count", new IntegerSchema().description("达美航空数量")); // Model组参数Schema Schema modelSchema = new ObjectSchema() .addProperty("Boeing_Count", new IntegerSchema().description("波音机型数量")) .addProperty("Jet_Count", new IntegerSchema().description("喷气式机型数量")); return new OpenAPI() .components(new Components() .addSchemas("CarrierParams", carrierSchema) .addSchemas("ModelParams", modelSchema) ) .paths(new Paths() .addPathItem("/api/flight/stats", new PathItem() .get(new Operation() .summary("获取航班统计数据") .parameters(List.of(unitedCountParam)) .requestBody(new RequestBody() .content(new Content() .addMediaType(MediaType.APPLICATION_JSON_VALUE, new MediaType() .schema(new ObjectSchema() .oneOf(List.of( new Schema().$ref("#/components/schemas/CarrierParams"), new Schema().$ref("#/components/schemas/ModelParams") )) ) ) ) ) .responses(new ApiResponses().addApiResponse("200", new ApiResponse().description("成功响应"))) ) ) ) .info(new Info().title("航班统计API").version("v1")); } }
- 控制器方法保持单个,接收所有Header参数:
@RestController @RequestMapping("/api/flight") public class FlightController { @GetMapping("/stats") public ResponseEntity<Map<String, Integer>> getStats( // Carrier组可选参数 @RequestHeader(value = "AmericanAir_Count", required = false) Integer americanAirCount, @RequestHeader(value = "Delta_Count", required = false) Integer deltaCount, // Model组可选参数 @RequestHeader(value = "Boeing_Count", required = false) Integer boeingCount, @RequestHeader(value = "Jet_Count", required = false) Integer jetCount, // 公共必填参数 @RequestHeader("United_Count") Integer unitedCount ) { // 业务逻辑:根据传入参数判断类型并处理 Map<String, Integer> stats = new HashMap<>(); stats.put("United_Count", unitedCount); if (americanAirCount != null) stats.put("AmericanAir_Count", americanAirCount); if (deltaCount != null) stats.put("Delta_Count", deltaCount); if (boeingCount != null) stats.put("Boeing_Count", boeingCount); if (jetCount != null) stats.put("Jet_Count", jetCount); return ResponseEntity.ok(stats); } }
此时Swagger UI会生成下拉框,选择CarrierParams或ModelParams后,会自动展示对应组的参数,同时保留公共的United_Count参数。
内容的提问来源于stack exchange,提问作者Satya

