springboot整合Swagger-UI 3.0
一、swagger简介
1.什么是swagger
Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务(2015年,Swagger项目被SmartBear Software收购。Swagger 规范被捐赠给 Linux 基金会并更名为 OpenAPI)。简单来说,Swagger是一个功能强大的接口管理工具,帮你设计接口API,生成接口API的文档,甚至可以对接口API进行测试,并且提供了多种编程语言的前后端分离解决方案。
Swagger有大致有3个优点:
- Swagger可以整合到代码中,在开发时通过注解,编写注释,自动生成API文档。
- 将前端后台分开,不会有过分的依赖。
- 界面清晰,无论是editor的实时展示还是ui的展示都十分人性化,如果自己仅仅用markdown来编写,又要纠结该如何展现,十分痛苦。
2.swagger注解
swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息的等等。
@Api:修饰整个类,描述Controller的作用
@ApiOperation:描述一个类的一个方法,或者说一个接口
@ApiParam:单个参数描述
@ApiModel:用对象来接收参数
@ApiProperty:用对象接收参数时,描述对象的一个字段
@ApiResponse:HTTP响应其中1个描述
@ApiResponses:HTTP响应整体描述
@ApiIgnore:使用该注解忽略这个API
@ApiError :发生错误返回的信息
@ApiImplicitParam:一个请求参数
@ApiImplicitParams:多个请求参数
二、springboot整合Swagger-UI 3.0
1、添加依赖
pom.xml中添加:
<!-- swagger --> |
备注:
什么是springfox?
springfox就是对swagger规范在spring下的封装实现,我们看得到的界面就是springfox-swagger-ui
Springfox官方文档:http://springfox.github.io/springfox/docs/snapshot/
Springfox的GitHub仓库:https://github.com/springfox/springfox
Springfox3.0版本特性:https://github.com/springfox/springfox/releases/tag/3.0.0
2、配置Swagger-UI
新建SwaggerConfig类,并在SwaggerConfig.java文件中进行配置:
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-ui配置
*/
public class SwaggerConfig {
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
public Docket restApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("标准接口")
.apiInfo(apiInfo("Spring Boot中使用Swagger3构建RESTful APIs", "1.0"))
.useDefaultResponseMessages(true)
.forCodeGeneration(false)
.select()
.apis(RequestHandlerSelectors.basePackage("com.qiancheng.springboot.controller"))
.paths(PathSelectors.any())
.build();
}
/**
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
* 访问地址:http://ip:port/swagger-ui/index.html
*
* @return
*/
private ApiInfo apiInfo(String title, String version) {
return new ApiInfoBuilder()
.title(title)//标题
.description("更多请关注: https://qianchenggit.github.io/")//描述
.termsOfServiceUrl("https://qianchenggit.github.io/")//服务条款URL
.contact(new Contact("qiancheng", "https://qianchenggit.github.io/", "zehong.zhang@qq.com"))
.version(version)//版本
.build();
}
}运行程序,如果报以下错误:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-08-24 21:42:28.564 ERROR 8600 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.22.jar:5.3.22]
at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_191]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) [spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.3.jar:2.7.3]
at com.qiancheng.springboot.SpringbootApplication.main(SpringbootApplication.java:12) [classes/:na]
Caused by: java.lang.NullPointerException: null
at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0]
at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113) ~[springfox-core-3.0.0.jar:3.0.0]
at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89) ~[springfox-spi-3.0.0.jar:3.0.0]
at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) ~[na:1.8.0_191]
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:1.8.0_191]
at java.util.TimSort.sort(TimSort.java:220) ~[na:1.8.0_191]
at java.util.Arrays.sort(Arrays.java:1512) ~[na:1.8.0_191]
at java.util.ArrayList.sort(ArrayList.java:1462) ~[na:1.8.0_191]
at java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:387) ~[na:1.8.0_191]
at java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:1.8.0_191]
at java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:1.8.0_191]
at java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:1.8.0_191]
at java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_191]
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_191]
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_191]
at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_191]
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_191]
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_191]
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_191]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.22.jar:5.3.22]
... 14 common frames omitted
Process finished with exit code 1
原因是:SpringFox正在使用 WebMvc 但尚未使用@EnableWebMvc
注解,请在SpringbootApplication启动类增加@EnableWebMvc注解:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
三、使用第三方UI(knife4j)
在pom.xml文件添加依赖(knife4j文档)
<!-- swagger-bootstrap-ui依赖,不使用增强功能只为swagger-ui换前端皮肤 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
<version>2.0.9</version>
</dependency>重新启动项目,访问:http://{ip}:{port}/doc.html。
若出现404页面,且控制台出现No mapping for GET /doc.html的提示。
出错原因:因为doc.html是在jar包里的,需要使用资源处理器注册静态资源。
解决办法:让SpringbootApplication启动类实现WebMvcConfigurer接口,使用资源处理器注册静态资源。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class SpringbootApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
/**
* 使用SpringBoot项目继承Knif4j访问doc.html页面,出现No mapping for GET /doc.html
* 出错原因:
* 因为doc.html是在jar包里的,需要使用资源处理器注册静态资源。
* @param registry
*/
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}