🌿 Swagger2构建Restful API 文档
🍁 Swagger简介
由于SpringBoot能够快速开发、便捷部署等特性,相信有很⼤⼀部分SpringBoot的⽤户会⽤来构建
RESTful API。⽽我们构建RESTfulAPI的⽬的通常都是由于多终端的原因,这些终端会共⽤很多底层 业务逻辑,因此我们会抽象出这样⼀层来同时服务于多个移动端或者Web前端。
这样⼀来,我们的RESTful API就有可能要⾯对多个开发⼈员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建⼀份 RESTful API⽂档来记录所有接⼝细节,然⽽这样的做法有以下⼏个问题:
- 由于接⼝众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容 等),⾼质量地创建这份⽂档本身就是件⾮常吃⼒的事,下游的抱怨声不绝于⽿。
- 随着时间推移,不断修改接⼝实现的时候都必须同步修改接⼝⽂档,⽽⽂档与代码⼜处于两个不同的媒介,除⾮有严格的管理机制,不然很容易导致不⼀致现象。
为了解决上⾯这样的问题,本⽂将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到SpringBoot中,并与SpringMVC程序配合组织出强⼤RESTfulAPI⽂档。它既可以减少我们创建⽂档 的⼯作量,同时说明内容⼜整合⼊实现代码中,让维护⽂档和修改代码整合为⼀体,可以让我们在修改代码逻辑的同时⽅便的修改⽂档说明。另外Swagger2也提供了强⼤的⻚⾯测试功能来调试每个RESTful API。
Swagger 是一系列 RESTful API 的工具,通过 Swagger 可以获得项目的⼀种交互式文档,客户端 SDK 的⾃ 动生成等功能。
使用 Swagger 集成文档具有以下几个优势:
- 功能丰富 :支持多种注解,自动生成接口文档界面,支持在界面测试API接口功能;
- 及时更新 :开发过程中花一点写注释的时间,就可以及时的更新API文档,省心省力;
- 整合简单 :通过添加pom依赖和简单配置,内嵌于应用中就可同时发布API接口文档界面,不需要部署独立服务。
在springboot中使用swagger分为两种方式:
- 使用springfox的支持
- 使用第三方个人(组织)提供的stater
🍁 Springfox方式使用Swagger
- 在项目中导入依赖:
<!-- swagger依赖:提供注解支持,核心依赖-->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
</dependency>
<!-- swagger-ui依赖:独立web项目,提供基于浏览器的接口访问界面-->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>
- 创建Swagger配置类
package com.moxuan.stargym.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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;@EnableSwagger2
@Configuration // 配置类
public class SwaggerConfig {@Beanpublic Docket createRestApi() {// DocumentationType.SWAGGER_2 固定的,代表swagger2return new Docket(DocumentationType.SWAGGER_2)// 如果配置多个文档的时候,那么需要配置groupName来分组标识//.groupName("分布式任务系统")// 用于生成API信息.apiInfo(apiInfo())// select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档.select()// 用于指定扫描哪个包下的接口.apis(RequestHandlerSelectors.basePackage("com.moxuan.stargym.controller"))// 默认选择所有的API,如果你想只为部分API生成文档,可以配置这里//.paths(PathSelectors.any()).build();}/*** 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本* @return*/private ApiInfo apiInfo() {return new ApiInfoBuilder()// 可以用来自定义API的主标题.title("健身房管理系统").description("软帝集团信息管理系统,接口地址介绍,包含用户等等信息") // 可以用来描述整体的API// .termsOfServiceUrl("") // 用于定义服务的域名.version("v1.0") // 可以用来定义版本。.license("服务条款").licenseUrl("https://www.softeem.com").contact(new Contact("moxuan","https://www.baidu.com","softeem@163.com")).build(); //}
}
- 在application.yml配置文件中配置对swagger的兼容
spring:mvc:pathmatch:matching-strategy: ant_path_matcher
启动项目,访问:http://localhost:8080/swagger-ui.html
🍁 使用starter方式配置Swagger
对于springboot设计思路来看应该是将所有配置统一在application.yml文件中完成,因此有第三方的依赖提供了swagger的stater支持,具体使用方式如下:
- 导入依赖
<dependency><groupId>io.github.wilson-he</groupId><artifactId>swagger2-spring-boot-starter</artifactId><version>1.1.2</version>
</dependency>
- 在application.yml中配置swagger(代替之前的配置类)
# 对swagger的配置
swagger:docket:# 配置文档扫描的基础包base-package: com.moxuan.stargym.controllerapi-info:title: 墨轩的健身房管理系统description: 这是第一版的快照版,后续持续更新中version: v1.1license: 接口文档许可license-url: http://www.baidu.comcontact:name: moxuanurl: https://www.baidu.comemail: moxuan@163.com
- 添加前一种方式的Spring.mvc配置
spring:mvc:pathmatch:matching-strategy: ant_path_matcher
🌿 常用注解
🍁 @Api & @ApiOperation
@Api: 注解在类(Controller)上,描述当前接口的
- tags:表示当前接口的标签,支持多个(同一个接口中可能出现多个功能的接口(重复的))
@ApiOperation:注解在方法(Controller类中的方法)上,描述当前方法的使用方式
- value: 表示对当前接口方法的命名
- notes: 对当前接口方法的具体描述
@Controller
@Api(tags = {"知识讲解功能测试"})
public class TestController {@ApiOperation(value = "测试统一异常处理",notes = "通过人为触发异常,演示统一异常处理")@RequestMapping("/hello")public String hello()throws Exception{throw new Exception("发生错误");}@ApiOperation(value = "测试MVC环境是否正常",notes = "通过发送请求,检测是否运行正常")@RequestMapping("/show")@ResponseBodypublic String show(){return "go ..........";}
}
🍁 @ApiImplicitParams & @ApiImplicitParam
@ApiImplicitParams & @ApiImplicitParam :用户描述接口中的请求参数
@ApiImplicitParams 里面放的是一个 @ApiImplicitParam 的数组
@ApiImplicitParam 里面的属性包含以下(可选填)
- name 请求参数名称
- value 对请求参数名称说明
- dataTpye 参数类型
- defaultValue 对默认参数值设定
- paramType 请求参数类型(如果使用的是Restfull风格的请求路径,则paramType的值为path)
package com.moxuan.stargym.controller;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;@Api(tags = {"用户功能模块"})
@Controller
@RequestMapping("/user")
public class UserController {@ApiOperation(value = "用户的登录模块",notes = "通过传入的用户名和密码进行登录")@ApiImplicitParams({@ApiImplicitParam(name="username",value="用户名",dataType = "string",defaultValue = "moxuan"),@ApiImplicitParam(name="password",value="密码",dataType = "string",defaultValue = "123456")})@PostMapping("/loginUser")public String loginUser(String username,String password){return "index";}@GetMapping("/{pageNum}/{pageSize}")@ApiOperation(value = "用户列表查询",notes = "功能描述:该功能用来实现用户列表查询,包含分页实现,需提供页码数和每页显示条数")@ApiImplicitParams({@ApiImplicitParam(name = "pageNum",value = "页码数",paramType = "path",defaultValue = "1"),@ApiImplicitParam(name = "pageSize",value = "每页显示条数",paramType = "path",defaultValue = "2")})public String getUserList(@PathVariable Integer pageNum, @PathVariable Integer pageSize){return "index";}
}
🍁 @ApiModel & @ApiModelpropertity
ApiModel & @ApiModelpropertity:用于注解在返回对象或者请求参数为对象中,用户描述对象以及对象中的属性,用在实体类上。
package com.moxuan.stargym.entity;import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.sql.Date;
import java.sql.Timestamp;@Data
@ApiModel(value = "用户对象",description = "一个包含基本信息的用户对象")
public class User {@ApiModelProperty(value="用户id")private Long id;@ApiModelProperty(value = "用户名",required = true)private String username;@ApiModelProperty(value = "密码",required = true)private String password;@ApiModelProperty(value = "昵称",required = true)private String name;@ApiModelProperty(value = "金额",allowEmptyValue = true)private Double money;@ApiModelProperty(value = "生日")private Date birthday;@ApiModelProperty(value = "等级")private Long level;@ApiModelProperty(value = "创建时间")@TableField("add_time")private Timestamp addTime;@ApiModelProperty(value = "性别")private String gender;@ApiModelProperty(value="电话")private String phone;@ApiModelProperty(value = "邮箱")private String email;@ApiModelProperty(value = "邮箱是否认证")private Integer isVerify;
}
🍁@ApiParam
@ApiParam 注解用于控制器方法参数中,用于对参数具体解释
@GetMapping("/user/{id}")
@ApiOperation(value = "根据用户id查询用户信息",notes = "功能描述: 提供一个用户的id查询用户信息")
public String getUserById(@ApiParam(name = "uid",value = "用户id",required = true,defaultValue = "2") @PathVariable Integer id){return "index";
}
🍁 @ApiResponses & @ApiResponse
@ApiResponses&@ApiResponse:用户接口的返回值信息统一说明,可以用于注解在类(Controller)上和方法上