文档交互、API开发框架Swagger的简单学习

  • Post author:
  • Post category:其他




Swagger


https://mp.weixin.qq.com/s?__biz=Mzg2NTAzMTExNg==&mid=2247483909&idx=1&sn=201ee629b9ce3b9276a263e18812e607&scene=19#wechat_redirect

学习目标:

  • 了解 Swagger 的概念以及作用
  • 了解前后端分离
  • 在 SpringBoot 中集成 Swagger



1、前后端分离



1.1 未分离时期

早期前后端未分离时期,通常都是使用传统的 MVC 架构,通过 JSP 和 Servlet 来实现

在这里插入图片描述

所有的请求都被发送给作为控制器的 Servlet,它接受请求,并根据请求信息将它们分发给适当的 JSP 来响应。同时,Servlet 还根据 JSP 的需求生成 JavaBeans 的实例并输出给 JSP 环境。JSP 可以通过直接调用方法或使用 UseBean 的自定义标签得到 JAVABeans 中的数据。需要说明的是,这个 View 还可以采用 Velocity、Freemaker 等模板引擎。使用了这些模板引擎,可以使得开发过程中的人员分工更加明确,还能提高开发效率。

那么,在这个时期,开发方式有如下两种:


方式一

:

在这里插入图片描述


方式二

在这里插入图片描述

方式二已经逐渐淘汰。主要原因有两点:

  • 前端在开发过程中严重依赖后端,在后端没有完成的情况下,前端根本无法干活。
  • 由于趋势问题,会JSP,懂velocity,freemarker的前端越来越少。

因此,方式二逐渐不被采用。然而,不得不说一点,方式一,其实很多小型传统软件公司至今还在使用。那么,方式一和方式二具有哪些共同的缺点呢?


  1. 前端无法单独调试

    在项目上线后,遇到一些问题。比如样式出问题了,由于前端不具备项目开发环境,那么就有可能出现如下对话

    前端 :“我这里没问题啊。后端,你那里正常么?”

    后端 :“我这里不正常啊。要不你过来看一下吧?”

    前端 :“一时我也看不出问题,我也没环境,怎么办?”

    后端 :“你没环境,坐我这边调吧。”

    然后,前端就满脸不爽的在你那调代码了。更有些情商低的后端就直接在旁边开摁手机,实在是。。。。。

    总结,因为前端无法单独调试。一方面开发效率降低。另一方面,还有可能引发公司内部人员上的矛盾。


  2. 前端不可避免会遇到后台代码

    比如前端可能碰到如下结构的代码

    <body>
        <%
        request.setCharacterEncoding("utf-8");
        String name=request.getParameter("username");
        out.print(name);
        %>
    </body>
    

    身为前端,在页面里看到了后台代码,必然内心是十分不快的,这种方式

    耦合性太强

    。那么,就算你用了 freemarker 等模板引擎,不能写 JAVA 代码。那前端也不可避免的要去重新学习该模板引擎的模板语法,无谓增加了前端的学习成本。

    正如我们后端开发不想写前端一样,你想想如果你的后台代码里嵌入前端代码,你是什么感受?因此,这种方式十分不妥。


  3. JSP本身所导致的一些其他问题

    比如,JSP 第一次运行的时候比较缓慢,因为里头包含一个翻译为 Servlet 的步骤。再比如因为同步加载的原因,在 jsp 中有很多内容的情况下,页面响应会很慢。



1.2 半分离时期

前后端半分离,前端负责开发页面,通过接口(Ajax)获取数据,采用 dom 操作对页面进行数据绑定,最终是由前端把页面渲染出来。这也就是其他博客里说的,Ajax 与 SPA 应用(单页应用)结合的方式。其结构图如下:

在这里插入图片描述

步骤如下:

  1. 浏览器请求,cdn 返回 html 页面
  2. html 中的 js 代码以 ajax 方式请求后台的 restful 接口
  3. 接口返回 json 数据,页面解析 json 数据,通过 dom 操作渲染页面


为什么说是半分离的?

因为不是所有页面都是单页面应用,在多页面应用的情况下,前端因为没有掌握 controller 层,前端需要跟后端讨论,我们这个页面是要同步输出呢,还是异步 json 渲染呢?因此,在这一阶段,只能算半分离。


这种方式的优缺点有哪些呢?

首先,这种方式的优点是很明显的。前端不会嵌入任何后台代码,前端专注于 html、css、js 的开发,不依赖于后端。自己还能够模拟 json 数据来渲染页面。发现 bug,也能迅速定位出是谁的问题,不会出现互相推脱的现象。

