SpringBoot学习总结(9)之使用Swagger2构建RESTful API文档

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jokeMqc/article/details/89211754

一、RESR简介

REST 这个词是Roy Thomas Fielding 在他2000 年的博士论文中提出的, Fielding 是一个非常重要的人,他是HTTP 协议( 1.0 版和1.1 版)的主要设计者、Apache 服务器软件的作者之一、Apache 基金会的第一任主席。所以,他的这篇论文发表后,就引起了广泛关注,并且对互联网开发产生了深远的影响。

Fielding 将他对互联网软件的架构原则定名为阻ST ,即Representational State Transfer 的缩写,翻译为“表现层状态转化” 。如果一个架构符合REST 原则,就称它为阻STful 架构。

要理解RESTful 架构,最好的方法就是去理解Representationa l State Transfer 这个词组到底是什么意思,它的每一个词代表了什么含义。如果你把这个名称搞懂了,也就不难体会REST是一种什么样的设计。

  • 资源(Resources)

REST的名称"表现层状态转化"中省略了主语,"表现层"其实指的是“资源”的“表现层”。

所谓的资源,就是网络上的一个实体,或者说是网络上的一个具体的信息,它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实体。你可以用一个URI(统一资源定位符〉指向它,每种资源对应一个特定的URI 。要获取这个资源,访问它的URI就可以,因此U阳就成了每一个资源的地址或独一无二的识别符。

  • 表现层

“资源”是一种信息实体,它可以有多种外在表现形式。我们把“资源”具体呈现出来的形式称为它的“表现层”( Representation ) 。比如,文本可以用txt 格式表现,也可以用HTML格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式:图片可以用JPG 格式表现,也可以用PNG 格式表现。

URI 只代表资源的实体,不代表它的形式。严格地说,有些网址最后的“ .html ”后缀名是不必要的,因为这个后缀名表示格式,属于“表现层”范畴,而URI 应该只代表“资源”的位置。它的具体表现形式应该在HTTP 请求的头信息中用Accep t 和Content-Type 字段指定,这两个字段才是对“表现层”的描述,不过在大部分应用中,通过后缀区分表现层己经足够了。

  • 状态转化

访问一个网站, 就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及数据和状态的变化。

HTTP 协议是一个无状态互联网通信协议, 这意味着所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”( State Transfer )。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。

客户端用到的手段只能是HTTP 协议。具体来说, HTTP 协议里有5 个常用的表示操作方式的动词: GET 、POST 、PUT 、DELETE 、PATCH 。它们分别对应5 种基本操作: GET 用来获取资源, POST 用来新建资源(也可以用于更新资源) , PUT 用来更新资源, DELETE 用来删除资源, PATCH 用来更新资源的部分属性。

1.1 REST风格的架构

现在流行的各种Web 框架,包括Spring Boot 都支持REST 开发,阻ST 井非是一种技术或者规范,而是一种架构风格,这种架构风格逐渐被各种编程语言的Web 框架所支持。它包括了REST 架构中如何标识资源,如何标识操作接口及操作的版本,如何标识操作的结果等, 主要内容如下:

  • 使用“ api ” 作为Web 上下文:
  • 增加版本标识:
  • 标识资源:
  • REST 中的HTTP Method;
  • REST 中的HTTP Status 。

1.2 使用“ api ” 作为Web 上下文

建议使用“ api ”作为上下文,如:

http://192.168.0.1/api

1.3 增加版本标识

http://192.168.0.1/api/vl.1

也有的做法是将版本信息放到HTTP 头中,但这里推荐还是通过U 虹来体现,这样使得REST 的相关代码更加容易阅读。

1.4 标识资源

将资源名称放到U也中,如果资源有层级关系,则放入层级关系:

http://192.168.0.1/api/vl.l/user

如果用户属于系统管理,也可以这么写:

http://192.168.0.1/api/vl.1/system/user

1.5 确定HTTP Method

在REST 中, HTTP Method 常常对应以下含义:

  • POST ,代表增加资源;
  • PUT ,代表更改资源,客户端提供需完整的资源属性:
  • GET ,代表查询资源;
  • PATCH ,更新资源,客户端提供仅需要更改的资源属性;
  • DELETE ,通常用于删除资源;
  • HEAD ,类似GET ,但仅仅只有HTTP 头信息,头信息包含了需要查找的信息:
  • OPTIONS ,用于获取URI 所支持的方法,响应信息会在HTTP 头中包含一个名为“ Allow ”的头,值是所支持的方法,如“ GET 、POST '’ 。

RESTful是一种软件架构设计风格,之目前互联网最流行的一个软件设计架构,他有一下几个优点。

  • 架构清晰
  • 符合标准
  • 易于理解
  • 扩展方便

在之前的博客也介绍了SpringBoot能够快速开发,敏捷部署等。所以现在很多的人都在SpringBoot中构建RESTful API,而我们构建RESTful API的原因往往是由于多个终端的原因,而这些终端共同使用很多底层业务逻辑。因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。

这样,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:

  1. 由于接口众多,而且细节复杂,需要考虑不同的HTTP请求类型,HTTP头部内容,HTTP请求内容等。那么随之带来的问题就是维护出一份高质量的文档就变得十分的困难。
  2. 并且随着时间久了,之前的接口可能因为需求变更或者改造,在我们修改接口的同时还要去修改这份接口文档,增加程序员的工作难度,并且可能有些因为忘记更新接口文档,导致接口与文档不一致的现象。

所以,这里将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。具体效果如下图所示:

1.1 RESTful 具体设计如下

二、Swagger2

Swagger2是一款让你更好的书写API文档的规范且完整框架。提供描述、生产、消费和可视化RESTful Web Service。是由庞大工具集合支撑的形式化规范。这个集合涵盖了从终端用户接口、底层代码库到商业API管理的方方面面.

它的出现就是为了方便进行测试后台的restful形式的接口,实现动态的更新,当我们在后台的接口修改了后,swagger可以实现自动的更新,而不需要认为的维护这个接口进行测试。

三、SpringBoot与Swagger2集成

3.1 修改pom文件,增加swagger2坐标

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

3.2 编写swagger2配置类

Application.java(启动类)同级创建Swagger2的配置类Swagger2,这个配置类的作用相当是说明书,在这个类中我们会使用注解来进行启动swagger。

package com.mqc;

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;

/**
 * @author maoqichuan
 * @ClassName: SwaggerConfig
 * @description: springboot整合使用swagger2
 * @Configuration 让spring加载该配置类
 * @EnableSwagger2:该注解的作用是用来标记启动swagger2
 * 注意:E在Springboot中nable*一般是用来开启啥功能的注解
 * @date 2019-04-1114:50
 **/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    /**
     * @description: swagger2的配置文件,这里可以配置swagger2的信息,如扫描的包等
     * @return Docket
     * @throws
     * @author maoqichuan
     * @date 2019-04-11 14:55
     */
    @Bean
    public Docket createDocket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.mqc.web"))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * @description: 构建api文档的详细函数
     * @return ApiInfo
     * @throws
     * @author maoqichuan
     * @date 2019-04-11 14:56
     */
    public ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                // 页面的标题
                .title("SpringBoot整合使用swagger2")
                //创建人
                .contact("jokerMqc")
                //api描述
                .description("更多springboot学习教程,请关注:https://blog.csdn.net/jokeMqc")
                //版本号
                .version("1.0")
                .build();
    }
}

