Swagger接口测试

Swagger

image-20230802151913510

学习目标
  • 了解Swagger的概念及作用
  • 掌握在项目中集成Swagger自动生成API文档

1、Swagger简介

前后端分离

  • 前端 -> 前端控制层、视图层
  • 后端 -> 后端控制层、服务层、数据访问层
  • 前后端通过API进行交互
  • 前后端相对独立且松耦合

产生的问题

  • 前后端集成,前端或者后端无法做到“及时协商,尽早解决”,最终导致问题集中爆发

解决方案

  • 首先定义schema [ 计划的提纲 ],并实时跟踪最新的API,降低集成风险

Swagger

  • 号称世界上最流行的API框架
  • Restful Api 文档在线自动生成器 => API 文档 与API 定义同步更新
  • 直接运行,在线测试API
  • 支持多种语言 (如:Java,PHP等)
  • 官网:https://swagger.io/

2、SpringBoot集成

Swagger

SpringBoot集成Swagger => springfox,两个jar包

  • Springfox-swagger2
  • swagger-springmvc

使用Swagger

要求:jdk 1.8 + 否则swagger2无法运行

步骤:

1、新建一个SpringBoot-web项目

2、添加Maven依赖

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<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>

3、编写HelloController,测试确保运行成功!

4、要使用Swagger,我们需要编写一个配置类-SwaggerConfig来配置 Swagger

@Configuration //配置类
@EnableSwagger2// 开启Swagger2的自动配置
@EnableWebMvc//SpringBoot和swagger版本不匹配出现空指针异常,使用该注解解决
public class SwaggerConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        /** 配置knife4j 显示文档 */
        registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        /**
         * 配置swagger-ui显示文档
         */
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        /** 公共部分内容 */
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}

5、访问测试 :http://localhost:8080/swagger-ui.html ,可以看到swagger的界面;

image-20230802152518689

6、可以看到swagger官网有几大模块内容

  • 基本信息
  • 接口信息
  • 实体类信息

在这里插入图片描述

2.1 配置基本信息

Swagger 有自己的实例 Docket,如果我们想要自定义基本信息,可以使用 docket 来配置 swagger 的基本信息,基本信息的设置在 ApiInfo 这个对象中。

Swagger 默认的基本信息展示:

在这里插入图片描述

ApiInfo 中默认的基本设置

  • title:Api Documentation //标题
  • description:Api Documentation //描述
  • version:1.0 //版本
  • termsOfServiceUrl:urn:tos //跳转链接
  • contact:无
  • license:Apache 2.0
  • licenseUrl:http://www.apache.org/licenses/LICENSE-2.0

SwaggerConfig.java 配置文件添加以下内容:

//配置docket以配置Swagger具体参数
    @Bean
    public Docket docket() {
        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)
                // 配置基本信息
                .apiInfo(apiInfo())
                ;
    }

    //配置文档信息
    private ApiInfo apiInfo() {
        Contact contact = new Contact("韦杰豪", //作者名称
                "https://blog.csdn.net/weixin_49023961?type=blog", //作者网址
                "2827673986@qq.com"); //作者邮箱
        return new ApiInfoBuilder()
                .title("韦杰豪Swagger接口API") // 标题
                .description("众里寻他千百度,慕然回首那人却在灯火阑珊处") // 描述
                .termsOfServiceUrl("https://www.baidu.com") // 跳转连接
                .version("1.0") // 版本
                .license("Swagger-的使用(详细教程)")
                .licenseUrl("https://blog.csdn.net/weixin_49023961?type=blog")
                .contact(contact)
                .build();
    }

重启服务,打开 Swagger 文档,基本信息改变如下所示:

image-20230802155923374

2.2 配置接口信息

默认情况下,Swagger 是会展示所有的接口信息的,包括最基础的 basic-error 相关的接口

在这里插入图片描述

有时候我们希望不要展示 basic-error-controller 相关的接口,或者是说这想要显示某些接口,比如说com.itheima.controller 下的接口,由该怎么去实现呢?这个时候就需要设置 扫描接口

    @Bean
    public Docket docket() {
        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)

                // 配置接口信息
                .select() // 设置扫描接口
                // 配置如何扫描接口
                .apis(RequestHandlerSelectors
                        //.any() // 扫描全部的接口,默认
                        //.none() // 全部不扫描
                        .basePackage("com.itheima.controller") // 扫描指定包下的接口,最为常用
                        //.withClassAnnotation(RestController.class) // 扫描带有指定注解的类下所有接口
                        //.withMethodAnnotation(PostMapping.class) // 扫描带有只当注解的方法接口

                )
            	//paths:过滤接口
                .paths(PathSelectors
                        .any() // 满足条件的路径,该断言总为true
                        //.none() // 不满足条件的路径,该断言总为false(可用于生成环境屏蔽 swagger)
                        //.ant("/user/**") // 满足字符串表达式路径
                        //.regex("") // 符合正则的路径
                )
                .build();
    }

