关闭

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

标签: Swaggerspringboot
2826人阅读 评论(0) 收藏 举报
分类:

概述

通常我们要构建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官方网站

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:38099次
    • 积分:1219
    • 等级:
    • 排名:千里之外
    • 原创:82篇
    • 转载:15篇
    • 译文:0篇
    • 评论:1条
    个人连接