Swagger 是一个用于生成、描述和调用 RESTful 接口的 Web 服务。通俗的来讲,Swagger 就是将项目中所有(想要暴露的)接口展现在页面上,并且可以进行接口调用和测试的服务。
OpenAPI 规范
OpenAPI 规范(OAS)是一种通用的、和编程语言无关的 API 描述规范,使人类和计算机都可以发现和理解服务的功能,而无需访问源代码、文档或针对接口进行嗅探。正确定义后,使用者可以使用最少的实现逻辑来理解远程服务并与之交互。
OpenAPI 始于 Swagger 规范,Swagger 规范已于 2015 年捐赠给 Linux 基金会后改名为 OpenAPI,并定义最新的规范为 OpenAPI 3.0。
官方 GitHub 地址: OpenAPI-Specification
什么是 Swagger
Swagger 是一个用于生成、描述和调用 RESTful 接口的 Web 服务。通俗的来讲,Swagger 就是将项目中所有(想要暴露的)接口展现在页面上,并且可以进行接口调用和测试的服务。
Swagger 有以下 3 个重要的作用:
- 将项目中所有的接口展现在页面上,这样后端程序员就不需要专门为前端使用者编写专门的接口文档;
- 当接口更新之后,只需要修改代码中的 Swagger 描述就可以实时生成新的接口文档了,从而规避了接口文档老旧不能使用的问题;
- 通过 Swagger 页面,我们可以直接进行接口调用,降低了项目开发阶段的调试成本。
Swagger3 完全遵循了 OpenAPI 规范。Swagger 官网地址:https://swagger.io/ (opens new window)
在 Spring 中,SpringFox
是 Swagger 规范的实现,其 Github 地址。
什么是 Knife4J?
Knife4j
的前身是 swagger-bootstrap-ui
,这是一个 Swagger 的 UI 增强方案,随着不断改进,更名为 Knife4j
,其官网地址。
SpringBoot 使用 Swagger
引入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
自定义 Swagger 配置
使用
@EnableOpenApi
开启 Swagger通过
@Bean
配置一个Docket` 对象,来配置 Swagger;
其中有一个重点配置是,使用
enable(boolean flag)
来控制 Swagger 是否开启;具体通过environment.acceptsProfiles()
方法判断当前环境是否符合Profiles
中定义,将结果传入enable()
方法。
@Configuration
@EnableOpenApi
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class SwaggerConfiguration {
/**
* 不生成文档的接口路径
*/
private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**");
@Bean
public Docket openApi(Environment environment) {
// 不在生产中使用
Profiles profiles = Profiles.of("dev", "test");
boolean enabled = environment.acceptsProfiles(profiles);
// openapi 规范 3.0
Docket docket = new Docket(DocumentationType.OAS_30)
.enable(enabled)
.groupName("ZeusBoot")
.apiInfo(apiInfo())
// 设置全局请求参数
.globalRequestParameters(getGlobalRequestParameters());
// 更细粒度的构造器
ApiSelectorBuilder selectorBuilder = docket.select();
// 设置为添加了 @ApiOperation 注解的接口生成文档
selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class));
// 配置不生成文档的路径
DEFAULT_EXCLUDE_PATH.forEach(path -> selectorBuilder.paths(PathSelectors.ant(path).negate()));
selectorBuilder.build();
// 如果需要使用 knife4j 增强的话,需要使用 extensions() 方法
return docket;
}
private List<RequestParameter> getGlobalRequestParameters() {
List<RequestParameter> parameters = new ArrayList<>();
parameters.add(new RequestParameterBuilder()
.name("token")
.description("用户 token")
.in(ParameterType.HEADER)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.required(false)
.build());
return parameters;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("ZeusBoot Api Documentation")
.description("ZeusBoot Api Documentation")
.contact(new Contact("AlexChen", "https://blog.alexchen.tech", "alexchen.tech@gmail.com"))
.version("1.0")
.build();
}
}
@Configuration
@EnableOpenApi
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class SwaggerConfiguration {
/**
* 不生成文档的接口路径
*/
private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**");
@Bean
public Docket openApi(Environment environment) {
// 不在生产中使用
Profiles profiles = Profiles.of("dev", "test");
boolean enabled = environment.acceptsProfiles(profiles);
// openapi 规范 3.0
Docket docket = new Docket(DocumentationType.OAS_30)
.enable(enabled)
.groupName("ZeusBoot")
.apiInfo(apiInfo())
// 设置全局请求参数
.globalRequestParameters(getGlobalRequestParameters());
// 更细粒度的构造器
ApiSelectorBuilder selectorBuilder = docket.select();
// 设置为添加了 @ApiOperation 注解的接口生成文档
selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class));
// 配置不生成文档的路径
DEFAULT_EXCLUDE_PATH.forEach(path -> selectorBuilder.paths(PathSelectors.ant(path).negate()));
selectorBuilder.build();
// 如果需要使用 knife4j 增强的话,需要使用 extensions() 方法
return docket;
}
private List<RequestParameter> getGlobalRequestParameters() {
List<RequestParameter> parameters = new ArrayList<>();
parameters.add(new RequestParameterBuilder()
.name("token")
.description("用户 token")
.in(ParameterType.HEADER)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.required(false)
.build());
return parameters;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("ZeusBoot Api Documentation")
.description("ZeusBoot Api Documentation")
.contact(new Contact("AlexChen", "https://blog.alexchen.tech", "alexchen.tech@gmail.com"))
.version("1.0")
.build();
}
}
接口层面添加 Swagger 注解
Swagger 注解见官方文档
@ApiOperation("添加用户")
@PostMapping("add")
@ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)
public ResponseEntity<String> add(@RequestBody UserParam userParam) {
return ResponseEntity.ok("success");
}
@ApiOperation("添加用户")
@PostMapping("add")
@ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)
public ResponseEntity<String> add(@RequestBody UserParam userParam) {
return ResponseEntity.ok("success");
}
访问 Swagger 页面
使用以下链接打开 Swagger,域名和端口视情况修改:
http://localhost:8080/swagger-ui/index.html
SpringBoot 使用 knife4j
单纯使用其 UI
引入 Pom
依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
<version>3.0.3</version>
</dependency>
打开 knife4j 页面
http://localhost:8080/doc.html
http://localhost:8080/doc.html
使用 knife4j 的增强功能
引入 Pom
依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
如果开发者使用的是 Knife4j 2.x 版本,并且 Spring Boot 版本高于 2.4,那么需要在 Spring Boot 的 yml 文件中做如下配置:
spring:
mvc:
pathmatch:
# 配置策略
matching-strategy: ant-path-matcher
spring:
mvc:
pathmatch:
# 配置策略
matching-strategy: ant-path-matcher
SpringBoot yaml 配置示例
knife4j:
enable: true
documents:
-
group: 2.X 版本
name: 接口签名
locations: classpath:sign/*
setting:
language: zh-CN
enableSwaggerModels: true
enableDocumentManage: true
swaggerModelName: 实体类列表
enableVersion: false
enableReloadCacheParameter: false
enableAfterScript: true
enableFilterMultipartApiMethodType: POST
enableFilterMultipartApis: false
enableRequestCache: true
enableHost: false
enableHostText: 192.168.0.193:8000
enableHomeCustom: true
homeCustomLocation: classpath:markdown/home.md
enableSearch: false
enableFooter: false
enableFooterCustom: true
footerCustomContent: Apache License 2.0 | Copyright 2019-[浙江八一菜刀股份有限公司](https://gitee.com/xiaoym/knife4j)
enableDynamicParameter: false
enableDebug: true
enableOpenApi: false
enableGroup: true
cors: false
production: false
basic:
enable: false
username: test
password: 12313
knife4j:
enable: true
documents:
-
group: 2.X 版本
name: 接口签名
locations: classpath:sign/*
setting:
language: zh-CN
enableSwaggerModels: true
enableDocumentManage: true
swaggerModelName: 实体类列表
enableVersion: false
enableReloadCacheParameter: false
enableAfterScript: true
enableFilterMultipartApiMethodType: POST
enableFilterMultipartApis: false
enableRequestCache: true
enableHost: false
enableHostText: 192.168.0.193:8000
enableHomeCustom: true
homeCustomLocation: classpath:markdown/home.md
enableSearch: false
enableFooter: false
enableFooterCustom: true
footerCustomContent: Apache License 2.0 | Copyright 2019-[浙江八一菜刀股份有限公司](https://gitee.com/xiaoym/knife4j)
enableDynamicParameter: false
enableDebug: true
enableOpenApi: false
enableGroup: true
cors: false
production: false
basic:
enable: false
username: test
password: 12313
自定义 Swagger 配置
在 Swagger 配置的基础上,需要多注入 OpenApiExtensionResolver
,并通过 docket.extensions()
方法注入扩展,扩展由 knife4j 自动配置类提供。
如果提示无法注入 OpenApiExtensionResolver
,可以通过增加 @EnableKnife4j
引入,在 2.0.6 版本后,只需要在配置文件中配置knife4j.enable=true
即可不在使用注解。
@EnableKnife4j
@Configuration
@EnableOpenApi
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class OpenApiConfig {
/**
* open api extension by knife4j.
*/
private final OpenApiExtensionResolver openApiExtensionResolver;
@Autowired
public OpenApiConfig(OpenApiExtensionResolver openApiExtensionResolver) {
this.openApiExtensionResolver = openApiExtensionResolver;
}
@Bean
public Docket openApi() {
return new Docket(DocumentationType.OAS_30)
.groupName("defaultGroup")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.extensions(openApiExtensionResolver.buildExtensions(groupName))
.extensions(openApiExtensionResolver.buildSettingExtensions());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// .other()
.build();
}
}
@EnableKnife4j
@Configuration
@EnableOpenApi
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class OpenApiConfig {
/**
* open api extension by knife4j.
*/
private final OpenApiExtensionResolver openApiExtensionResolver;
@Autowired
public OpenApiConfig(OpenApiExtensionResolver openApiExtensionResolver) {
this.openApiExtensionResolver = openApiExtensionResolver;
}
@Bean
public Docket openApi() {
return new Docket(DocumentationType.OAS_30)
.groupName("defaultGroup")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.extensions(openApiExtensionResolver.buildExtensions(groupName))
.extensions(openApiExtensionResolver.buildSettingExtensions());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// .other()
.build();
}
}
打开 knife4j 页面
在接口中使用 Swagger 注解,添加文档注释后,使用下面链接打开 knife4j,域名和端口视情况修改:
http://localhost:8080/doc.html