您现在的位置是:首页 >技术教程 >【微服务】springboot整合swagger多种模式使用详解网站首页技术教程
【微服务】springboot整合swagger多种模式使用详解
目录
一、前言
在如今迭代速度越来越快的开发模式下,使用springboot作为服务端框架进行开发的项目越来越多,当后端API开发并自测完成后,如何能让前端同事与你快速高效的对接API呢?可能大家知道的有下面几种方式:
1.1 编写API文档
这是很多公司比较传统的做法,一般来说,这种方式对API开发者有着较高的要求,因为文档的编写过程相对耗时,所以API在开发之前,需要对API的各项参数进行严格的评审,以便减少在对接过程中的改动带来的事件成本。文档可以使用传统的word文档,或者使用markdown编辑。
1.2 使用一些在线调试工具
如今市面上出现了很多在线接口调试工具,只需要将你的API服务部署到服务器,然后就可以在线远程调试了。
1.3 postman
这是一个比较传统但也很好用的本地调试工具,对于团队来说,服务端开发人员可将A开发完成的API录入进去,然后通过团队分享的模式将API分享出去,前端就可以拿到API列表进行调试对接了。
1.4 swagger
随着swagger的使用规模越来越大,知名度也越来越高,尤其是在敏捷开发模式下具备更多的优势而被很多开发团队接纳,只需要服务端集成swagger依赖,再做简单的配置即可使用了,而且使用学习成本可以说几乎为零。
二、swagger简介
2.1 背景
在当前前后端分离成了产品快速迭代的基本模式后,如何快速完成API与前端的快速联调成了产品阶段性发布的关键因素,在这个背景下,尽管前端可以通过mock数据完成自身的功能验证,但是没有与服务端进行真实数据的联调,总觉得不踏实,但不同的团队联调的方式不一样,这就造成了有的团队使用的工具简单,联调效率高,有的复杂,造成联调效率很低,甚至带来了新的学习成本。
在这样的背景下,如何提升与API的快速联调,并尽可能的降低团队人员的学习成本呢?于是swagger的出现就很好的解决了这样一个难题。
2.2 swagger优缺点
2.2.1 swagger优点
使用swager具备如下优点:
- 整合简单,只需要引入一个swagger的jar包,并做简单的配置即可;
- 自动生成文档,只需在接口中使用swagger的相关注解进行标注,就能生成对应的接口文档;
- 自动更新文档,由于是动态生成的,所以如果你修改了接口,文档也会自动对应修改(如果你也更新了注解的话)。这样就不会发送我修改了接口,却忘记更新接口文档的情况;
- 支持在线调试,swagger提供了在线调用接口的功能;
2.2.2 swagger缺点
尽管swagger为API的管理带来了便利,但仍然存在一些缺点,
- 不能创建测试用例,只能提供一个简单的在线调试,如果你想存储测试用例,则需要选择其他的工具了,比如postman,或者通过swagger导出yaml文件进行存储;
- 程序中需要遵循一些基本的编码规范。比如你需要返回一个json数据,而这个数据可能是一个Map格式的,那么我们此时不能标注这个Map格式的返回数据的每个字段的说明,而如果是一个实体类的话,则需要为实体类中的属性标注特定的注解,这样带来的问题很明显就是程序的实体类中看起来有些乱,不够整洁,显得冗余;
- 做不到API的动态刷新,假如当前前端正在使用的某个接口你在本地改了之后忘了重启,可能前端用到的还是老接口;
- 存在一定程度的安全问题,UI界面上会暴露太多的信息,比如某个接口中,前端可能只需要3个必填的参数,但是在swagger的UI界面上,会把对象的所有字段信息都填进去,这样看起来显得比较凌乱冗余;
2.2.3 swagger使用场景
并不是所有的项目都适合使用swagger,比如一些比较老的项目,可能因为版本的问题如果强势集成,带来的时间人力成本巨大,还有一些比如对安全性要求特别高的项目,不允许随意暴露服务端的API到外网,使用swagger就不太合适了,不过从目前的趋势来看,swagger的使用还是能够整体提升开发和对接效率的,这里总结下面的一些场景提供参考:
- 业务体量较小,功能迭代迅速,对开发时间要求很紧的项目,可以考虑使用swagger;
- 对安全性要求较低,或者仅在公司内网环境使用,或者仅仅是开发阶段使用,这种也是可以考虑在开发阶段使用swagger的;
- 服务端框架是springboot的,springboot目前占据着微服务框架的主流,因此与swagger的集成比较方便;
三、swagger常用的几种整合模式
以springboot与swagger整合为例,提供了多种方式可以使用,常用的主要有下面几种,掌握这几种应该足够可以应对大多数的场景了,
3.1 swagger2
这是原始的一种方式,也是很多小团队经常使用的一种方式,直接引入swagger的基本依赖jar包就可以使用了。与springboot的整合主要包括下面几个包:
- springfox-swagger2;
- springfox-swagger-ui;
3.2 knife4j
Knife4j的前身是swagger-bootstrap-ui,前身swagger-bootstrap-ui是一个纯swagger-ui的ui皮肤项目;
项目初衷是为了写一个增强版本的swagger的前端ui,但随着项目的发展,面对越来越多个性化需求,不得不编写后端Java代码以满足新的需求。
在swagger-bootstrap-ui的1.8.5~1.9.6版本之间,采用的是后端Java代码和Ui都混合在一个Jar包里面的方式提供给开发者使用。这种方式虽说对于集成swagger来说很方便,只需要引入jar包即可,但是在微服务架构下显得有些臃肿。因此项目正式更名为knife4j,取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍。更名也是希望把她做成一个为Swagger接口文档服务的通用性解决方案,不仅仅只是专注于前端Ui前端。
3.2.1 knife4j特点
- swagger-bootstrap-ui的所有特性都会集中在knife4j-spring-ui包中,并且后续规划也会满足开发者更多的个性化需求;
- 主要的变化是,项目的相关类包路径更换为com.github.xiaoymin.knife4j前缀,开发者使用增强注解时需要替换包路径;
- 后端Java代码和ui包分离为多个模块的jar包,以面对在目前微服务架构下,更加方便的使用增强文档注解(使用SpringCloud微服务项目,只需要在网关层集成UI的jar包即可,因此分离前后端);
- knife4j沿用swagger-bootstrap-ui的版本号,第1个版本从1.9.6开始,关于使用方法,请参考文档(摘自 knife4j 官方介绍);
3.2.2 knife4j版本说明
knife4j 主要的版本基本如下
1.9.6 | 蓝色皮肤风格,开始更名,增加更多后端模块 |
2.0~2.0.5 | Ui重写,底层依赖的springfox框架版本是2.9.2 |
2.0.6~ | springfox框架版本升级知2.10.5,OpenAPI规范是v2 |
3.0~ | 底层依赖springfox框架版本升级至3.0.3,OpenAPI规范是v3 |
3.3 Springdoc
相对前两种来说,目前springdoc的热度很高,一是这个框架比较新,而且代码维护更新速度快,而且在与springboot项目整合的时候还提供了安全插件,可以在一定程度上提升使用的安全性。git的地址为:springdoc源码地址
3.3.1 SpringDoc简介
SpringDoc是一款可以结合SpringBoot使用的API文档生成工具,基于OpenAPI 3,目前在Github上已有1.7K+Star,更新发版还是挺勤快的,是一款更好用的Swagger库!值得一提的是SpringDoc不仅支持Spring WebMvc项目,还可以支持Spring WebFlux项目,甚至Spring Rest和Spring Native项目,总之非常强大,下面是一张SpringDoc的架构图。
四、springboot整合swagger多种模式案例
以上从理论上对swagger常用的几种使用方式做了了解,接下来将通过实际案例分别做详细的说明。
4.1 springboot整合swagger2
前置准备,搭建springboot工程,目录结构如下
4.1.1 添加如下核心依赖
如下仅为核心依赖,可以根据自身情况酌情添加
<dependencies>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--swagger API获取-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger-ui API获取-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
4.1.2 配置文件
使用这种方式不需要有太多配置,这里只配置一个端口即可
server.port=8088
4.1.3 自定义swagger配置类
该类是整个整合过程中最重要的一个配置,主要包括:
- 定义接口的扫描路径;
- swagger-ui的界面显示信息;
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;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
//用于生成API信息
.apiInfo(apiInfo())
//select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
.select()
//用于指定扫描哪个包下的接口
.apis(RequestHandlerSelectors.basePackage("com.congge.controller"))
//选择所有的API,如果你想只为部分API生成文档,可以配置这里
.paths(PathSelectors.any())
.build();
}
/**
* 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//用来自定义API的标题
.title("SpringBoot项目SwaggerAPIAPI测试")
//用来描述整体的API
.description("SpringBoot项目SwaggerAPI描述信息")
//创建人信息
.contact(new Contact("测试人员","http://localhost:8082/swagger-ui.html","congge@qq.com"))
//用于定义服务的域名
//.termsOfServiceUrl("")
.version("1.0") //可以用来定义版本
.build();
}
}
4.1.4 自定义测试接口
自定义一个测试接口,可以说为了能够让工程中的接口在swagger-ui中能够调试,最重要的就是需要在类上添加这个注解:@Api,其他的方法上面的一些注解,可以参考官方文档进行配置即可;
//http://localhost:8088/swagger-ui.html 主页访问地址
@RestController
@Api(tags = "UserController", description = "UserController | 测试swagger")
public class UserController {
@GetMapping("getById")
@ApiOperation(value="getById 方法", notes="getById,根据ID获取账户信息")
public User getById(){
return new User("001","jerry","123456");
}
@PostMapping("/save")
public String saveUser(UserRequest userRequest){
User user = new User();
BeanUtils.copyProperties(userRequest,user);
return "success";
}
}
4.1.5 自定义实体类
在很多情况下,接口中的参数是对象类型,这时候为了让前端对接的同事知道对象中的每个参数的含义,最好按照swagger的规范,给每个对象的属性添加一些swagger的注解,下面提供一个示例;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="用户登录表单对象",description="用户登录表单对象")
public class User implements Serializable {
private static final long serialVersionUID = -2896873555774275129L;
@ApiModelProperty(value = "用户ID",required = true,example = "001")
private String id;
@ApiModelProperty(value = "用户名称",required = true,example = "jerry")
private String userName;
@ApiModelProperty(value = "密码",required = true,example = "123456")
private String passWord;
}
4.1.6 访问swagger界面
启动服务,然后浏览器访问:http://localhost:8088/swagger-ui.html,至于怎么调试使用的话,有兴趣的同学可以自行尝试下,还是比较简单的;
4.2 springboot整合knife4j
上文简单介绍了knife4j的背景,接下来看看在springboot中整合knife4j的详细步骤,首先还是提前创建一个空的springboot工程,目录结构如下
4.2.1 引入核心依赖
这里做演示只需要两个包,如果有其他的需求可以继续追加即可;
<dependencies>
<!-- Spring Boot Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
4.2.2 自定义配置类
这个和上面整合swagger2类似,需要自定义一个类,里面定义UI界面的显示信息,以及扫描的接口类所在的包路径等信息
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.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Knife4jConfiguration {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
String groupName="3.X版本";
Docket docket=new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("这是knife4j API ")
.description("这是knife4j,记录了API相关的出参和入参信息")
.termsOfServiceUrl("http://yaomaoyang.com")
.contact(new Contact("congge","http://127.0.0.1","congge@qq.com"))
.version("3.0")
.build())
//分组名称
.groupName(groupName)
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.congge.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
4.2.3 添加测试接口
为了能够让接口在UI界面上展示,最重要的就是在类上添加的这个@Api注解,其他的注解可根据需要在接口类方法上进行标注即可,和上面使用swagger类似;
@RestController
@RequestMapping(value = "/user")
@Api(tags = "用户管理API")
public class UserController {
/**
* 根据ID获取账户信息
* @param id
* @return
*/
@GetMapping(value = "/getById")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("根据ID获取账户信息")
public User test(@RequestParam("id") String id){
User user = new User();
user.setId(id);
user.setPassWord("123456");
user.setUserName("jerry");
return user;
}
}
4.2.4 自定义实体类
某些接口中接收的参数如果是一个对象的话,为了让其他同学能够看懂对象中的参数,可以在对象上添加knife4j提供的注解,下面给一个示例
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="用户登录表单对象",description="用户对象参数")
public class User implements Serializable {
private static final long serialVersionUID = -2896873555774275129L;
@ApiModelProperty(value = "用户ID",required = true,example = "001")
private String id;
@ApiModelProperty(value = "用户名称",required = true,example = "jerry")
private String userName;
@ApiModelProperty(value = "密码",required = true,example = "123456")
private String passWord;
}
4.2.5 访问UI界面
启动工程,然后通过这个地址访问界面:http://localhost:8082/doc.html,看这个界面是不是觉得风格上显得更专业一点;
4.3 springboot整合springdoc
springdoc相比前两种,出现的稍晚,但是目前来看,其受欢迎的程度似乎更好,一方面来说swagger的基本功能它都有,同时,在访问的安全性上有一定的保障,下面来看具体的整合步骤,提前创建一个springboot工程,目录结构如下:
4.3.1 添加核心依赖
其他的依赖柯根据自身的情况酌情引用
<dependencies>
<!-- Spring Boot Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springdoc swagger ui -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-javadoc</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
4.3.2 核心配置文件
在application.yml文件中添加如下配置,这些配置见名知意这里就不做过多解释,其中:
api-docs.path: /v3/api-docs这个配置是为了获取接口的yml文档的地址
里面还有更丰富的配置可以参阅网上的资料,都有比较详细的说明,比如还可以配置打开UI界面的前置路径等;
# springdoc配置
springdoc:
# 分组配置
group-configs:
- group: 用户管理
packages-to-scan: com.congge.controller
paths-to-match: /users/**
- group: 角色管理
packages-to-scan: com.congge.controller
paths-to-match: /roles/**
api-docs:
enabled: true
path: /v3/api-docs
server:
port: 8087
4.3.3 自定义配置类
自定义配置可以对项目中的各类API进行分组管理,以bean的方式注入到spring容器中;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
@Configuration
public class OpenApiConfig {
/*@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("Springdoc OAS3.0 - RESTful API")
.description("Springdoc OAS3.0 构建RESTful API")
.version("1.0")
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.servers(Arrays.asList(
new Server().description("开发环境").url("http://localhost:8087")
))
.externalDocs(new ExternalDocumentation()
.description("SpringShop Wiki Documentation")
.url("https://springshop.wiki.github.org/docs"));
}*/
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.components(new Components())
.info(new Info()
.title("User Manager API")
.description("用户管理系统API.")
.version("1.0"));
}
@Bean
public GroupedOpenApi frontApi() {
return GroupedOpenApi.builder()
.group("frontApi")
.pathsToMatch(new String[]{"/users/**", "/roles/**"})
.packagesToExclude("com.congge.controller")
.build();
}
}
4.3.4 自定义测试接口
注意接口类上的这个注解,@Tag,是UI界面上能够识别的关键;
//http://localhost:8087/swagger-ui/index.html?urls.primaryName=%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86
@Tag(name = "用户管理", description = "用户管理FrontApi")
@RestController
@RequestMapping("/users")
public class UserController {
/**
* 查询用户详细信息
*
* @param id 用户ID
* @return 用户信息
*/
@GetMapping("/get")
public UserInfo getUser(@RequestParam String id) {
return new UserInfo();
}
}
@Data
@Schema(description = "用户返回实体对象")
class UserInfo {
@Schema(description = "用户名称")
private String userName;
@Schema(description = "用户密码")
private String passWord;
}
4.3.5 访问UI界面
启动工程,访问界面地址:http://localhost:8087/swagger-ui/index.html,看到如下效果,具体在UI界面上进行接口调试的时候与上面两种是类似的;
五、写在结尾
本篇详细总结了springboot整合swagger的多种使用方式,希望能够为您的日常开发带去帮助,本篇到此结束,感谢观看!