澳门新葡萄京官网注册 7

澳门新葡萄京官网注册在Spring REST API中使用Swagger2进行文档管理

本文由码农网 –
Pansanday原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

    上一篇我们介绍了如何使用Spring Boot快速构建RESTful API “Spring
Boot与RESTful API”
,本篇则介绍一个配合Spring Boot快速构建RESTful文档的工具

写在前面

澳门新葡萄京官网注册 ,使用RESTful
API作为Web服务对外提供服务的入口,基本上已经成为了标准,在提供REST
API的同时,如何进行
API文档管理是一个较为麻烦的事情,作为开发人员我们都了解API文档的重要性,但总是嫌其编写的麻烦,Swagger的
出现很好地帮我们解决文档编写的事情,开发人员可以采取自己喜欢的姿势进行API文档编写,例如使用Swagger-Editor
进行API的提前设计,进而使用Swagger-Codegen来生成多种语言的客户端代码,使用Swagger-UI来进行API文档
的直观查看,当然你也可以在代码中直接进行API文档的编写,本教程将介绍如何在Spring
REST API项目中,进行
Swagger2的集成,这样便可以很方便地进行API文档编写了。

在本篇教程中将使用Springfox的Swagger实现来集成,关于 Swagger2 和
Springfox 的介绍如下:

  • Swagger 2
  • Springfox

在上一篇文章中,我谈到了使用Spring Boot创建RESTFul服务的经验。当创建一个REST
API的时候,合适的文档是很重要的一部分。

    由于Spring Boot具有快速开发、便捷部署的特点,很多用户会使用Spring
Boot构建RESTful
API,一个RESTful接口往往对应不止一个终端,有WEB端、安卓端、IOS端等等。正因为这样,一个接口可能要面对多个开发人员或者团队,为了减少沟通来带的时间成本,大家往往会准备一个RESTful
API的文档,但是这种文档往往有几个致命的问题:

项目配置

本教程将假设你已经有了一个Spring
REST服务,如果没有话,可以参考Spring官方项目示例:

Building a RESTful Web
Service

Swagger是什么

Swagger(Swagger 2)是描述和记录REST
API的一个规范。它指定了REST
Web服务的格式,包括URL,资源,方法等。Swagger将从应用程序代码生成文档,并处理渲染部分。

在这篇文章中,我会将Swagger 2文档集成到基于Spring Boot的REST
Web服务中。我将使用Springfox实现来生成swagger文档。如果你想知道是如何运行/构建Spring
Boot项目的,请参考我上一篇文章。

Springfox提供了两个依赖关系来生成API文档和Swagger
UI。如果你不希望将Swagger UI集成到你的API中,则无需添加Swagger
UI依赖关系。

<dependency>

<groupId>io.springfox</groupId>

<artifactId>springfox-swagger2</artifactId>

<version>2.7.0</version>

</dependency>

<dependency>

<groupId>io.springfox</groupId>

<artifactId>springfox-swagger-ui</artifactId>

<version>2.7.0</version>

</dependency>

@
EnableSwagger2注解启用了Springfox
Swagger在类中的支持。为了记录这个服务,Springfox使用了一个Docket类。Docket有助于配置要记录的服务,并通过名称等进行分组。后台是Springfox通过使用基于Spring配置的API语义,在运行时检查应用程序。换句话说,你必须创建一个使用Spring的@Configuration注解的Spring
Java Configuration类。

在我的例子中,我会生成一个基于我添加的RestController类的swagger文档。

import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class ApplicationConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.chandana.helloworld.controllers"))
                .paths(PathSelectors.any())
                .build();
    }
}

由于我添加了两个控制器,因此将分别对每个控制器相关的API进行分组(标记)。

澳门新葡萄京官网注册 1

开箱即用,Springfox提供了5种断言,它们分别是any,none,withClassAnnotation,withMethodAnnotation和basePackage【译者注:参见springfox.documentation.builders. RequestHandlerSelectors类】

  1. 由于接口过多,细节复杂,文档本身构建起来就比较麻烦
  2. 随着时间的推移,接口往往会修改或者废弃,这就需要对所有调用方同步文档,如果出现遗漏,很容易造成接口调用失败

添加Maven依赖

在你的Spring REST项目中添加maven依赖,打开项目的pom.xml,添加如下内容:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.6.1</version>
</dependency>

ApiInfo

Swagger提供了一些默认值,例如“API文档”,“通过联系人电子邮件创建”,“Apache
2.0”。当然你可以通过添加apiInfo(ApiInfo
apiInfo)方法来更改这些默认值。ApiInfo类包含有关API的自定义信息。

@Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.chandana.helloworld.controllers"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo getApiInfo() {
        Contact contact = new Contact("Chandana Napagoda", "http://blog.napagoda.com", "cnapagoda@gmail.com");
        return new ApiInfoBuilder()
                .title("Example Api Title")
                .description("Example Api Definition")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .contact(contact)
                .build();
    }

