本文最后更新于 2024-02-22,文章内容可能已经过时。

1.前言

1.为什么需要接口文档

当前后端分离时,需要前后端共同定义接口,编写接口文档。所以,在项目开发过程中需要有一个统一的文件进行沟通交流开发。
对开发人员而言,项目的维护和人员更迭,都需要文档来作为记录。方便后期人员查看、维护。

2.apidoc

apidoc是一个轻量级的在线REST接口文档生成系统,可以根据其特定的规则的代码注释来生成静态网页。首先看下它生成的文档界面和风格。

支持
apidoc支持多种主流的编码语言,包括Java、C、C#、php和javascript。一般情况下,语言会有多种注释方法,例如就Java中有普通风格的多行注释和Javadoc风格的注释。apidoc并不支持所有的注释,譬如Java仅中支持Javadoc风格的注释。首先要说明的是,apidoc并不具备语义识别能力,它不会发现代码中是否有BUG,它仅仅通过文件后缀来判断语言类型。

3.有哪些常用的API自动生成文档工具

swagger 这款工具感觉是最常用的一款自动生成文档的工具。
附上官网地址:https://swagger.io/
apidoc。第一次见到这个api文档是在公司的cmdb的接口文档中看见,个人比较喜欢这种风格的。
附上github地址:https://github.com/apidoc/apidoc

2. apidoc 生成接口文档

2.1、使用前的准备工作

  1. 确认当前电脑安装了node.js。检测是否安装
node -v

出现提示则表示已安装
2. 安装apidoc
默认安装的是最新版本,但是0.29.0或以下版本是无法生成api_data.json文件的,导致无法导入 apifox。

npm install apidoc@0.29.0 -g
npm install apidoc -g
  1. 然后再测试一下apidoc是否安装成功
apidoc -v

出现提示则为,安装成功


2.2、.springboot项目中使用apidoc

  1. 首先准备一个空的springboot的项目。

  2. 在项目中新建package.json 文件
    位置:与 pom.xml 文件的级别相同

  3. package.json 文件的内容:

{
  "name": "测试api文档",
  "version": "0.1.0",
  "description": "这只是一个测试的页面",
  "title": "APIDOC 测试",
  "url" : "https://127.0.0.1:8080/",
}

2.3.方法接口前加上注释

@Autowired
    private MemberListService memberListService;
    /**
     * @api {get} /memberlist/:会员用户列表
     * @apiDescription  会员用户列表展示
     * @apiName memberlist
     * @apiParam {String} phoneNo 用户的电话
     * @apiParamExample {json} Request-Example:
     * {
     *     "phoneNo":"15713669254"
     * }
     * @apiGroup memberlist
     * @apiSampleRequest /memberlist
     */
 
    @RequestMapping("/memberlist")
    public List<UserCouponRecord> memberList(String phoneNo){
        return  memberListService.getMemberList(phoneNo);
    }

注意:在idea中,直接在插件商店中安装 apidoc 插件,然后在接口方法里边右击生成接口注释。

2.4.生成文档

apidoc 和 swagger不同的是,接口文档和代码文件都是分开的。一开始只需要专心编写接口代码,当代码编写完成时,只需在方法上加上指定的注释。(到这里,也就是我上述所描述的内容)。最终通过一段命令执行生成最终的html文档。
回归正题,在准备工作中我们已经安装了apidoc,然后我们通过apidoc命令生成文档:

apidoc -i apiTestDemo/ -o apidocDemo/
``
-i 指定源文件的目录,也就是项目的根目录。  
-o 指定输出 文档的目录,生成文档的地址。

3、使用 Swagger3 生成 API 接口文档

3.1、导入依赖

<dependency> 
  <groupId>io.springfox</groupId> 
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version> 
</dependency>

3.2、构建 Swagger 配置类

为了统一管理 Swagger,这里还是推荐给 Swagger3 添加一个配置类。当然这里也可以根据自己的需求,可要可不要,但总体来说还是建议配置。

另外,在之前集成 Swagger2 的文章中,忘记了给大家说一点。平常在工作中,Swagger 的使用仅限于在开发环境,而在生产环境中,我们是要将其移除的。这里为了灵活管理,推荐大家在项目配置文件 application.yml 中添加关于 Swagger 开关的配置,比如这里我添加的配置如下,true 则代表开启 Swagger,false 则表示关闭 Swagger。

swagger: enabled: true

配置完成之后,我们就需要在 Swagger 配置类中获取 Swagger 开关的值了,关于具体用法就可以看下边配置代码。

package com.imooc.bilibili.service.config;  
  
import io.swagger.models.auth.In;  
import org.springframework.beans.factory.annotation.Value;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import springfox.documentation.builders.RequestHandlerSelectors;  
import springfox.documentation.oas.annotations.EnableOpenApi;  
import springfox.documentation.service.*;  
import springfox.documentation.spi.DocumentationType;  
import springfox.documentation.spi.service.contexts.SecurityContext;  
import springfox.documentation.spring.web.plugins.Docket;  
  
import java.util.ArrayList;  
import java.util.Collections;  
import java.util.List;  
  
