SpringBoot 利用 Swagger2 调试 API

SpringBoot 利用 Swagger2 调试 API

文章目录

  !版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。


系统环境:

  • SpringBoot版本: 2.1.5
  • Swagger版本: 2.9.2
  • 示例Github地址:https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-swagger-example

一、背景:

       由于Spring Boot能够快速开发、便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API。而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。

       这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:

  • 由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳。
  • 随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象。

       为了解决上面这样的问题,本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到SpringBoot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。

二、Swagger简介:

       Swagger 既是一款接口的文档在线自动生成软件,也是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。Swagger 让部署管理和使用功能强大的API从未如此简单。

三、Springboot 项目集成 Swagger2

1、Maven 引入 Swagger2 依赖

新建 Maven 项目,往其 pom.xml 中引入 Springboot 及 Swagger 相关 Jar。

 1<?xml version="1.0" encoding="UTF-8"?>
 2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4    <modelVersion>4.0.0</modelVersion>
 5
 6    <groupId>club.mydlq</groupId>
 7    <artifactId>swagger-example-service</artifactId>
 8    <version>1.0.0</version>
 9    <name>swagger-example-service</name>
10    <description>springboot swagger api example service</description>
11
12    <properties>
13        <java.version>1.8</java.version>
14    </properties>
15
16    <dependencies>
17    	<!-- SpringBoot Web -->
18        <dependency>
19            <groupId>org.springframework.boot</groupId>
20            <artifactId>spring-boot-starter-web</artifactId>
21            <version>2.1.5.RELEASE</version>
22        </dependency>
23        <!-- 引入Lombok,方便开发 -->
24        <dependency>
25            <groupId>org.projectlombok</groupId>
26            <artifactId>lombok</artifactId>
27            <version>1.18.8</version>
28            <scope>provided</scope>
29        </dependency>
30        <!-- 引入Swagger相关依赖 -->
31        <dependency>
32            <groupId>io.springfox</groupId>
33            <artifactId>springfox-swagger2</artifactId>
34            <version>2.9.2</version>
35        </dependency>
36        <dependency>
37            <groupId>io.springfox</groupId>
38            <artifactId>springfox-swagger-ui</artifactId>
39            <version>2.9.2</version>
40        </dependency>
41    </dependencies>
42
43    <build>
44        <plugins>
45            <plugin>
46                <groupId>org.springframework.boot</groupId>
47                <artifactId>spring-boot-maven-plugin</artifactId>
48            </plugin>
49        </plugins>
50    </build>
51
52</project>

2、创建 Swagger 配置类

创建 Swagger 配置类,设置 Swagger 文档信息。

注意:配置中不要设置 “groupName” 参数,否则可能无法文档聚合。

 1import org.springframework.beans.factory.annotation.Value;
 2import org.springframework.context.annotation.Bean;
 3import org.springframework.context.annotation.Configuration;
 4import springfox.documentation.builders.ApiInfoBuilder;
 5import springfox.documentation.builders.PathSelectors;
 6import springfox.documentation.builders.RequestHandlerSelectors;
 7import springfox.documentation.service.ApiInfo;
 8import springfox.documentation.spi.DocumentationType;
 9import springfox.documentation.spring.web.plugins.Docket;
10
11@Configuration
12public class SwaggerConfig {
13
14    @Value("${swagger.enable}")
15    private boolean swaggerEnable;  // 读取配置文件中 swagger 开关参数的值
16
17    @Bean
18    public Docket createRestApi() {
19        return new Docket(DocumentationType.SWAGGER_2)
20                .enable(swaggerEnable)                  // 是否启用 Swagger
21                .apiInfo(apiInfo())
22                //.groupName("swagger-example-service") // 项目组名
23                .select()                               // 选择那些路径和api会生成document
24                .apis(RequestHandlerSelectors.any())    // 对所有api进行监控
25                .paths(PathSelectors.any())             // 对所有路径进行监控
26                .paths(Predicates.not(PathSelectors.regex("/error.*")))//错误路径不监控
27                .paths(Predicates.not(PathSelectors.regex("/actuator.*")))//actuator路径跳过
28                .build();
29    }
30
31    private ApiInfo apiInfo() {
32        return new ApiInfoBuilder()
33                .title("swagger-example-service")           // 文档标题
34                .description("This is a swagger project.")  // 文档描述
35                .version("1.0.0")                           // 文档版本
36                .build();
37    }
38
39}

