Swagger2配合YAPI自动生成文档

Easter79
• 阅读 536

前置说明

编写API文档,可能是最为枯燥无味的工作了,大部分程序猿都不太愿意干这个活,但是大部分人还是苦于没有找到更好的解决方案来处理这个问题,或者之前的代码不允许去做类似的工作,只能老老实实自己去写API。

但是,作为新项目启动,必须提前考虑这个问题,解放程序员双手,让他们撸更多业务代码,而不是整天纠结文档方面的工作。

如果要做到这些,那必须有一个前置条件,那就是你的代码足够规范,实体类命名、注释完备、数据库描述完善。

数据库结构

数据表结构必须规范、字段描述、表描述、主键策略、非空定义

CREATE TABLE `t_website` (
  `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '网站ID',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '网站名称',
  `logo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '网站LOGO',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='网站信息';

出入参实体

如下,是一个比较规范的入参样本,使用ApiModelProperty描述好了字段的基本信息、是否非空

/**
* <p>
* 语言设置请求类
* </p>
*
* @author 聪明笨狗
* @since 2019-04-13 10:47
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="网站信息", description="网站信息")
public class WebsiteReqDTO implements Serializable {

    private static final long serialVersionUID = 1L;
    
    
    @ApiModelProperty(value = "网站ID", required=true)
    private String id;
    
    @ApiModelProperty(value = "网站名称", required=true)
    private String name;
    
    @ApiModelProperty(value = "网站LOGO")
    private String logo;
    
}

控制器类

如下,是一个比较规范的Controller控制器类

/**
* <p>
* 语言设置控制器
* </p>
*
* @author 聪明笨狗
* @since 2019-04-13 10:47
*/
@Api(tags={"网站信息"})
@Controller
@RequestMapping("/admin/website")
public class WebsiteController extends BaseController {

    @Autowired
    private WebsiteService baseService;

    /**
    * 添加
    * @param reqDTO
    * @return
    */
    @ResponseBody
    @ApiOperation(value = "添加")
    @RequestMapping(value = "/add", method = { RequestMethod.POST})
    public ApiRest<WebsiteRespDTO> add(@RequestBody WebsiteReqDTO reqDTO) {
        //保存数据并返回数据
    }

    /**
    * 根据ID修改
    * @param reqDTO
    * @return
    */
    @ResponseBody
    @ApiOperation(value = "根据ID修改")
    @RequestMapping(value = "/update", method = { RequestMethod.POST})
    public ApiRest edit(@RequestBody WebsiteReqDTO reqDTO) {
        //保存数据并返回数据
    }

    /**
    * 批量删除
    * @param reqDTO
    * @return
    */
    @ResponseBody
    @ApiOperation(value = "批量删除")
    @RequestMapping(value = "/delete", method = { RequestMethod.POST})
    public ApiRest edit(@RequestBody DeleteReqDTO reqDTO) {
        //删除数据并返回结果
    }

    /**
    * 查找详情
    * @param reqDTO
    * @return
    */
    @ResponseBody
    @ApiOperation(value = "查找详情")
    @RequestMapping(value = "/detail", method = { RequestMethod.POST})
    public ApiRest<WebsiteRespDTO> find(@RequestBody FindReqDTO reqDTO) {
       //返回详情数据
    }
    
}

Swagger配置

Swagger2.java

/**
 * Swagger2配置
 */
@Configuration
@EnableSwagger2
@ConfigurationProperties(prefix = "swagger")
public class Swagger2 {

    private static final String BASE_PACKAGE = "com.mycompany";
    @Value("${swagger.enable}")
    private boolean enableSwagger;

    @Bean
    public Docket helloDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                //用于分组功能,也可以不配置
                .groupName("admin")
                //注册整体api信息
                .apiInfo(apiInfo())
                //swagger功能是否启用,可以通过配置设置,也可以先写死
                .enable(enableSwagger)
                .select()
                //指定扫描的包
                .apis(RequestHandlerSelectors.basePackage(BASE_PACKAGE))
                //设置此组只匹配admin/**的请求
                .paths(PathSelectors.ant("/admin/**"))
                .build();
    }


    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("后台管理项目")
                .description("通用的CRUD")
                .contact(new Contact("Van", "", ""))
                .version("1.0.0")
                .build();
    }

pom.xml

<!-- 引入swagger2包 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<!-- 引入自带UI,可选-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

