Still using Swagger2 to generate Restful API documentation? Come try Api2Doc!

This article introduces a very useful tool for automatically generating Restful API documentation - Api2Doc, which is based on SpringBoot, similar in principle to Swagger2, but simpler and easier to use than Swagger2.

This project has been put in github, if you need the source code, please click here

The latest version 1.0.2 has been released (on 2018-04-06)

The following features have been added:

  1. Support various methods decorated with @XxxMapping to generate documentation, including: @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping; (Previously only supported @RequestMapping.)
  2. Various forms of parameters are supported, including: @PathVariable, @RequestHeader, @CookieValue, @RequestPart; (previously only supported @RequestParam.) In the "Request Parameters" table on the documentation page, add the "Parameter Form" column.
  3. Documentation page, "URL example" changed to "Request example", the request example is in curl command format and supports all HTTP methods, (previously it was URL format and only supported GET method).

Fixed the following bugs:

  1. Fixed a bug that was not displayed in the documentation when the return type was a simple type.

Welcome to use!

content

  • Background of the project
  • Introduction to Api2Doc
  • Introduce Api2Doc dependency
  • Enable Api2Doc service
  • Add documentation annotations to the Controller class
  • @Api2Doc annotation details
  • @ApiComment annotation details
  • @ApiError annotation details
  • Sort document menu items
  • Supplemental custom documentation
  • Welcome page for custom documentation
  • Customize the title and icon of the document
  • Close the Api2Doc service

Background of the project

In the development process of Internet/mobile Internet software, most R&D teams have a very clear division of front-end and back-end work. Back-end engineers are responsible for the development of server-side systems, generally providing HTTP/HTTPS Restful API interfaces, while front-end engineers are responsible for Android and iOS. , H5 page development, you need to call the Restful API interface.

This requires a set of Restful API documents to help the two parties communicate on the API interface and reach a consensus. In general, the work of writing documentation will fall on the backend engineers, after all, they provide the API.

But the problem is that writing Restful API documentation is a tedious, time-consuming, and labor-intensive chore that doesn’t help improve technical capabilities, especially in projects with rapid iteration and frequent revisions, where code changes need to be synchronously changed. , Any mistakes or omissions may result in inconsistencies in the front-end and back-end implementations, resulting in the discovery of bugs during joint debugging. The back-end engineers will eventually have to bear the blame (baby is bitter...).

Therefore, there are some open source projects in the industry that automatically generate Restful API documents according to the code . The best combination with Spring Boot is Swagger2. Swagger2 automatically generates API documents by reading the annotation information in the Controller code, which can save a lot of manual work. Effort to write documentation.

The author of this project also used Swagger2 before, but found that Swagger2 also has many places that are uncomfortable:

First, the annotations of Swagger2 are very bloated . Let's take a look at this code:


@RestController
@RequestMapping(value = "/user3")
public class UserController2Swagger2 {

    @ApiOperation(value = "获取指定id用户详细信息",
            notes = "根据user的id来获取用户详细信息",
            httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName", value = "用户名",
                    paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name = "password", value = "用户密码",
                    paramType = "query", required = true, dataType = "String")
    })
    @RequestMapping(name = "用户注册", value = "/regist",
            method = RequestMethod.GET)
    public UserInfo regist(@RequestParam("userName") String userName,
                           @RequestParam("password") String password) {
        return new UserInfo();
    }
}

@ApiOperation and @ApiImplicitParam are annotations provided by Swagger2 to define API information. In fact, the API method itself contains a lot of information, such as HTTP Method, parameter name, parameter type, etc. For example, in @ApiImplicitParam, except the value attribute is useful, other descriptions are repeated.

Second, the page layout of Swagger2 is not very friendly, it is a vertical arrangement, which is not conducive to the display of information. And looking at the API details, it is necessary to expand one by one, and there are also testing functions in the middle. Anyway, it is not easy to read as a document; as for a testing tool... Now there are many professional testing tools, and testers do not seem to choose it.

Third, Swagger2 still has a lot of details that have not been done well, such as looking at this picture:

swgger2-1.png

The API in the red box actually corresponds to the same method. The reason why there are so many is because the method is not specified when writing this method:

@RestController
@RequestMapping(value = "/user2")
public class UserController2Swagger2 {
    
    @RequestMapping(value = "/do_something")
    public void doSomethingRequiredLogon() {
    }
    
    // 其它方法,这里省略...
}