3、配置文件中添加 swagger 开关参数

配置文件 application.yml 中添加 swagger.enable 配置参数,方便控制是否开启 swagger,一般在生产环境中我们会设置这个值为 false

1spring:
2  application:
3    name: swagger-example-service
4
5### Swagger开关配置参数
6swagger:
7  enable: true

4、创建 user 实体类

为了方便测试,这里创建一个 User 实体类,并且利用 Swagger 的 @ApiModelProperty 注解对实体类某个属性描述,方便Swagger文档中描述实体类中信息。

 1import io.swagger.annotations.ApiModelProperty;
 2import java.util.Date;
 3
 4public class User {
 5	// @ApiModelProperty:用于描述字段信息
 6    @ApiModelProperty(value = "姓名", required = true)
 7    private String name;
 8    @ApiModelProperty(value = "性别", required = true)
 9    private String sex;
10    @ApiModelProperty(value = "岁数", required = true)
11    private Integer age;
12    @ApiModelProperty(value = "生日")
13    private Date birthday;
14}

5、创建示例 Controller 接口

创建一个 Controller 类,且运用 Swagger 注解,将接口信息详细描述。

这里用了几个 Swagger 注解,分别为:

  • @Api:对整个 Controller 接口信息的描述
  • @ApiOperation:对某个接口信息进行描述
  • @ApiResponses:对某个反馈信息状态码进行描述
  • @ApiParam:对某个接口参数进行描述
 1import io.swagger.annotations.*;
 2import org.springframework.http.HttpHeaders;
 3import org.springframework.http.HttpStatus;
 4import org.springframework.http.ResponseEntity;
 5import org.springframework.util.MimeTypeUtils;
 6import org.springframework.web.bind.annotation.*;
 7
 8@RestController
 9@Api(tags = "Example Controller Document")
10public class ExampleController {
11
12    @GetMapping(value = "/example")
13    @ApiOperation(value = "获取示例信息", notes = "用 Get 请求发送,获取示例设置的字符串信息。")
14    @ApiResponses({
15            @ApiResponse(code = 200, message = "成功处理请求"),
16            @ApiResponse(code = 401, message = "没有权限访问该服务"),
17            @ApiResponse(code = 403, message = "权限不足无法访问该服务"),
18            @ApiResponse(code = 404, message = "未发现该微服务"),
19            @ApiResponse(code = 500, message = "服务器内部错误")
20    })
21    public String getExample(
22            @ApiParam(value = "输入一个 Key") @RequestParam(value = "key") String key,
23            @ApiParam(value = "输入一个 Value", required = true) @RequestParam(value = "value") String value) {
24        return "The value you enter is:" + key + ":" + value;
25    }
26
27    @PostMapping(value = "/example")
28    @ApiOperation(value = "发送示例信息", notes = "Post方法,发送示例信息")
29    @ApiResponses({
30            @ApiResponse(code = 200, message = "成功处理请求"),
31            @ApiResponse(code = 401, message = "没有权限访问该服务"),
32            @ApiResponse(code = 403, message = "权限不足无法访问该服务"),
33            @ApiResponse(code = 404, message = "未发现该微服务"),
34            @ApiResponse(code = 500, message = "服务器内部错误")
35    })
36    public ResponseEntity<User> postExample(@ApiParam(value = "用户信息") @RequestBody User user) {
37        // 设置状态码,且设置默认值为200
38        HttpStatus httpStatus = HttpStatus.OK;
39        return new ResponseEntity<User>(user,httpStatus);
40    }
41
42    @PutMapping(value = "/example")
43    @ApiResponses({
44            @ApiResponse(code = 200, message = "成功处理请求"),
45            @ApiResponse(code = 201, message = "被创建"),
46            @ApiResponse(code = 401, message = "没有权限访问该服务"),
47            @ApiResponse(code = 403, message = "权限不足无法访问该服务"),
48            @ApiResponse(code = 404, message = "未发现该微服务"),
49            @ApiResponse(code = 500, message = "服务器内部错误")
50    })
51    @ApiOperation(value = "修改示例信息", notes = "Put方法,修改示例信息")
52    public ResponseEntity<User> putExample(@ApiParam(value = "用户信息") @RequestBody User user) {
53        // 设置状态码,且设置默认值为200
54        HttpStatus httpStatus = HttpStatus.OK;
55        // 设置 Headers
56        HttpHeaders httpHeaders = new HttpHeaders();
57        httpHeaders.add(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE);
58        // 错误就发送 500 错误
59        if (user == null) {
60            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
61        }
62        return new ResponseEntity<User>(user, httpHeaders, httpStatus);
63    }
64
65    @DeleteMapping(value = "/example/{key}")
66    @ApiOperation(value = "删除示例信息", notes = "Delete方法,删除示例信息。")
67    @ApiResponses({
68            @ApiResponse(code = 200, message = "成功处理请求"),
69            @ApiResponse(code = 204, message = "成功处理请求,服务器无返回内容"),
70            @ApiResponse(code = 401, message = "没有权限访问该服务"),
71            @ApiResponse(code = 403, message = "权限不足无法访问该服务"),
72            @ApiResponse(code = 404, message = "未发现该微服务"),
73            @ApiResponse(code = 500, message = "服务器内部错误")
74    })
75    public void deleteExample(@ApiParam(value = "输入一个 Key") @PathVariable(value = "key") String key) {
76        System.out.println("delete info " + key);
77    }
78
79}