以上配置好以后就OK了,项目启动以后,通过以下URL可以访问到API文档的JSON数据:

带分组的:
http://localhost:8080/v2/api-docs?group=admin
不带分组的:
http://localhost:8080/v2/api-docs

访问URL返回以下JSON:

{
    "swagger": "2.0",
    "info": {
        "description": "通用的CRUD",
        "version": "1.0.0",
        "title": "后台管理项目",
        "contact": {
            "name": "Van"
        }
    },
    "host": "127.0.0.1:8080",
    "basePath": "/",
    "tags": [{
        "name": "网站信息",
        "description": "WebsiteController"
    }],
    "paths": {
        "/admin/website/add": {
            "post": {
                "tags": ["网站信息"],
                "summary": "添加",
                "operationId": "addUsingPOST",
                "consumes": ["application/json"],
                "produces": ["*/*"],
                "parameters": [{
                    "in": "body",
                    "name": "reqDTO",
                    "description": "reqDTO",
                    "required": true,
                    "schema": {
                        "$ref": "#/definitions/网站信息"
                    }
                }],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/接口响应"
                        }
                    },
                    "201": {
                        "description": "Created"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "403": {
                        "description": "Forbidden"
                    },
                    "404": {
                        "description": "Not Found"
                    }
                },
                "deprecated": false
            }
        },
        "/admin/website/delete": {
            "post": {
                "tags": ["网站信息"],
                "summary": "批量删除",
                "operationId": "editUsingPOST",
                "consumes": ["application/json"],
                "produces": ["*/*"],
                "parameters": [{
                    "in": "body",
                    "name": "reqDTO",
                    "description": "reqDTO",
                    "required": true,
                    "schema": {
                        "$ref": "#/definitions/删除参数"
                    }
                }],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/接口响应"
                        }
                    },
                    "201": {
                        "description": "Created"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "403": {
                        "description": "Forbidden"
                    },
                    "404": {
                        "description": "Not Found"
                    }
                },
                "deprecated": false
            }
        },
        "/admin/website/detail": {
            "post": {
                "tags": ["网站信息"],
                "summary": "查找详情",
                "operationId": "findUsingPOST",
                "consumes": ["application/json"],
                "produces": ["*/*"],
                "parameters": [{
                    "in": "body",
                    "name": "reqDTO",
                    "description": "reqDTO",
                    "required": true,
                    "schema": {
                        "$ref": "#/definitions/查询参数"
                    }
                }],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/接口响应«网站信息»"
                        }
                    },
                    "201": {
                        "description": "Created"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "403": {
                        "description": "Forbidden"
                    },
                    "404": {
                        "description": "Not Found"
                    }
                },
                "deprecated": false
            }
        },

        "/admin/website/update": {
            "post": {
                "tags": ["网站信息"],
                "summary": "根据ID修改",
                "operationId": "editUsingPOST_1",
                "consumes": ["application/json"],
                "produces": ["*/*"],
                "parameters": [{
                    "in": "body",
                    "name": "reqDTO",
                    "description": "reqDTO",
                    "required": true,
                    "schema": {
                        "$ref": "#/definitions/网站信息"
                    }
                }],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/接口响应"
                        }
                    },
                    "201": {
                        "description": "Created"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "403": {
                        "description": "Forbidden"
                    },
                    "404": {
                        "description": "Not Found"
                    }
                },
                "deprecated": false
            }
        }
    },
    "definitions": {


        "删除参数": {
            "type": "object",
            "required": ["ids"],
            "properties": {
                "ids": {
                    "type": "array",
                    "description": "要删除的ID列表",
                    "items": {
                        "type": "string"
                    }
                }
            },
            "title": "删除参数",
            "description": "删除参数"
        },
        "接口响应": {
            "type": "object",
            "required": ["code"],
            "properties": {
                "code": {
                    "type": "integer",
                    "format": "int32",
                    "description": "响应代码,0为成功,1为失败"
                },
                "data": {
                    "type": "object",
                    "description": "响应内容"
                },
                "msg": {
                    "type": "string",
                    "description": "响应消息"
                },
                "success": {
                    "type": "boolean"
                }
            },
            "title": "接口响应",
            "description": "接口响应"
        },

        "接口响应«List«网站信息»»": {
            "type": "object",
            "required": ["code"],
            "properties": {
                "code": {
                    "type": "integer",
                    "format": "int32",
                    "description": "响应代码,0为成功,1为失败"
                },
                "data": {
                    "type": "array",
                    "description": "响应内容",
                    "items": {
                        "$ref": "#/definitions/网站信息"
                    }
                },
                "msg": {
                    "type": "string",
                    "description": "响应消息"
                },
                "success": {
                    "type": "boolean"
                }
            },
            "title": "接口响应«List«网站信息»»",
            "description": "接口响应"
        },
        "接口响应«网站信息»": {
            "type": "object",
            "required": ["code"],
            "properties": {
                "code": {
                    "type": "integer",
                    "format": "int32",
                    "description": "响应代码,0为成功,1为失败"
                },
                "data": {
                    "description": "响应内容",
                    "$ref": "#/definitions/网站信息"
                },
                "msg": {
                    "type": "string",
                    "description": "响应消息"
                },
                "success": {
                    "type": "boolean"
                }
            },
            "title": "接口响应«网站信息»",
            "description": "接口响应"
        },
        "查询参数": {
            "type": "object",
            "required": ["id"],
            "properties": {
                "id": {
                    "type": "string",
                    "description": "要查询的ID"
                }
            },
            "title": "查询参数",
            "description": "查询参数"
        },
        "网站信息": {
            "type": "object",
            "required": ["code", "id", "name", "state"],
            "properties": {
                "id": {
                    "type": "string",
                    "description": "网站ID"
                },
                "name": {
                    "type": "string",
                    "description": "网站名称"
                },
                "logo": {
                    "type": "string",
                    "description": "网站LOGO"
                }
            },
            "title": "网站信息",
            "description": "网站信息"
        }
    }
}

