Swagger,说白了其实就是专门为解决前后端开发人员的矛盾而生的,既可以有效解决前后端开发人员协商、沟通不及时的问题,也可以在很大程度上提高工作效率。Swagger号称世界上最流行的API框架。
对于后端开发人员来说,有了Swagger之后,不用再手写Wiki接口拼大量参数,避免手写错误;对代码侵入性低,采用全注解的方式,开发简单;方法参数名修改、新增、减少参数都可以直接生效,不用手动维护。
缺点:增加了开发成本,写接口还得再写一套参数配置
对前端开发来说,后端只需要定义好接口,会自动生成文档,接口功能、参数一目了然;联调方便,如果出了问题,直接测试接口,实时检查参数和返回值,就可以快速定位是前端还是后端的问题。
对于测试人员来说,操作简单,不用了解具体代码就可以操作进行相关测试。
在我们的项目中集成Swagger时,首先必须导入相应的包和依赖。具体操作如下:
1.新建一个Spring Boot项目。命名为swagger。在maven仓库中找到相应的swagger的包,并添加相应依赖于项目中。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.编写一个hello工程。在swagger包下新建一个controller的包,并新建一个HelloControl的java文件。
HelloController.java文件
package com.example.swagger.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping(value = "/hello")
public String hello() {
return "Hello World !";
}
}
测试运行:
3.配置swagger。编写SwaggerConfig文件。
SwaggerConfig.java文件:
package com.example.swagger.config;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
//开启Swagger
@EnableSwagger2
public class SwaggerConfig {
}
虽然是个空的文件,但是本身就有默认的页面,此时我们访问swagger-ui.html网站,就会得到以下页面。
以上界面是swagger本身的默认界面,我们可以看到此界面能够被分成四部分,即swagger信息、接口信息、实体类信息Models和组信息(选择框)。但是此时我们只是做了swagger的集成工作,还没有对其进行配置呢。那么,配置的时候,swagger有一个自己的Bean实例Docket,我们只需要配置这个Docket即可。我们对Docket进行配置之后就会发现我们在进入这个html界面时,和上面展示的完全不一样,因为我们使用Docket覆盖了其本身的配置。
其实这些关于Swagger的配置信息,我们都可以从源码中得到,关于默认的界面是如何配置,以及如何修改配置等。
public class ApiInfo {
public static final Contact DEFAULT_CONTACT = new Contact("", "", "");
public static final ApiInfo DEFAULT;
private final String version;
private final String title;
private final String description;
private final String termsOfServiceUrl;
private final String license;
private final String licenseUrl;
private final Contact contact;
private final List<VendorExtension> vendorExtensions;
}
之前说过,swagger-ui.html可以被分为四部分,其中有一部分叫做接口信息,我们点进去会发现,有众多的接口。
为什么会有这么多的请求方式呢?这是因为我们在使用RequestMapping的时候没有指定具体的请求方式,所以它才会展示出所有的请求方式。那么,我们如何才能让Swagger不扫描所有接口,而由我们自定义扫描呢?这就是我们接下来要处理的事情,配置swagger扫描接口。
swagger配置扫描接口的时候是通过Docket的select()方法来实现的。
public Docket docket() {
Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
//配置要扫描接口的方式,指定只扫描controller包下的方法
.select().apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
.build();
return docket;
}
启动运行之后我们发现,之前的接口信息里现在只有hello-controller接口了。
除此之外,我们还可以配置是否启动swagger。这个其实挺简单的,通过源码可知道,只需要修改一个参数而已。
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;
}
public Docket docket() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo()).enable(false);
return docket;
}
我们发现,网页显示找不到,让我们看控制台,其实控制台也没有。
如果说,我们只需要swagger在生产环境中使用,不让其在发布的时候使用。那我们又该如何处理呢?这就涉及到了多环境配置文件的情况。我们需要首先判断是不是生产环境,如果不是,那就直接设置enable参数为false就行。
首先,我们新创建两个不同环境下的配置文件,并做简单的端口的配置,在主配置文件中选择我们要使用的环境。
之后我们在SwaggerConfig.java的 配置文件中判断我们的环境是否为开发环境,如果是,则配置swagger。
public Docket docket(Environment environment) {
//设置要显示swagger的环境
Profiles profiles = Profiles.of("dev");
//通过environment.acceptsProfiles()来判断是否处在自己设定的环境中
boolean flag = environment.acceptsProfiles(profiles);
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag);
return docket;
}
判断我们的环境是否为"dev"环境,并返回一个布尔值,让这个布尔值去作为enable的值,直接来控制swagger的启动与否。如上代码所示,我们选择在开发环境下启动swagger的配置,而且我们在配置文件中也确实选择了开发环境,那么启动运行之后效果如下。需要注意的是,我们修改了开发环境的端口号,所以不能再使用8080端口去访问了。
接下来我们考虑配置一下swagger的组信息,即之前提到过的swagger的主页被分为四部分中的右上角的组信息,默认分组为default。
配置组信息就是修改一下groupName()。
//配置swagger组信息
public Docket docket() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo()).groupName("张三");
return docket;
}
启动之后,我们看到,组信息已经明显被改掉了。
但是,这样的话我们只设置了一个分组。我们如果要设置多个分组的话要如何做呢?首先,我们需明白,这个分组的出现是因为docket实例的出现,那么我们就可以使用多个docket实例来设置多个分组。
@Bean
public Docket docket1() {
Docket docket = new Docket(DocumentationType.SWAGGER_2).groupName("ABC");
return docket;
}
@Bean
public Docket docket2() {
Docket docket = new Docket(DocumentationType.SWAGGER_2).groupName("abc");
return docket;
}
@Bean
public Docket docket3() {
Docket docket = new Docket(DocumentationType.SWAGGER_2).groupName("@#$");
return docket;
}
如上所示,我们新建了三个docket实例,需要注意的是,每个docket实例,都必须使用@Bean。加上之前的,现在我们有四个分组了,我们启动程序看一下。
在创建docket实例时,组名的选择不要使用特殊符号,不然会出错。由于我们新增加的三个docket实例没有配置apiInfo()文档信息,所以还是默认的接口信息和swagger信息等。但是我们"张三"组使用了自己配置的swagger文档信息。
这样的话我们就完成了swagger的多个分组的配置,我们其实可以理解,当多个组在协同工作时,就可以选择自己所在的组了,而每个组对swagger的 配置可能不一样,就像我们示例给出的那样,有配置了的,有没配置的,那么这种多样性可能在协同工作的时候就体现出来了。
那么此时我们对接口信息、swagger基本信息和分组信息都做了一些操作,swagger界面的四个部分如今就只剩下实体类models了。既然models是个实体类,那么我们首先新建一个实体类User。
在新建实体类之前,我们发现,在ABC组中,它的实体类是空的。
我们在pojo文件下创建User实体类,内容如下:
package com.example.swagger.pojo;
public class User {
public String name;
public String pwd;
}
并在HelloController.java文件中添加其获取方式:
@RestController
public class HelloController {
@GetMapping(value = "/hello")
public String hello() {
return "Hello World !";
}
//只要我们的接口中,返回值中存在实体类,就会被扫描到swagger中
@PostMapping(value = "/user")
public User user() {
return new User();
}
}
之后,启动运行。很明显,User类已经被ABC组扫描到了。
当然,User实体类也可以被"abc","123"组扫描到。
除此之外,我们为了避免有些类难以理解和其字段较多的现象,我们还可以使用一些方法来为类或者字段添加注释。
// @ApiModel只能用来为class添加注释
@ApiModel("用户实体类")
public class User {
// @ApiModelProperty用来为字段添加注释
@ApiModelProperty("用户名")
public String name;
@ApiModelProperty("密码")
public String pwd;
}
之后,启动运行就会看到关于类和字段的注释。
除此之外,我们还能发现,swagger具有测试的功能。
因为这个hello()方法是直接输出的,所以我们不用传递参数,直接测试之后就会显示200提示码,表示成功。
参考自狂神发表在哔哩哔哩上的《狂神说Java》的相关视频,在此表示感谢!