可根据自己的需求去设置对应的配置,这里我就不再一一赘述了,以上是我所设置的配置,重启服务,打开 Swagger 文档,接口信息改变如下所示:

image-20230802215708803

2.3 配置分组信息

Swagger 默认只有一个 default 分组选项,如果没有设置,所有的接口都会显示在default分组下,如果功能模块和接口数量一多,就会显得比较凌乱,不方便查找和使用。

swagger 文档中组名默认是 default,可通过 .groupName(String )

image-20230802220012984

//配置docket以配置Swagger具体参数
    @Bean
    public Docket docket() {
        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("韦杰豪")
                // 配置基本信息
                .apiInfo(apiInfo())
                .select() // 设置扫描接口
                // 配置如何扫描接口
                .apis(RequestHandlerSelectors
                   //.any() // 扫描全部的接口,默认
                   //.none() // 全部不扫描
                   .basePackage("com.itheima.controller") // 扫描指定包下的接口,最为常用
                   //.withClassAnnotation(RestController.class) // 扫描带有指定注解的类下所有接口
                   //.withMethodAnnotation(PostMapping.class) // 扫描带有只当注解的方法接口
                    )
                .paths(PathSelectors
                       .any() // 满足条件的路径,该断言总为true
                        // .none() // 不满足条件的路径,该断言总为false(可用于生成环境屏蔽 swagger)
                        // .ant("/user/**") // 满足字符串表达式路径
                        //.regex("") // 符合正则的路径
                )
                .build();

    }

image-20230802220127089

如果需要配置多个组的话,就需要配置多个 docket() 方法,这里我就简单写两组,代码如下:

    /**
     * 展示 controller 包下所有的接口
     */
    @Bean
    public Docket docket1() {
        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("mike") // 修改组名为 "mike"
                // 配置接口信息
                .select() // 设置扫描接口
                // 配置如何扫描接口
                .apis(RequestHandlerSelectors
                        .basePackage("com.duojiala.mikeboot.controller") // 扫描指定包下的接口,最为常用
                )
                .paths(PathSelectors
                         .any() // 满足条件的路径,该断言总为true
                )
                .build();
    }

    /**
     * 展示路径为 /error 的所有接口(基础接口)
     */
    @Bean
    public Docket docket2() {
        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("yank") // 修改组名为 "yank"
                // 配置接口信息
                .select() // 设置扫描接口
                // 配置如何扫描接口
                .apis(RequestHandlerSelectors
                        .any() // 扫描全部的接口,默认
                )
                .paths(PathSelectors
                        .ant("/error") // 满足字符串表达式路径
                )
                .build();
    }

重启服务,打开 Swagger 文档,接口信息改变如下所示:

组名为 mike 的文档中只有 user-controller 相关的接口信息

在这里插入图片描述

组名为 yank 的文档中只有 basic-error-controller 相关的接口信息

在这里插入图片描述

组名为 mike 的文档

在这里插入图片描述

2.4 控制Swagger的开关

在开发或者测试环境下,我们开启 swagger 会方便前端和后端的交互,但是如果在生产环境下也开启 swagger 的话,是会将接口暴露出去的,有极大风险,如何让 swagger 根据不同的环境来决定是否开启?

这里我准备了四个项目的配置文件,devtestpro 三个环境的配置文件仅是端口上的不同

在这里插入图片描述

  • application.yml -------------------------- 全局配置文件
  • application-dev.yml -------------------- 开发环境配置文件
  • application-test.yml -------------------- 测试环境配置文件
  • application-pro.yml -------------------- 生产环境配置文件

application.yml 内容如下,用于指定选择的环境:

spring:
  profiles:
    active: dev

可以通过代码判断此时是在什么环境:devtestpro,如果是在 pro 生产环境,则关闭 swagger。

    /**
     * swagger 配置
     * @param environment 环境
     */
    @Bean
    public Docket docket(Environment environment) {

        // 设置环境范围
        Profiles profiles = Profiles.of("dev","test");
        // 如果在该环境返回内则返回:true,反之返回 false
        boolean flag = environment.acceptsProfiles(profiles);

        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(flag) // 是否开启 swagger:true -> 开启,false -> 关闭
                ;
    }