/**  
 * swagger API文档生成配置  
 * @author dreamChaser  
 * @date 2022-12-07  
 */@Configuration  
@EnableOpenApi  
public class SwaggerConfig {  
  
    @Value("${swagger.enabled}")  
    private Boolean swaggerEnabled;  
  
    @Bean("docket")  
    public Docket docket() {  
        return new Docket(DocumentationType.OAS_30)  
                .apiInfo(apiInfo())  
                // 是否开启swagger  
                .enable(swaggerEnabled)  
                .select()  
                // 过滤条件,扫描指定路径下的文件  
                .apis(RequestHandlerSelectors.basePackage("com.imooc.api"))  
                .build()  
                // 授权信息设置,必要的header token等认证信息  
                .securitySchemes(securitySchemes())  
                // 授权信息全局应用  
                .securityContexts(securityContexts());  
  
    }  
  
    /**  
     * 设置授权信息  
     */  
    private List<SecurityScheme> securitySchemes() {  
        ApiKey apiKey = new ApiKey("BASE_TOKEN", "token", In.HEADER.toValue());  
        return Collections.singletonList(apiKey);  
    }  
  
    /**  
     * 授权信息全局应用  
     */  
    private List<SecurityContext> securityContexts() {  
        return Collections.singletonList(  
                SecurityContext.builder()  
                        .securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN", new AuthorizationScope[]{new AuthorizationScope("global", "")})))  
                        .build()  
        );  
    }  
  
    private ApiInfo apiInfo() {  
        // 作者信息  
        Contact contact = new Contact("dreamChaser", "http://localhost:15505", "3368316006@qq.com");  
        return new ApiInfo(  
                "仿bilibili的Springboot后端项目",  
                "仿bilibili的Springboot后端项目接口文档展示",  
                "v1.0",  
                "http://localhost:15505",  
                contact,  
                "Apache 2.0",  
                "http://www.apache.org/licenses/LICENSE-2.0",  
                new ArrayList()  
        );  
    }  
  
}

3.3、swagger里边的接口注释解释:

  1. @ApiOperation("获取用户公钥")
    用在方法上,标注这个接口的作用,它会显示在index.html 的接口UI上。
  2. @ApiResponses({@ApiResponse(code = 200, message = "请求成功")})
    @ApiResponses 用于方法上,用于返回响应结果示例说明,其中可以包含多个@ApiResponse 用于声明每一个响应结果的具体信息,其中 code 是状态码,message请求的信息。
  3. @ApiImplicitParams 和 @ApiImplicitParam
    示例如下:
@ApiImplicitParams({@ApiImplicitParam(name = "user", value = "用户实体",required = true, paramType = "body", dataType = "user", example = "{phone:'', email:'', password:''}")})

@ApiImplicitParams 标注在方法上,用于声明一个接口里边需要用到的参数。其中里边可以包含多个 @ApiImplicitParam ,每一个@ApiImplicitParam中都声明每个参数的信息。
@ApiImplicitParam 标注一个参数的名称、值、是否必须,参数类型、数据类型、用例等信息。
@ApiImplicitParam 参数详解:

参数名称 参数作用 参数类型 参数种类 示例
name 参数名 String --- name="username"
value 参数的具体意义和作用 String --- value="用户名称"
required 参数是否必填 Boolean --- required=true
dataType 参数的数据类型 String 参数类型,默认String,其它值dataType="Integer" @ApiImplicitParams({@ApiImplicitParam(name = "user", value = "用户实体",required = true, paramType = "body", dataType = "user", example = "{phone:'', email:'', password:''}")})
paramType 查询参数类型: String path:以地址的形式提交数据;query:直接跟参数完成自动映射赋值,以?号拼接;body:以流的形式提交数据,仅支持post ;header:参数在request header里边提交;form:以form表单的形式提交,仅支持post提交
defaultValue 参数的默认值
dataTypeClass 数据类型 符合java语法的数据类型 在设置了 dataTypeClass 属性的情况下,会覆盖 dataType 属性。 推荐采用这个方式

有时候 @ApiImplicitParam 会和 @Requestody 注释发生冲突

  1. @Api(tags = {"用户相关服务"})
    用在类上,为这个类里边的所有接口方法贴上一个标签,注意的是需要用 tags 这个参数进行标注。
  2. @ApiModel():用于响应实体类上,用于说明实体作用:
    参数:
description="描述实体的作用"  
  1. @ApiModelProperty:用在属性上,描述实体类的属性
    参数:
value="用户名"  描述参数的意义
name="name"    参数的变量名
required=true     参数是否必选
  1. @ApiParam():用于方法的参数上进行参数说明,可以替换 @ApiImplicitParam 和 @ApiImplicitParams 表示对参数的要求和说明
name="参数名称"
value="参数的简要说明"
defaultValue="参数默认值"
required="true" 表示属性是否必填,默认为false

示例:

@ApiOperation("用户登录")
@PostMapping("find")
public JsonData login(
        @ApiParam(name = "name", value = "用户名", example = "mike") @RequestParam("name") String name,
        @ApiParam(name = "phone", value = "手机号", example = "110") @RequestParam("phone") String phone
        ) {
    //返回数据
    return JsonData.buildSuccess();
}