spring boot REST 通过Swagger2生成接口文档(含例子源码下载)

作者 xqlee
浏览次数 267


一、使用背景

    如今,REST和微服务已经有了很大的发展势头。但是,REST规范中并没有提供一种规范来编写我们的对外REST接口API文档。每个人都在用自己的方式记录api文档,因此没有一种标准规范能够让我们很容易的理解和使用该接口。我们需要一个共同的规范和统一的工具来解决文档的难易理解文档的混乱格式。
    Swagger(在谷歌、IBM、微软等公司的支持下)做了一个公共的文档风格来填补上述问题。在本博客中,我们将会学习怎么使用Swagger的swagger 2注解去生成REST API文档。

二、本博客将会讲解以下内容

  1. 什么是Swagger?
  2. 项目结构和技术堆栈
  3. 创建REST api文档
  4. Swagger2的配置
  5. Swagger2注释的使用
  6. 一个简单的例子

三、什么是Swagger?

    Swagger(现在是“开放API计划”)是一种规范和框架,它使用一种人人都能理解的通用语言来描述REST API。还有其他一些可用的框架,比如RAML、求和等等,但是,考虑到它在开发者社区中的特性和接受度,在这个时候,Swagger是最受欢迎的。

    它提供了人类可读和机器可读的文档格式。它提供了JSON和UI支持。JSON可以用作机器可读的格式,而 Swagger-UI 是用于可视显示的,通过浏览api文档,人们很容易理解它。

四、项目结构和技术堆栈

  项目结构图如下:
项目结构图
  我们将在这个演示中使用下面的技术
  1. Eclipse开发工具
  2. Maven 构建工具
  3. Spring Boot 应用框架
  4. Spring Rest 的REST API框架
  5. Swagger2 来作为REST API文档框架
  6. Java 1.8

五、创建REST api

    我们将首先创建一些REST api接口,这些api接口将用于演示Swagger的文档功能。我们将使用Spring boot风格来显示rest API,以获得更快的开发时间。

    1.去spring boot官网创建一个web带Rest接口依赖的spring boot项目。提供其他maven GAV坐标并下载该项目。这个屏幕看起来是这样的:
spring  boot    解压缩并将项目导入到Eclipse中,作为现有的maven项目。在此步骤中,将从maven存储库下载所有必需的依赖项。在这个步骤中执行一个新的mvn清洁安装,这样所有spring boot相关的依赖组件都得到了正确的下载。

2.打开application.properties配置文件。添加以下属性。他将会从 /swagger2-democontext 路径启动应用.
server.contextPath=/swagger2-demo
3.添加一个REST的contrller,名称为Swagger2DemoRestController,他将会为学生实体提供基本的基于REST的功能。
Swagger2DemoRestController.java
package com.example.springbootswagger2.controller;
 
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.springbootswagger2.model.Student;
 
@RestController
public class Swagger2DemoRestController {
 
    List<Student> students = new ArrayList<Student>();
    {
        students.add(new Student("Sajal", "IV", "India"));
        students.add(new Student("Lokesh", "V", "India"));
        students.add(new Student("Kajal", "III", "USA"));
        students.add(new Student("Sukesh", "VI", "USA"));
    }
 
    @RequestMapping(value = "/getStudents")
    public List<Student> getStudents() {
        return students;
    }
 
    @RequestMapping(value = "/getStudent/{name}")
    public Student getStudent(@PathVariable(value = "name") String name) {
        return students.stream().filter(x -> x.getName().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0);
    }
 
    @RequestMapping(value = "/getStudentByCountry/{country}")
    public List<Student> getStudentByCountry(@PathVariable(value = "country") String country) {
        System.out.println("Searching Student in country : " + country);
        List<Student> studentsByCountry = students.stream().filter(x -> x.getCountry().equalsIgnoreCase(country))
                .collect(Collectors.toList());
        System.out.println(studentsByCountry);
        return studentsByCountry;
    }
 
    @RequestMapping(value = "/getStudentByClass/{cls}")
    public List<Student> getStudentByClass(@PathVariable(value = "cls") String cls) {
        return students.stream().filter(x -> x.getCls().equalsIgnoreCase(cls)).collect(Collectors.toList());
    }
}

