Swagger 枚举enum类型参数显示下拉框效果

Swagger下拉框

Swagger 中可以接收枚举类型,并且利用枚举的一些特性在swagger ui 上显示出下拉框,单选框,甚至多选框的效果,此外,还讲述在枚举中显示中文。

背景

利用 SpringBoot 可以快速构建 Java 项目,此次构建使用的版本为 1.5.9.RELEASE

项目雏形

实体类
package com.mapull.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;

@Data
@AllArgsConstructor
public class Product {

    @NotBlank
    private double price;

    private String name;

    private String type;
}
Controller
package com.mapull.web;

import com.mapull.entity.Product;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/product")
public class ProductController {

    @GetMapping("/type")
    public Product findByType(String type){
        if("book".equals(type)){
            return new Product(49.9,"Think in Java", "book");
        }
        return null;
    }
}
启动类
package com.mapull;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

项目暴露的 API 如下:

http://localhost:8080/product/type?type=book

集成 swagger2

这里使用最少配置,基于 springfox swagger 版本 2.8.0

添加依赖
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.8.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.8.0</version>
    </dependency>
Swagger 配置
package com.mapull.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.mapull.web"))
                .paths(PathSelectors.any())
                .build();
    }

    public ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("API 演示平台")
                .description("更多详情,请关注码谱:https://www.mapull.com")
                .version("1.0.0")
                .build();
    }
}

测试结果

在浏览器中访问 http://localhost:8080/swagger-ui.html,可以查看到 swagger ui 页面。

利用页面的执行功能,可以运行借口进行测试 http://localhost:8080/product/type?type=book。该 API 用来模拟根据商品类型获取商品详细信息。

项目重构

商品的类型是通过 string 字符串来确定的,为了能统一管理,使用 enum 来管理商品类型。

商品类型枚举
public enum TypeEnum {
    BOOK("book"),
    FOOD("food"),
    OTHER("other");

    private String type;

    TypeEnum(String type) {
        this.type = type;
    }

    public String getType(){
        return type;
    }
}
商品类改造
@Data
@AllArgsConstructor
public class Product {

    @NotBlank
    private double price;

    private String name;

    private TypeEnum type;
}
Controller 改造
    @GetMapping("/type")
    public Product findByType(String type) {
        if (TypeEnum.BOOK.getType().equals(type)) {
            return new Product(49.9, "Think in Java", TypeEnum.BOOK);
        }
        return null;
    }

测试结果

在 swagger 页面中,测试 http://localhost:8080/product/type?type=book 接口。

{
“price”: 49.9,
“name”: “Think in Java”,
“type”: “BOOK”
}

此时,项目改造完成了,但是 swagger 页面上,当需要不同的类型时,需要输入类型的字符串值,并不方便。

让 swagger ui 支持下拉框

如果 swagger 的参数是枚举类型,在 swagger UI 上就表现出下拉框的效果:

Controller 改造

入参由字符串类型改为枚举类型。

    @GetMapping("/type")
    public Product findByType(TypeEnum type) {
        if (TypeEnum.BOOK.equals(type)) {
            return new Product(49.9, "Think in Java", TypeEnum.BOOK);
        }
        return null;
    }

swagger 2.6.0 版本以上

对于高版本(>2.6.0)的 swagger 来说,不需要特别的配置就能支持下拉框:

下拉框的默认值是空,选择以后就能对 API 进行测试。

此时,如果下拉框不选值(默认为空),也可以执行请求,因此需要在后台判空处理。

Swagger下拉框

swagger 2.8.0 版本以上

由于 swagger UI 有重要调整,视觉体验更好。

Swagger下拉框

swagger 2.5.0 版本以下

低版本的 swagger,没有对枚举类型特殊处理,因此,枚举参数在页面上显示为输入框,需要用下面的办法解决:

使用 @ApiImplicitParam 注解
    @ApiImplicitParam(name = "type", paramType = "query", allowableValues = "BOOK,FOOD,OTHERS")
    @GetMapping("/type")
    public Product findByType(TypeEnum type) {
        System.out.println(type);
        if (TypeEnum.BOOK.equals(type)) {
            return new Product(49.9, "Think in Java", TypeEnum.BOOK);
        }
        return null;
    }

在注解中,用 allowableValues 使前端页面显示为下拉框,显示效果同 2.6.0 版本一致。

自定义下拉框

指定下拉框中的选值

默认情况下,下拉框中会将枚举类中所有取值都显示在页面上。
但是业务上,可能只会有某几个值会被用到,于是利用注解 allowableValues

@ApiImplicitParam(name = "type", paramType = "query", allowableValues = "BOOK,FOOD")

Swagger下拉框

去掉空值

默认情况下,下拉框中会显示一条空记录,可以使用 required = true 去掉空值。
这样,就不用在后台判空处理。

@ApiImplicitParam(name = "type", paramType = "query", allowableValues = "BOOK,FOOD", required = true)

Swagger下拉框

修改默认值

下拉框中默认显示枚举的第一条记录,如果想指定显示值,可以使用 defaultValue

@ApiImplicitParam(name = "type", paramType = "query", defaultValue = "FOOD")

Swagger下拉框

多选框

多选框无法借助枚举值实现,需要在注解中指定两个参数allowableValuesallowMultiple

@ApiImplicitParam(name = "type", paramType = "query",allowableValues = "BOOK,FOOD,OTHER",allowMultiple = true)

Swagger下拉框

用鼠标选择一个值,按住 Ctrl 键多选。

发出的请求:
http://localhost:8080/product/type?type=BOOK&type=FOOD

在 swagger 版本 2.8.0 之后的显示效果:

Swagger下拉框

显示枚举值

上面的例子中,下拉框中的值取值来自枚举的名称,要是想在页面上显示枚举的说明怎么操作呢?

Swagger2 不支持这种形式,但是可以通过下面这种方式曲线救国。

定义枚举
public enum ProductEnum {
    BOOK("书籍"),
    FOOD("食物"),
    OTHER("其他");

    private String type;

    ProductEnum(String type) {
        this.type = type;
    }

    public String getType(){
        return type;
    }

    public static ProductEnum fromType(String type){
        for(ProductEnum typeEnum: values()){
            if(typeEnum.type.equals(type)){
                return typeEnum;
            }
        }
        return null;
    }
}

定义了一个带中文的枚举。

    @ApiImplicitParam(name = "type", paramType = "query", allowableValues = "书籍,食物")
    @GetMapping("/query")
    public Product queryByType(String type) {
        ProductEnum productEnum = ProductEnum.fromType(type);
        return new Product(49.9, "Think in Java", TypeEnum.BOOK);
    }

参数使用字符串,并且加上 swagger 注解allowableValues,取值与枚举定义一致。

然后在代码中,将字符串转换为枚举类型。

在 swagger UI 页面上的显示效果:

Swagger下拉框

结语

Swagger 通过少量的配置,能形成不错的可视化文档,如果能充分利用原声 UI 的功能,带来交互体验的提升,想必也是一件美事。

关于源代码点击这里

标签: