
李幽微
2022/12/04阅读:103主题:Pornhub黄
Swagger 3
❝开发环境
开发工具:旗舰版IDEA 2022.2 项目管理工具:Maven 3.6.3 开发技术:SpringBoot 2.7.5 、Swagger 3.0.0
学习目标
-
了解Swagger 3的作用和概念 -
了解前后端分离 -
在SpringBoot中集成Swagger 3
1. Swagger3 简介
1.1 IT开发历史
-
后端时代 -
前端:只负责管理静态页面html==>依赖后端。 -
后端:用模板引擎JSP处理业务逻辑。 -
前后端交互:使用JSP进行处理。
-
-
前后端分离时代 -
前端:前端控制层,视图层【前端团队】==>利用JSON伪造后端数据,可以独立运行。 -
后端:后端控制器,服务层,数据访问层【后端团队】 -
前后端交互:API
-
-
前后端分离的影响 -
问题 -
前后端集成联调,前后端人员无法做到即使协商,所以常采用规定统一的标准,避免后期问题的爆发。
-
-
解决方案 -
首先指定schema(计划),实时更新最新的API,降低集成风险。 -
前端测试接口:postman。 -
后端提供接口:实时更新。
-
-
1.2 Swagger
1.2.1 Swagger概念
Swagger是一个最流行的API框架,它具有地球上最大的API工具生态系统,绝大多数的的程序员都在使用它。与手动编写接口文档不同,Swagger是一个自动生成接口文档的工具。在需求不断变更的环境下,手动编写文档的效率实在太低。与Swagger2相比新版的swagger3配置更少,使用更加方便。
使用Restful API文档在线文档在线生成工具,可以实现API文档与API定义同步更新;并且它可以直接运行,在线测试API接口,支持多种语言。
1.2.2 Swagger的作用
-
在页面上展现项目接口 -
修改代码中的 Swagger 描述来实时更新接口文档 -
进行接口调用
1.2.3 Swagger的5种开源工具
现在SWAGGER官网主要提供了几种开源工具,提供相应的功能。可以通过配置甚至是修改源码以达到 你想要的效果
-
Swagger Codegen
❝Swagger Codegen 通过Codegen 可以将描述文件生成html格式和cwiki形式的接口文档,同时也能生成多钟语言的服务端和客户端的代码。支持通过jar包,docker,node等方式在本地化执行生成。也可以在后面的Swagger Editor中在线生成。
-
Swagger UI
❝Swagger UI提供了一个可视化的UI页面展示描述文件。接口的调用方、测试、项目经理等都可以在该页面中对相关接口进行查阅和做一些简单的接口请求。该项目支持在线导入描述文件和本地部署UI项目。
-
Swagger Editor
❝Swagger Editor类似于markendown编辑器的编辑Swagger描述文件的编辑器,该编辑支持实时预览描述文件的更新效果。也提供了在线编辑器和本地部署编辑器两种方式。
-
Swagger Inspector
❝Swagger Inspector感觉和postman差不多,是一个可以对接口进行测试的在线版的postman。比在Swagger UI里面做接口请求,会返回更多的信息,也会保存你请求的实际请求参数等数据。
-
Swagger Hub
❝Swagger Hub集成了上面所有项目的各个功能,你可以以项目和版本为单位,将你的描述文件上传到Swagger Hub中。在Swagger Hub中可以完成上面项目的所有工作,需要注册账号,分免费版和收费版。
2. SpringBoot整合Swagger
❝开发环境
开发工具:旗舰版IDEA 2022.2 项目管理工具:Maven 3.6.3 开发技术:SpringBoot 2.7.5 、Swagger 3.0.0
步骤一:新建web项目swagger_demo
❝需要测试接口,所以需要进行服务器访问
步骤二:pom.xml中添加Swagger 3依赖
<!--pom.xml的配置-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
步骤三:在application.yml添加Swagger配置
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
步骤四:编写Controller
package com.example.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 李幽微
* @since 2022/12/02 15:47
**/
@RestController
public class HelloWorldController{
@GetMapping("/helloWorld")
public String hello(){
return "Hello Swagger!";
}
}
启动项目,浏览器输入:http://localhost:8080/helloWorld

步骤五:访问swagger-ui,查看接口文档
浏览器访问:http://localhost:8080/swagger-ui/

展开HelloWorldController接口定义:

这里我们能看到枚举了所有可能的请求类型,因为我们用了 @RequestMapping ,以及请求地址 /hello ,我们再点开任意一个请求,

我们可以看到,接口没有参数,返回值是 String 类型;
这里描述了完整的接口定义信息;前端开发人员一目了然,假如接口定义变化,前端开发人员刷新下swagger-ui就能及时看到,比起以往的人工编写接口文档方便很多;
步骤六:Swagger注解描述接口
在接口描述的时候,控制器类,以及方法,参数,返回值等,默认的话,是英文无备注信息,可能会让 前端开发人员看起来吃力,会增加沟通成本;
Swagger提供一套注解,我们给接口添加中文注释;
我们在类上添加 @API 注解,以及在方法上添加 @ApiOperation 注解
package com.example.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 李幽微
* @since 2022/12/02 15:47
**/
@Api(tags="helloWorld类测试")
@RestController
public class HelloWorldController {
@ApiOperation("测试方法")
@RequestMapping ("/helloWorld")
public String hello(){
return "Hello World!";
}
}
重启项目,刷新swagger-ui,发现已经以后中文注释了;

3. Swagger3常用配置注解
3.1 Swagger3常用配置
❝Swagger提供了一些配置用来描述接口,下面是一些常用的注解,必须掌握;

3.2 实例一 @ApiImplicitParams 和 @ApiImplicitParam 参数描述
❝post方式,根据name和age两个参数查询数据,返回信息;
我们用 @ApiImplicitParams 和 @ApiImplicitParam ,描述请求参数
package com.example.controller;
//省略了import...
@Api(tags="hello类测试")
@RestController
public class HelloWorldController {
//省略了无关代码
/**
* <p>
* 查询
* </p>
* @param name 姓名
* @param age 年龄
* @return java.lang.String
* @author 李幽微
* @since 2022/12/2 19:53
*/
@PostMapping("/search")
@ApiImplicitParams({
@ApiImplicitParam(name = "name",value = "姓名",required = true,paramType
= "query"),
@ApiImplicitParam(name = "age",value = "年龄",required = true,paramType =
"query",dataType = "Integer")
})
@ApiOperation("测试查询")
public String search(String name,Integer age){
return name+":"+age;
}
}
swagger控制台显示:

3.3 实例二 @ApiModel 与@ApiModelProperty 实体参数描述
❝我们搞一个用户信息添加,使用 @ApiModel , @ApiModelProperty 注解来描述输入参数;
package com.example.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* <p>
* 用户实体类
* </p>
* @author 李幽微
* @since 2022/12/02 21:48
**/
@ApiModel("用户信息实体")
@Data
public class User {
@ApiModelProperty("编号")
private Integer id;
@ApiModelProperty("姓名")
private String name;
@ApiModelProperty("年龄")
private Integer age;
}
package com.example.controller;
//省略了import...
@Api(tags="hello类测试")
@RestController
public class HelloWorldController {
/**
* <p>
* 添加测试
* </p>
* @param user 用户实体
* @return java.lang.String
* @author 李幽微
* @since 2022/12/2 21:51
*/
@PostMapping("/add")
@ApiOperation("测试添加")
public String add(User user){
return user.getName()+":"+user.getAge();
}
}
swagger控制台显示:

3.4 实例三 @ApiResponses 与 @ApiResponse
❝我们搞一个根据id获取用户信息案例,通过 @PathVariable 获取id,返回User对象,以及通过 @ApiResponses , @ApiResponse ,描述响应码对应的描述信息
package com.example.controller;
//省略了import...
@Api(tags="hello类测试")
@RestController
public class HelloWorldController {
/**
* <p>
* 根据ID获取用户信息
* </p>
* @param id ID号码
* @return com.example.entity.User
* @author 李幽微
* @since 2022/12/2 22:07
*/
@GetMapping("/user/{id}")
@ApiOperation("根据ID获取用户信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id",value = "用户编号",required = true,paramType
= "path")
})
@ApiResponses({
@ApiResponse(code=408,message="指定业务得报错信息,返回客户端"),
@ApiResponse(code=400,message="请求参数没填好"),
@ApiResponse(code=404,message="请求路径没有或页面跳转路径不对")
})
public User load(@PathVariable("id") Integer id){
return new User(id,"jack",32);
}
}
swagger控制台显示:

Schemas也对应有视图用户实体描述信息显示:

4. Swagger3 接口测试
swagger-ui图形客户端提供了接口测试功能;

默认情况下,这些参数都不能填写,禁用的;

我们点击“Try it out”按钮;即可开启接口测试功能;

输入请求参数后,点击“Execute‘按钮,即可执行,下方是后端返回信息; 类似的,我们可以测试添加功能;

说明:很多时候,前后端分离,传的是json,键值对,用swagger-ui提供的简陋接口测试工具很难用, 所以接口测试我们还是用专业的 postman
5. wagger3 API信息配置
默认情况,显示的API信息如下:

通过源码,我们可以看到:这个信息是通过 springfox.documentation.service.ApiInfo.java
类来 构造的;

最终通过springfox.documentation.spring.web.plugins.Docket.java
类的构造方法传入 ApiInfo 类来最终构造;

我们要修改API信息默认配置的话,可以通过新建一个 com.example.config.Swagger3Config.java
配置类,重写 ApiInfo 实现,以及重写 Docket 实现并且设置apiInfo;
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
/**
* @author 李幽微
* @since 2022/12/02 22:29
**/
@Configuration
public class Swagger3Config {
/**
* <p>
* 配置swagger的Docket bean
* </p>
* @return springfox.documentation.spring.web.plugins.Docket
* @author 李幽微
* @since 2022/12/2 23:22
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30) // 指定swagger3.0版本
.apiInfo(createApiInfo());
}
/**
*<p>
* 配置swagger的ApiInfo bean
*</p>
* @return springfox.documentation.service.ApiInfo
* @author 李幽微
* @since 2022/12/2 23:16
*/
@Bean
public ApiInfo createApiInfo() {
return new ApiInfo("李幽微 Swagger",
"李幽微 API Documentation",
"3.0",
"https://cunkebai.github.io/",
new Contact("李幽微",
"https://cunkebai.github.io/",
"liyouwe2022@126.com"),
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
重启项目,我们发现,APIInfo信息变了;

❝这个API信息主要作用是让前端开发人员看的,谁开发的接口,或者哪个小组负责,有问题方便联系沟通;
6. Swagger3 Docket 开关&过滤&分组 配置详解
❝我们可以通过设置Docket,可以配置很多功能,比如是否开启swagger,过滤,分组等
6.1 开关设置enable
一般情况,我们只有在开发环境才会用到swagger,正式环境需要关闭swagger,一是安全问题,二是用了swagger会影响系统运行速度;我们通过设置Docket对象的enable即可;
package com.example.config;
//省略import...
/**
* @author 李幽微
* @since 2022/12/02 22:29
**/
@Configuration
public class Swagger3Config {
/**
* <p>
* 配置swagger的Docket bean
* </p>
* @return springfox.documentation.spring.web.plugins.Docket
* @author 李幽微
* @since 2022/12/2 23:22
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30) // 指定swagger3.0版本
.enable(false) // 开关
.apiInfo(createApiInfo());
}
//省略若干代码
}

设置后,重启项目,发现已经看不到API信息了;
6.2 设置过滤
有些情况,我们需要指定固定包路径下的类生成API,或者根据前端用户路径请求过滤;
使用过滤,必须先调用 select
方法;
通过apis
方法, basePackage 可以根据包路径来生成特定类的API,any
方法是默认所有都有效, none
方法都无效;withClassAnnotation
根据类注解, withMethodAnnotation
是根据方法注解;一般我们用的是 basePackage 方法;

具体实例:
package com.example.config;
//省略了import...
/**
* @author 李幽微
* @since 2022/12/02 22:29
**/
@Configuration
public class Swagger3Config {
/**
* <p>
* 配置swagger的Docket bean
* </p>
* @return springfox.documentation.spring.web.plugins.Docket
* @author 李幽微
* @since 2022/12/2 23:22
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30) // 指定swagger3.0版本
.enable(true) // 开关
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller")) // 指定扫描的包常用方式
.build()
.apiInfo(createApiInfo());
}
// 省略了若干方法
}
最后要加 build() 方法;
Swagger控制台显示结果:

类似的还有一个根据请求路径的 paths
方法;一般用 ant
匹配路径;any
是匹配任意路径, none
是都不匹配, regex
是正则匹配;

具体实例:
package com.example.config;
//省略了import ...
/**
* @author 李幽微
* @since 2022/12/02 22:29
**/
@Configuration
public class Swagger3Config {
/**
* <p>
* 配置swagger的Docket bean
* </p>
* @return springfox.documentation.spring.web.plugins.Docket
* @author 李幽微
* @since 2022/12/2 23:22
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30) // 指定swagger3.0版本
.enable(true) // 开关
.select()
.paths(PathSelectors.ant("/java1234/**"))// 匹配 /java1234/**请求路径
.build()
.apiInfo(createApiInfo());
}
}
Swagger控制台显示:

❝swagger-ui视图只显示过滤后的API接口信息;
6.3 设置分组
在实际项目开发中,把复杂项目划分多模块给多个小组或者多个人负责开发,所以每个小组或者个人要实现自己的分组,方便查找到API接口开发负责人,沟通和处理问题;
我们通过 groupName
方法可以设置组名;
实例:
package com.example.config;
//省略了import ...
/**
* @author 李幽微
* @since 2022/12/02 22:29
**/
@Configuration
public class Swagger3Config {
/**
* <p>
* 配置swagger的Docket bean
* </p>
* @return springfox.documentation.spring.web.plugins.Docket
* @author 李幽微
* @since 2022/12/2 23:22
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30) // 指定swagger3.0版本
.groupName("开发组001")
.enable(true) // 开关
.select()
.paths(PathSelectors.ant("/java1234/**"))// 匹配 /java1234/**请求路径
.build()
.apiInfo(createApiInfo());
}
}

发现组名变了;
现在话,我们结合前面学过的过滤,通过apis的basePackage方法,搞两个组,分别扫描不同的包路径;
模拟分组开发,controller包下建两个子包,分别是one和two包,用来模拟两个业务模块;

简单搞个 HelloWorldController2
package com.example.controller.two;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 李幽微
* @since 2022/12/03 00:14
**/
@Api(tags="helloWorld2类测试")
@RestController
public class HelloWorldController2 {
/**
* <p>
* helloWorld测试
* </p>
* @return java.lang.String
* @author 李幽微
* @since 2022/12/3 0:17
*/
@ApiOperation("测试方法2")
@GetMapping("/helloWorld2")
public String helloWorld(){
return "helloWorld2";
}
}
我们搞两个 Docket 和两个 ApiInfo
启动项目运行;
开发组001

开发组002

测试OK;
作者介绍
