Swagger 3.0快速入门

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swagger 3.0快速入门相关的知识,希望对你有一定的参考价值。



一。Swagger简介

1. 前后端分离

后端时代:前端只用管理静态页面;html等静态资源交给后端通过模板引擎进行渲染

前后端分离时代:

  • 后端:控制层controller、服务层service、数据访问层dao
  • 前端:前端控制层、视图层
  • 前后端交互:通过API接口
  • 前后端相对独立,松耦合,甚至可以部署在不同的服务器上
  • 随之产生的问题:前后端联调,前端人员和后端人员无法做到及时协商,尽早解决

解决方案:

  • 首先指定schema(计划),实时更新最新的API,降低集成风险
  • 早些年:指定word计划文档
  • 前后端分离:
  • 前端测试后端接口数据是否正确:postman
  • 后端提供接口,需要实时更新最新的消息和改动

于是Swagger应运而生


2. Swagger引入

  • 号称历史上最流行的api框架
  • RestFul Api文档在线生成工具=》Api文档与Api定义同步更新
  • 直接运行,可以在线测试Api接口
  • 支持多种语言

springfox-swagger 2

SpringBoot项目整合swagger2需要用到两个依赖:springfox-swagger2和springfox-swagger-ui,用于自动生成swagger文档。

  • springfox-swagger2:这个组件的功能用于帮助我们自动生成描述API的json文件
  • springfox-swagger-ui:就是将描述API的json文件解析出来,用一种更友好的方式呈现出来。

SpringFox 3.0.0 发布

此版本的亮点:

  • Spring5,Webflux支持(仅支持请求映射,尚不支持功能端点)。
  • Spring Integration支持。
  • SpringBoot支持springfox Boot starter依赖性(零配置、自动配置支持)。
  • 支持OpenApi 3.0.3。
  • 零依赖。几乎只需要spring-plugin,swagger-core ,现有的swagger2注释将继续工作并丰富openapi3.0规范。

兼容性说明:

  • 需要Java 8
  • 需要Spring5.x(未在早期版本中测试)
  • 需要SpringBoot 2.2+(未在早期版本中测试)

swagger3.0 与2.xx配置差异:

  • 应用主类添加注解@EnableOpenApi (swagger2是@EnableSwagger2)
  • swagger配置类SwaggerProperties.class,与swagger2.xx 版本有差异,具体看下文
  • 自定义一个配置类 SwaggerConfiguration.class,看下文
  • 访问地址:http://localhost:8080/swagger-ui/index.html
    (swagger2.xx版本访问的地址为http://localhost:8080/swagger-ui.html)

具体使用教程如下


1.导入依赖

Maven项目中引入springfox-boot-starter依赖:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

2.application.yml配置

spring:
  application:
    name: springfox-swagger
server:
  port: 8080
# ===== 自定义swagger配置 ===== #
swagger:
  enable: true
  application-name: ${spring.application.name}
  application-version: 1.0
  application-description: springfox swagger 3.0整合Demo
  try-host: http://localhost:${server.port}

3.配置Swagger API信息


在Swagger提供的ui界面,其中的Swagger信息模块我们可以自定义信息内容
我们只需要在Swagger配置类SwaggerConfig中实例化Docket类队对象的bean实例,通过配置ApiInfo类的信息然后传入Docket的bean实例即可


4.修改默认API文档显示页面

@Configuration
@EnableOpenApi //开启Swagger3
public class SwaggerConfig {
    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());//配置Swagger信息
    }

    //配置Swagger信息
    /*String title, String description,
     String version, String termsOfServiceUrl,
     Contact contact, String license,
     String licenseUrl,
     Collection<VendorExtension> vendorExtensions*/
    private ApiInfo apiInfo() {
        return new ApiInfo(
                "大忽悠项目",
                "大忽悠的Swagger API文档",
                "2.0",//版本信息
                "https://blog.csdn.net/m0_53157173",//团队信息的url
                new Contact("大忽悠", "https://blog.csdn.net/m0_53157173", "3076679680@qq.com"),//作者信息
                /*Contact(String name, String url, String email)*/
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList<VendorExtension>());
    }
}


配置Swagger自定义扫描接口