application.yml 全局配置文件中环境指向 dev 时,是可以打开 swagger 的

在这里插入图片描述

如果我将 application.yml 全局配置文件中环境指向 pro 时,就不能打开 swagger 了,提示 Could not render e, see the console

在这里插入图片描述

拓展

通过enable()方法配置是否启用swagger,如果是false,swagger将不能在浏览器中访问了

@Bean
public Docket docket() {
   return new Docket(DocumentationType.SWAGGER_2)
      .apiInfo(apiInfo())
      .enable(false) //配置是否启用Swagger,如果是false,在浏览器将无法访问
      .select()// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口
      .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
       // 配置如何通过path过滤,即这里只扫描请求以/kuang开头的接口
      .paths(PathSelectors.ant("/kuang/**"))
      .build();
}

图片

2.5 实体类的配置

1、新建一个实体类

@ApiModel("图书实体")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
        @ApiModelProperty("图书ID")
        private Integer id;
        @ApiModelProperty("图书类型")
        private String type;
        @ApiModelProperty("图书名称")
        private String name;
        @ApiModelProperty("图书描述信息")
        private String description;

}

2、只要这个实体在请求接口的返回值上(即使是泛型),都能映射到实体项中:

@RequestMapping("/getUser")
public User getUser(){
   return new User();
}

3、重启查看测试

image-20230802221020536

注:并不是因为@ApiModel这个注解让实体显示在这里了,而是只要出现在接口方法的返回值上的实体都会显示在这里,而@ApiModel和@ApiModelProperty这两个注解只是为实体添加注释的。

@ApiModel为类添加注释

@ApiModelProperty为类属性添加注释

3、常用注解

@Api:修饰整个类,描述Controller的作用
@ApiOperation:描述一个类的一个方法,或者说一个接口
@ApiParam:单个参数描述
@ApiModel:用对象来接收参数
@ApiModelProperty:用对象接收参数时,描述对象的一个字段
@ApiImplicitParam:一个请求参数
@ApiImplicitParams:多个请求参数

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

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

我们也可以给请求的接口配置一些注释

@ApiOperation("狂神的接口")
@PostMapping("/kuang")
@ResponseBody
public String kuang(@ApiParam("这个名字会被返回")String username){
   return username;
}

这样的话,可以给一些比较难理解的属性或者接口,增加一些配置信息,让人更容易阅读!

@ApiModel和==@ApiModelProperty==常用于实体类当中,如下:

@ApiModel("查询机构入参") //默认是value
//@ApiModel(value="User对象", description="")   //value属性就是对所需要特别说明的接口相关实体类进行描述。
//description属性就是对所需要特别说明的接口相关实体类进行较长的描述。
public class OrgDTO{
 
    @ApiModelProperty(value = "机构号")
    private String orgCode;
 
    @ApiModelProperty("名字")
    private String name;
 
}

@Api@ApiOperation 常用于 Controller 中,如下

@Api(tags = "购物车接口")
public class ShoppingController{
 
    @ApiOperation("购物车删除")
    @GetMapping("/t1")
    public void t1(){}
 
 
    @ApiOperation("购物车新增")
    @PostMapping("/t2")
    public void t2(){}
}
@Api

通常用在Controller上。表明是swagger资源。

@Api(tags = "购物车接口")
public class ShoppingController{}
 
@Api(tags = {"对外:员工信息对接接口","对内:员工信息接口"})
public class StaffController{}

@API拥有两个属性:value、tags。生成的api文档会根据tags分类,即该controller中所有接口生成的文档都会在此tags下。tags可以有多个值,value的作用类似tags,但是不能有多个值。一般用tags,源码里说如果没有用tags,就会把value的值给tags。

@ApiOperation

用在方法上

@ApiOperation("购物车分页查询")
@GetMapping("/t1")
public void t1(){}

属性:

value 简短描述,一般用来做标题

notes 详细描述,一般用来做解释

tags 分组,对应@Api的tags,如果@Api的tags用了多个,方法会根据这个来分组

@ApiModel()

一般用在实体类上

@ApiModel("机构")
public class OrgEntity{}
 
@ApiModel("查询机构入参")
public class QueryOrgDTO{}
 
@ApiModel("查询机构出参")
public class QueryOrgVO{}
@ApiModelProperty()

一般用在字段上

@ApiModelProperty(value = "主键")
private String id;
 
@ApiModelProperty(value = "名字")
private String name;

required 是否必填,该字段后面会有一个红色的星号

@ApiParam

