Swagger3.0 从0到1快速入门!
一、简介
1.1Swagger是什么?
Swagger 是一套基于 OpenAPI 规范(OpenAPI Specification,OAS)构建的开源工具,后来成为了 Open API 标准的主要定义者,现在最新的版本为17年发布的 Swagger3(Open Api3)。 对于 Rest API 来说很重要的一部分内容就是文档,Swagger 为我们提供了一套通过代码和注解自动生成文档的方法,这一点对于保证API 文档的及时性将有很大的帮助
。
OAS本身是一个API规范,它用于描述一整套API接口,包括一个接口是哪种请求方式、哪些参数、哪些header等,都会被包括在这个文件中。它在设计的时候通常是YAML格式,这种格式书写起来比较方便,而在网络中传输时又会以json形式居多,因为json的通用性比较强。
Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。
- Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
- Swagger 是最流行的 API 开发工具,它遵循 OpenAPI Specification(OpenAPI 规范,也简称 OAS)。
- Swagger 可以贯穿于整个 API 生态,如 API 的设计、编写 API 文档、测试和部署。
- Swagger 是一种通用的,和编程语言无关的 API 描述规范。
1.2Swagger应用场景
- 如果你的 RESTful API 接口都开发完成了,你可以用 Swagger-editor 来编写 API 文档( yaml 文件 或 json 文件),然后通过 Swagger-ui 来渲染该文件,以非常美观的形式将你的 API 文档,展现给你的团队或者客户。
- 如果你的 RESTful API 还未开始,也可以使用 Swagger ,来设计和规范你的 API,以 Annotation (注解)的方式给你的源代码添加额外的数据。这样,Swagger 就可以检测到这些数据,自动生成对应的 API 文档。
1.3Swagger的优势
- 支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。
- 提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。
1.4Swagger提供的工具
现在Swagger官网主要提供了几种开源工具,提供相应的功能。可以通过配置甚至是修改源码以达到你想要的效果。
Swagger Codegen
: 通过Codegen 可以将描述文件生成html格式和cwiki形式的接口文档,同时也能生成多钟语言的服务端和客户端的代码。支持通过jar包,docker,node等方式在本地化执行生成。也可以在后面的Swagger Editor中在线生成。Swagger UI
:提供了一个可视化的UI页面展示描述文件。接口的调用方、测试、项目经理等都可以在该页面中对相关接口进行查阅和做一些简单的接口请求。该项目支持在线导入描述文件和本地部署UI项目。Swagger Editor
: 类似于markendown编辑器的编辑Swagger描述文件的编辑器,该编辑支持实时预览描述文件的更新效果。也提供了在线编辑器和本地部署编辑器两种方式。Swagger Inspector
: 感觉和postman差不多,是一个可以对接口进行测试的在线版的postman。比在Swagger UI里面做接口请求,会返回更多的信息,也会保存你请求的实际请求参数等数据。Swagger Hub
:集成了上面所有项目的各个功能,你可以以项目和版本为单位,将你的描述文件上传到Swagger Hub中。在Swagger Hub中可以完成上面项目的所有工作,需要注册账号,分免费版和收费版。
SpringFox Swagger
: Spring 基于Swagger规范,可以将基于SpringMVC和Spring Boot项目的项目代码,自动生成JSON格式的描述文件。本身不是属于Swagger官网提供的,在这里列出来做个说明,方便下面作一个使用的展开。SpringFox是 spring 社区维护的一个项目(非官方),帮助使用者将 swagger2 集成到 Spring 中。
1.5SpringFox 3.0.0
由于Spring的流行,Marty Pitt编写了一个基于Spring的组件Swagger-Springmvc,用于将Swagger集成到Springmvc中来,而SpringFox则是从这个组件发展而来。
通常SpringBoot项目整合Swagger需要用到两个依赖:springfox-swagger2
和springfox-swagger-ui
,用于自动生成swagger文档。
- springfox-swagger2:这个组件的功能用于帮助我们自动生成描述API的json文件。
- springfox-swagger-ui:就是将描述API的json文件解析出来,用一种更友好的方式呈现出来。
Swagger2(17年停止维护并更名为Swagger3),SpringFox 的前身是Swagger-Springmvc,是一个开源的 API doc 框架,可以将 Controller 的方法以文档的形式展现。
亮点
- Spring5,Webflux支持(仅支持请求映射,尚不支持功能端点)。
- Spring Integration支持。
- SpringBoot支持springfox Boot starter依赖性(零配置、自动配置支持)。
- 具有自动完成功能的文档化配置属性。
- 更好的规范兼容性与2.0。
- 支持OpenApi 3.0.3。
- 零依赖。几乎只需要spring-plugin,swagger-core(https://github.com/swagger-api/swagger-core) ,现有的swagger2注释将继续工作并丰富openapi3.0规范。
以上简介内容整理于网络。
二、SpringBoot集成Swagger
2.1引入依赖坐标
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
2.2application.yml配置
# Swagger3.0 配置
swagger:
enable: true
application-name: "Java 求职助手项目"
application-version: 1.0
application-description: Java 求职助手项目 swagger 3.0
try-host: http://localhost:${server.port}
2.3创建SwaggerProperties
创建SwaggerProperties用于读取配置!
/**
* @Classname SwaggerProperties
* @Description TODO
* @Date 2022/11/13 14:57
* @Created by YJS
* @WebSite www.imyjs.cn
*/
@Component
@Data
@ConfigurationProperties("swagger")
public class SwaggerProperties {
/**
* 是否开启swagger,生产环境一般关闭,所以这里定义一个变量
*/
private Boolean enable;
/**
* 项目应用名
*/
private String applicationName;
/**
* 项目版本信息
*/
private String applicationVersion;
/**
* 项目描述信息
*/
private String applicationDescription;
/**
* 接口调试地址
*/
private String tryHost;
}
2.4自定义swagger3文档信息
package cn.imyjs.config;
import cn.imyjs.common.SwaggerProperties;
import io.lettuce.core.dynamic.support.ReflectionUtils;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.boot.SpringBootVersion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
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.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.lang.reflect.Field;
import java.util.*;
/**
* @Classname Swagger3Config
* @Description 自定义swagger3文档信息
* @Date 2022/11/08 12:39
* @Created by YJS
* @WebSite www.imyjs.cn
*/
@Configuration
//@ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
@EnableOpenApi
public class Swagger3Config implements WebMvcConfigurer {
private final SwaggerProperties swaggerProperties;
public Swagger3Config(SwaggerProperties swaggerProperties) {
this.swaggerProperties = swaggerProperties;
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30).pathMapping("/")
// 定义是否开启swagger,false为关闭,可以通过变量控制
.enable(swaggerProperties.getEnable())
// 将api的元信息设置为包含在json ResourceListing响应中。
.apiInfo(apiInfo())
// 接口调试地址
.host(swaggerProperties.getTryHost())
// 选择哪些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
// 支持的通讯协议集合
.protocols(newHashSet("https", "http"))
// 授权信息设置,必要的header token等认证信息
.securitySchemes(securitySchemes())
// 授权信息全局应用
.securityContexts(securityContexts());
}
/**
* API 页面上半部分展示信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title(swaggerProperties.getApplicationName() + " Api Doc")
.description(swaggerProperties.getApplicationDescription())
.contact(new Contact("编程那点事儿", "https://www.imyjs.cn", "2410685763@qq.com"))
.version("Application Version: " + swaggerProperties.getApplicationVersion() + ", Spring Boot Version: " + SpringBootVersion.getVersion())
.build();
}
/**
* 设置授权信息
*/
private List<SecurityScheme> securitySchemes() {
ApiKey apiKey = new ApiKey("BASE_TOKEN", "token", In.HEADER.toValue());
return Collections.singletonList(apiKey);
}
/**
* 授权信息全局应用
*/
private List<SecurityContext> securityContexts() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
.build()
);
}
@SafeVarargs
private final <T> Set<T> newHashSet(T... ts) {
if (ts.length > 0) {
return new LinkedHashSet<>(Arrays.asList(ts));
}
return null;
}
/**
* 通用拦截器排除swagger设置,所有拦截器都会自动加swagger相关的资源排除信息
*/
@SuppressWarnings("unchecked")
@Override
public void addInterceptors(InterceptorRegistry registry) {
try {
Field registrationsField = FieldUtils.getField(InterceptorRegistry.class, "registrations", true);
List<InterceptorRegistration> registrations = (List<InterceptorRegistration>) ReflectionUtils.getField(registrationsField, registry);
if (registrations != null) {
for (InterceptorRegistration interceptorRegistration : registrations) {
interceptorRegistration
.excludePathPatterns("/swagger**/**")
.excludePathPatterns("/webjars/**")
.excludePathPatterns("/v3/**")
.excludePathPatterns("/doc.html");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@ConditionalOnProperty
注解声明了当springfox.documentation.enabled
为true
时启用配置,而且默认值就是true
。这非常有用,Swagger仅仅建议在开发阶段使用,这个正好是个开关。另外有时候我们自定义配置的时候最好把这个开关也加上。
2.4使用注解标注
@RestController
@RequestMapping("/admin/cards")
@Slf4j
@Api("任务卡片Controller")
public class CardController {
@Autowired
private CardService cardService;
@GetMapping()
public R<List<Card>>getAllCards(){
return R.success(cardService.list(),"查询所有任务卡片成功!");
}
@DeleteMapping("/{id}")
@ApiOperation("根据ID删除任务卡片")
public R<Boolean> deleteCardById(@PathVariable @ApiParam("需要被删除的任务卡片ID") Integer id){
}
@PutMapping()
@ApiOperation("根据ID更新任务卡片")
public R<Boolean> updateCard(@ApiParam("更新的任务卡片实体") @RequestBody Card card){
}
@PostMapping()
@ApiOperation(value = "任务卡片添加", notes = "测试notes")
public R<Boolean> addCard(@RequestBody @ApiParam(value = "添加的任务卡片实体", required = true) Card card){
}
@GetMapping("/search")
@ApiOperation("根据条件查询任务卡片")
public R<List<Card>>getCardsByCondition(@ApiParam("查询条件数据模型") CardSearchModel cardSearchModel) {
@GetMapping("/runningcard")
@ApiOperation("获取状态为进行中的任务卡片")
public R<List<RunningCardVO>> getRunningCards(){
}
}
2.5拦截器放行(不需要!)
若项目中有使用拦截器,需要进行如下配置
@Configuration
public class MyInterceptorConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/** swagger配置 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController( "/swagger-ui/")
.setViewName("forward:/swagger-ui/index.html");
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns 方法用来添加要拦截的请求,这里我们拦截所有的请求
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/admin/**")
.addPathPatterns("/user/update")
.addPathPatterns("/user/logout");
super.addInterceptors(registry);
}
}
2.6文档访问地址
http://ip:port/context-path/swagger-ui/
http://ip:port/context-path/swagger-ui/index.html
三、常用注解说明
@Api:用在controller类,描述API接口
@ApiOperation:描述接口方法
@ApiImplicitParams:描述接口参数
@ApiModel:描述实体
@ApiModelProperty:描述实体属性
@ApiResponses:描述接口响应
@ApiIgnore:忽略接口方法
3.1、类
@Api()
:表示这个类是 swagger 资源
- tags:表示说明内容,只写 tags 就可以省略属性名
- value:同样是说明,不过会被 tags 替代
3.2、方法
@ApiOperation()
:对方法的说明,注解位于方法上
- value:方法的说明
- notes:额外注释说明
- response:返回的对象
- tags:这个方法会被单独摘出来,重新分组,若没有,所有的方法会在一个Controller分组下
3.3、方法入参
@ApiParam()
:对方法参数的具体说明,用在方法入参括号里
,该注解在post请求参数时,参数名不显示
- name:参数名
- value:参数说明
- required:是否必填
@ApiImplicitParam
对方法参数的具体说明,用在方法上@ApiImplicitParams之内
,该注解在get,post请求参数时,参数名均正常显示
- name 参数名称
- value 参数的简短描述
- required 是否为必传参数
- dataType 参数类型,可以为类名,也可以为基本类型(String,int、boolean等)指定也不起作用,没卵用
- paramType 参数的传入(请求)类型,可选的值有path, query, body, header or form。
3.4、实体
@ApiModel
描述一个Model的信息(一般用在请求参数无法使用@ApiImplicitParam
注解进行描述的时候)
- value model的别名,默认为类名
- description model的详细描述
@ApiModelProperty
描述一个model的属性
- value 属性简短描述
- example 属性的示例值
- required 是否为必须值
3.5、header参数
@ApiImplicitParams({ @ApiImplicitParam(paramType="header",name="USERTOKEN",dataType="String",required=true,value="用户token")
})
3.6、file入参
需要使用@RequestPart
注解
@ApiOperation(value = "上传文件接口",notes = "上传文件接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "上传人")
})
@PostMapping(value = "/uploadFile")
public String uploadFile(@RequestParam("name") String name,@RequestPart("file") MultipartFile file){
}