我们在这个ui界面中,可以看到扫描了两个controller接口;

  • 一个是默认的/error请求,也就是我们启动springboot主程序未加配置默认访问8080端口的默认controller

  • 剩余的就是我们自己再controller层写的请求映射了

自定义扫描接口

    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket()
    {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())//配置Swagger信息
                .select()
                /**
                 * apis():指定扫描的接口
                 *  RequestHandlerSelectors:配置要扫描接口的方式
                 *       basePackage:指定要扫描的包
                 *       any:扫面全部
                 *       none:不扫描
                 *       withClassAnnotation:扫描类上的注解(参数是类上注解的class对象)
                 *       withMethodAnnotation:扫描方法上的注解(参数是方法上的注解的class对象)
                 */
                .apis(RequestHandlerSelectors.basePackage("com.Controller"))
                /**
                 * paths():过滤路径
                 *  PathSelectors:配置过滤的路径
                 *      any:过滤全部路径
                 *      none:不过滤路径
                 *      ant:过滤指定路径:按照按照Spring的AntPathMatcher提供的match方法进行匹配
                 *      regex:过滤指定路径:按照String的matches方法进行匹配
                 */
                .paths(PathSelectors.any())
                .build();
    }

其中.select().apis.paths.build是一套组合进行使用

只有被过滤筛选出来并且在指定包下面的请求路径才会显示在页面上


配置是否启动Swagger

我么通过Docket对象的.enable方法来配置swagger是否启动

    @Bean
    public Docket docket()
    {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())//配置Swagger信息
                .enable(false)//enable是否启动swagger,如果为false,那么浏览器中无法访问swagger
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.Controller"))
                .paths(PathSelectors.any())
                .build();
    }


Swagger只在生产环境下使用

  • 首先要判断是不是开发环境,可以设置一个flag表示用来表示:flag=1即表示生产环境
  • 然后将flag的值传给enable(flag)

首先在resources目录下新建两种springboot配置文件

开发环境:application-dev.properties

server.port=8081

正式环境:application-pro.properties

server.port=8082


然后在主配置文件application.properties中激活开发环境

spring.profiles.active=dev

然后我们到SwaggerConfig中的docket()方法中添加代码:

首先给该方法传一个参数Environment的实例

Environment environment

首先设置要配置的Swagger环境:这里可以添加多个环境

Profiles.of("dev", "test");

然后通过environment.acceptsProfiles方法判断是否处在上一步设定的dev/test环境中,返回一个boolean的值,我们用flag接收

boolean flag = environment.acceptsProfiles(profiles);

然后修改enable中的参数为flag,即通过flag来判断是否开启Swagger

.enable(flag)//通过flag判断是否开启

完整代码:

@Configuration
@EnableOpenApi //开启Swagger3
public class SwaggerConfig {
    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket(Environment environment)
    {
        //设置要配置的Swagger环境
        Profiles p = Profiles.of("dev", "test");
        //通过environment.acceptsProfiles判断是否处在自己设定的环境中
        boolean flag = environment.acceptsProfiles(p);
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())//配置Swagger信息
                .enable(flag)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.Controller"))
                .paths(PathSelectors.any())
                .build();
    }

    //配置Swagger信息
    private ApiInfo apiInfo() {
        return new ApiInfo(
                "大忽悠项目",
                "大忽悠的Swagger API文档",
                "2.0",//版本信息
                "https://blog.csdn.net/m0_53157173",//团队信息的url
                new Contact("大忽悠", "https://blog.csdn.net/m0_53157173", "3076679680@qq.com"),//作者信息
                /*Contact(String name, String url, String email)*/
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList<VendorExtension>());
    }
}

然后启动主程序测试:由于激活了dev开发环境,所以访问localhost:8081/swagger-ui.html


成功开启swagger,如果我们修改主配置文件,激活pro正式发布环境

spring.profiles.active=pro

再次重启主程序测试,访问端口8082对应的地址localhost:8082/swagger-ui.html


无法进入,因为pro环境不在我们配置的test/dev环境中,所以无法开启


配置API文档分组

1. 设置默认组名

可以看到,我们默认只有一个组且组名为default

