1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > SpringBoot应用生成RESTful API文档 - Swagger 2.0 OAS 3.0 Springfox Springdoc Smart-doc

SpringBoot应用生成RESTful API文档 - Swagger 2.0 OAS 3.0 Springfox Springdoc Smart-doc

时间:2021-07-09 05:24:33

相关推荐

SpringBoot应用生成RESTful API文档 - Swagger 2.0 OAS 3.0 Springfox Springdoc Smart-doc

目录

1. Swagger及OpenAPI2. Springfox & Springdoc & Smart-doc2.1 Springfox2.2 Springdoc2.3 smart-doc2.4 总结3. Springfox2集成Swagger24. Springfox3集成OAS 3.05. Springdoc集成OAS 3.06. Smart-doc + Springdoc集成OAS 3.06.1 openapi.json集成Knife4j7. springdoc-openapi-javadoc对比smart-doc

通常开发初期架构师需要给出DB设计、API接口设计,

而API接口设计或者以文档(word文档、markdown等)、或者以在线API文档(swagger-ui、yapi、showdoc等)形式给出,

设计先行模式(本人也比较推崇此模式)为例,架构师通常通过如下两种方式输出API文档:

方式一:纯API文档编写(无代码输出)编写Word文档(公司级接口文档模板) - 不好迁移,不是业界通用标准通过在线文档设计工具编写(yapi、showdoc等)- 方便统一管理,兼容通用标准如Swagger2.0、OAS3.0等方式二:通过代码集成Swagger注解生成文档(侵入代码) - 同时输出:API接口文档、程序的接口框架(理想情况下文档和代码同步)直接以swagger-ui进行文档展示将swagger.json文件导入到其他在线文档平台进行统一管理

记得N年之前用的是公司统一规范的word文档进行API文档编写,

后续迁移到了在线文档平台YAPI(兼容Swagger 2.0),

迁移过程中写了工具把word文档转换成swagger.json,然后再导入YAPI中(在此基础上再手动修改),

后续用的比较多的就是直接在YAPI编写文档。

之前一直不用Swagger是觉得这个东西太重了,需要在代码中添加好多和业务无关的注解,

但是Swagger这个文档规范还是很通用的(业界标准),

在编写Swagger注解的同时也是在定义程序接口框架(输出代码,提高后续开发效率),

所以就萌生了不通过Swagger注解 而是结合Java代码注释就可以生成Swagger统一规范文档(后续可导入其他在线API平台)的想法,

注:代码及注释可以借助DB定义通过代码生成工具进行生成,而后再进一步修改

本文就是在实现此种想法过程中的一些记录,

这个过程的探索也借助了业内比较通用的工具:

swaggerspringfox2、springfox3springdocsmart-doc

接下来依次对各工具进行介绍与集成示例讲解。

1. Swagger及OpenAPI

Swagger提供了一整套API设计、文档编写及展示的工具,提供开源版、企业版、cloud版,

开源版主要包括:

OpenAPI规范(简称OAS) -RESTful API的接口定义规范,目前支持OAS 2.0和OAS 3.0(前身也叫Swagger规范,在后捐赠给Linux Foundation后更名为OpenAPI)Swagger Core - 基于Java注解生成OAS文档(*.json或.yaml格式)Swagger UI - 根据OAS文档生成可视化文档展示Swagger Editor - API在线编辑OAS及文档生成Swagger Codegen - 根据OAS文档生成Server端、client端接口代码

OAS规范的发展历史见下表(目前最新版本为OAS 3.0.3):

Swagger 2.0和OAS 3.0常用注解对比:

2. Springfox & Springdoc & Smart-doc

Springfox 和 Springdoc均是spring社区(非官方)开发的,

支持在Spring生态中根据SpringMvc代码、Swagger注解、JSR303注解(@NotNull, @Min, @Max, @Size)自动生成接口文档的工具,并且支持集成Swagger UI。

而Smart-doc则是国内开源的根据SpringMvc代码、Java源码注释、JSR303注解、泛型推导等自动生成接口文档的工具。

2.1 Springfox

Springfox支持Swagger 2.0 和 OAS 3.0规范,

对Swagger 2.0的支持较为成熟,比较流行,

但对OAS 3.0的支持并不完善(可参见springfox 3.0整合OAS 3.0及其问题),

目前社区也不是很活跃(目前最新版本3.0.0发布在-07-14,已经1年多没有更新了)。

SpringFox 3.0.0 的新特性:

支持Spring5、Webflux、Spring Integration支持Springboot零配置启动 springfox-boot-starter支持OAS 3.0.3且兼容Swagger 2.0(注:对OSA 3.0支持不是很完善,且github上已好久没有更新)精简依赖(仅依赖spring-plugin, swagger-core)

2.2 Springdoc

而Springdoc仅支持OAS 3.0规范,但对OAS 3.0的支持比较完善,

社区较为活跃(目前最新版本1.6.4发布在-01-06),

Springdoc核心特性如下:

支持OpenAPI 3(不支持Swagger 2.0)支持Spring-boot (v1 and v2)支持JSR-303验证注解(@NotNull, @Min, @Max, @Size)支持集成Swagger-ui支持OAuth 2支持GraalVM native images

从 SpringFox 迁移到 SpringDoc

可参见官网文档:Migrating from SpringFox

2.3 smart-doc

Smart-doc为国内开源的根据Java源码注释JSR303注解泛型推导等自动生成接口文档的工具。你只需要按照java-doc标准编写注释,smart-doc就能帮你生成一个简易明了的Markdown、HTML5、Postman Collection2.0+、OpenAPI 3.0+的文档。

smart-doc最吸引我的特性就是基于注释,而不是基于注解

我们在写Java代码的时候,都要求书写规范的文档注释,

而使用Swagger生态则需要侵入代码再书写大量swagger-core注解,

如@Api, @ApiOperation,…,@Tag,@Operation,…,增加了一定学习成本,

