这篇文章主要介绍“java集成开发SpringBoot生成接口文档的方法是什么”,在日常操作中,相信很多人在java集成开发SpringBoot生成接口文档的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java集成开发SpringBoot生成接口文档的方法是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
作为一名程序员,我们最讨厌两件事:1. 别人不写注释。2. 自己写注释。
而作为一名接口开发者,我们同样讨厌两件事:
1. 别人不写接口文档,文档不及时更新。
2. 需要自己写接口文档,还需要及时更新。
相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。
而随着Springboot、Springcloud等微服务的流行,每个项目都有成百上千个接口调用,这时候再要求人工编写接口文档并且保证文档的实时更新几乎是一件不可能完成的事,所以这时候我们迫切需要一个工具,一个能帮我们自动化生成接口文档以及自动更新文档的工具。它就是Swagger。
Swagger 提供了一个全新的维护 API 文档的方式,有4大优点:
自动生成文档:只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。
跨语言性,支持 40 多种语言。
Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,省去了准备复杂的调用参数的过程。
还可以将文档规范导入相关的工具(例如 SoapUI), 这些工具将会为我们自动地创建自动化测试。
现在我们知道了Swagger的作用,接下来将其集成到我们项目中。
集成Swagger很简单,只需要简单三步。
<!--swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!--swagger-ui--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
application.properties 加入配置
# 用于控制是否开启Swagger,生产环境记得关闭Swagger,将值设置为 false springfox.swagger2.enabled = true
增加一个swagger配置类
@Configuration @EnableSwagger2 @ConditionalOnClass(Docket.class) public class SwaggerConfig { private static final String VERSION = "1.0"; @Value("${springfox.swagger2.enabled}") private Boolean swaggerEnabled; @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2) .enable(swaggerEnabled) .groupName("SwaggerDemo") .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) .paths(PathSelectors.any()) .build(); } /** * 添加摘要信息 */ private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("接口文档") .contact(new Contact("JAVA日知录","http://javadaily.cn","jianzh6@163.com")) .description("Swagger接口文档") .version(VERSION) .build(); } }
这里通过 .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
表面给加上 @Api注解的类自动生成接口文档。
@RestController @Api(tags = "参数校验") @Slf4j @Validated public class ValidController { @PostMapping("/valid/test1") @ApiOperation("RequestBody校验") public String test1(@Validated @RequestBody ValidVO validVO){ log.info("validEntity is {}", validVO); return "test1 valid success"; } @ApiOperation("Form校验") @PostMapping(value = "/valid/test2") public String test2(@Validated ValidVO validVO){ log.info("validEntity is {}", validVO); return "test2 valid success"; } @ApiOperation("单参数校验") @PostMapping(value = "/valid/test3") public String test3(@Email String email){ log.info("email is {}", email); return "email valid success"; } }
通过 @Api
注解标注需要生成接口文档,通过 @ApiOperation
注解标注接口名。
同时我们给 ValidVO
也加上对应的注解
@Data @ApiModel(value = "参数校验类") public class ValidVO { @ApiModelProperty("ID") private String id; @ApiModelProperty(value = "应用ID",example = "cloud") private String appId; @NotEmpty(message = "级别不能为空") @ApiModelProperty(value = "级别") private String level; @ApiModelProperty(value = "年龄") private int age; ... }
通过 @ApiModel
标注这是一个参数实体,通过 @ApiModelProperty
标注字段说明。
简单三步,我们项目就集成了Swagger接口文档,赶紧启动服务,访问 http://localhost:8080/swagger-ui.html 体验一下。
好吧,出了点小问题,不过不用慌。
出现这个问题的原因是因为我们加上了 ResponseBodyAdvice
统一处理返回值/响应体,导致给Swagger的返回值也包装了一层,UI页面无法解析。可以通过 http://localhost:8080/v2/api-docs?group=SwaggerDemo观察Swagger返回的json数据。
既然知道了问题原因那就很好解决了,我们只需要在ResponseBodyAdvice处理类中只转换我们自己项目的接口即可。
@RestControllerAdvice(basePackages = "com.jianzh6.blog") @Slf4j public class ResponseAdvice implements ResponseBodyAdvice<Object> { ... }
通过添加basePackage属性限定统一返回值的范围,这样就不影响Swagger了。
重启服务器再次访问swagger接口地址,就可以看到接口文档页面了。
Swagger2.9.2有个bug,就是当我们参数实体有int类型的参数时,打开Swagger接口页面时后端会一直提示异常:
java.lang.NumberFormatException: For input string: "" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Long.parseLong(Long.java:702) at java.base/java.lang.Long.valueOf(Long.java:1144)
有两种解决方案:
给int类型的字段使用@ApiModelPorperty
注解时添加example属性
@ApiModelProperty(value = "年龄",example = "10") private int age;
去除原swagger中的swagger-models
和swagger-annotations
,自行引入高版本的annotations和models
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> <exclusions> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> </exclusion> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.5.22</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>1.5.22</version> </dependency>
集成Swagger过程中虽然会出现两个小问题,解决后我们就可以愉快享受Swagger给我们带来的便利了。
Swagger原生UI有点丑,我们可以借助Swagger的增强工具 knife4j
优化一下。
<!--整合Knife4j--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.4</version> </dependency>
由于knife4j中已经带了 swagger-annotations和 swagger-models的依赖,所以我们可以把上文中手动添加的两个依赖删除。
@Configuration @EnableSwagger2 @ConditionalOnClass(Docket.class) @EnableKnife4j public class SwaggerConfig { ... }
通过上面两步我们就完成了Swagger的美化,通过浏览器访问 http://localhost:8080/doc.html 即可看到效果。
看到这里的同学心理肯定会想,就这?这就是老鸟的做法?跟我们新手也没啥区别呀
别急,我们先来看一个效果。
首先我们定义了两个接口,一个新增,一个编辑
@ApiOperation("新增") @PostMapping(value = "/valid/add") public String add(@Validated(value = {ValidGroup.Crud.Create.class}) ValidVO validVO){ log.info("validEntity is {}", validVO); return "test3 valid success"; } @ApiOperation("更新") @PostMapping(value = "/valid/update") public String update(@Validated(value = ValidGroup.Crud.Update.class) ValidVO validVO){ log.info("validEntity is {}", validVO); return "test4 valid success"; }
注意看,这里用的是同一个实体 ValidVO
来接收前端参数,只不过使用了参数校验中的分组,然后我们打开kife4j页面观察两者的接口文档有何不同。
新增:
编辑:
通过上面可以看到,虽然用于接受参数的实体一样,但是当分组不一样时展示给前端的参数也不一样,这就是Swagger的分组功能。
当然原生的Swagger是不支持分组功能的,我们需要对Swagger进行扩展。我已经将代码上传到了github上,由于代码量比较多这里就不展示了,大家可以自行查阅。
引入扩展类后还需要在Swagger配置类 SwaggerConfig
中注入对应的Bean。
@Configuration @EnableSwagger2 @ConditionalOnClass(Docket.class) @EnableKnife4j public class SwaggerConfig { ... @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupOperationModelsProviderPlugin groupOperationModelsProviderPlugin() { return new GroupOperationModelsProviderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupModelBuilderPlugin groupModelBuilderPlugin() { return new GroupModelBuilderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupModelPropertyBuilderPlugin groupModelPropertyBuilderPlugin() { return new GroupModelPropertyBuilderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupExpandedParameterBuilderPlugin groupExpandedParameterBuilderPlugin() { return new GroupExpandedParameterBuilderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupOperationBuilderPlugin groupOperationBuilderPlugin() { return new GroupOperationBuilderPlugin(); } @Bean @Primary @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupModelAttributeParameterExpander groupModelAttributeParameterExpander(FieldProvider fields, AccessorsProvider accessors, EnumTypeDeterminer enumTypeDeterminer) { return new GroupModelAttributeParameterExpander(fields, accessors, enumTypeDeterminer); } }
@Null(groups = ValidGroup.Crud.Create.class) @NotNull(groups = ValidGroup.Crud.Update.class,message = "应用ID不能为空") @ApiModelProperty(value = "应用ID",example = "cloud") private String appId;
当新增场景的时候,appId为空,不需要传值; 当修改场景的时候,appId不能为空,需要传值 ;其他没有配置组的皆为默认组(Default)
@ApiOperation("新增") @PostMapping(value = "/valid/add") public String add(@Validated(value = {ValidGroup.Crud.Create.class}) ValidVO validVO){ log.info("validEntity is {}", validVO); return "test3 valid success"; }
当前接口会针对默认组的bean属性进行校验,同时针对保存常见的属性进行校验。
到此,关于“java集成开发SpringBoot生成接口文档的方法是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。