Student.java
package com.example.springbootswagger2.model;
 
public class Student {
     
    private String name;
    private String cls;
    private String country;
 
    public Student(String name, String cls, String country) {
        super();
        this.name = name;
        this.cls = cls;
        this.country = country;
    }
 
    public String getName() {
        return name;
    }
 
    public String getCls() {
        return cls;
    }
 
    public String getCountry() {
        return country;
    }
 
    @Override
    public String toString() {
        return "Student [name=" + name + ", cls=" + cls + ", country=" + country + "]";
    }
}
4.以spring boot方式启动这个程序应用。测试下面的一两个REST端点来检查他们是否正常工作:
  • http://localhost:8080/swagger2-demo/getStudents
  • http://localhost:8080/swagger2-demo/getStudent/sajal
  • http://localhost:8080/swagger2-demo/getStudentByCountry/india
  • http://localhost:8080/swagger2-demo/getStudentByClass/v

六、配置Swagger2

我们的REST api已经准备好了。现在,我们为项目增加swagger 2 的支持

6.1首先添加Swagger2 的maven依赖库

打开项目中的pom.xml文件,添加以下两个swagger依赖。springfox-swagger2 、springfox-swagger-ui
<dependency>
       <groupId>io.springfox</groupId>
       <artifactId>springfox-swagger2</artifactId>
       <version>2.6.1</version>
</dependency>
 
<dependency>
       <groupId>io.springfox</groupId>
       <artifactId>springfox-swagger-ui</artifactId>
       <version>2.6.1</version>
</dependency>

提示:实际上,Swagger的API有两种类型,并在不同的工件中维护。今天我们将使用springfox,因为这个版本可以很好地适应任何基于spring的配置。我们还可以很容易地尝试其他配置,这应该提供相同的功能——配置中没有任何变化。
 

6.2添加Swagger2配置

使用Java config的方式添加配置。为了帮助你理解这个配置,我在代码中写了相关的注释
package com.example.springbootswagger2.configuration;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.google.common.base.Predicates;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
 
