SpringBoot&Swagger构建REST API并生成API文档

##概述
通常我们要构建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中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YT813S8K-1591961823853)(https://img-blog.csdn.net/20170419183042208?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvempjamF2YQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]

##API文档访问与调试

先添加数据
这里写图片描述

在上图请求的页面中,我们看到user的Value是个输入框?是的,Swagger除了查看接口功能外,还提供了调试测试功能,我们可以点击上图中右侧的Model Schema(黄色区域:它指明了User的数据结构),此时Value中就有了user对象的模板,我们只需要稍适修改,点击下方“Try it out!”按钮,即可完成了一次请求调用!

此时,你也可以通过几个GET请求来验证之前的POST请求是否正确。

相比为这些接口编写文档的工作,我们增加的配置内容是非常少而且精简的,对于原有代码的侵入也在忍受范围之内。因此,在构建RESTful API的同时,加入swagger来对API文档进行管理,是个不错的选择。

完整结果示例可查看github

携带token

参考资料
https://cloud.tencent.com/developer/article/1642728

参考信息

Swagger官方网站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值