然而,在这种架构下,还是存在明显的弊端的。最明显的有如下几点:

  1. js 存在大量冗余,在业务复杂的情况下,页面的渲染部分的代码,非常复杂。
  2. 在 json 返回的数据比较大的情况下,渲染的十分缓慢,会出现页面卡顿的情况
  3. seo 非常不方便,由于搜索引擎的爬虫无法爬下js异步渲染的数据,导致这样的页面,SEO 会存在一定的问题。
  4. 资源消耗严重,在业务复杂的情况下,一个页面可能要发起多次 http 请求才能将页面渲染完毕。可能有人不服,觉得 pc 端建立多次 http 请求也没啥。那你考虑过移动端么,知道移动端建立一次 http 请求需要消耗多少资源么?

正是因为如上缺点,真正的前后端分离架构诞生了



1.3 分离时期

在这一时期,扩展了前端的范围。认为 controller 层也属于前端的一部分。在这一时期


  • 前端:负责 View(视图层) 和 Controller 层(前端控制层)。


    • 可以伪造后端数据(Json)

  • 后端:只负责后端控制层,服务层,数据访问层。


  • 前后端通过 API 进行交互


  • 前后端相对独立,松耦合


  • 前后端可以部署到不同的服务器上


前后端分离产生的问题

  • 前后端集成联调,前端人员和后端人员无法做到

    及时协商,建造解决

    ,最终导致问题的集中爆发


解决方案

  • 要制定好 schema(计划提纲),实时更新最新的 API,降低集成的风险
  • 前端测试后端接口:postman 等等
  • 后端提供接口,需要实时更新最新的消息以及改动


前后端分离的窘境从而孕育了一个框架的出现,Swagger!



2、Swagger 简介

Swagger 号称为世界上最为流行的 API 框架

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RestFul 风格的 Web 服务。

Swagger 的目标是对 Rest API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。


Swagger 的优势

  • 流行的 API 框架
  • RestFul API 文档在线自动生成工具(支持 API 自动生成同步的在线文档,API 文档与 API 定义同步更新)
  • 提供 Web 页面在线测试 API(参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口)
  • 支持多种语言:Java、Php 等等



3、SpringBoot 集成 Swagger

Swagger 官网:

https://swagger.io

使用 Swagger 需要:

  • springfox
  • swagger2
  • ui


集成 Swagger 步骤

  1. 新建一个 SpringBoot 项目(Web 项目)

  2. 编写一个 hello 程序,测试一下

  3. 导入相关依赖

    • swagger2

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

      <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger-ui</artifactId>
          <version>2.9.2</version>
      </dependency>
      
  4. 配置 Swagger 的配置文件(SwaggerConfig)

    • 最简洁的 SwaggerConfig 配置文件

      @Configuration // 等价于 Component
      @EnableSwagger2 // 开启 Swagger2
      public class SwaggerConfig {
          
      }
      

      看上去什么都没配置,其实有很多默认的配置

  5. 测试运行,访问

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

    在这里插入图片描述



4、配置 Swagger

在 Swagger 配置文件中,配置 Swagger 的 Docket 的 bean 实例,通过源码可知,同时可以配置 apiInfo等等的信息,如下:

// 默认配置
public Docket(DocumentationType documentationType) {
    this.apiInfo = ApiInfo.DEFAULT;
    this.groupName = "default";
    this.enabled = true;
    this.genericsNamingStrategy = new DefaultGenericTypeNamingStrategy();
    this.applyDefaultResponseMessages = true;
    this.host = "";
    this.pathMapping = Optional.absent();
    this.apiSelector = ApiSelector.DEFAULT;
    this.enableUrlTemplating = false;
    this.vendorExtensions = Lists.newArrayList();
    this.documentationType = documentationType;
}

手动配置

package com.aze.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;

import java.util.ArrayList;

@Configuration // 等价于 Component
@EnableSwagger2 // 开启 Swagger2
public class SwaggerConfig {

    // 配置 Swagger 的 Docket 的 bean 实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
    }

    // 配置 Swagger 信息:apiInfo
    private ApiInfo apiInfo(){
        // 作者信息
        Contact contact = new Contact("开完喜", "https://blog.csdn.net/qq_34172440?spm=1001.2014.3001.5343", "aze1031952566@163.com");
        return new ApiInfo("阿泽的 Swagger API 文档"
                , "卟卟车"
                , "v1.0"
                , "https://blog.csdn.net/qq_34172440?spm=1001.2014.3001.5343"
                , contact
                , "Apache 2.0"
                , "http://www.apache.org/licenses/LICENSE-2.0"
                , new ArrayList());
    }

}

配置完成后,访问

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

进行测试

在这里插入图片描述



5、Swagger 配置扫描接口