6、启动类加上注解 @EnableSwagger2

在启动类上加上 @EnableSwagger2 注解以开启 Swagger2。

 1import org.springframework.boot.SpringApplication;
 2import org.springframework.boot.autoconfigure.SpringBootApplication;
 3import springfox.documentation.swagger2.annotations.EnableSwagger2;
 4
 5@EnableSwagger2
 6@SpringBootApplication
 7public class Application {
 8
 9    public static void main(String[] args) {
10        SpringApplication.run(Application.class, args);
11    }
12
13}

7、访问 Swagger API

项目创建完成后,本地启动然后输入地址 http://localhost:8080/v2/api-docs,可以看见 Swagger API 接口返回的 JSON 信息。

 1{
 2    "swagger": "2.0",
 3    "info": {
 4        "description": "This is a swagger project.",
 5        "version": "1.0.0",
 6        "title": "swagger-example-service"
 7    },
 8    "host": "localhost:8080",
 9    "basePath": "/",
10    "tags": [
11        {
12            "name": "Example Controller Doc",
13            "description": "Example Controller"
14        },
15        {
16            "name": "basic-error-controller",
17            "description": "Basic Error Controller"
18        }
19    ],
20    "paths": {
21        "/error": {
22            "get": {
23                "tags": [
24                    "basic-error-controller"
25                ],
26                "summary": "error",
27                "operationId": "errorUsingGET",
28                "produces": [
29                    "*/*"
30                ],
31                "responses": {
32                    "200": {
33                        "description": "OK",
34                        "schema": {
35                            "type": "object",
36                            "additionalProperties": {
37                                "type": "object"
38                            }
39                        }
40                    },
41                    "401": {
42                        "description": "Unauthorized"
43                    },
44                    "403": {
45                        "description": "Forbidden"
46                    },
47                    "404": {
48                        "description": "Not Found"
49                    }
50                }
51......

8、访问 Swagger UI

Swagger 除了有 Json 形式的数据外,也有对 Json 数据页面化展示的 Swagger UI,在开始的时候 pom.xml 就已经引入该 Swagger UI 相关 Jar,所以这里我们将项目启动后,输入地址 http://localhost:8080/swagger-ui.html 就能访问到 Swagger 接口信息。


  !版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。