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 2.8.0 版本以上
由于 swagger UI 有重要调整,视觉体验更好。
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")
去掉空值
默认情况下,下拉框中会显示一条空记录,可以使用 required = true
去掉空值。
这样,就不用在后台判空处理。
@ApiImplicitParam(name = "type", paramType = "query", allowableValues = "BOOK,FOOD", required = true)
修改默认值
下拉框中默认显示枚举的第一条记录,如果想指定显示值,可以使用 defaultValue
@ApiImplicitParam(name = "type", paramType = "query", defaultValue = "FOOD")
多选框
多选框无法借助枚举值实现,需要在注解中指定两个参数allowableValues
和 allowMultiple
@ApiImplicitParam(name = "type", paramType = "query",allowableValues = "BOOK,FOOD,OTHER",allowMultiple = true)
用鼠标选择一个值,按住 Ctrl 键多选。
发出的请求:
http://localhost:8080/product/type?type=BOOK&type=FOOD
在 swagger 版本 2.8.0 之后的显示效果:
显示枚举值
上面的例子中,下拉框中的值取值来自枚举的名称,要是想在页面上显示枚举的说明怎么操作呢?
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 通过少量的配置,能形成不错的可视化文档,如果能充分利用原声 UI 的功能,带来交互体验的提升,想必也是一件美事。
关于源代码点击这里