@Configuration 让spring加载该配置类,@EnableSwagger2:该注解的作用是用来标记启动swagger2,在Springboot中nable*一般是用来开启啥功能的注解。

3.3 编写RESTful风格的controller

package com.mqc.web;

import com.mqc.model.User;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author maoqichuan
 * @ClassName: RestFulController
 * @description: springboot整合swagger2
 * @date 2019-04-1114:46
 **/
@RestController
@RequestMapping("/users")
public class RestFulController {

    /**
     * @description: 获取用户列表,注意RequestMapping的value为空,而请求的方法则要求为get
     * @return List<User>
     * @throws
     * @author maoqichuan
     * @date 2019-04-11 15:42
     */
    @ApiOperation(value = "获取用户列表",notes = "获取用户的列表")
    @RequestMapping(value = "",method = RequestMethod.GET)
    public List<User> getUserList(){
        List<User> list =  new ArrayList<>();

        list.add(new User("zhangsan","1557700194",21));
        list.add(new User("list","15577343194",24));
        list.add(new User("王五","15343700194",26));
        return list;
    }

    /**
     * @description: 创建用户
     * @return String
     * @throws
     * @author maoqichuan
     * @date 2019-04-11 15:43
     */
    @ApiOperation(value = "创建用户",notes = "创建用户")
    @ApiImplicitParam(name = "user",value = "用户实体详细信息",required = true,dataType ="User")
    @RequestMapping(value = "",method = RequestMethod.POST)
    public String postUser(User user){
        //调用对应的service增加用户信息
        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 new User("zhangsan","1557700194",21);
    }

    @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,User user) {
        // 这里调用对应的service更新用户信息
        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) {
        //调用service删除对应的用户
        return "success";
    }
}

到这里,我们springboot与swagger2的整合已经完毕了,我们启动项目,在浏览器输入http://localhost:8080/swagger-ui.html,便可以看到:

这些便是我们刚刚写的接口,swagger2也为我们提供的强大的测试功能,我们点击对应的接口进入:

点击 Try it out!便可以调用我们的接口,之后便返回服务器给我们返回的结果。

到这里,SpringBoot整合使用swagger2已经整合完毕了,记得关注我,我会把每次我学到的都会用博客纪录下来,让我们一起加油,一起进步!

猜你喜欢

转载自blog.csdn.net/jokeMqc/article/details/89211754