(When no method is specified, Spring Boot will make this interface support all methods by default)

Therefore, considering that it is better to spend some time making a better "automated documentation system" than to endure the various discomforts of Swagger2 for a long time, this project was born: Api2Doc .

Introduction to Api2Doc

Api2Doc focuses on the automatic generation of Restful API documents. Its principle is similar to that of Swagger2. It generates documents by analyzing the information in the Controller through reflection, but it is much better than Swagger2.

The biggest difference is: Api2Doc requires a lot less code than Swagger2 .

For example, the code using Swagger2 looks like this:


@RestController
@RequestMapping(value = "/user")
public class UserController {

    @ApiOperation(value = "添加用户", httpMethod = "POST",
            notes = "向用户组中添加用户,可以指定用户的类型")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "group", value = "用户组名",
                    paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name = "name", value = "用户名",
                    paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name = "type", value = "用户类型",
                                paramType = "query", required = true, dataType = "String")
    })
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public User addUser(String group, String name, String type) {
        return null; // TODO:  还未实现。
    }
}

Let's take a look at the code decorated with Api2Doc annotations:

@Api2Doc(id = "users")
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo2")
public class UserController2 {

    @ApiComment("向用户组中添加用户,可以指定用户的类型")
    @RequestMapping(name = "添加用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(String group, String name, String type) {
        return null; // TODO:  还未实现。
    }
    
    // 其它方法,这里省略...
}

See, Api2Doc only needs to add a very small amount of code such as @Api2Doc @ApiComment annotations to methods, but the documentation it generates can be unambiguous, as shown in the following figure:

api2doc-2-1.png api2doc-2-2.png

Some friends may find it very strange: the descriptions and example values ​​on the documentation page are not written in the code. Where do these come from?

This involves the core design concept of Api2Doc, that is: it automatically collects the information needed to generate documents through intelligent analysis as much as possible, so that users can write less code .

It's a bit abstract, let's answer this question head-on, please note that there is an annotation on this class:

@ApiComment(seeClass = User.class)

It means: When encountering no description information on the API method, please refer to the description information defined in the User class.

Here is the code for the User class:

public class User {

    @ApiComment(value = "用户id", sample = "123")
    private Long id;

    @ApiComment(value = "用户名", sample = "terran4j")
    private String name;

    @ApiComment(value = "账号密码", sample = "sdfi23skvs")
    private String password;

    @ApiComment(value = "用户所在的组", sample = "研发组")
    private String group;

    @ApiComment(value = "用户类型", sample = "admin")
    private UserType type;

    @ApiComment(value = "是否已删除", sample = "true")
    @RestPackIgnore
    private Boolean deleted;

    @ApiComment(value = "创建时间\n也是注册时间。")
    private Date createTime;

    // 省略  getter / setter 方法。
}

Do you understand? If the parameters in the API method have the same name as the attributes of the User class, they will be automatically filled in with the @ApiComment description information of the class attributes.

In fact, this is also in line with the actual business logic. Because in most projects, some fields will be used in multiple entity classes and API methods, there is no need to repeat the description information, as long as one place is defined, and then referenced in other places.

Of course, this is just one of the features that Api2Doc is more useful than Swagger2, and there are many more useful features than Swagger2.

Next, we will explain its usage in a comprehensive way, hoping to help developers get rid of the bitter sea of ​​documentation writing.

Introduce Api2Doc dependency

If it is maven, please add the dependency in pom.xml as follows:

        <dependency>
            <groupId>com.github.terran4j</groupId>
            <artifactId>terran4j-commons-api2doc</artifactId>
            <version>${api2doc.version}</version>
        </dependency>

If it is gradle, please add dependencies in build.gradle as follows:

compile "com.github.terran4j:terran4j-commons-api2doc:${api2doc.version}"

${api2doc.version} The latest stable version, please refer to here

Enable Api2Doc service

The sample code for this tutorial is in com.terran4j.demo.api2doc in the src/test/java directory, and you can also get it here .

First, we need to add the @EnableApi2Doc annotation to the class annotated with @SpringBootApplication to enable the Api2Doc service, as shown in the following code:

package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.config.EnableApi2Doc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//  文档访问地址: http://localhost:8080/api2doc/home.html
@EnableApi2Doc
@SpringBootApplication
public class Api2DocDemoApp {

    public static void main(String[] args) {
        SpringApplication.run(Api2DocDemoApp.class, args);
    }

}

