Spring Boot中使用Swagger2构建API文档
2017-09-11 16:20
267 查看
由于Spring Boot能够快速开发、便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API。而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。
这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:
1)由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳。
2)随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象。
为了解决上面这样的问题,本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful
API。具体效果如下图所示:
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。Swagger 让部署管理和使用功能强大的API从未如此简单。以下是在Springboot中使用方式。
新建Maven工程SpringbootSwagger,在pom.xml添加依赖:
2、创建Swagger2配置类
上面代码通过@Configuration注解,让Spring来加载该类配置。再通过@EnableSwagger2注解来启用Swagger2。再通过createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现
经过这2步配置后,我们启动服务后,访问:http://localhost:8080/swagger-ui.html 就完成了集成。
3、编写Controller测试类
路径为/api/*的controller,可以匹配在SwaggerConfig中配置的api组,代码如下:
路径为/demo/*的controller,可以匹配在SwaggerConfig中配置的demo组,代码如下:
代码中都加了注释,相信有java基础的很容易就看懂,我就不一一解释了。
4、测试集成效果
再次访问:http://127.0.0.1:8080/swagger-ui.html,即可看到效果。
选择默认的api分组:
选择demo分组
这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:
1)由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳。
2)随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象。
为了解决上面这样的问题,本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful
API。具体效果如下图所示:
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。Swagger 让部署管理和使用功能强大的API从未如此简单。以下是在Springboot中使用方式。
1、Springboot集成swagger
新建Maven工程SpringbootSwagger,在pom.xml添加依赖:<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>swagger</groupId> <artifactId>jsx.swagger</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>SpringbootSwagger</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- jdk版本号,angel在这里使用1.8,大家修改为大家本地配置的jdk版本号即可 --> <java.version>1.8</java.version> </properties> <!-- spring boot 父节点依赖, 引入这个之后相关的引入就不需要添加version配置, spring boot会自动选择最合适的版本进行添加。 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> </parent> <dependencies> <!-- spring boot web支持:mvc,aop... --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> </dependencies> </project>这里Swagger版本选择的是2.7.0,解决了前面版本参数结构的写问题。
2、创建Swagger2配置类
package com.springboot.swagger; import com.google.common.base.Predicates; import io.swagger.annotations.Api; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.ResponseEntity; import org.springframework.web.context.request.async.DeferredResult; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList; /** * Swagger配置类: * * @author jiasx * @create 2017/9/11 15:08 **/ @Configuration @EnableSwagger2 public class SwaggerConfig { /** * SpringBoot默认已经将classpath:/META-INF/resources/和classpath:/META-INF/resources/webjars/映射 * 所以该方法不需要重写,如果在SpringMVC中,需要在xml中定义 * 重写该方法需要 extends WebMvcConfigurerAdapter * */ // @Override // public void addResourceHandlers(ResourceHandlerRegistry registry) { // registry.addResourceHandler("swagger-ui.html") // .addResourceLocations("classpath:/META-INF/resources/"); // // registry.addResourceHandler("/webjars/**") // .addResourceLocations("classpath:/META-INF/resources/webjars/"); // } /** * 可以定义多个组,比如本类中定义把test和demo区分开了 * (访问页面就可以看到效果了) */ @SuppressWarnings("unchecked") @Bean public Docket testApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2) .groupName("Api") .genericModelSubstitutes(DeferredResult.class) .useDefaultResponseMessages(false) .forCodeGeneration(true) .pathMapping("/")// base,最终调用接口后会和paths拼接在一起 .select() // .apis(RequestHandlerSelectors.basePackage("com.swagger.test"))//根据包名去过滤接口 .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//根据注解去过滤接口 .paths(Predicates.or(PathSelectors.regex("/api/.*")))//通过路径的方式过滤的接口 .build() .apiInfo(testApiInfo()); ; return docket; } @SuppressWarnings("unchecked") @Bean public Docket demoApi() { return new Docket(DocumentationType.SWAGGER_2) .groupName("Demo") // .genericModelSubstitutes(DeferredResult.class) .genericModelSubstitutes(ResponseEntity.class) .useDefaultResponseMessages(false) .forCodeGeneration(false) .pathMapping("/") .select() // .apis(RequestHandlerSelectors.basePackage("com.swagger.test"))//根据包名去过滤接口 .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//根据注解去过滤接口 .paths(Predicates.or(PathSelectors.regex("/demo/.*")))//过滤的接口 .build() .apiInfo(demoApiInfo()); } private ApiInfo testApiInfo() { ApiInfo apiInfo = new ApiInfo("Test相关接口",//大标题 "Test相关接口,主要用于测试.",//小标题 "1.0",//版本 "http://baidu.com", new Contact("测试人", "", ""),//作者 "一只小蚂蚁",//链接显示文字 "http://baidu.com",//网站链接 new ArrayList<>() ); return apiInfo; } private ApiInfo demoApiInfo() { ApiInfo apiInfo = new ApiInfo("Demo相关接口",//大标题 "Demo相关接口,主要用于demo演示.",//小标题 "1.0",//版本 "http://baidu.com", new Contact("演示人", "", ""),//作者 "一只小蚂蚁",//链接显示文字 "http://baidu.com",//网站链接 new ArrayList<>() ); return apiInfo; } }
上面代码通过@Configuration注解,让Spring来加载该类配置。再通过@EnableSwagger2注解来启用Swagger2。再通过createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现
经过这2步配置后,我们启动服务后,访问:http://localhost:8080/swagger-ui.html 就完成了集成。
3、编写Controller测试类
路径为/api/*的controller,可以匹配在SwaggerConfig中配置的api组,代码如下:
package com.swagger.test; /** * Swagger2默认将所有的Controller中的RequestMapping方法都会暴露,然而在实际开发中,我们并不一定需要把所有API都提现在文档中查看,这种情况下,使用注解@ApiIgnore来解决,如果应用在Controller范围上,则当前Controller中的所有方法都会被忽略,如果应用在方法上,则对应用的方法忽略暴露API。 注解@ApiOperation和@ApiParam可以理解为API说明,如果我们不使用这样注解进行说明,Swagger2也是有默认值的。 */ import io.swagger.annotations.*; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; /** * 增加api注解的控制类 * * @author jiasx * @create 2017-09-09 14:57 **/ @RequestMapping("/api") @RestController @Api(tags = {"Api接口"},description="api接口服务") public class ApiCityController { @PostMapping(value = "/show")// 这里指定RequestMethod,如果不指定Swagger会把所有RequestMethod都输出,在实际应用中,具体指定请求类型也使接口更为严谨。 @ApiOperation(value="测试接口", notes="根据名称查询城市测试接口") public String testStr( @ApiParam(name="name", value="城市姓名",required=true) @RequestParam(name = "name") String cityName){ return "根据名称查询城市成功"; } /** * 查询城市 * @param city * @return */ @PostMapping("get") @ApiOperation(value="查询城市", notes="根据条件查询单个城市",httpMethod = "POST", response = City.class) public City getCity(@RequestBody City city) { city.setProvience("中国分省"); return city; } /** * 查询城市 * @param id * @param name * @param province * @return */ @PostMapping("insert") @ApiOperation(value="新增城市", notes="新增城市",httpMethod = "POST", response = City.class) @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String"), @ApiImplicitParam(name = "name", value = "城市名称", required = true, dataType = "String"), @ApiImplicitParam(name = "province", value = "所属省份", required = true, dataType = "String") }) public City insert(String id,String name,String province) { return new City(id,name,province); } }
路径为/demo/*的controller,可以匹配在SwaggerConfig中配置的demo组,代码如下:
package com.swagger.test; /** * Swagger2默认将所有的Controller中的RequestMapping方法都会暴露,然而在实际开发中,我们并不一定需要把所有API都提现在文档中查看,这种情况下,使用注解@ApiIgnore来解决,如果应用在Controller范围上,则当前Controller中的所有方法都会被忽略,如果应用在方法上,则对应用的方法忽略暴露API。 注解@ApiOperation和@ApiParam可以理解为API说明,多动手尝试就很容易理解了。 如果我们不使用这样注解进行说明,Swagger2也是有默认值的,没什么可说的试试就知道了。 * */ import io.swagger.annotations.*; import org.springframework.web.bind.annotation.*; /** * 增加api注解的控制类 * * @author jiasx * @create 2017-09-09 14:57 **/ @RequestMapping("/demo") @RestController @Api(tags = {"Demo接口"},description="Demo接口服务") public class DemoController { @PostMapping(value = "/show")// 这里指定RequestMethod,如果不指定Swagger会把所有RequestMethod都输出,在实际应用中,具体指定请求类型也使接口更为严谨。 @ApiOperation(value="测试接口", notes="根据名称查询城市测试接口") public String testStr( @ApiParam(name="name", value="城市姓名",required=true) @RequestParam(name = "name") String cityName){ return "根据名称查询城市成功"; } /** * 查询城市 * @param city * @return */ @PostMapping("get") @ApiOperation(value="查询城市", notes="根据条件查询单个城市",httpMethod = "POST", response = City.class) public City getCity(@RequestBody City city) { city.setProvience("中国分省"); return city; } /** * 查询城市 * @param id * @param name * @param province * @return */ @PostMapping("insert") @ApiOperation(value="新增城市", notes="新增城市",httpMethod = "POST", response = City.class) @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String"), @ApiImplicitParam(name = "name", value = "城市名称", required = true, dataType = "String"), @ApiImplicitParam(name = "province", value = "所属省份", required = true, dataType = "String") }) public City insert(String id,String name,String province) { return new City(id,name,province); } }
代码中都加了注释,相信有java基础的很容易就看懂,我就不一一解释了。
4、测试集成效果
再次访问:http://127.0.0.1:8080/swagger-ui.html,即可看到效果。
选择默认的api分组:
选择demo分组
相关文章推荐
- Spring Boot中使用Swagger2构建RESTful API文档
- Spring Boot中使用Swagger2构建RESTful API文档
- SpringBoot开发详解(八) -- 使用Swagger2构建API文档
- 8.5 Spring Boot集成Swagger2构建自动化Rest API文档
- Spring Boot 整合Swagger2构建API文档
- Spring Boot(5)— 使用Swagger2构建强大的RESTful API文档
- 在spring-boot中使用swagger2来构建RESTful API文档
- Springboot中使用Swagger2构建RESTful API文档
- 《Spring Boot极简教程》第14章 Spring Boot集成Swagger2构建自动化Rest API文档
- Spring Boot中使用Swagger2构建API文档
- SpringBoot开发详解(八) -- 使用Swagger2构建API文档
- Spring Boot 2.0.0.M7 中使用Swagger2构建RESTful API文档
- Spring Boot使用Swagger2构建RESTful文档
- Spring Boot中使用Swagger2构建强大的RESTful API文档
- 使用Swagger2构建RESTful API文档遇到的坑
- Spring Boot中使用Swagger2构建强大的RESTful API文档
- Spring Boot 中使用 Swagger2 构建强大的 RESTful API 文档
- Spring Cloud Spring Boot mybatis分布式微服务云架构(十)使用Swagger2构建强大的RESTful API文档(2)
- 使用Swagger2Markup实现API文档的静态部署(二):Markdown和Confluence
- 使用Swagger2Markup实现API文档的静态部署(一):AsciiDoc