Swagger-的使用(详细教程)
前言
作为后端开放人员 ,最烦的事就是自己写接口文档和别人没有写接口文档 ,不管是前端还是后端开发 ,多多少少都会被接口文档所折磨 ,前端会抱怨后端没有及时更新接口文档 ,而后端又会觉得编写接口文档太过麻烦 。Swagger 可以较好的接口接口文档的交互问题 ,以一套标准的规范定义接口以及相关的信息 ,就能做到生成各种格式的接口文档 ,生成多种语言和客户端和服务端的代码 ,以及在线接口调试页面等等 。只需要更新 Swagger 描述文件 ,就能自动生成接口文档 ,做到前端 、后端联调接口文档的及时性和便利性 。
一 、简介
官网:https://swagger.io/
Swagger 是一个规范且完整的框架 ,用于生成 、描述 、调用和可视化 RESTful 风格的 Web 服务 。
Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码 、文档或网络流量监测就可以发现和理解服务的能力 。当通过 Swagger 进行正确定义 ,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互 。与为底层编程所实现的接口类似 ,Swagger 消除了调用服务时可能会有的猜测 。
Swagger 的优势
支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了 ,对程序员来说非常方便 ,可以节约写文档的时间去学习新技术 。 提供 Web 页面在线测试 API:光有文档还不够 ,Swagger 生成的文档还支持在线测试 。参数和格式都定好了 ,直接在界面上输入参数对应的值即可在线测试接口 。二 、基本使用
1. 导入相关依赖
通过在项目中引入 Springfox ,可以扫描相关的代码 ,生成该描述文件 ,进而生成与代码一致的接口文档和客户端代码 。
<!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-spring-web</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>2. 编写配置文件
在配置文件 config 目录下 ,添加 swagger 的配置文件 SwaggerConfig.java
@Configuration // 配置类 @EnableSwagger2 // 开启 swagger2 的自动配置 public class SwaggerConfig { }这个时候 Swagger 已经算是整合到项目之中了 ,可以启动下服务 ,输入:http://localhost:8080/swagger-ui.html# (这里我的项目端口是 8868 ,项目路径是 /mike ,所以我打开的文档地址为 http://localhost:8868/mike/swagger-ui.html# )即可查看 swagger 文档 。
可以看到 Swagger 文档中大概有这四类信息
组 基本信息 接口信息 实体类信息2.1 配置基本信息
Swagger 有自己的实例 Docket,如果我们想要自定义基本信息 ,可以使用 docket 来配置 swagger 的基本信息 ,基本信息的设置在 ApiInfo 这个对象中。
Swagger 默认的基本信息展示
ApiInfo 中默认的基本设置
title:Api Documentation description:Api Documentation version:1.0 termsOfServiceUrl:urn:tos contact:无 license:Apache 2.0 licenseUrl:http://www.apache.org/licenses/LICENSE-2.0SwaggerConfig.java 配置文件添加以下内容:
@Bean public Docket docket() { // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) // 配置基本信息 .apiInfo(apiInfo()) ; } // 基本信息设置 private ApiInfo apiInfo() { Contact contact = new Contact( "米大傻", // 作者姓名 "https://blog.csdn.net/xhmico?type=blog", // 作者网址 "777777777@163.com"); // 作者邮箱 return new ApiInfoBuilder() .title("多加辣-接口文档") // 标题 .description("众里寻他千百度,慕然回首那人却在灯火阑珊处") // 描述 .termsOfServiceUrl("https://www.baidu.com") // 跳转连接 .version("1.0") // 版本 .license("Swagger-的使用(详细教程)") .licenseUrl("https://blog.csdn.net/xhmico/article/details/125353535") .contact(contact) .build(); }重启服务 ,打开 Swagger 文档 ,基本信息改变如下所示:
2.2 配置接口信息
默认情况下 ,Swagger 是会展示所有的接口信息的 ,包括最基础的 basic-error 相关的接口
有时候我们希望不要展示 basic-error-controller 相关的接口 ,或者是说这想要显示某些接口 ,比如说:user-controller 下的接口 ,由该怎么去实现呢?这个时候就需要设置 扫描接口
@Bean public Docket docket() { // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) // 配置接口信息 .select() // 设置扫描接口 // 配置如何扫描接口 .apis(RequestHandlerSelectors //.any() // 扫描全部的接口 ,默认 //.none() // 全部不扫描 .basePackage("com.duojiala.mikeboot.controller") // 扫描指定包下的接口 ,最为常用 //.withClassAnnotation(RestController.class) // 扫描带有指定注解的类下所有接口 //.withMethodAnnotation(PostMapping.class) // 扫描带有只当注解的方法接口 ) .paths(PathSelectors .any() // 满足条件的路径 ,该断言总为true //.none() // 不满足条件的路径 ,该断言总为false(可用于生成环境屏蔽 swagger) //.ant("/user/**") // 满足字符串表达式路径 //.regex("") // 符合正则的路径 ) .build(); }可根据自己的需求去设置对应的配置 ,这里我就不再一一赘述了,以上是我所设置的配置 ,重启服务 ,打开 Swagger 文档,接口信息改变如下所示:
可以看到之前 basic-error-controller 相关的接口已经没有了
2.3 配置分组信息
Swagger 默认只有一个 default 分组选项 ,如果没有设置 ,所有的接口都会显示在 default `分组下 ,如果功能模块和接口数量一多 ,就会显得比较凌乱 ,不方便查找和使用 。
swagger 文档中组名默认是 default ,可通过 .groupName(String )
@Bean public Docket docket() { // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) .groupName("mike") // 修改组名为 "mike" ; }修改后:
如果需要配置多个组的话 ,就需要配置多个 docket() 方法 ,这里我就简单写两组 ,代码如下: /** * 展示 controller 包下所有的接口 */ @Bean public Docket docket1() { // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) .groupName("mike") // 修改组名为 "mike" // 配置接口信息 .select() // 设置扫描接口 // 配置如何扫描接口 .apis(RequestHandlerSelectors .basePackage("com.duojiala.mikeboot.controller") // 扫描指定包下的接口 ,最为常用 ) .paths(PathSelectors .any() // 满足条件的路径 ,该断言总为true ) .build(); } /** * 展示路径为 /error 的所有接口(基础接口) */ @Bean public Docket docket2() { // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) .groupName("yank") // 修改组名为 "yank" // 配置接口信息 .select() // 设置扫描接口 // 配置如何扫描接口 .apis(RequestHandlerSelectors .any() // 扫描全部的接口 ,默认 ) .paths(PathSelectors .ant("/error") // 满足字符串表达式路径 ) .build(); }重启服务,打开 Swagger 文档 ,接口信息改变如下所示:
组名为 mike 的文档中只有 user-controller 相关的接口信息
组名为 yank 的文档中只有 basic-error-controller 相关的接口信息
3. 控制 Swagger 的开启
在开发或者测试环境下 ,我们开启 swagger 会方便前端和后端的交互,但是如果在生产环境下也开启 swagger 的话 ,是会将接口暴露出去的 ,有极大风险 ,如何让 swagger 根据不同的环境来决定是否开启?
这里我准备了四个项目的配置文件 ,dev 、test 、pro 三个环境的配置文件仅是端口上的不同
application.yml -------------------------- 全局配置文件 application-dev.yml -------------------- 开发环境配置文件 application-test.yml -------------------- 测试环境配置文件 application-pro.yml -------------------- 生产环境配置文件application.yml 内容如下 ,用于指定选择的环境:
spring: profiles: active: dev可以通过代码判断此时是在什么环境:dev 、test 、pro ,如果是在 pro 生产环境 ,则关闭 swagger 。
/** * swagger 配置 * @param environment 环境 */ @Bean public Docket docket(Environment environment) { // 设置环境范围 Profiles profiles = Profiles.of("dev","test"); // 如果在该环境返回内则返回:true ,反之返回 false boolean flag = environment.acceptsProfiles(profiles); // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) .enable(flag) // 是否开启 swagger:true -> 开启 ,false -> 关闭 ; }在 application.yml 全局配置文件中环境指向 dev 时 ,是可以打开 swagger 的
如果我将 application.yml 全局配置文件中环境指向 pro 时 ,就不能打开 swagger 了 ,提示 Could not render e, see the console
4. 常用注解使用
之前有说 Swagger 会将接口请求或者相应的实体类信息展示在 Models 下的,比如我 UserController.java 下有一个接口如下所示:
@PostMapping(value = "/query-user-info") public ResponseBean queryUserInfo(@RequestBody @Validated IdReq req) { return ResponseBean.success(userService.queryUserInfo(req)); }它的请求体是 IdReq ,响应是 ResponseBean ,Models 展示这两个实体类信息如下:
前端可通过看这个 Models 知道后端定义实体类的信息。
@ApiModel
该注解是作用于类上面的,是用来描述类的一些基本信息的 。
相关属性:
value:提供类的一个备用名 ,如果不设置 ,默认情况下将使用 class 类的名称 description:对于类 ,提供一个详细的描述信息 parent:这个属性用于描述的是类的一些父类信息 discriminator:这个属性解释起来比较麻烦 ,因为这个类主要体现在断言当中 subTypes:可以通过这个属性 ,指定我们想要使用的子类譬如:这个为给 IdReq 这个类添加该注解
@Data @NoArgsConstructor @AllArgsConstructor @ApiModel(value = "Id请求体") public class IdReq { private String id; }可以看到这里的名字从 IdReq 变成 Id请求体 了
@ApiModelProperty
它的作用是添加和操作属性模块的数据 。
该注解的使用详情可参见博客:@ApiModelProperty注解的用法
这里我还是以 IdReq 类为例 ,为该类的属性添加说明
@Data @NoArgsConstructor @AllArgsConstructor @ApiModel(value = "Id请求体") public class IdReq { @ApiModelProperty("主键id") private String id; }可以看到这里对该字段有一个备注说明 。
@ApiOperation
该注解用来对某个方法/接口进行描述
该注解的使用详情可参见博客:Swagger @ApiOperation 注解详解
这里我以 UserController 下的接口为例:
@PostMapping(value = "/query-user-info") @ApiOperation(value = "根据id查询用户详情") public ResponseBean queryUserInfo(@RequestBody @Validated IdReq req) { return ResponseBean.success(userService.queryUserInfo(req)); }可以看见该接口就多了对其的描述信息 。
@ApiParam
该注解使用在方法上或者参数上 ,字段说明 ,表示对参数的添加元数据(说明或者是否必填等)
相关属性:
name:参数名 value:参数说明 required:是否必填这里我以 UserController 下的接口为例:
@PostMapping(value = "/query-user-infos") @ApiOperation(value = "条件查询用户信息") public ResponseBean queryUserInfos( // name 用户名称 不必填 @ApiParam(value = "用户名称", required = false) @RequestParam(required = false) String name, // gender 用户性别 必填 @ApiParam(value = "用户性别", required = true) @RequestParam(required = true) GenderEnum gender ) { return ResponseBean.success(userService.queryUserInfos(name,gender)); }这里会展示请求参数的备注信息 ,以及是否必填等 。
5. 接口调用
使用 swagger 除了让前后端交互变得方便 ,也让接口的请求变得简单 ,只需要填写好请求所需要的参数信息 ,便可直接发起请求 。
比如说接口 /user/query-user-info
点击 Try it out
设置好请求所需的参数,点击 Execute 执行
就能看到接口响应的结果了
接口 /user/query-user-infos 也差不多
三 、进阶使用
1. 添加请求头
有时候我们的接口是需要获取请求头信息的 ,这样的话就还需要在 swagger 配置中添加请求头的配置 。
@Bean public Docket docket() { // 设置请求头 List<Parameter> parameters = new ArrayList<>(); parameters.add(new ParameterBuilder() .name("token") // 字段名 .description("token") // 描述 .modelRef(new ModelRef("string")) // 数据类型 .parameterType("header") // 参数类型 .defaultValue("default value") // 默认值:可自己设置 .hidden(true) // 是否隐藏 .required(false) // 是否必须 .build()); // 创建一个 swagger 的 bean 实例 return new Docket(DocumentationType.SWAGGER_2) .groupName("mike") // 修改组名为 "mike" // 配置接口信息 .select() // 设置扫描接口 // 配置如何扫描接口 .apis(RequestHandlerSelectors .basePackage("com.duojiala.mikeboot.controller") // 扫描指定包下的接口 ,最为常用 ) .paths(PathSelectors .any() // 满足条件的路径,该断言总为true ) .build() // 添加请求头参数 .globalOperationParameters(parameters); }比如接口:
@GetMapping(value = "/get-token") @ApiOperation(value = "获取请求头中的token信息") public void getToken( @RequestHeader(value = "token",required = false) String token ) { // 直接获取 token 信息 System.out.println("token = " + token); // 通过代码获取 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (servletRequestAttributes != null) { HttpServletRequest request = servletRequestAttributes.getRequest(); String header = request.getHeader("token"); System.err.println("header = " + header); } }可以看到这个接口已经可以去设置请求头了 ,调用接口
后端也能获取到 。
四 、项目下载
以下是我这个项目所编写的代码
链接:百度网盘
提取码:na2o相关博客:
SpringBoot - 快速搭建创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!