Add documentation annotations to the Controller class

Then we add the @Api2Doc annotation to the RestController class, and add the @ApiComment annotation where documentation is required, as shown below:

package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@Api2Doc(id = "demo1", name = "用户接口1")
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo1")
public class UserController1 {

    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(String group, String name,
                        @ApiComment("用户类型") UserType type) {
        return null; // TODO:  还未实现。
    }
}

The return type of this method of the User class is defined as:

public class User {

    @ApiComment(value = "用户id", sample = "123")
    private Long id;

    @ApiComment(value = "用户名", sample = "terran4j")
    private String name;

    @ApiComment(value = "账号密码", sample = "sdfi23skvs")
    private String password;

    @ApiComment(value = "用户所在的组", sample = "研发组")
    private String group;

    @ApiComment(value = "用户类型", sample = "admin")
    private UserType type;

    @ApiComment(value = "是否已删除", sample = "true")
    @RestPackIgnore
    private Boolean deleted;

    @ApiComment(value = "创建时间\n也是注册时间。")
    private Date createTime;

    // 省略  getter / setter 方法。
}

And the type of the type attribute, that is, the definition of the UserType class is:

package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.ApiComment;

public enum UserType {

    @ApiComment("管理员")
    admin,

    @ApiComment("普通用户")
    user
}

After writing the code, we run the main function to visit the main page of Api2Doc:

http://localhost:8080/api2doc/home.html

The documentation page is as follows:

api2doc-3-1.png api2doc-3-2.png

It shows that the Api2Doc service works, it's that simple!

@Api2Doc annotation details

Api2Doc has a total of 3 annotations: @Api2Doc, @ApiComment and @ApiError.

@Api2Doc is used to control the generation of documentation.

@Api2Doc is decorated on a class, indicating that this class will participate in the document generation process. The Api2Doc service will scan all Controller classes in the Spring container. Only classes with @Api2Doc on the class will generate documents. One class corresponds to the document. The first-level menu item on the left side of the page, the name attribute of @Api2Doc represents the name of this menu item.

@Api2Doc can also be modified on methods, but @Api2Doc on methods can usually be omitted. Api2Doc service will scan all methods with @RequestMapping in this class, and each such method corresponds to the secondary menu on the left side of the document page Item, the name of the menu item takes the name attribute of @RequestMapping, of course, you can still use the name attribute of @Api2Doc to redefine the method.

@ApiComment annotation details

@ApiComment is used to describe the API, it can be decorated in many places:

  • Modified on the class, it means to describe this group of API interfaces;
  • Modified on the method, it means to describe the API interface;
  • Modified on the parameters, it means to describe the request parameters of this API interface;
  • Modified on the attribute of the return type, indicating the description of the return field of this API interface;
  • Modified on the enumeration item, indicating the description of the enumeration item;

If the description of the attribute or parameter field with the same name and meaning has been defined elsewhere, the seeClass attribute of @ApiComment can be used to indicate the description information on the field with the same name of the specified class, so as in this code:

@Api2Doc(id = "demo1", name = "用户接口1")
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo1")
public class UserController1 {

    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(String group, String name, UserType type) {
        return null; // TODO:  还未实现。
    }
}

Although the three parameters of group, name and type are not described with @ApiComment, since there is @ApiComment(seeClass = User.class) on this class, as long as the User class has group, name, type fields and @ApiComment description That's it.

@ApiError annotation details

@ApiError is used to define error codes. Some API methods will generate errors when executing business logic. After an error occurs, the error code will be included in the returned message to facilitate further processing by the client according to the error code. The description of the error code is shown above.

The following code demonstrates the usage of @ApiError:

@Api2Doc(id = "demo", name = "用户接口", order = 0)
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/src/test/resources/demo")
public class UserController {
    
    @Api2Doc(order = 50)
    @ApiComment("根据用户id,删除指定的用户")
    @ApiError(value = "user.not.found", comment = "此用户不存在!")
    @ApiError(value = "admin.cant.delete", comment = "不允许删除管理员用户!")
    @RequestMapping(name = "删除指定用户",
            value = "/user/{id}", method = RequestMethod.DELETE)
    public void delete(@PathVariable("id") Long id) {
    }
}

The value attribute of @ApiError represents the error code, and comment represents the description of the error code.

The error code information will be displayed at the end of the document, and the effect is as follows:

api2doc-7.png

Sort document menu items