docket.select().apis().paths().build()

  • se;ect().build():这是一套东西,apis 以及 paths 都只能在其中间添加
  • apis():配置扫描的方式

    • RequestHandlerSelectors:配置要扫描接口的方式

      • basePackage:指定要扫描的包
      • any():扫描所有
      • none():都 不扫描
      • withClassAnnotation():扫描类上的注解,需要指定参数,参数是一个注解的反射对象,例如:

        RestController.class
      • withMethodAnnotation():扫描方法上的注解,也是需要指定方法上注解的反射对象
  • paths():配置过滤的方式

    • PathSelectors:配置过滤路径的方式

      • ant():指定路径
      • any():过滤所有
      • none():都不过滤
// 配置 Swagger 的 Docket 的 bean 实例
@Bean
public Docket docket(){
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.aze.controller"))
            .paths(PathSelectors.ant("/aze/**"))
            .build();
}



6、配置是否启动 Swagger


enable()

:是否启动 Swagger,如果为 false 则不能在浏览器中访问 Swagger

// 配置 Swagger 的 Docket 的 bean 实例
@Bean
public Docket docket(){
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            // enable():是否启动 Swagger,如果为 false 则不能在浏览器中访问 Swagger
            .enable(false)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.aze.controller"))
            //.paths(PathSelectors.ant("/aze/**"))
            .build();
}


开发过程问题:怎样使 Swagger 在生产环境中使用,在发布的时候不使用?

  • 判断是否是生产环境

  • 注入 enable(flag)

    步骤:

    1. 在 resource 目录下,修改并添加配置文件

      在这里插入图片描述

      • application-dev.yaml(生产环境)

        server:
          port: 8081 
        
      • application-pro.yaml(发布环境)

        server:
          port: 8082
        
      • application.yaml

        # 选择环境
        spring:
          profiles:
            active: dev
        
    2. 修改 Swagger 的配置文件

      在这里插入图片描述

      // 配置 Swagger 的 Docket 的 bean 实例
      @Bean
      public Docket docket(Environment environment){
      
          // 设置需要显示 Swagger 的环境
          Profiles profiles = Profiles.of("dev");
          // 通过
          boolean flag = environment.acceptsProfiles(profiles);
      
          return new Docket(DocumentationType.SWAGGER_2)
                  .apiInfo(apiInfo())
                  // enable():是否启动 Swagger,如果为 false 则不能在浏览器中访问 Swagger
                  .enable(flag)
                  .select()
                  .apis(RequestHandlerSelectors.basePackage("com.aze.controller"))
                  //.paths(PathSelectors.ant("/aze/**"))
                  .build();
      }
      
    3. 测试



7、配置 API 文档的分组


groupName(“组名”)

.groupName("aze")


问题:协同开发中,如何配置多个分组?

  • 配置多个 Docket 实例,放入 Bean 容器中即可

    @Bean
    public Docket docket1(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("开发人员A");
    }
    
    @Bean
    public Docket docket2(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("开发人员B");
    }
    
    ...
        
    



8、配置注释

配置实体类注释

  • @Api(“注释”)
  • @ApiModel(“xxx实体类”):作用于类上
  • @ApiModelProperty(“xxx”):作用于属性

配置 controller 注释:

  • ApiOperation(“xxx控制类”):作用于方法上

Swagger的所有注解定义在io.swagger.annotations包下

下面列一些经常用到的,未列举出来的可以另行查阅说明:

Swagger注解 简单说明
@Api(tags = “xxx模块说明”) 作用在模块类上
@ApiOperation(“xxx接口说明”) 作用在接口方法上
@ApiModel(“xxxPOJO说明”) 作用在模型类上:如VO、BO
@ApiModelProperty(value = “xxx属性说明”,hidden = true) 作用在类方法和属性上,hidden设置为true可以隐藏该属性
@ApiParam(“xxx参数说明”) 作用在参数、方法和字段上,类似@ApiModelProperty



拓展:不同的 UI 界面

我们可以导入不同的包实现不同的皮肤定义:

  1. 默认的

    访问

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

<dependency> 
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.9.2</version>
</dependency>
  1. bootstrap-ui

    访问

    http://localhost:8080/doc.html

<!-- 引入swagger-bootstrap-ui包 /doc.html-->
<dependency>
   <groupId>com.github.xiaoymin</groupId>
   <artifactId>swagger-bootstrap-ui</artifactId>
   <version>1.9.1</version>
</dependency>
  1. Layui-ui

    访问

    http://localhost:8080/docs.html

<!-- 引入swagger-ui-layer包 /docs.html-->
<dependency>
   <groupId>com.github.caspar-chen</groupId>
   <artifactId>swagger-ui-layer</artifactId>
   <version>1.1.3</version>
</dependency>
  1. mg-ui

    访问

    http://localhost:8080/document.html

<!-- 引入swagger-ui-layer包 /document.html-->
<dependency>
   <groupId>com.zyplayer</groupId>
   <artifactId>swagger-mg-ui</artifactId>
   <version>1.0.6</version>
</dependency>



版权声明:本文为qq_34172440原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。