我们可以在docket通过.groupName中设置组名

    @Bean
    public Docket docket(Environment environment)
    {
        //设置要配置的Swagger环境
        Profiles p = Profiles.of("dev", "test");
        //通过environment.acceptsProfiles判断是否处在自己设定的环境中
        boolean flag = environment.acceptsProfiles(p);
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())//配置Swagger信息
                .enable(flag)
                .groupName("大忽悠")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.Controller"))
                .paths(PathSelectors.any())
                .build();
    }


2. 配置多个组

上述我们成功修改了组名,但是只有一个组,如果我们想要多个组呢?
观察代码可以知道,一个Docket实例就对应着一个组,因此我们配置多个docket就对应着多个组

    @Bean
    public Docket docket1() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("大忽悠1号");
    }

    @Bean
    public Docket docket2() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("大忽悠2号");
    }


配置Model实体类

只要我们的controoler层方法中,返回值中存在实体类,他就会被扫描到Swagger中

@RestController
public class UserControoler
{
    //只要我们的接口中,返回值中存在实体类,他就会被扫描到Swagger中
    @GetMapping("/User")
    public User showUser(User u)
    {
        return u;
    }
}


现在的问题是,页面显示出来的返回的User类,如果是非常复杂的情况下,没有注释就很难看懂,这样就有了注解来进行解释


@ApiModel为类添加注释

@ApiModelProperty为类属性添加注释

@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel("用户实体类")
public class User
{
    @ApiModelProperty("姓名")
    String name;
    @ApiModelProperty("年龄")
    Integer age;
   @TableId(value="id",type = IdType.AUTO)
   @ApiModelProperty("主键id")
    Integer id;
    //字段添加填充内容
    @TableField(fill = FieldFill.INSERT)
    @ApiModelProperty("创建时间")
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty("修改时间")
    private Date updateTime;
    @Version
    @ApiModelProperty("版本,用于乐观锁")
    Integer version;
    //逻辑删除字段
    @TableLogic
    @ApiModelProperty("逻辑删除字段")
    private Integer deleted;
}


我们同样可以在Controller类和其中的方法上添加相应的注解

@Api

@ApiOperation

没加前:

加注解中…

@RestController
@Api(tags ="User数据交互")
public class UserControoler
{
    //只要我们的接口中,返回值中存在实体类,他就会被扫描到Swagger中
    @GetMapping("/User")
    @ApiOperation("展示用户")
    public User showUser(User u)
    {
        return u;
    }
}

效果展示:


@ApiParam–给参数上加上解释

@RestController
@Api(tags ="User数据交互")
public class UserControoler
{
    //只要我们的接口中,返回值中存在实体类,他就会被扫描到Swagger中
    @GetMapping("/User")
    @ApiOperation("展示用户")
    public String showUser(@ApiParam("特殊的名字") String u)
    {
        return u;
    }
}


我们可以简单测试一下,点击Try it out,然后点击Execute执行



常用注解总结

// @Api: 修饰整个类,描述Controller的作用
@Api(value = "注册登陆", tags = "注册登陆相关接口")
// @ApiOperation: 描述一个类的一个方法,或者说一个接口
@ApiOperation(value = "用户注册", notes = "用户注册", httpMethod = "POST")
@ApiParam			// 单个参数描述
// @ApiModel: 用对象来接收参数
@ApiModel(value = "用户对象BO", description = "用户从客户端传入的数据的封装")
// @ApiModelProperty: 用对象接收参数时,描述对象的一个字段
@ApiModelProperty(value = "用户名", name = "username", example = "Orcas", required = true)
@ApiResponse        // HTTP响应其中1个描述
@ApiResponses       // HTTP响应整体描述
@ApiIgnore		    // 使用该注解忽略这个API 
@ApiError 		    // 发生错误返回的信息
@ApiImplicitParam   // 一个请求参数
@ApiImplicitParams  // 多个请求参数
   =@ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "size", value = "每页记录数", required = true, paramType = "path", dataType = "int")})

@ApiImplicitParam属性


总结: 发布的时候,记得关闭Swagger,可以通过生产环境设置来完成这一需求


以上是关于Swagger 3.0快速入门的主要内容,如果未能解决你的问题,请参考以下文章

Swagger(丝袜哥) 快速入门(超详细介绍)

Swagger入门教程

Swagger入门教程(转)

Swagger 简单快速入门教程

swaager快速入门

SpringBoot集成Swagger2生成API接口文档