导入接口到YAPI

切换到YAPI的数据管理选项卡

Swagger2配合YAPI自动生成文档

有两种方式导入YAPI

1、将JSON保存到文件,上传。
2、如果你的项目有外网URL的话,直接开启URL导入。
Swagger2配合YAPI自动生成文档

导入好的接口

Swagger2配合YAPI自动生成文档

Swagger2配合YAPI自动生成文档

总结

只要你的代码足够规范,使用此方案进行文档导入,可以节省90%的文档工作量,生成的内容只需要少量修改就可以直接交于前端同事对接,是不是美滋滋?

另外提供一个自己写的SpringCloud代码生成器,只需要要贴入建表语句,即可一键生成符合规范的DTO/Entity/Controller/Service/Mapper/

https://jeegen.com/

注:以上部分内容经过加工,只做演示用,并非真实代码
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Karen110 Karen110
2年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
liam liam
1年前
先写API文档还是先写代码?
代码未动,文档先行其实大家都知道API文档先行的重要性,但是在实践过程中往往会遇到很多困难。程序员最讨厌的两件事:1.写文档,2.别人不写文档。大多数开发人员不愿意写API文档的原因是写文档短期收益远低于付出的成本,然而并不是所有人都能够坚持做有长期收益的事情的。作为一个前后端分离模式开发的团队,我们经常会看到这样的场景:前端开发和后端开发在一起
Wesley13 Wesley13
2年前
35岁,真的是程序员的一道坎吗?
“程序员35岁是道坎”,“程序员35岁被裁”……这些话咱们可能都听腻了,但每当触及还是会感到丝丝焦虑,毕竟每个人都会到35岁。而国内互联网环境确实对35岁以上的程序员不太友好:薪资要得高,却不如年轻人加班猛;虽说经验丰富,但大部分公司并不需要太资深的程序员。但35岁危机并不是不可避免的,比如你可以不断精进技术,将来做技术管理或者
Wesley13 Wesley13
2年前
Unity横屏
Android下发现Unity里面的Player设置,并不能完全有效,比如打开了自动旋转,启动的时候还是会横屏,修改XML添加以下代码<applicationandroid:icon"@drawable/ic\_launcher"                    android:label"@string/app\_name"
Stella981 Stella981
2年前
JOptionPane修改图标
1.在Linux平台下.JOptionPane会显示Java默认的图标,在window平台不显示图标,如何替换这个图标了?2JOptionPane.setIcon(Icon)修改的是内容区域的icon,而不是左上角的Icon.所以需要通过修改Jdialog/Frame的图标来达到修改默认图标的问题.3.代码:if(JOptio
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k