Swagger UI 2.x、3.x 可视化 web API 文档
目录Swagger 概 述Swagger 快速入门Swagger 常用注解Swagger 概 述1、Swagger 官网:https://swagger.io/ 提供了以下几种开源工具,分别提供了相应的功能,本文只关心 Swagger UI 。Swagger Codegen通过 Codegen 可以将描述文件生成 html 格式和 cwiki 形式的接口文档,同时也能生成多钟语言的服务端和客户端的
目录
Multiple Dockets with the same group name are not supported.
Swagger UI 概 述
1、Swagger 官网:API Documentation & Design Tools for Teams | Swagger 提供了以下几种开源工具,分别提供了相应的功能,本文只关心 Swagger UI 。
REST API Documentation Tool | Swagger UI
Swagger Codegen | 通过 Codegen 可以将描述文件生成 html 格式和 cwiki 形式的接口文档,同时也能生成多钟语言的服务端和客户端的代码。支持通过 jar 包,docker,node 等方式在本地化执行生成。也可以在 Swagger Editor 中在线生成。 |
Swagger UI | Swagger UI 允许任何人(无论是您的开发团队还是最终用户)在没有任何实现逻辑的情况下可视化并与 API 的资源交互。它是根据 OpenAPI(以前称为 Swagger)规范自动生成的,可视化文档使后端实现和客户端使用变得容易。 |
Swagger Editor: | 类似于 markendown 编辑器,支持在线编辑 Swagger 描述文件,以及实时预览描述文件的更新效果,也提供了在线编辑器和本地部署编辑器两种方式。 |
Swagger Inspector | 类似于 postman ,是一个可以对接口进行测试的在线版的 postman。比在 Swagger UI 里面做接口请求,会返回更多的信息,也会保存你请求的实际请求参数等数据。 |
Swagger Hub | 集成了上面所有项目的各个功能,可以以项目和版本为单位,将描述文件上传到 Swagger Hub 中,在 Swagger Hub 中可以完成上面项目的所有工作,需要注册账号,分免费版和收费版。 |
Swagger UI V2.X 快速入门
1、pom.xml 文件中导入 Swagger 依赖如下(本文环境:Java jdk 1.8 + Spring boot 2.1.3 + Swagger 2.9.2):(版本不匹配时容易导致服务启动无法成功,也什么异常输出)
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
在线源码地址:pom.xml · 汪少棠/thymeleafapp - Gitee.com
2、配置 swagger,主要开启 swagger 功能,以及配置文档基本信息:
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger 配置
* <p>
* 1、@EnableSwagger2:表示应用开启 Swagger2 支持。
* 2、@EnableSwagger2 注解需要和 @Configuration 注解一起使用
* 3、@ConditionalOnProperty 使用自定义配置 sys.config.swagger-is-open,如果值为 true,则此配置类生效,
* 否则如果不为 true,或者直接没有配置,则此配置类不会生效。通常上线后,swagger 在线文档可以关掉.
*
* @author wangmaoxiong
* @version 1.0
* @date 2020/5/20 9:50
*/
@Configuration
@EnableSwagger2
@ConditionalOnProperty(prefix = "sys.config", name = "swagger-is-open", havingValue = "true")
public class SwaggerConfig {
/**
* {@link Docket} 是一个构建器,它是 SpringFox 框架的主要接口,用于提供合理的默认值和方便的配置方法。
* 1、必须使用 @Bean 将 Docket 添加到容器中
* 2、DocumentationType.SWAGGER_2:表示 文档类型为 2.0 版本.
* 3、apiInfo(ApiInfo apiInfo): 将 api 的元信息设置为包含在 ResourceListing 响应 json 中
* 4、ApiSelectorBuilder select(): 启动用于 api 选择生成器。
* 5、RequestHandlerSelectors.basePackage:表示生成 api 的基础包路径,即对这个包下进行扫描
* 6、PathSelectors.any:表示对任意请求路径都加入文档、同理还有 none 都不加入、regex 满足正则的请求加入
* 7、build(): 返回构建好的的 docket
*
* @return
*/
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wmx"))
.paths(PathSelectors.any())
.build().pathMapping("");
}
/**
* 创建 api 基本信息
* 1、title(String title):页面标题内容,会显示在页面头部,默认 <h2> 标签包裹.
* 2、description(String description):Api 描述信息,显示在 title 下方
* 3、termsOfServiceUrl: 服务条款 url。页面上默认显示在描述信息下面,显示为 "Terms of service",然后用值作为超链接地址.
* 4、version:更新版本
* 5、contact:联系人信息,有: 名称、网站 url 地址、联系 email 地址。显示在服务条款下面。
* 6、license:更新此 API 的许可证信息,显示在联系人下面
* 7、这些值可以为空
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("REST full APIs")
.description("技术支持 2268461750@qq.com ")
.termsOfServiceUrl("https://wangmaoxiong.blog.csdn.net/")
.version("1.0")
.contact(new Contact("汪茂雄", "https://blog.csdn.net/wangmx1993328", "2268461750@qq.com"))
.license("蚩尤后裔 - 汪茂雄 为您提供技术支持!")
.build();
}
}
src/main/java/com/wmx/thymeleafapp/config/SwaggerConfig.java · 汪少棠/thymeleafapp - Gitee.com
@ConditionalOnProperty :使用自定义配置 sys.config.swagger-is-open,如果值为 true,则此配置类生效,否则如果不为 true,或者直接没有配置,则此配置类不会生效。通常上线后,swagger 在线文档可以关掉.
#自定义属性,是否开启 Swagger 在线文档功能,通常上线之后,可以关掉.
sys:
config:
swagger-is-open: true
src/main/resources/application.yml · 汪少棠/thymeleafapp - Gitee.com
3、此时便可以从浏览器访问了:http://localhost:8080/swagger-ui.html。
可以看到 Swagger 默认会对 ApiSelectorBuilder.apis(RequestHandlerSelectors.basePackage("com.wmx")) 设置的基础包路径下的所有控制层进行扫描,并提供页面文档访问。
文档显示的内容有:控制层名称、方法名称、方法的访问路径、访问方式(如 get、post、put、delete等)、接口的参数名称、参数类型,返回值名称与类型、调用的示例等等。
swagger-ui.html 是 springfox-swagger-ui-x.x.x.jar 包中 META-INF/resources 目录下,属于 Spring boot 约定的四大静态目录之一,所以可以从页面直接访问。
4、如果应用中设置了拦截器或者权限认证,则可以对以下路径放开权限,否则可能会导致无法访问:/swagger*/**、/webjars/**、/v2/api-docs。
5、Swagger-UI 文档上面还可以直接对接口发起请求,而且不止支持 get 请求、post 等请求方式同样可以。
Swagger UI V3.X 快速入门
1、环境:Java jdk 1.8 + Spring boot 2.3.5.RELEASE + Swagger 3.0。(版本不匹配时容易导致服务启动无法成功,也没什么异常输出)
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter -->
<!-- 从 3.0.0开始,可以直接引用如下依赖,它内部依赖了springfox-swagger-ui与springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
pom.xml · 汪少棠/fileServer - Gitee.com
2、配置 swagger,主要开启 swagger 功能,以及配置文档基本信息:
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.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* Swagger V3.X 配置
* <p>
* 1、EnableOpenApi 表示开启 Swagger 3 支持。
*
* @author wangmaoxiong
* @version 1.0
* @date 2020/5/20 9:50
*/
@Configuration
@EnableOpenApi
public class SwaggerConfig {
/**
* {@link Docket} 是一个构建器,它是 SpringFox 框架的主要接口,用于提供合理的默认值和方便的配置方法。
* 1、必须使用 @Bean 将 Docket 添加到容器中
* 2、DocumentationType.OAS_30:表示 文档类型为 3.0 版本.
* 3、apiInfo(ApiInfo apiInfo): 将 api 的元信息设置为包含在 ResourceListing 响应 json 中
* 4、ApiSelectorBuilder select(): 启动用于 api 选择生成器。
* 5、RequestHandlerSelectors.basePackage:表示生成 api 的基础包路径,即对这个包下进行扫描
* 6、PathSelectors.any:表示对任意请求路径都加入文档、同理还有 none 都不加入、regex 满足正则的请求加入
* 7、build(): 返回构建好的的 docket
*
* @return
*/
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(this.apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wmx"))
.paths(PathSelectors.any())
.build()
.pathMapping("");
}
/**
* 创建 api 基本信息
* 1、title(String title):页面标题内容,会显示在页面头部,默认 <h2> 标签包裹.
* 2、description(String description):Api 描述信息,显示在 title 下方
* 3、termsOfServiceUrl: 服务条款 url。页面上默认显示在描述信息下面,显示为 "Terms of service",然后用值作为超链接地址.
* 4、version:更新版本,显示在title的右上角。
* 5、contact:联系人信息,有: 名称、网站 url 地址、联系 email 地址。显示在服务条款下面。
* 6、license:更新此 API 的许可证信息,显示在联系人下面。
* 7、这些值可以为空
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("fileServer 应用提供的 REST full APIs")
.description("技术支持 2268461750@qq.com ")
.termsOfServiceUrl("https://wangmaoxiong.blog.csdn.net/")
.version("1.0")
.contact(new Contact("汪茂雄", "https://blog.csdn.net/wangmx1993328", "2268461750@qq.com"))
.license("蚩尤后裔 & 汪茂雄 为您提供技术支持!")
.build();
}
}
src/main/java/com/wmx/www/config/SwaggerConfig.java · 汪少棠/fileServer - Gitee.com
3、此时便可以从浏览器访问了:http://localhost:8080/swagger-ui/index.htm
4、如果应用中设置了拦截器或者权限认证,则可以对以下路径放开权限,否则可能会导致无法访问:/swagger*/**、/webjars/**、/v3/api-docs。
Swagger UI 常用注解
1、由上面快速入门可知,只要导入 Swagger 依赖,然后配置了 Swagger ,就可以在线生成文档,而且只要后台创建的类、方法名、参数名等命名的比较到位,从页面上浏览时也是很友好的。
2、如果想要添加中文注释方便阅读,则需要借助 Swagger 注解来实现,优点是阅读起来更加直观,缺点是后台代码需要额外添加 Swagger 代码,增加了负担以及影响美观。
3、所以推荐是:后台的 Swagger 注解编写的越简单越好,因为注解的各个属性通常都有默认值,比如参数类型、参数是否必填项等等,所以没必要反复设置。控制层关联的实体类都会一并显示。写的越少、Swagger 的侵入性就越低。
@Api | 1、将类标记为 Swagger 的资源,默认情况下 ApiSelectorBuilder.apis(RequestHandlerSelectors.basePackage("com.wmx")) 设置的基础包路径下的所有控制层进行扫描,所以控制层上,此注解可以省略不写。 2、可以用于 Class, interface,enum 上面,常用属性为 tags,用于给此 API 打上标签。 |
@ApiOperation | 1、描述针对特定路径的操作,通常用于 HTTP 方法上面。常用属性有: value - 方法的简要描述, notes - 方法的详细描述 |
@ApiImplicitParam | 1、描述单个参数,常用属性: name - 参数名称,比如 userId value - 参数的简要说明,比如 用户ID dataType - 参数的数据类型,可以是类名,也可以是数据类型,如 String required - 参数是否为必须项,默认 false paramType - 参数的参数类型(可选值有 query,body,header,form) 2、这些属性都会默认赋值,通常只需要指定 name、value 即可。特别注意 paramType 要么不要指定,要么指定对,比如 post 请求时,将 @RequestBody 请求体参数设置为 query 时,页面会把它当作url中的查询参数,而不再作为请求体参数,导致无法正常调用。 3、对于参数是实体对象时,如 Person,此时不再推荐使用 @ApiImplicitParam,因为加了后,页面不再显示实体类的属性了,会把它当做普通的字符串,而不是实体。 |
@ApiImplicitParams | 1、当方法有多个参数时,用 @ApiImplicitParams 包裹 @ApiImplicitParam 。 |
@ApiIgnore | 1、当不想对某个控制层、或者方法、或者参数对外提供文档时,则可以使用 @ApiIgnore 标识进行忽略。可以用于类、接口、枚举、方法、参数上。 |
@ApiModel | 1、通常用于添加在实体对象上,可以使用 description 属性对实体类进行描述, |
@ApiModelProperty | 1、通常用于实体类的属性上,使用 name - 属性名称, value - 属性描述。 |
在线演示源码:/thymeleafapp/controller/PersonController.java · 汪少棠/thymeleafapp - Gitee.com
src/main/java/com/wmx/thymeleafapp/pojo/Person.java · 汪少棠/thymeleafapp - Gitee.com
Multiple Dockets with the same group name are not supported.
1、Spring Boot 环境原本还是好好的,修改配置文件后,给腾讯云环境打包的时候突然报如下错误:Multiple Dockets with the same group name are not supported. The following duplicate groups were discovered. default
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-04-11 15:04:14 ERROR [main] org.springframework.boot.SpringApplication:837 Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.IllegalStateException: Multiple Dockets with the same group name are not supported. The following duplicate groups were discovered. default
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386) [spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242) [spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230) [spring-boot-2.0.7.RELEASE.jar!/:2.0.7.RELEASE]
at grp.BgtBasicApplication.main(BgtBasicApplication.java:34) [classes!/:3.1.0.TX]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_282]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_282]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_282]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_282]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) [bgt-basic-controller-3.1.0.TX.jar:3.1.0.TX]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) [bgt-basic-controller-3.1.0.TX.jar:3.1.0.TX]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) [bgt-basic-controller-3.1.0.TX.jar:3.1.0.TX]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) [bgt-basic-controller-3.1.0.TX.jar:3.1.0.TX]
Caused by: java.lang.IllegalStateException: Multiple Dockets with the same group name are not supported. The following duplicate groups were discovered. default
at springfox.documentation.spring.web.plugins.DuplicateGroupsDetector.ensureNoDuplicateGroups(DuplicateGroupsDetector.java:45) ~[springfox-spring-web-2.9.2.TSF-RELEASE.jar!/:na]
at springfox.documentation.spring.web.plugins.DocumentationPluginsManager.documentationPlugins(DocumentationPluginsManager.java:97) ~[springfox-spring-web-2.9.2.TSF-RELEASE.jar!/:na]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:162) ~[springfox-spring-web-2.9.2.TSF-RELEASE.jar!/:na]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) ~[spring-context-5.0.11.RELEASE.jar!/:5.0.11.RELEASE]
... 22 common frames omitted
2、可能原因:注入了多个 swagger 而又没有进行分组,于是都分配到默认的组里,出现重复组 default 导致不支持。
3、解决办法: swagger 配置时进行分组。
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("基础库服务接口") //分组
.apiInfo(this.apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wmx"))
.paths(PathSelectors.any())
.build().pathMapping("");
}
paramType 参数类型定义
值 | 描述 |
header | 请求头参数,@RequestHeader 注解接收的值 |
query | 查询参数,@RequestParam 注解接收的值 |
path | 路径参数,@Pathvariab 注解接收的值 |
body | 请求体参数,@RequestBody 注解接收的参数 |
form | 表单参数,不常用 |
@ApiOperation(value = "根据用户 id 查询", notes = "直接将结果返回给用户页面")
@ApiImplicitParam(name = "pId", value = "用户 id", dataType = "Integer", required = true, paramType = "path")
@GetMapping("/person/findById/{pId}")
public Person findPersonById(@PathVariable("pId") Integer pId) {
Person person = personMapper.findPersonById(pId);
return person;
}
Swagger UI V2 权限认证
1、通过自定义配置属性开关 Swagger 功能就不说了,上面也有介绍。
2、如果不想完全关掉文档访问功能,也可以让其进行登陆认证,即必须输入正确的账号密码才能访问。
3、原生的 springfox-swagger-ui 是没有权限认证功能的,需要追加下面的依赖,它即能增强原生的功能,同时提供了新的UI界面(可访问 http://10.104.65.195:8080/doc.html),添加依赖后就可以访问此地址,原生的地址也能继续访问。
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/swagger-bootstrap-ui -->
<!--Swagger UI页面增强,支持登陆认证-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
pom.xml · 汪少棠/thymeleafapp - Gitee.com。
4、账户权限配置1:全局配置文件中添加配置进行开启。
swagger:
basic:
#开启basic登陆认证,登陆后才允许访问swagger文档,同时需要开启@SwaggerBootstrapUI注解会进行登陆认证
enable: true
username: root #登陆账号
password: root #登陆密码
src/main/resources/application.yml · 汪少棠/thymeleafapp - Gitee.com。
5、账户权限配置2:在swaggerConfig中添加注解。
启用SwaggerBootstrapUi增强型注释并同时使用@EnableSwagger2注释。
包含:接口排序;界面文档下载(word);
@com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI
src/main/java/com/wmx/thymeleafapp/config/RedisConfig.java · 汪少棠/thymeleafapp - Gitee.com。
更多推荐
所有评论(0)