SpringBoot&Swagger构建REST API并生成API文档
2017-04-19 18:36
1116 查看
概述
通常我们要构建API 服务,自然少不了文档,但由于API与文档的分离使得我们每次对API进行的更改都需要再去修改文档后同步文档,不但编写稳定繁琐而且稍有纰漏难免就会出现调用的异常,而编写、同步文档通常是比较繁琐无趣的事。现在得益于Spring Boot 与Swagger,我们不但可以极速的搭建REST、RESTful风格的API服务并且还可以生成优美、强大的在线或离线API文档。开始
引入Maven依赖<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>com.bamboo</groupId> <artifactId>springboot-1-1</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-1-1</name> <url>http://maven.apache.org</url> <repositories><!--ali 代码库 --> <repository> <id>maven-ali</id> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> <updatePolicy>always</updatePolicy> <checksumPolicy>fail</checksumPolicy> </snapshots> </repository> </repositories> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <!-- spring boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.0.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <dependencies> <!-- spring boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 引入 spring-boot -swagger 并生成优美的API文档--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.2.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
其他依赖和springboot入门的要求一样
application.properties
# \u76D1\u542C\u7AEF\u53E3 server.port=8080
Application.java
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @Api(value = "springboot服务",description="简单的计算服务API") @RestController @SpringBootApplication public class Application extends SpringBootServletInitializer { @RequestMapping("/") String home() { return "sms server"; } @ApiOperation("查询城市") @RequestMapping("/city") String city(String id) { return "杭州"; } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
配置文件swagger2
package com; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class Swagger2 { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("API文档构建Restful Api") .description("更多Spring Boot相关文章请关注:http://www.xialeme.com/") .termsOfServiceUrl("http://www.xialeme.com/") .contact("zjcjava@163.com") .version("1.0") .build(); } }
设置扫描的根目录
apis(RequestHandlerSelectors.basePackage(“com”))
UserController.java
package com; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; /** * @Title: UserController.java * @Package com * @Description: TODO(用一句话描述该文件做什么) * @author bamboo <a href="mailto:zjcjava@163.com?subject=hello,bamboo&body=Dear Bamboo:%0d%0a描述你的问题:">Bamboo</a> * @date 2017年4月19日 下午2:48:25 * @version V1.0 */ @Api(value = "users接口",description="users服务API根目录") @RestController @RequestMapping(value="/users") // 通过这里配置使下面的映射都在/users下,可去除 public class UserController { static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>()); @ApiOperation(value="获取用户列表", notes="") @RequestMapping(value={""}, method=RequestMethod.GET) public List<User> getUserList() { List<User> r = new ArrayList<User>(users.values()); return r; } @ApiOperation(value="创建用户", notes="根据User对象创建用户") @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User") @RequestMapping(value="", method=RequestMethod.POST) public String postUser(@RequestBody User user) { users.put(user.getId(), user); return "success"; } @ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息") @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long") @RequestMapping(value="/{id}", method=RequestMethod.GET) public User getUser(@PathVariable Long id) { return users.get(id); } @ApiOperation(value="更新用户详细信息", notes="根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"), @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User") }) @RequestMapping(value="/{id}", method=RequestMethod.PUT) public String putUser(@PathVariable Long id, @RequestBody User user) { User u = users.get(id); u.setName(user.getName()); u.setAge(user.getAge()); users.put(id, u); return "success"; } @ApiOperation(value="删除用户", notes="根据url的id来指定删除对象") @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long") @RequestMapping(value="/{id}", method=RequestMethod.DELETE) public String deleteUser(@PathVariable Long id) { users.remove(id); return "success"; } }
注解说明
其中@ApiOperation和@ApiParam为添加的API相关注解,个参数说明如下:@ApiOperation(value = “接口说明”, httpMethod = “接口请求方式”, response = “接口返回参数类型”, notes = “接口发布说明”;其他参数可参考源码;
@ApiParam(required = “是否必须参数”, name = “参数名称”, value = “参数具体描述”
在上面只展示了如何使用,这里将对上面添加的swagger注解进行说明,笔记使用时参考了swagger annotations Api 手册,接下来进行部分常用注解使用说明介绍。
- @ApiIgnore 忽略注解标注的类或者方法,不添加到API文档中
@ApiOperation 展示每个API基本信息
value api名称
notes 备注说明
@ApiImplicitParam 用于规定接收参数类型、名称、是否必须等信息
name 对应方法中接收参数名称
value 备注说明
required 是否必须 boolean
paramType 参数类型 body、path、query、header、form中的一种
body 使用@RequestBody接收数据 POST有效
path 在url中配置{}的参数
query 普通查询参数 例如 ?query=q ,jquery ajax中data设置的值也可以,例如 {query:”q”},springMVC中不需要添加注解接收
header 使用@RequestHeader接收数据
form 笔者未使用,请查看官方API文档
dataType 数据类型,如果类型名称相同,请指定全路径,例如 dataType = “java.util.Date”,springfox会自动根据类型生成模型
@ApiImplicitParams 包含多个@ApiImplicitParam
@ApiModelProperty 对模型中属性添加说明,例如 上面的PageInfoBeen、BlogArticleBeen这两个类中使用,只能使用在类中。
value 参数名称
required 是否必须 boolean
hidden 是否隐藏 boolean
其他信息和上面同名属性作用相同,hidden属性对于集合不能隐藏,目前不知道原因
@ApiParam 对单独某个参数进行说明,使用在类中或者controller方法中都可以。注解中的属性和上面列出的同名属性作用相同
以上为主要常用的注解介绍,请结合springfox使用查看
给一个各个参数类型的demo
@Controller @RequestMapping(value = "/v1/api") public class HomeApiController{ //这里使用POST @RequestBody必须使用POST才能接收,这里方便讲解 @ApiOperation(value = "一个测试API", notes = "第一个测试API") @ResponseBody @RequestMapping(value = "/test/{path}", method = RequestMethod.POST) @ApiImplicitParams({ @ApiImplicitParam(name = "blogArticleBeen", value = "文档对象", required = true, paramType = "body", dataType = "BlogArticleBeen"), @ApiImplicitParam(name = "path", value = "url上的数据", required = true, paramType = "path", dataType = "Long"), @ApiImplicitParam(name = "query", value = "query类型参数", required = true, paramType = "query", dataType = "String"), @ApiImplicitParam(name = "apiKey", value = "header中的数据", required = true, paramType = "header", dataType = "String") }) public JSONResult test(@RequestBody BlogArticleBeen blogArticleBeen, @PathVariable Long path, String query, @RequestHeader String apiKey, PageInfoBeen pageInfoBeen){ System.out.println("blogArticleBeen.getLastUpdateTime():"+blogArticleBeen.getLastUpdateTime()); System.out.println("blogArticleBeen.getSorter():"+blogArticleBeen.getSorter()); System.out.println("path:"+path); System.out.println("query:"+query); System.out.println("apiKey:"+apiKey); System.out.println("pageInfoBeen.getNowPage():"+pageInfoBeen.getNowPage()); System.out.println("pageInfoBeen.getPageSize():"+pageInfoBeen.getPageSize()); JSONResult jsonResult = new JSONResult(); jsonResult.setMessage("success"); jsonResult.setMessageCode(null); jsonResult.setCode(0); jsonResult.setBody(null); return jsonResult; } }
运行效果
运行application.java如下图http://localhost:8080/swagger-ui.html
点击user接口 会显示所有扫描的接口路径,但是视乎和我们想要的不太一样,如果不在接口的mapping中加入method则会把所有的可能都会显示到doc中
API文档访问与调试
先添加数据在上图请求的页面中,我们看到user的Value是个输入框?是的,Swagger除了查看接口功能外,还提供了调试测试功能,我们可以点击上图中右侧的Model Schema(黄色区域:它指明了User的数据结构),此时Value中就有了user对象的模板,我们只需要稍适修改,点击下方“Try it out!”按钮,即可完成了一次请求调用!
此时,你也可以通过几个GET请求来验证之前的POST请求是否正确。
相比为这些接口编写文档的工作,我们增加的配置内容是非常少而且精简的,对于原有代码的侵入也在忍受范围之内。因此,在构建RESTful API的同时,加入swagger来对API文档进行管理,是个不错的选择。
完整结果示例可查看github
参考信息
Swagger官方网站
相关文章推荐
- 使用Spring Boot&Swagger快速构建REST API并生成优美的API文档
- SpringBoot + mybatis + Swagger快速构建REST API并生成优美的API文档
- Springboot | SpringBoot 微服务整合Swagger生成API文档
- spring boot rest接口自动生成文档(包含swagger)
- 基于spring-boot使用Swagger构建restful api文档
- Swagger2 生成 Spring Boot API 文档
- SpringCloud SpringBoot mybatis 分布式微服务(二十三)Restdoc生成api文档
- SpringCloud SpringBoot mybatis 分布式微服务(二十九)Restdoc生成api文档
- 使用 SpringBoot + Swagger 生成接口 API 文档
- Spring boot结合swagger自动生成api文档
- Spring Boot如何让Web API自动生成文档,并解决swagger-annotations的API注解description属性废弃的问题
- spring-boot整合swagger生成在线api文档
- SpringBoot:番外篇SpringBoot+Swagger生成可视图的API文档
- SwaggerUI自动生成API文档(SwaggerUI+SpringBoot)
- 在Spring中使用Springfox和swagger生成restful风格的API文档
- 利用Swagger Maven Plugin生成Rest API文档
- springboot集成swagger2构建RESTful API文档
- spring boot+swagger 生成Restful风格API
- Spring Boot中使用Swagger2构建API文档
- SpringBoot非官方教程 | 第十篇: 用spring Restdocs创建API文档