一旦添加了ApiInfo,生成的文档看起来就像这样:

澳门新葡萄京官网注册 2

    为了解决以上问题,就要介绍一下Swagger2,它可以很简单的整合到Spring
Boot中,它可以组织出强大的RESTful API文档。效果如图:

在项目中集成Swagger2

Controller和POJO层文档

@Api注解用于说明每个控制器类(有点像类注释)。

@ApiOperation注解用于描述资源和方法。

@ApiResponse注解用于说明操作返回的其他响应值。例如:200
ok或202 accepted等

@ApiModelProperty注解用来描述POJO(Bean)类的属性(属性描述)。

添加上述注释后,最终生成的swagger文档如下所示:

澳门新葡萄京官网注册 3

Spring RestController类:

package com.chandana.helloworld.controllers;

import com.chandana.helloworld.bean.Greeting;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
@Api(value = "user", description = "Rest API for user operations", tags = "User API")
public class HelloWorldController {

    @RequestMapping(value = "/hello/{name}", method = RequestMethod.GET, produces = "application/json")
    @ApiOperation(value = "Display greeting message to non-admin user", response = Greeting.class)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "OK"),
            @ApiResponse(code = 404, message = "The resource not found")
    }
    )
    public Greeting message(@PathVariable String name) {
        Greeting msg = new Greeting(name, "Hello " + name);
        return msg;
    }
}

Greeting模型类:

package com.chandana.helloworld.bean;

import io.swagger.annotations.ApiModelProperty;

public class Greeting {

    @ApiModelProperty(notes = "Provided user name", required =true)
    private String player;

    @ApiModelProperty(notes = "The system generated greeting message" , readOnly =true)
    private String message;

    public Greeting(String player, String message) {
        this.player = player;
        this.message = message;
    }

    public String getPlayer() {
        return player;
    }

    public void setPlayer(String player) {
        this.player = player;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

AppConfig类:

package com.chandana.helloworld.config;

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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class ApplicationConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.chandana.helloworld.controllers"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo getApiInfo() {
        Contact contact = new Contact("Chandana Napagoda", "http://blog.napagoda.com", "cnapagoda@gmail.com");
        return new ApiInfoBuilder()
                .title("Example Api Title")
                .description("Example Api Definition")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .contact(contact)
                .build();
    }
}

你也可以从我的GitHub repo 下载  Swagger Spring Boot
Project 源代码。

译者注:

  1. 如果你对Spring Boot不是很熟悉,建议先fork下源码,因为有些依赖文中没有提到。
  2. 启动Spring Boot后,在浏览器中输入:127.0.0.1:8080/swagger-ui.html即可查看生成的文档信息。

在生成的文档页面中,可以输入参数,点击“Try it
out!”即可进行接口测试,有点类似于Postman的功能。

澳门新葡萄京官网注册 4

集成Swagger2

首先创建一个SwaggerConfiguration类,如下:

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {                                    
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)  
          .select()                                  
          .apis(RequestHandlerSelectors.any())              
          .paths(PathSelectors.any())                          
          .build();                                           
    }
}

通过使用@EnableSwagger2注解来开启Swagger2,在整个类中最重要的便是Docket的Bean,Docket定义了
Swagger的版本、需要暴露的API等信息,我们来看看Docket生成后都做了些什么工作:

  1. 创建一个Docket对象
  2. 调用select()方法,生成ApiSelectorBuilder对象实例,该对象负责定义外漏的API入口
  3. 通过使用RequestHandlerSelectorsPathSelectors来提供Predicate,在此我们使用any()方法,将所有API都通过Swagger进行文档管理

如果你的项目是一个Spring
Boot项目,上面的配置已经OK了,可以开始进行API文档的编写了,但如果你的项目
不是Spring Boot项目,只是Spring项目的话,需要稍微多做些工作。

    此次以上篇文章的代码为例对Swagger2进行讲解。

非Spring Boot项目中,配置Resource Handler

由于没有使用Spring Boot,这样就不能自动配置Resource
Handler,需要自己进行下配置,因为我们接下来要使用
Swagger
UI,它有些静态资源需要加载,新建一个类,继承WebMvcConfigurerAdapter并使用@EnableWebMvc注解,然后添加如下代码,如果你已经有了一个这样的类,可以进行将以下代码添加至该类:

@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/");
}

导入Swagger2依赖

    在pom.xml中添加对Swagger2的依赖

<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>

体验成果

假设我是使用Spring REST官方示例项目的话,打开浏览器,输入:

http://localhost:8080/v2/api-docs

你应该会看到JSON格式的API文档,如下图所示:

澳门新葡萄京官网注册 5

Swagger2 API Docs

这样的JSON文件,读起来是很不方便的,接下来我们用Swagger UI来进行查看。

创建Swagger2类

    Swagger2类需要与Application.java同级