作为开发人员会觉得很痛苦,同样的说明功能被做了2次(注释、注解),后续维护也要修改2次,

而且代码中需要添大量和业务无关的Swagger-core注解,

而使用smart-doc可以直接提取我们文档中的注释来生成API文档,不需要再添加额外的注解。

同时smart-doc支持生成多种文档格式:

如可以直接展示的(支持group):HTML5、Markdown、Adoc用于Postman调试的:Postman Collection2.0+OAS 3.0生态:OpenAPI 3.0+

smart-doc的相关特性如下:

零注解、零学习成本、只需要写标准JAVA注释。基于源代码接口定义自动推导,强大的返回结构推导。支持Spring MVC、Spring Boot、Spring Boot Web Flux(controller书写方式)、Feign。支持JavaBean上的JSR303参数校验规范,包括分组验证。支持导出错误码和定义在代码中的各种字典码到接口文档。支持Maven、Gradle插件式轻松集成。支持Apache Dubbo RPC接口文档生成。支持生成多种格式文档:Markdown、HTML5、Asciidoctor、Postman Collection、OpenAPI 3.0debug接口调试html5页面完全支持文件上传,下载(@download tag标记下载方法)测试。开放文档数据,可自由实现接入文档管理系统。支持Callable、Future、CompletableFuture等异步接口返回的推导。对JSON请求参数的接口能够自动生成模拟JSON参数。对一些常用字段定义能够生成有效的模拟值。支持生成JSON返回值示例。支持从项目外部加载源代码来生成字段注释(包括标准规范发布的jar包)。

smart-doc关于注释也支持一些特殊格式:

@apiNote来说明详细描述(长注释)@tag表示分类、分组@mock指定基本类型mock值@required、@ignored、@ignoreParams@download、@page参数对象替换 @param pageable com.power.doc.model.PageRequestDto@param pageable 你的注释|com.power.doc.model.PageRequestDto@param pageable com.power.doc.model.PageRequestDto<com.power.doc.model.User> 设置参数mock值 @param author 作者|村上春树 …

实际使用smart-doc中遇到的问题:

@RequestMapping等注解value属性若指定为数组,则会解析path为: “[/api/v1/xxx]”,指定value为字符串时会被正确解析为:“/api/v1/xxx”分组配置groups不支持openapi、postman模式分组配置groups.apis只支持包名格式(不支持到特定类名),如:com.luo.controller.biz1.*关于OpenApi支持有限,如server定义过于简单,不支持多server定义关于源码包的解析也有要求,可提供源码包、手动exclude解析报错的包

2.4 总结

综上,

【不推荐】继续使用Swagger 2.0则可继续使用Springfox 2.x用过的稳定版本【推荐】现阶段推荐接入OAS 3.0,则Springdoc + Swagger Core 3.0注解【⭐️最推荐⭐️】推荐smart-doc openapi模式(集成Springdoc Swagger-ui展示 或者导入到其他文档平台统一管理) 即代码仅需标准Java注释、JSR303然后通过smart-doc openapi模式生成OAS 3.0文档 - openapi.json亦可根据需要按照OAS 3.0规范手动修改openapi.json【可选】最后通过Springdoc接入openapi.json进行Swagger UI渲染展示【可选】【⭐️推荐⭐️】亦可将openapi.json导入其他已有的文档平台进行展示与管理注:此种方法以OAS 3.0规范形成统一格式文档,便于后续维护修改、迁移到其他文档管理平台

3. Springfox2集成Swagger2

maven依赖:

<!-- 父依赖定义 --><parent><!-- 依赖SpringBoot2.6.2 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><springfox2.version>2.9.2</springfox2.version><swagger.version>1.6.4</swagger.version></properties><dependencies><!-- Spring Boot Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Springfox2集成swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>${springfox2.version}</version></dependency><!-- Springfox集swagger-ui --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>${springfox2.version}</version></dependency><!-- Springfox支持JSR-303验证注解 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-bean-validators</artifactId><version>${springfox2.version}</version></dependency><!-- 升级swagger annotations和models - 从1.5.20升级到最新(解决input string ""报错) --><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>${swagger.version}</version></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>${swagger.version}</version></dependency></dependencies>

应用配置application.yaml:

spring:mvc:pathmatch:# 设置path匹配策略,解决高版本springboot启动springfox报空指针异常问题,# 具体参见:/Faint35799/article/details/122344731matching-strategy: ant_path_matcher

代码配置:

import com.luo.demo.sc.base.enums.RespCodeEnum;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.bind.annotation.RequestMethod;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.builders.ResponseMessageBuilder;import springfox.documentation.service.ApiInfo;import springfox.documentation.service.Contact;import springfox.documentation.service.ResponseMessage;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream;/*** Springfox配置** @author luohq* @date -01-15 17:33*/@Configuration@EnableSwagger2public class SpringfoxConfig {@Beanpublic Docket createRestApi() {List<ResponseMessage> respMsgList = this.convertRespMsgList();return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())//设置全局响应信息.globalResponseMessage(RequestMethod.GET, respMsgList).globalResponseMessage(RequestMethod.POST, respMsgList).globalResponseMessage(RequestMethod.PUT, respMsgList).globalResponseMessage(RequestMethod.DELETE, respMsgList).select()//为当前包路径.apis(RequestHandlerSelectors.basePackage("com.luo.demo.api.controller")).paths(PathSelectors.any()).build();}@Beanpublic ApiInfo apiInfo() {return new ApiInfoBuilder()// 页面标题.title("Springfox Swagger2 - RESTful API")// 创建人信息.contact(new Contact("luohq", "/luo15242208310", "luohengquan@"))// 版本号.version("1.0")// 描述.description("Springfox Swagger2构建RESTful API").build();}/*** 转换响应码枚举RespCodeEnum为响应信息列表** @return 响应信息列表*/private List<ResponseMessage> convertRespMsgList() {return Stream.of(RespCodeEnum.values()).map(respCodeEnum -> {return new ResponseMessageBuilder().code(respCodeEnum.getCode()).message(respCodeEnum.getMessage()).build();}).collect(Collectors.toList());}}

如上配置完成后,则可以直接访问swagger-ui界面:http://localhost:8080/swagger-ui.html

在不添加任何Swagger 2.0注解的情况下,Springfox也可根据SpringMvc相关结构生成文档如下图:

可以发现在英文环境下,规范的Controller方法名、参数名称、变量名称皆可起到说明的作用,

但是在中文环境这种纯英文的描述还不够,我们还需要中文的描述,

如此便可通过Swagger 2.0注解(或者后续的OAS 3.0注解、中文注释)的进行详细的中文说明。

添加Swagger 2.0注解的示例代码如下:

//=======================================================================================//================================ Controller层代码 ======================================//=======================================================================================@Api(description = "用户信息管理")@Slf4j@RestController@RequestMapping("/users")@Validatedpublic class UserController {@ApiOperation(value = "查询用户信息", notes = "根据用户ID查询用户信息")@ApiImplicitParam(name = "id", value = "用户ID", paramType = "path", required = true)@GetMapping("/{id}")public RespResult<UserInfo> getUser(@NotNull @PathVariable Long id) {log.info("get user, param: id={}", id);return RespResult.successData(this.buildUser(id));}@ApiOperation(value = "查询用户信息列表", notes = "查询用户信息列表")@GetMappingpublic RespResult<UserInfo> getUsers(@Validated UserQueryDto userQueryDto) {log.info("get users, param: {}", userQueryDto);return RespResult.successRows(TOTAL_DEFAULT, this.buildUsers(Optional.ofNullable(userQueryDto.getId()).orElse(ID_DEFAULT), TOTAL_DEFAULT));}@ApiOperation(value = "新增用户及设备绑定信息")@PostMappingpublic RespResult<Integer> addUser(@Validated @RequestBody UserAddDto userAddDto) {log.info("add user, param: {}", userAddDto);return RespResult.successData(1);}@ApiOperation(value = "修改用户及设备绑定信息")@PutMappingpublic RespResult<Integer> updateUser(@Validated @RequestBody UserEditDto userEditDto) {log.info("update user, param: {}", userEditDto);return RespResult.successData(1);}@ApiOperation(value = "删除用户信息", notes = "根据用户ID列表删除用户信息")@ApiImplicitParams({@ApiImplicitParam(name = "ids", value = "用户ID列表(逗号分隔)", paramType = "path", required = true)})@DeleteMapping("/{ids}")public RespResult<Integer> deleteUsers(@NotEmpty @PathVariable List<Long> ids) {log.info("delete users, param: ids={}", ids);return RespResult.successData(ids.size());}//省略...}//=======================================================================================//================================= Model对象层代码 ======================================//=======================================================================================/*** 新增用户参数** @author luohq* @date -01-15 12:21*/@Data@Builder@ApiModel("新增用户参数")public class UserAddDto {/*** 用户名称*/@ApiModelProperty(value = "用户名称")@NotBlank@Size(min = 1, max = 30)private String name;/*** 用户性别(1:男,2:女)*/@ApiModelProperty(value = "用户性别(1:男,2:女)")@NotNull@Range(min = 1, max = 2)private Integer sex;/*** 设备列表*/@ApiModelProperty(value = "设备列表")@NotEmptyprivate List<DeviceAddDto> deviceInfoList;}

添加Swagger 2.0相关注解完成后重启应用,Swagger-ui效果如下图:

4. Springfox3集成OAS 3.0

maven依赖:

<!-- 父依赖定义 --><parent><!-- 依赖SpringBoot2.6.2 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><springfox3.version>3.0.0</springfox3.version><swagger.version>1.6.4</swagger.version></properties><dependencies><!-- Spring Boot Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Springfox3集成OAS 3.0 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>${springfox3.version}</version></dependency><!-- 升级swagger annotations和models - 从1.5.20升级到最新(解决input string ""报错) --><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>${swagger.version}</version></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>${swagger.version}</version></dependency></dependencies>

应用配置application.yaml:

spring:mvc:pathmatch:# 设置path匹配策略,解决springfox启动空指针异常问题,# 具体参见:/Faint35799/article/details/122344731matching-strategy: ant_path_matcher

代码配置:

import com.luo.demo.sc.base.enums.RespCodeEnum;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpMethod;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import springfox.documentation.builders.*;import springfox.documentation.service.ApiInfo;import springfox.documentation.service.Contact;import springfox.documentation.service.Response;import springfox.documentation.service.ResponseMessage;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream;/*** Springfox配置** @author luohq* @date -01-15 17:33*/@Configurationpublic class SpringfoxConfig {@Beanpublic Docket createRestApi() {List<Response> respMsgList = this.convertRespMsgList();return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).globalResponses(HttpMethod.GET, respMsgList).globalResponses(HttpMethod.POST, respMsgList).globalResponses(HttpMethod.PUT, respMsgList).globalResponses(HttpMethod.DELETE, respMsgList).select()// 为当前包路径.apis(RequestHandlerSelectors.basePackage("com.luo.demo.api.controller")).paths(PathSelectors.any()).build();}@Beanpublic ApiInfo apiInfo() {return new ApiInfoBuilder()// 页面标题.title("Springfox OAS3.0 - RESTful API")// 创建人信息.contact(new Contact("luohq", "/luo15242208310", "luohengquan@"))// 版本号.version("1.0")// 描述.description("Springfox OAS3.0 构建RESTful API" + this.convertRespMsgHtmlTable()).build();}/*** 转换响应码枚举RespCodeEnum为响应信息列表** @return 响应信息列表*/private List<Response> convertRespMsgList() {return Stream.of(RespCodeEnum.values()).map(respCodeEnum -> {return new ResponseBuilder().code(respCodeEnum.getCode().toString()).description(respCodeEnum.getMessage()).build();}).collect(Collectors.toList());}/*** 转换通用响应码Table** @return 响应码Table*/private String convertRespMsgHtmlTable() {StringBuilder sb = new StringBuilder("<table><tr><th align=\"left\">响应码</th><th align=\"left\">提示信息</th></tr>");Stream.of(RespCodeEnum.values()).forEach(respCodeEnum -> {sb.append("<tr><td>").append(respCodeEnum.getCode()).append("</td><td>").append(respCodeEnum.getMessage()).append("</td></tr>");});return sb.append("</table>").toString();}}

添加OAS 3.0注解的示例代码如下:

//=======================================================================================//================================ Controller层代码 ======================================//=======================================================================================@Tag(name = "用户信息管理")@Slf4j@RestController@RequestMapping("/users")@Validatedpublic class UserController {private final Integer TOTAL_DEFAULT = 3;private final Long ID_DEFAULT = 1L;/*** 查询用户详细信息** @param id 用户ID* @return 用户信息*/@Operation(summary = "查询用户信息", description = "根据用户ID查询用户信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@GetMapping("/{id}")public RespResult<UserInfo> getUser(@Parameter(name = "id", description = "用户ID", example = "1", in = ParameterIn.PATH, required = true)@NotNull @PathVariable Long id) {log.info("get user, param: id={}", id);return RespResult.successData(this.buildUser(id));}/*** 查询用户列表** @param userQueryDto 查询参数* @return 用户列表*/@Operation(summary = "查询用户信息列表", description = "查询用户信息列表",parameters = {@Parameter(name = "id", description = "用户ID", example = "1", in = ParameterIn.QUERY),@Parameter(name = "name", description = "用户姓名", in = ParameterIn.QUERY),@Parameter(name = "sex", description = "用户性别(1:男,2:女)", example = "1", in = ParameterIn.QUERY),@Parameter(name = "createTimeStart", description = "起始创建日期", example = "-01-01 10:00:00", in = ParameterIn.QUERY),@Parameter(name = "createTimeEnd", description = "结束创建日期", example = "-01-01 10:00:00", in = ParameterIn.QUERY),},responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})//@Operation(summary = "查询用户信息列表", description = "查询用户信息列表")@GetMappingpublic RespResult<UserInfo> getUsers(@Parameter(hidden = true) @Validated UserQueryDto userQueryDto) {log.info("get users, param: {}", userQueryDto);return RespResult.successRows(TOTAL_DEFAULT, this.buildUsers(Optional.ofNullable(userQueryDto.getId()).orElse(ID_DEFAULT), TOTAL_DEFAULT));}/*** 新增用户及设备绑定信息** @param userAddDto 新增参数* @return 响应结果*/@Operation(summary = "新增用户及设备绑定信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@PostMappingpublic RespResult<Integer> addUser(@Validated @RequestBody UserAddDto userAddDto) {log.info("add user, param: {}", userAddDto);return RespResult.successData(1);}/*** 修改用户及设备绑定信息** @param userEditDto 修改参数* @return 响应结果*/@Operation(summary = "修改用户及设备绑定信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@PutMappingpublic RespResult<Integer> updateUser(@Validated @RequestBody UserEditDto userEditDto) {log.info("update user, param: {}", userEditDto);return RespResult.successData(1);}/*** 删除用户信息** @param ids 用户ID列表* @return 响应结果*/@Operation(summary = "删除用户信息", description = "根据用户ID列表删除用户信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@DeleteMapping("/{ids}")public RespResult<Integer> deleteUsers(@Parameter(name = "ids", description = "用户ID列表(逗号分隔)", in = ParameterIn.PATH, required = true)@NotEmpty @PathVariable List<Long> ids) {log.info("delete users, param: ids={}", ids);return RespResult.successData(ids.size());}//省略...}//=======================================================================================//================================ Model对象层代码 =======================================//=======================================================================================/*** 新增用户参数** @author luohq* @date -01-15 12:21*/@Data@Builder@Schema(description = "新增用户参数")public class UserAddDto {/*** 用户名称*/@Schema(description = "用户名称")@NotBlank@Size(min = 1, max = 30)private String name;/*** 用户性别(1:男,2:女)*/@Schema(description = "用户性别(1:男,2:女)", example = "1")@NotNull@Range(min = 1, max = 2)private Integer sex;/*** 设备列表*/@Schema(description = "设备列表")@NotEmptyprivate List<DeviceAddDto> deviceInfoList;}

启动项目,浏览器访问:http://localhost:8080/swagger-ui/

注:Springfox2和Springfox3版本的swagger-ui访问地址不同

Springfox2 Swagger 2.0版本swagger-ui访问地址: http://localhost:8080/swagger-ui.htmlSpringfox3 OAS 3.0版本swagger-ui访问地址: http://localhost:8080/swagger-ui/

启动后Swagger-ui效果如下图:

5. Springdoc集成OAS 3.0

maven依赖:

<!-- 父依赖定义 --><parent><!-- 依赖SpringBoot2.6.2 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><springdoc.version>1.6.4</springdoc.version></properties><dependencies><!-- Spring Boot Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependencies><!-- springdoc swagger ui --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>${springdoc.version}</version></dependency></dependencies></dependencies>

应用配置application.yaml:

# springdoc配置springdoc:# 分组配置group-configs:- group: 用户管理packages-to-scan: com.luo.demo.api.controllerpaths-to-match: /users/**- group: 角色管理packages-to-scan: com.luo.demo.api.controllerpaths-to-match: /roles/**

代码配置:

import com.luo.demo.sc.base.enums.RespCodeEnum;import io.swagger.v3.oas.models.ExternalDocumentation;import io.swagger.v3.oas.models.OpenAPI;import io.swagger.v3.oas.models.info.Info;import io.swagger.v3.oas.models.info.License;import io.swagger.v3.oas.models.servers.Server;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.Arrays;import java.util.stream.Stream;/*** OAS 3.0 配置** @author luohq* @date -01-16 12:34*/@Configurationpublic class OpenApiConfig {@Beanpublic OpenAPI springShopOpenAPI() {return new OpenAPI().info(new Info().title("Springdoc OAS3.0 - RESTful API").description("Springdoc OAS3.0 构建RESTful API" + this.convertRespMsgHtmlTable()).version("1.0").license(new License().name("Apache 2.0").url(""))).servers(Arrays.asList(new Server().description("开发环境").url("http://localhost:8080"))).externalDocs(new ExternalDocumentation().description("SpringShop Wiki Documentation").url("https://springshop./docs"));}///**// * 全局设置响应码(实际测试如果设置group(代码或配置文件)则此段代码不生效)// *// * @return// *///@Bean//public OperationCustomizer customizeOperation() {// return (operation, handlerMethod) -> {// System.out.println("op: " + operation.getSummary());// ApiResponses curResponses = operation.getResponses();// Stream.of(RespCodeEnum.values()).forEach(respCodeEnum -> {// curResponses.addApiResponse(//String.valueOf(respCodeEnum.getCode()),//new ApiResponse().description(respCodeEnum.getMessage()));// });// return operation.responses(curResponses);// };//}//代码配置分组(亦可直接通过配置文件进行配置springdoc.group-configs[*])//@Bean//public GroupedOpenApi publicApi() {// return GroupedOpenApi.builder()// .group("用户管理")// .pathsToMatch("/users/**")// .build();//}//@Bean//public GroupedOpenApi adminApi() {// return GroupedOpenApi.builder()// .group("角色管理")// .pathsToMatch("/roles/**")// .build();//}/*** 转换通用响应码Table** @return 响应码Table*/private String convertRespMsgHtmlTable() {StringBuilder sb = new StringBuilder("<table><tr><th align=\"left\">响应码</th><th align=\"left\">提示信息</th></tr>");Stream.of(RespCodeEnum.values()).forEach(respCodeEnum -> {sb.append("<tr><td>").append(respCodeEnum.getCode()).append("</td><td>").append(respCodeEnum.getMessage()).append("</td></tr>");});return sb.append("</table>").toString();}}

添加OAS 3.0注解的示例代码如下(同之前Springfox3中使注解相同):

//=======================================================================================//================================ Controller层代码 ======================================//=======================================================================================@Tag(name = "用户信息管理")@Slf4j@RestController@RequestMapping("/users")@Validatedpublic class UserController {private final Integer TOTAL_DEFAULT = 3;private final Long ID_DEFAULT = 1L;/*** 查询用户详细信息** @param id 用户ID* @return 用户信息*/@Operation(summary = "查询用户信息", description = "根据用户ID查询用户信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@GetMapping("/{id}")public RespResult<UserInfo> getUser(@Parameter(name = "id", description = "用户ID", example = "1", in = ParameterIn.PATH, required = true)@NotNull @PathVariable Long id) {log.info("get user, param: id={}", id);return RespResult.successData(this.buildUser(id));}/*** 查询用户列表** @param userQueryDto 查询参数* @return 用户列表*/@Operation(summary = "查询用户信息列表", description = "查询用户信息列表",parameters = {@Parameter(name = "id", description = "用户ID", example = "1", in = ParameterIn.QUERY),@Parameter(name = "name", description = "用户姓名", in = ParameterIn.QUERY),@Parameter(name = "sex", description = "用户性别(1:男,2:女)", example = "1", in = ParameterIn.QUERY),@Parameter(name = "createTimeStart", description = "起始创建日期", example = "-01-01 10:00:00", in = ParameterIn.QUERY),@Parameter(name = "createTimeEnd", description = "结束创建日期", example = "-01-01 10:00:00", in = ParameterIn.QUERY),},responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})//@Operation(summary = "查询用户信息列表", description = "查询用户信息列表")@GetMappingpublic RespResult<UserInfo> getUsers(@Parameter(hidden = true) @Validated UserQueryDto userQueryDto) {log.info("get users, param: {}", userQueryDto);return RespResult.successRows(TOTAL_DEFAULT, this.buildUsers(Optional.ofNullable(userQueryDto.getId()).orElse(ID_DEFAULT), TOTAL_DEFAULT));}/*** 新增用户及设备绑定信息** @param userAddDto 新增参数* @return 响应结果*/@Operation(summary = "新增用户及设备绑定信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@PostMappingpublic RespResult<Integer> addUser(@Validated @RequestBody UserAddDto userAddDto) {log.info("add user, param: {}", userAddDto);return RespResult.successData(1);}/*** 修改用户及设备绑定信息** @param userEditDto 修改参数* @return 响应结果*/@Operation(summary = "修改用户及设备绑定信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@PutMappingpublic RespResult<Integer> updateUser(@Validated @RequestBody UserEditDto userEditDto) {log.info("update user, param: {}", userEditDto);return RespResult.successData(1);}/*** 删除用户信息** @param ids 用户ID列表* @return 响应结果*/@Operation(summary = "删除用户信息", description = "根据用户ID列表删除用户信息",responses = {@ApiResponse(responseCode = "1000", description = "操作成功", content = @Content),@ApiResponse(responseCode = "1101", description = "参数无效", content = @Content),@ApiResponse(responseCode = "2000", description = "操作失败", content = @Content),})@DeleteMapping("/{ids}")public RespResult<Integer> deleteUsers(@Parameter(name = "ids", description = "用户ID列表(逗号分隔)", in = ParameterIn.PATH, required = true)@NotEmpty @PathVariable List<Long> ids) {log.info("delete users, param: ids={}", ids);return RespResult.successData(ids.size());}//省略...}//=======================================================================================//================================ Model对象层代码 =======================================//=======================================================================================/*** 新增用户** @author luohq* @date -01-15 12:21*/@Data@Builder@Schema(description = "新增用户参数")public class UserAddDto {/*** 用户名称*/@Schema(description = "用户名称")@NotBlank@Size(min = 1, max = 30)private String name;/*** 用户性别(1:男,2:女)*/@Schema(description = "用户性别(1:男,2:女)", example = "1")@NotNull@Range(min = 1, max = 2)private Integer sex;/*** 设备列表*/@Schema(description = "设备列表")@NotEmptyprivate List<DeviceAddDto> deviceInfoList;}

启动项目,浏览器访问:http://localhost:8080/swagger-ui.html

注:

Springfox2 Swagger 2.0版本swagger-ui访问地址: http://localhost:8080/swagger-ui.htmlSpringfox3 OAS 3.0版本swagger-ui访问地址: http://localhost:8080/swagger-ui/Springdoc OAS 3.0版本swagger-ui访问地址: http://localhost:8080/swagger-ui.html

启动后Swagger-ui效果如下图:

6. Smart-doc + Springdoc集成OAS 3.0

smart-doc提供maven(或gradle)插件,通过集成插件运行mvn相关命令即可生成文档。

示例命令如下:

# 生成 Open Api 3.0+,Since smart-doc-maven-plugin 1.1.5mvn -Dfile.encoding=UTF-8 smart-doc:openapi# 生成htmlmvn -Dfile.encoding=UTF-8 smart-doc:html# 生成markdownmvn -Dfile.encoding=UTF-8 smart-doc:markdown# 生成adocmvn -Dfile.encoding=UTF-8 smart-doc:adoc# 生成postman json数据mvn -Dfile.encoding=UTF-8 smart-doc:postman# 生成文档推送到Torna平台mvn -Dfile.encoding=UTF-8 smart-doc:torna-rest

maven依赖:

<!-- 父依赖定义 --><parent><!-- 依赖SpringBoot2.6.2 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><springdoc.version>1.6.4</springdoc.version><smart.doc.version>2.3.6</smart.doc.version></properties><dependencies><!-- Spring Boot Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- springdoc swagger ui --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>${springdoc.openapi.version}</version></dependency></dependencies><build><plugins><!-- smart-doc插件定义 --><plugin><groupId>com.github.shalousun</groupId><artifactId>smart-doc-maven-plugin</artifactId><version>${smart.doc.version}</version><configuration><!--指定生成文档的使用的配置文件,配置文件放在自己的项目中--><configFile>./src/main/resources/smart-doc.json</configFile><!--smart-doc实现自动分析依赖树加载第三方依赖的源码,如果一些框架依赖库加载不到导致报错,这时请使用excludes排除掉--><excludes><!--格式为:groupId:artifactId;参考如下--><!--也可以支持正则式如:com.alibaba:.* --><exclude>com.alibaba:.*</exclude><exclude>cn.hutool:hutool-core</exclude></excludes></configuration><executions><execution><!--如果不需要在执行编译时启动smart-doc,则将phase注释掉--><phase>compile</phase><goals><!--smart-doc提供了html、openapi、markdown等goal,可按需配置--><goal>openapi</goal></goals></execution></executions></plugin></plugins></build>

smart-doc.json配置:

注:

smart-doc.json文件位置需和之前maven插件smart-doc-maven-plugin中configuration.configFile指定位置一致 如<configFile>./src/main/resources/smart-doc.json</configFile>即对应resources/smart-doc.json文件。 如下配置中的groups在openapi、postman模式下并不生效(仅适用于html、markdown、adoc)如下配置中的outPath即为smart-doc生成文件的存放位置 若使用openapi模式且需要通过Springdoc渲染此openapi.json,则outPath需输出到./src/main/resources/static目录下 关于smart-doc.json详细配置参见:https://smart-doc-group.github.io/#/zh-cn/diy/config

{"projectName": "Smartdoc + springdoc + OAS3.0 - RESTful API","serverUrl": "http://localhost:8080","pathPrefix": "/","outPath": "./src/main/resources/static/doc","allInOne": true,"showAuthor": true,"groups": [{"name": "用户管理","apis": "com.luo.demo.api.controller.user.*"},{"name": "角色管理","apis": "com.luo.demo.api.controller.role.*"}],"revisionLogs": [{"version": "1.0","revisionTime": "-01-17 16:30","status": "create","author": "luohq","remarks": "Smartdoc OAS3集成Springdoc"}]}

应用配置application.yaml:

# custom path for swagger-uispringdoc:swagger-ui:# 自定义openapi.json文件位置(需在/resources/static目录下)url: /doc/openapi.json

代码配置:

示例代码如下(仅添加标准的Java注释即可):

//=======================================================================================//================================ Controller层代码 ======================================//=======================================================================================/*** 用户信息管理** @author luohq* @apiNote 用户信息管理* @date -01-15 12:29*/@Slf4j@RestController@RequestMapping("/users")@Validatedpublic class UserController {private final Integer TOTAL_DEFAULT = 3;private final Long ID_DEFAULT = 1L;/*** 查询用户信息** @param id 用户ID* @return 用户信息* @apiNote 根据用户ID查询用户信息*/@GetMapping("/{id}")public RespResult<UserInfo> getUser(@NotNull @PathVariable Long id) {log.info("get user, param: id={}", id);return RespResult.successData(this.buildUser(id));}/*** 查询用户信息列表** @param userQueryDto 查询参数* @return 用户列表*/@GetMappingpublic RespResult<UserInfo> getUsers(@Validated UserQueryDto userQueryDto) {log.info("get users, param: {}", userQueryDto);return RespResult.successRows(TOTAL_DEFAULT, this.buildUsers(Optional.ofNullable(userQueryDto.getId()).orElse(ID_DEFAULT), TOTAL_DEFAULT));}/*** 新增用户及设备绑定信息** @param userAddDto 新增参数* @return 响应结果*/@PostMappingpublic RespResult<Integer> addUser(@Validated @RequestBody UserAddDto userAddDto) {log.info("add user, param: {}", userAddDto);return RespResult.successData(1);}/*** 修改用户及设备绑定信息** @param userEditDto 修改参数* @return 响应结果*/@PutMappingpublic RespResult<Integer> updateUser(@Validated @RequestBody UserEditDto userEditDto) {log.info("update user, param: {}", userEditDto);return RespResult.successData(1);}/*** 删除用户信息** @param ids 用户ID列表* @return 响应结果* @apiNote 根据用户ID列表删除用户信息*/@DeleteMapping("/{ids}")public RespResult<Integer> deleteUsers(@NotEmpty @PathVariable List<Long> ids) {log.info("delete users, param: ids={}", ids);return RespResult.successData(ids.size());}//省略...}//=======================================================================================//================================ Model对象层代码 =======================================//=======================================================================================/*** 新增用户参数** @author luohq* @date -01-15 12:21*/@Data@Builderpublic class UserAddDto {/*** 用户名称*/@NotBlank@Size(min = 1, max = 30)private String name;/*** 用户性别(1:男,2:女)*/@NotNull@Range(min = 1, max = 2)private Integer sex;/*** 设备列表*/@NotEmptyprivate List<DeviceAddDto> deviceInfoList;}

之前集成Springfox、Springdoc皆是在程序运行时扫描代码和Swagger相关注解后生成的Api文档,

而Smart-doc可以在编译期(mvn compile)或者程序启动前通过插件命令预先生成Api文档,

即可依次通过如下几步进行集成和启动:

首先通过maven插件smart-doc-maven-plugin的openapi模式生成openapi.json mvn命令:mvn -Dfile.encoding=UTF-8 smart-doc:openapiopenapi.json文件位置:./src/main/resources/static/doc/openapi.json然后通过应用配置springdoc.swagger-ui.url去引用此openapi.jsonspringdoc.swagger-ui.url=/doc/openapi.json最后启动应用通过springdoc swagger-ui去渲染此openapi.json对应的应用文档

启动项目,浏览器访问:http://localhost:8080/swagger-ui.html (对应Springdoc OAS3 Swagger-ui界面),

启动后Swagger-ui效果如下图:

6.1 openapi.json集成Knife4j

除了使用swagger-ui渲染,还发现了国内开源的Knife4j,

Knife4j提供了一个swagger-ui增强界面(还提供其他增强功能,本文暂未涉及),

通过Disk本地模式聚合OpenAPI文档模式,

即通过Knife4j去渲染之前生成的openapi.json文件,

实际测试后发现其对OAS 3.0的解析及渲染还不是很完善,如对象嵌套的结构皆显示不出来

开源不易,还是得感谢大神,希望Knife4j可以越来越好。

关于Knife4j聚合本地文件openapi.json的具体集成见下文。

maven配置:

<properties><knife4j.aggregation.version>2.0.9</knife4j.aggregation.version></properties><dependencies><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-aggregation-spring-boot-starter</artifactId><version>${knife4j.aggregation.version}</version></dependency></dependencies>

应用配置application.yaml:

# knife4j聚合配置knife4j:enableAggregation: truedisk:enable: trueroutes:- name: 用户location: classpath:static/doc/openapi.json

启动后即可通过http://localhost:8080/doc.html进行访问,

实际集成后发现其对OAS 3.0的解析及渲染还不是很完善,如对象嵌套的结构皆显示不出来,如下图:

7. springdoc-openapi-javadoc对比smart-doc

在springdoc生态中提供了一个Javadoc模块 -springdoc-openapi-javadoc

该模块增强了springdoc对Java注释及Tag的处理能力,

但支持有限,目前仅支持:

方法上的注释 - 被解析为@Operation.description(即接口的描述信息,不支持@Operation.summary)@param注释 - 被解析为@Parameter.description(即参数的描述信息)@return注释 - 被解析为@Operation.response.description(即返回结果的描述信息)对象属性上的注释 - 被解析为@Schema.description

Smart-doc相较于Springdoc-openapi-javadoc的源码模式,Smart-doc额外支持:

smart-doc支持方法上的注释为@Operation.summary(此处缺失可参见下文图片效果)smart-doc支持方法上的@apiNote注释为@Operation.description支持通过注释设置mock值(@param desc|mockVal、@mock mockVal)smart-doc关于注释的更多使用参见:https://smart-doc-group.github.io/#/zh-cn/start/javadoc

Springdoc-openapi-javadoc除了支持在运行时获取代码注释信息,

也可配合springdoc生态提供的maven插件 -springdoc-openapi-maven-plugin使用,

该插件可在mvn verify阶段扫描源码来生成对应的openapi.json文件。

具体springdoc-openapi-javadoc和springdoc-openapi-maven-plugin的集成及使用见下文。

maven依赖:

<!-- 父依赖定义 --><parent><!-- 依赖SpringBoot2.6.2 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><springdoc.version>1.6.4</springdoc.version><springdoc.plugin.version>1.3</springdoc.plugin.version></properties><dependencies><!-- Spring Boot Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- springdoc swagger ui --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>${springdoc.version}</version></dependency><!-- springdoc javadoc --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-javadoc</artifactId><version>${springdoc.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><!-- springdoc-openapi-javadoc依赖此处配置 --><configuration><!-- 必须添加此处配置javadoc才生效,注:该配置和lombok冲突,存在该配置则导致lombok编译报错 --><annotationProcessorPaths><path><groupId>com.github.therapi</groupId><artifactId>therapi-runtime-javadoc-scribe</artifactId><version>0.13.0</version></path></annotationProcessorPaths></configuration></plugin><!-- springdoc插件(用于在verify阶段生成openapi.json) --><plugin><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-maven-plugin</artifactId><version>${springdoc.plugin.version}</version><executions><execution><id>integration-test</id><goals><goal>generate</goal></goals></execution></executions><configuration><!-- The local url of your (json or yaml) - 需依赖springdoc-openapi-ui--><apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl><!-- api文件名称 --><outputFileName>openapi.json</outputFileName><!-- api文件输出路径(默认${project.build.directory},即target下) --><outputDir> ${project.build.directory}</outputDir><!-- <outputDir>/home/springdoc/maven-output</outputDir> --><!-- 是否跳过(默认false)--><skip>false</skip></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!--springdoc-openapi-maven-plugin插件依赖以下配置 --><configuration><jvmArguments>-Dspring.application.admin.enabled=true</jvmArguments></configuration><executions><execution><id>pre-integration-test</id><goals><goal>start</goal></goals></execution><execution><id>post-integration-test</id><goals><goal>stop</goal></goals></execution></executions></plugin></plugins></build>

代码配置:

示例代码同smart-doc示例(仅添加标准的Java注释即可)

//=======================================================================================//================================ Controller层代码 ======================================//=======================================================================================/*** 用户信息管理** @author luohq* @apiNote 用户信息管理* @date -01-15 12:29*/@Slf4j@RestController@RequestMapping("/users")@Validatedpublic class UserController {private final Integer TOTAL_DEFAULT = 3;private final Long ID_DEFAULT = 1L;/*** 查询用户信息** @param id 用户ID* @return 用户信息* @apiNote 根据用户ID查询用户信息*/@GetMapping("/{id}")public RespResult<UserInfo> getUser(@NotNull @PathVariable Long id) {log.info("get user, param: id={}", id);return RespResult.successData(this.buildUser(id));}/*** 查询用户信息列表** @param userQueryDto 查询参数* @return 用户列表*/@GetMappingpublic RespResult<UserInfo> getUsers(@Validated UserQueryDto userQueryDto) {log.info("get users, param: {}", userQueryDto);return RespResult.successRows(TOTAL_DEFAULT, this.buildUsers(Optional.ofNullable(userQueryDto.getId()).orElse(ID_DEFAULT), TOTAL_DEFAULT));}/*** 新增用户及设备绑定信息** @param userAddDto 新增参数* @return 响应结果*/@PostMappingpublic RespResult<Integer> addUser(@Validated @RequestBody UserAddDto userAddDto) {log.info("add user, param: {}", userAddDto);return RespResult.successData(1);}/*** 修改用户及设备绑定信息** @param userEditDto 修改参数* @return 响应结果*/@PutMappingpublic RespResult<Integer> updateUser(@Validated @RequestBody UserEditDto userEditDto) {log.info("update user, param: {}", userEditDto);return RespResult.successData(1);}/*** 删除用户信息** @param ids 用户ID列表* @return 响应结果* @apiNote 根据用户ID列表删除用户信息*/@DeleteMapping("/{ids}")public RespResult<Integer> deleteUsers(@NotEmpty @PathVariable List<Long> ids) {log.info("delete users, param: ids={}", ids);return RespResult.successData(ids.size());}//省略...}//=======================================================================================//================================ Model对象层代码 =======================================//=======================================================================================/*** 新增用户参数** @author luohq* @date -01-15 12:21*/@Data@Builderpublic class UserAddDto {/*** 用户名称*/@NotBlank@Size(min = 1, max = 30)private String name;/*** 用户性别(1:男,2:女)*/@NotNull@Range(min = 1, max = 2)private Integer sex;/*** 设备列表*/@NotEmptyprivate List<DeviceAddDto> deviceInfoList;}

启动方式一:

可以直接启动项目,浏览器访问:http://localhost:8080/swagger-ui.html,

启动方式二:

执行mvn verify命令,生成openapi.json到target目录下,拷贝target/openapi.json到应用代码目录resources/static/doc/openapi.json添加application.yaml配置springdoc.swagger-ui.url=/doc/openapi.json(可参见前文smart-doc结合springdoc展示openapi.json)然后再启动项目,浏览器访问:http://localhost:8080/swagger-ui.html

以上两种启动方式的最终展示效果都是一样的,

具体Swagger-ui界面如下图(左边为smart-doc,右边为springdoc javadoc,可以对比着看):

综合对比springdoc-openapi-javadoc和smart-doc,现阶段我还是更倾向于smart-doc,主要原因如下:

smart-doc文档更完善(中文文档对国内开发者更友好😂)smart-doc对注释的支持更完善(如@apiNote及其他自定义注释语法)实际使用过程中javadoc模块和lombok框架冲突,集成javadoc后在Idea开发工具中提示Lombok相关代码编译失败

参考链接:

swagger:

https://swagger.io/

openapi:

OAS2.0 & 3.0 规范 - https://swagger.io/resources/open-api/

OAS3.0规范 - https://swagger.io/specification/

springfox:

http://springfox.github.io/springfox/

http://springfox.github.io/springfox/docs/current/

从Springfox2迁移到SpringDoc - /#migrating-from-springfox

springdoc:

/

/springdoc/springdoc-openapi-maven-plugin

springdoc设置全局response:

/springdoc/springdoc-openapi/issues/114

/springdoc/springdoc-openapi/issues/381

/questions/60869480/default-response-class-in-springdoc

springdoc maven plugin 404报错:

/questions/59616165/what-is-the-function-of-springdoc-openapi-maven-plugin-configuration-apidocsurl

smart-doc:

https://smart-doc-group.github.io/

其他:

Spring Boot 中使用 SpringFox 整合 Swagger 3(OpenAPI 3)生成 API 文档

Spring Boot 中使用 SpringDoc 整合 Swagger 3(OpenAPI 3)生成 API 文档

/spring-rest-openapi-documentation

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。