SpringBoot无侵入集成OpenAPI

前言

SpringBoot 接口文档中, 大多是集成 swagger 文档来实现, 代码侵入性比较高, 下边是基于标准的 Javadoc 实现的接口文档, 数据结构基于 OpenAPI, UI基于 swagger-ui

springdoc

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.idea360</groupId>
<artifactId>spring-restdoc</artifactId>
<version>0.0.1</version>

<name>spring-restdoc</name>
<description>spring-restdoc</description>
<url>https://idea360.cn</url>

<developers>
<developer>
<name>cuishiying</name>
<email>idea360@foxmail.com</email>
</developer>
</developers>

<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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>
<dependency>
<groupId>com.github.therapi</groupId>
<artifactId>therapi-runtime-javadoc-scribe</artifactId>
<version>0.15.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>cn.idea360.restdoc.SpringRestdocApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>

application.properties

1
2
3
4
5
# 应用服务 WEB 访问端口
server.port=8080

logging.level.root=info
logging.level.org.springdoc=debug

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package cn.idea360.restdoc.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;

/**
* @author 公众号:当我遇上你
*/
public class User {

/**
* 用户名,长度在1到50之间
*/
@JsonProperty("username")
private String username;

/**
* 用户的年龄,必须大于0
*/
@JsonProperty("age")
private int age;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package cn.idea360.restdoc.web;

import cn.idea360.restdoc.model.User;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
* 测试注释提取
*
* @author cuishiying
*/
@RequestMapping("/doc")
@RestController
public class DocController {

/**
* 用户详情
*
* @param username 用户信息
* @return 用户信息
*/
@CrossOrigin
@RequestMapping(value = "/info", method = {RequestMethod.GET, RequestMethod.POST})
public Object info(@RequestParam String username, HttpServletRequest request) {
System.out.println(username);
System.out.println(request.getHeader("host"));
Map<String, Object> map = new HashMap<>();
map.put("username", username);
Map<String, Object> c = new HashMap<>();
c.put("k1", "v1");
map.put("detail", c);
return map;
}

/**
* 新增用户
* @param user 用户信息
* @param enable 启用
* @return 用户信息
*/
@PostMapping("/add")
public Object add(@RequestBody User user, @RequestParam Boolean enable) {
return user;
}
}

测试

访问 http://localhost:8080/swagger-ui.html 即可看到接口文档

smart-doc

pom.xml 配置插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>2.4.8</version>
<configuration>
<configFile>./src/main/resources/smart-doc.json</configFile>
<projectName>${project.description}</projectName>
</configuration>
<executions>
<execution>
<!--如果不需要在执行编译时启动smart-doc,则将phase注释掉-->
<phase>compile</phase>
<goals>
<!--smart-doc提供了html、openapi、markdown等goal,可按需配置-->
<goal>html</goal>
</goals>
</execution>
</executions>
</plugin>

./src/main/resources/smart-doc.json 增加配置文件

1
2
3
{
"outPath": "E:\\source\\spring-restdoc\\src\\main\\resources\\doc"
}

生成接口文档

1
mvn -D"file.encoding"=UTF-8 smart-doc:html