@Configuration
@EnableSwagger2
public class Swagger2 {
    @Bean
    public Docket createRestApi() {
        //需要配置正确需要扫面的的包名
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.wangxin.restapi"))
                .paths(PathSelectors.any())
                .build();
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2构建RESTful APIs")
                .description("更多Spring Boot相关文章请关注:https://my.oschina.net/wangxincj/blog/")
                .termsOfServiceUrl("https://my.oschina.net/wangxincj/blog/")
                .contact("老虎是个蛋蛋")
                .version("1.0")
                .build();
    }
}

    如上所示,

  • 添加@Configuration注解,表示让Spring在启动时加载该配置
  • @EnableSwagger2表示在Spring Boot中启动Swagger2
  • createRestApi方法创建Docket的Bean
  • apiInfo()用来创建该API的基本信息
  • ApiInfoBuilder实力来控制那些接口需要暴露给Swagger来展现

Swagger UI

Swagger UI提供了Web页面以方便开发人员查看API文档等。

添加文档内容注解

   
我们通过使用@ApiOperation注解对接口进行描述,通过@ApiImplicitParam和@ApiImplicitParams对参数进行描述

@RestController
@RequestMapping("/book")
public class BookController {
    public static Map<String,Book> bookMap = new HashMap<String,Book>();

    /**
     * 添加一本书
     * @param book
     * @return
     */
    @ApiOperation(value="创建一本书", notes="创建一本书")
    @ApiImplicitParam(name = "book", value = "book实体bean", required = true, dataType = "Book")
    @RequestMapping(value="",method = RequestMethod.POST)
    public String postBook (@ModelAttribute Book book){
        bookMap.put(book.getIsbn(),book);
        return "SUCCESS";
    }

    /**
     * 查询出所有book集合
     * @return
     */
    @ApiOperation(value="查询出所有book集合", notes="")
    @RequestMapping(value={""},method = RequestMethod.GET)
    public List<Book> getBookList (){
        List<Book> bookList = new ArrayList<Book>(bookMap.values());
        return bookList;
    }

    /**
     * 根据ISBN获取book
     * @param isbn
     * @return
     */
    @ApiOperation(value="图书详细信息", notes="根据url的isbn来获取图书详细信息")
    @ApiImplicitParam(name = "isbn", value = "ISBN", required = true, dataType = "String")
    @RequestMapping(value="/{isbn}",method = RequestMethod.GET)
    public Book getBook(@PathVariable String isbn){
        Book book = bookMap.get(isbn);
        return book;
    }

    /**
     * 更新book参数
     * @param isbn
     * @param book
     * @return
     */
    @ApiOperation(value="更新图书详细信息", notes="根据url的ISBN来指定更新对象,并根据传过来的book信息来更新图书详细信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "isbn", value = "ISBN", required = true, dataType = "String"),
            @ApiImplicitParam(name = "book", value = "图书详细实体book", required = true, dataType = "Book")
    })
    @RequestMapping(value="/{isbn}",method = RequestMethod.PUT)
    public String putBook(@PathVariable String isbn, @ModelAttribute Book book){
        Book b = bookMap.get(isbn);
        b.setAuthor(book.getAuthor());
        b.setName(book.getName());
        bookMap.put(isbn,b);
        return "SUCCESS";
    }

    /**
     * 根据isbn删除book
     * @param isbn
     * @return
     */
    @ApiOperation(value="删除图书", notes="根据url的ISBN来指定删除图书")
    @ApiImplicitParam(name = "isbn", value = "ISBN", required = true, dataType = "String")
    @RequestMapping(value="/{isbn}",method = RequestMethod.DELETE)
    public String deleteBook(@PathVariable String isbn){
        bookMap.remove(isbn);
        return "SUCCESS";
    }
}

    完成以上操作,我们启动Spring
Boot,访问,即可看到Swagger2生成的RESTful
API,如下:

澳门新葡萄京官网注册 6

集成Swagger UI

在项目pom.xml中引入:

<dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.1</version>
</dependency>

在此运行示例项目,在浏览器中输入:

http://localhost:8080/swagger-ui.html

可以看到如下Web页面:

澳门新葡萄京官网注册 7

Swagger UI

API调试

    Swagger2不仅可以生成API文档,还可以在线调试接口,如上图,有两种填写参数方式,第一种是在Parameter列表项中有Book对象需要填写的参数,大家可以根据实际情况填写参数值;第二种方式我们可以点击上图中右侧的Model
Schema(黄色区域:它指明了Book的数据结构),此时Value中就有了book对象的模板,我们只需要稍适修改。填写完参数点击“Try
it out!”即可完成接口请求。

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

  • swagger官网

 

写在后面

到此你已经成功地在项目中集成了Swagger2,接下来可以使用Springfox的注解进行API文档编写了,详细阅读:

http://springfox.github.io/springfox/docs/current/

发表评论

电子邮件地址不会被公开。 必填项已用*标注