@Configuration
@EnableSwagger2
public class Swagger2UiConfiguration extends WebMvcConfigurerAdapter 
{
    @Bean
    public Docket api() {
        // @formatter:off
        //Register the controllers to swagger
        //Also it is configuring the Swagger Docket
        return new Docket(DocumentationType.SWAGGER_2).select()
                // .apis(RequestHandlerSelectors.any())
                .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
                // .paths(PathSelectors.any())
                // .paths(PathSelectors.ant("/swagger2-demo"))
                .build();
        // @formatter:on
    }
 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
    {
        //enabling swagger-ui part for visual documentation
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

6.3验证Swagger2的JSON格式文档

    maven构建并启动服务器。打开链接http://localhost:8080/swagger2-demo/v2/api-docs,会生成一个JSON格式的文档。这并不是那么容易理解和理解的,实际上Swagger已经提供该文档在其他三方工具中使用,例如当今流行的API管理工具,它提供了API网关、API缓存、API文档等功能。
JSON格式文档

6.4验证Swagger2 UI文档

    打开链接 http://localhost:8080/swagger2-demo/swagger-ui.html 在浏览器中来查看Swagger UI文档

swagger2 UI文档6.5Swagger2 注解的使用

默认生成的API文档很好,但是它们缺乏详细的API级别信息。Swagger提供了一些注释,可以将这些详细信息添加到api中。如。
@Api –我们可以添加这个注解在controller上,去添加一个基本的controller说明
@Api(value = "Swagger2DemoRestController", description = "REST APIs related to Student Entity!!!!")
@RestController
public class Swagger2DemoRestController {
    //...
}
@ApiOperation and @ApiResponses – 我们添加这个注解到任何controller的rest方法上来给方法添加基本的描述。例如:
@ApiOperation(value = "Get list of Students in the System ", response = Iterable.class, tags = "getStudents")
@ApiResponses(value = { 
            @ApiResponse(code = 200, message = "Success|OK"),
            @ApiResponse(code = 401, message = "not authorized!"), 
            @ApiResponse(code = 403, message = "forbidden!!!"),
            @ApiResponse(code = 404, message = "not found!!!") })
 
@RequestMapping(value = "/getStudents")
public List<Student> getStudents() {
    return students;
}
在这里,我们可以向方法中添加标签,来在swagger-ui中添加一些分组。
@ApiModelProperty – 这个注解用来在数据模型对象中的属性上添加一些描述,会在Swagger UI中展示模型的属性。例如:
@ApiModelProperty(notes = "Name of the Student",name="name",required=true,value="test name")
private String name;
Controller 和 Model 类添加了swagger2注解之后,代码清单:
Swagger2DemoRestController.java
package com.example.springbootswagger2.controller;
 
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.springbootswagger2.model.Student;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
 
@Api(value = "Swagger2DemoRestController", description = "REST Apis related to Student Entity!!!!")
@RestController
public class Swagger2DemoRestController {
 
    List<Student> students = new ArrayList<Student>();
    {
        students.add(new Student("Sajal", "IV", "India"));
        students.add(new Student("Lokesh", "V", "India"));
        students.add(new Student("Kajal", "III", "USA"));
        students.add(new Student("Sukesh", "VI", "USA"));
    }
 
    @ApiOperation(value = "Get list of Students in the System ", response = Iterable.class, tags = "getStudents")
    @ApiResponses(value = { 
            @ApiResponse(code = 200, message = "Suceess|OK"),
            @ApiResponse(code = 401, message = "not authorized!"), 
            @ApiResponse(code = 403, message = "forbidden!!!"),
            @ApiResponse(code = 404, message = "not found!!!") })
 
    @RequestMapping(value = "/getStudents")
    public List<Student> getStudents() {
        return students;
    }
 
    @ApiOperation(value = "Get specific Student in the System ", response = Student.class, tags = "getStudent")
    @RequestMapping(value = "/getStudent/{name}")
    public Student getStudent(@PathVariable(value = "name") String name) {
        return students.stream().filter(x -> x.getName().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0);
    }
 
    @ApiOperation(value = "Get specific Student By Country in the System ", response = Student.class, tags = "getStudentByCountry")
    @RequestMapping(value = "/getStudentByCountry/{country}")
    public List<Student> getStudentByCountry(@PathVariable(value = "country") String country) {
        System.out.println("Searching Student in country : " + country);
        List<Student> studentsByCountry = students.stream().filter(x -> x.getCountry().equalsIgnoreCase(country))
                .collect(Collectors.toList());
        System.out.println(studentsByCountry);
        return studentsByCountry;
    }
 
    // @ApiOperation(value = "Get specific Student By Class in the System ",response = Student.class,tags="getStudentByClass")
    @RequestMapping(value = "/getStudentByClass/{cls}")
    public List<Student> getStudentByClass(@PathVariable(value = "cls") String cls) {
        return students.stream().filter(x -> x.getCls().equalsIgnoreCase(cls)).collect(Collectors.toList());
    }
}
Student.java
package com.example.springbootswagger2.model;
 
import io.swagger.annotations.ApiModelProperty;
 
public class Student 
{
    @ApiModelProperty(notes = "Name of the Student",name="name",required=true,value="test name")
    private String name;
 
    @ApiModelProperty(notes = "Class of the Student",name="cls",required=true,value="test class")
    private String cls;
 
    @ApiModelProperty(notes = "Country of the Student",name="country",required=true,value="test country")
    private String country;
 
    public Student(String name, String cls, String country) {
        super();
        this.name = name;
        this.cls = cls;
        this.country = country;
    }
 
    public String getName() {
        return name;
    }
 
    public String getCls() {
        return cls;
    }
 
    public String getCountry() {
        return country;
    }
 
    @Override
    public String toString() {
        return "Student [name=" + name + ", cls=" + cls + ", country=" + country + "]";
    }
}

七、例子

现在,当我们的REST api得到适当的注释时,让我们看看最终的输出。打开http://localhost:8080 / swagger2-demo / swagger-ui。在浏览器中查看Swagger ui 文档。
ui

demo源码下载
暂无评论
站内搜索
搜索
广而告之(广告说明)
加入QQ群(641395244)
qq group
支持博客发展
support
推荐博客
暂无推荐
分享本文