大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
以下是正文!
接口文档是一个软件系统的重要组成部分,它描述了系统中所有可供外部应用程序使用的接口。简单来说,接口文档就是用来帮助开发者开发和对接系统的指南。
在软件开发过程中,不同的系统之间需要进行数据交互和信息传递,这就要求系统必须提供一些公开的接口。
接口文档的展现形式也很多如:Swagger、Word、PDF、Postman、开放平台文档等。不同的展现形式提供了不同的载体来呈现接口文档,但是最终的关键还是内容本身。
一份清晰、详细、准确的接口文档是开发团队是否能够准确理解和使用系统接口的关键。
总之,一份好的接口文档应该覆盖所有的接口使用场景,详尽而不冗长,方便开发者快速查找和使用。而对于不同的展现形式,开发者需要根据项目的需求和开发流程选择最适合的展现方式,从而提高开发效率和工作质量。
Swagger是一套用于设计、构建、记录和使用RESTful API的工具集,可以自动生成API文档,并提供交互式UI,能够大大提高开发效率和协作效率。它支持多种编程语言和框架,能够生成多种展现形式,如Swagger UI、Swagger Editor和Swagger Codegen等工具。同时,Swagger还提供强大的API管理功能,包括API监控、调试、测试和安全性等,能够帮助开发者更好地管理和维护API。
访问地址:http://localhost:8080/swagger-ui.html#/
访问地址:http://localhost:8080/doc.html
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.6.RELEASEversion>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>springboot-swaggerartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springboot-swaggername>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.8.0version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.7.0version>
dependency>
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>swagger-bootstrap-uiartifactId>
<version>1.9.2version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
这里需要注意一个版本对应的问题,如果使用了高版本的SpringBoot框架,低版本的Swagger,
会出现如下报错:
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
这是因为:因为Springfox 使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher。
以下几个版本是兼容的
SpringBoot版本 | Swagger版本 |
---|---|
2.5.6 | 2.9.2 |
SpringBoot版本 | Swagger版本 |
---|---|
2.6.5 | 3.0.0 |
package com.example.springbootswagger.config;
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;
@Configuration
public class SwaggerConfig {
@Bean
public Docket createDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(true)
.groupName("我的接口文档")
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.springbootswagger.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//标题
.title("凤求凰")
//作者、链接、邮箱等
.contact(new Contact(
"司马相如",
"https://hanyu.baidu.com/shici/detail?pid=ecb82707a98c418995c5a0c50b770af0&from=kg0",
""
))
//描述
.description("有一美人兮,见之不忘。\n" +
"一日不见兮,思之如狂。\n" +
"凤飞翱翔兮,四海求凰。\n" +
"无奈佳人兮,不在东墙。\n" +
"将琴代语兮,聊写衷肠。\n" +
"何日见许兮,慰我彷徨。\n" +
"愿言配德兮,携手相将。\n" +
"不得於飞兮,使我沦亡。\n" +
"凤兮凤兮归故乡,遨游四海求其凰。\n" +
"时未遇兮无所将,何悟今兮升斯堂!\n" +
"有艳淑女在闺房,室迩人遐毒我肠。\n" +
"何缘交颈为鸳鸯,胡颉颃兮共翱翔!\n" +
"凰兮凰兮从我栖,得托孳尾永为妃。\n" +
"交情通意心和谐,中夜相从知者谁?\n" +
"双翼俱起翻高飞,无感我思使余悲。")
//更新说明
.termsOfServiceUrl("这是第一版")
//版本号
.version("1.0.0").build();
}
}
package com.example.springbootswagger.controller;
import com.example.springbootswagger.req.AddReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@RestController
@Api(tags = {"测试接口类"}, hidden = true)
@RequestMapping("/test")
public class TestController {
@ApiOperation("GET请求,查询方法")
@GetMapping("/query")
public String query() {
return "查询成功";
}
@ApiImplicitParams({
@ApiImplicitParam(name = "param1", value = "参数1", required = true),
@ApiImplicitParam(name = "param2", value = "参数2", required = false)
})
@ApiOperation("PUT请求,添加方法")
@PutMapping("/update")
public String update(
@RequestParam(required = true) String param1,
@RequestParam(required = false) String param2) {
return "更新成功";
}
@ApiOperation("POST请求,修改方法")
@PostMapping("/add")
public String add(@RequestBody AddReq addReq) {
return "添加成功";
}
@ApiImplicitParam(name = "id", value = "用户ID", required = true)
@ApiOperation("DELETE请求,删除方法")
@DeleteMapping("/del")
public String del(Long id) {
return "删除成功";
}
}
package com.example.springbootswagger.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("添加参数")
public class AddReq {
@ApiModelProperty("名字")
private String name;
@ApiModelProperty("密码")
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.example.springbootswagger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableSwagger2
@SpringBootApplication
public class SpringbootSwaggerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootSwaggerApplication.class, args);
}
}
为什么还需要文件类接口文档呢?首先,Swagger文档存在兼容性问题,有些系统不支持,这时候文件类接口文档就能派上用场。其次,Swagger文档不能离线使用,如果网络不稳定或者没有网络连接,就无法查看接口文档,而文件类接口文档可以在任何时候离线浏览。
之前我有写过一篇关于系统间交互的文章:多方合作时,系统间的交互是怎么做的?,系统间的接口交互一般提供的都是文件类文档,像Word、PDF这种。
在实际开发中,我发现不同的开发团队提供的接口文档格式存在很大的差异。有些团队提供的文档非常详细,甚至会给出调用示例代码,而有些团队则只提供了非常简单的接口说明,甚至连参数说明都没有。这种情况下,如果接口文档很详细,我可以很快地进行调试和联调,但是如果文档不够详细,很容易遇到各种坑(一言难尽的坑),必须要去找对方的开发。
我觉得一份好的接口文档应该包括以下内容:
接口概述:包括接口的名称、描述、版本号等信息,让开发者了解接口的基本信息。
接口参数:包括请求参数和返回参数,需要详细说明每个参数的名称、类型、描述、默认值、是否必须等信息,让开发者清晰地知道每个参数的含义和使用方法。
接口使用示例:提供一个或多个请求和相应的示例,让开发者更好地理解接口的使用方法和返回结果。
接口错误码:列出所有可能出现的错误码和相应的错误信息,让开发者了解如何识别和处理接口返回的错误。
接口限制和安全性:包括接口的访问限制、频次限制、安全性等信息,让开发者知道如何正确地使用接口。
以下是我认为样式较为简洁和清晰的 Word 模板接口文档示例(最下方是模板下载链接):
模板下载链接