用在参数上

  • name 参数名
  • value 参数说明
  • required 是否必填

4、接口调用

使用 swagger 除了让前后端交互变得方便,也让接口的请求变得简单,只需要填写好请求所需要的参数信息,便可直接发起请求。

比如说接口 /user/query-user-info

点击 Try it out

在这里插入图片描述

设置好请求所需的参数,点击 Execute 执行

在这里插入图片描述

就能看到接口响应的结果了

在这里插入图片描述

接口 /user/query-user-infos 也差不多

在这里插入图片描述

在这里插入图片描述

5、进阶使用

5.1. 添加请求头

有时候我们的接口是需要获取请求头信息的,这样的话就还需要在 swagger 配置中添加请求头的配置。

    @Bean
    public Docket docket() {
        // 设置请求头
        List<Parameter> parameters = new ArrayList<>();
        parameters.add(new ParameterBuilder()
                .name("token") // 字段名
                .description("token") // 描述
                .modelRef(new ModelRef("string")) // 数据类型
                .parameterType("header") // 参数类型
                .defaultValue("default value") // 默认值:可自己设置
                .hidden(true) // 是否隐藏
                .required(false) // 是否必须
                .build());

        // 创建一个 swagger 的 bean 实例
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("mike") // 修改组名为 "mike"
                // 配置接口信息
                .select() // 设置扫描接口
                // 配置如何扫描接口
                .apis(RequestHandlerSelectors
                        .basePackage("com.duojiala.mikeboot.controller") // 扫描指定包下的接口,最为常用
                )
                .paths(PathSelectors
                        .any() // 满足条件的路径,该断言总为true
                )
                .build()

                // 添加请求头参数
                .globalOperationParameters(parameters);
    }

比如接口:

    @GetMapping(value = "/get-token")
    @ApiOperation(value = "获取请求头中的token信息")
    public void getToken(
            @RequestHeader(value = "token",required = false) String token
    ) {
        // 直接获取 token 信息
        System.out.println("token = " + token);

        // 通过代码获取
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (servletRequestAttributes != null) {
            HttpServletRequest request = servletRequestAttributes.getRequest();
            String header = request.getHeader("token");
            System.err.println("header = " + header);
        }
    }

在这里插入图片描述

可以看到这个接口已经可以去设置请求头了,调用接口

在这里插入图片描述

6、访问地址

/swagger-ui.html

http://localhost:8080/项目名(默认无)/swagger-ui.html

如果配置了,如下,那地址就是:http://localhost:8050/aliba/swagger-ui.html

server:
  port: 8050
  servlet:
    context-path: /aliba
6.1 依赖
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

访问swagger的页面需要上面两个依赖。

6.2 配置类

无该配置类也没关系,可以打开Swagger界面

import org.springframework.beans.factory.annotation.Value;
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;
 
/**
 1. swagger配置类
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                //是否开启 (true 开启  false隐藏。生产环境建议隐藏)
                //.enable(false)
                .select()
                //扫描的路径包,设置basePackage会将包下的所有被@Api标记类的所有方法作为api
                .apis(RequestHandlerSelectors.basePackage("com.**.controller"))
                //指定路径处理PathSelectors.any()代表所有的路径
                .paths(PathSelectors.any())
                .build();
    }
 
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //设置文档标题(API名称)
                .title("SpringBoot中使用Swagger2接口规范")
                //文档描述
                .description("接口说明")
                //服务条款URL
                .termsOfServiceUrl("http://localhost:8080/")
                //版本号
                .version("1.0.0")
                .build();
    }
}
6.3 SpringSecurity中配置

Spring Boot项目中集成了Spring Security,接口会被拦截,需要在Spring Security的配置类中重写configure方法,对接口进行过滤

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
            .antMatchers("/swagger-ui.html")
            .antMatchers("/v2/**")
            .antMatchers("/swagger-resources/**");
}

piInfo apiInfo() {
return new ApiInfoBuilder()
//设置文档标题(API名称)
.title(“SpringBoot中使用Swagger2接口规范”)
//文档描述
.description(“接口说明”)
//服务条款URL
.termsOfServiceUrl(“http://localhost:8080/”)
//版本号
.version(“1.0.0”)
.build();
}
}


#### 6.3 SpringSecurity中配置

Spring Boot项目中集成了Spring Security,接口会被拦截,需要在Spring Security的配置类中重写configure方法,对接口进行过滤

```java
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
            .antMatchers("/swagger-ui.html")
            .antMatchers("/v2/**")
            .antMatchers("/swagger-resources/**");
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值