We can use the order property in @Api2Doc to order the menu items, the smaller the order value, the higher the menu item is, for example, for this code:

package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Api2Doc(id = "demo2", name = "用户接口2", order = 1)
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo2")
public class UserController2 {

    @Api2Doc(order = 10)
    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(
            @ApiComment("用户组名称") String group,
            @ApiComment("用户名称") String name,
            @ApiComment("用户类型") UserType type) {
        return null; // TODO:  还未实现。
    }

    @Api2Doc(order = 20)
    @ApiComment("根据用户id,查询此用户的信息")
    @RequestMapping(name = "查询单个用户",
            value = "/user/{id}", method = RequestMethod.GET)
    public User getUser(@PathVariable("id") Long id) {
        return null; // TODO:  还未实现。
    }

    @Api2Doc(order = 30)
    @ApiComment("查询所有用户,按注册时间进行排序。")
    @RequestMapping(name = "查询用户列表",
            value = "/users", method = RequestMethod.GET)
    public List<User> getUsers() {
        return null; // TODO:  还未实现。
    }

    @Api2Doc(order = 40)
    @ApiComment("根据指定的组名称,查询该组中的所有用户信息。")
    @RequestMapping(name = "查询用户组",
            value = "/group/{group}", method = RequestMethod.GET)
    public UserGroup getGroup(@PathVariable("group") String group) {
        return null; // TODO:  还未实现。
    }
}

The result displayed is:

api2doc-3.png

@Api2Doc on the class can also sort the first-level menu, the rules are the same, and I will not demonstrate it here.

Supplemental custom documentation

Sometimes it seems that the automatically generated API documentation is not perfect. Maybe we want to add something else, such as: background introduction to the project, technical architecture description, etc. How to do this?

Api2Doc allows manual documentation with md syntax and integration into automatically generated API documentation as follows:

First, define the id attribute in @Api2Doc on the class, such as the following class:

package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api2Doc(id = "demo3", name = "用户接口3")
@RestController
@RequestMapping(value = "/api2doc/demo3")
public class UserController3 {

    @Api2Doc(order = 10)
    @RequestMapping(name = "接口1", value = "/m1")
    public void m1() {
    }

    @Api2Doc(order = 20)
    @RequestMapping(name = "接口2", value = "/m2")
    public void m2() {
    }
}

@Api2Doc(id = "demo3", name = "User Interface 3") means: the id of the corresponding first-level menu "User Interface 3" is demo3.

Then, we create a directory api2doc/demo3 in src/main/resources. The former api2doc is fixed, and the latter demo3 indicates that the documents in this directory are added to the first-level document menu with the id of demo3.

Then we write the md format document in the api2doc/demo3 directory, as shown in the following figure:

api2doc-4.png

The format of the file name is ${order}-${document name}.md, that is, the number in front of the - sign indicates the order of the document, which is the same as the order attribute in @Api2Doc, and the - sign is followed by the document name, also It is the name of the secondary menu.

Therefore, the final document will look like this:

api2doc-5.png

Look, the hand-written supplemental documentation and the automatically generated API documentation, sorted by order, seem to have no inconsistencies.

Welcome page for custom documentation

Every time you visit the documentation page http://localhost:8080/api2doc/home.html , the content in the middle is a very simple sentence:

欢迎使用 Api2Doc !

This may seem a little bad, but that's okay, we can write our own welcome page.

The method is very simple, in the api2doc directory of the src/main/resources directory, create a file named welcome.md (the name is fixed), and then write the content in md syntax.

Configure the title and icon of the document

The document's title and icon can be configured in application.yml as follows:

api2doc:
  title: Api2Doc示例项目——接口文档
  icon: https://spring.io/img/homepage/icon-spring-framework.svg

The icon is a full path URL, or a relative path URL of this site.

The display effect after configuration is:

api2doc-6.png

Close the Api2Doc service

You configure the api2doc.enabled property in application.yml to enable or disable the Api2Doc service, such as:

# 本地环境
api2doc:
  title: Api2Doc示例项目——接口文档
  icon: https://spring.io/img/homepage/icon-spring-framework.svg

---
# 线上环境
spring:
  profiles: online

api2doc:
  enabled: false

api2doc.enabled is false to close the Api2Doc service, not written or true to enable.

Since the Api2Doc service has no access permission check, it is recommended that you enable the Api2Doc service in a trusted network environment (such as a company intranet).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324536140&siteId=291194637