Swagger一篇文章就够了

Swagger简介

就我自己的理解来说,Swagger应用于前后端分离项目中,前端和后端之间的联系就是Controller层的接口,Swagger中有一个swagger-ui.html,后端配置好之后Controller层的接口都会显示在swagger-ui.html上,前端就可以直接访问这个swagger-ui.html来调用接口,最重要的是这个网页是实时显示的。可以有效的降低前后端打架几率。

SpringBoot简单集成Swagger

1.导入依赖


<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger2artifactId>
    <version>2.9.2version>
dependency>

<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger-uiartifactId>
    <version>2.9.2version>
dependency>

2.简单编写Swagger配置类

创建一个Swagger配置类,加上@Configuration注解,放到Spring容器中,然后添加@EnableSwagger2,指示应用开启Swagger的支持,@EnableSwagger2注解的源码里的解释如下

/**
 * Indicates that Swagger support should be enabled. 
 * 指示应启用Swagger支持。
 * 
 * This should be applied to a Spring java config and should have an accompanying 		    '@Configuration' annotation.
 * 这应该应用于Spring java config,并带有“ @Configuration”注释
 * 
 * Loads all required beans defined in @see SpringSwaggerConfig
 * 加载@see SpringSwaggerConfig中定义的所有必需bean,这里@see所必需的的bean是下面一句写的Docket,
 * 意思就是说,添加这个注解的类必须要将Docket加载到bean中,因为这是他所必须的
 *
 * @see springfox.documentation.spring.web.plugins.Docket
 */
package springfox.documentation.swagger2.annotations;

import org.springframework.context.annotation.Import;
import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * Indicates that Swagger support should be enabled.
 *
 * This should be applied to a Spring java config and should have an accompanying 		    '@Configuration' annotation.
 *
 * Loads all required beans defined in @see SpringSwaggerConfig
 *
 * @see springfox.documentation.spring.web.plugins.Docket
 */
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({Swagger2DocumentationConfiguration.class}) //这里是最关键的,引入了Swagger的配置类
public @interface EnableSwagger2 {
}

Swagger配置类:大体都是固定的代码,直接复制稍微修改就行。

package shiro.demo.config;

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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @Auther Shen
 * @Date 2020-07-06
 */

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                /* RequestHandlerSelectors:配置要扫描的接口的方式
                        .basePackage():指定要扫描的包,一般就配置自己Controller所在的包
                        .any():扫描全部
                        .none():不扫描
                        .withClassAnnotation():扫描类上的注解,参数是一个注解的反射对象
                        .withMethodAnnotation():扫描方法上的注解
                */
                .apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
                /* paths(): 配置过滤的请求
                     .any():不过滤,所有请求都放行,结果就是在swagger-ui.html上显示扫描包
                      的所有的RequestMapping
                     .none():过滤全部,所有请求都不放行,结果就是在swagger-ui.html上什么都不显示
                     .ant():括号里填请求地址,就是过滤其他,只剩下ant()括号里的请求显示在网页上
                 */
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * String title;             标题
     * String description;       描述
     * String termsOfServiceUrl; 服务条款网址
     * Contact contact;          负责这个 api 的人的联系方式
     * String license;           这个 api 的许可证信息
     * String licenseUrl;        这个 api 的许可证地址
     * String version;           Api版本
     *
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("我的Api文档")
                .description("这是一个测试文档")
                .termsOfServiceUrl("https://gitee.com/") //随便填的,不填也行,不配置这一项也行
                .contact(new Contact("老申", "", "***********@qq.com"))
                .license("许可证信息")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .version("1.0x")
                .build();
    }
}

具体的对应关系如下:
Swagger一篇文章就够了_第1张图片

3.简单测试

随便写一个Controller,然后访问swagger-ui.html

package shiro.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Auther Shen
 * @Date 2020-07-06
 */
@RestController
public class SwaggerTestController {
    @GetMapping("/test")
    public String swaggerTest(){
        return "swagger";
    }
}

结果如下
Swagger一篇文章就够了_第2张图片

环境问题

开发时需要Swagger,但是上线时,我们不想让它生效,因为如果上线后还生效的话,用户就会知道你的服务端的所有的接口,可能会受到攻击。所以现在出来一个问题,怎么能简单的实现这样的功能:开发环境启用Swagger,上线后关闭Swagger。

直接上代码

package shiro.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
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;


/**
 * @Auther Shen
 * @Date 2020-07-06
 */

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket docket(Environment environment) {
        //设置要显示Swagger的环境
        Profiles profiles = Profiles.of("dev");
        //通过environment.acceptsProfiles判断是否处在自己设定的环境中
        boolean flag = environment.acceptsProfiles(profiles);

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(flag)//enable是否启动Swagger,如果为false,则Swagger-ui不能在浏览器中访问
                .select()
                .apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
                .paths(PathSelectors.any())
                .build();
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("我的Api文档")
                .description("这是一个测试文档")
                .termsOfServiceUrl("https://gitee.com/")
                .contact(new Contact("Shen", "", "***********@qq.com"))
                .license("许可证信息")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .version("1.0x")
                .build();
    }
}

在application.yml中配置环境,如下图所示
在这里插入图片描述
然后在开发环境就会生效,上线时可以改为 spring.profiles.active=prod。

分组问题

分组问题:多个组就创建多个Docket,每个Docket的groupName设置为不同就行了,各自组扫描各自的包

package shiro.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
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;


/**
 * @Auther Shen
 * @Date 2020-07-06
 */

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket docket(Environment environment) {
        //设置要显示Swagger的环境
        Profiles profiles = Profiles.of("dev");
        //通过environment.acceptsProfiles判断是否处在自己设定的环境中
        boolean flag = environment.acceptsProfiles(profiles);

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(flag)//enable是否启动Swagger,如果为false,则Swagger-ui不能在浏览器中访问
                .groupName("Shen")
            	.select()
                .apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
                .paths(PathSelectors.any())
                .build();
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("我的Api文档")
                .description("这是一个测试文档")
                .termsOfServiceUrl("https://gitee.com/")
                .contact(new Contact("Shen", "", "***********@qq.com"))
                .license("许可证信息")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .version("1.0x")
                .build();
    }
}

Model配置

在Controller中只要存在这种,返回值为实体类对象的就会直接添加到Swagger中

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

Swagger一篇文章就够了_第3张图片
然后还可以在User类上加注释,让生成的文档更易懂,下面是效果

@ApiModel:作用于类,接口,枚举上

@ApiModelProperty:作用于实体类属性上

Swagger一篇文章就够了_第4张图片
Controller下的接口也可以加注释

@GetMapping("/user")
@ApiOperation("User访问控制接口")
public User getUser(){
    return new User();
}

@GetMapping("/test")
@ApiOperation("test测试注解")
public String test(@ApiParam("用户名") String username){
    return username;
}

加了注释的效果就是下面的图
Swagger一篇文章就够了_第5张图片

注意事项

在与shiro或者SpringSecurity整合的时候需要配置过滤器放行,不然会出现弹窗问题,如下图所示Swagger一篇文章就够了_第6张图片
这里提供了shiro需要放行的路径,放到shiro中的过滤器中即可

filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/v2/**", "anon");
filterMap.put("/swagger-resources/**", "anon");

完整代码

用户实体类

package shiro.demo.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 用户实体类
 * @Auther Shen
 * @Date 2020-07-06
 */

@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("用户实体类")
public class User implements Serializable {

    @ApiModelProperty("用户的编号")
    private int id;
    @ApiModelProperty("用户名")
    private String username;
    @ApiModelProperty("密码")
    private String password;
    @ApiModelProperty("用户具备的权限")
    private String perms;
}

Swagger配置类

package shiro.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
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;


/**
 * @Auther Shen
 * @Date 2020-07-06
 */

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket docket(Environment environment) {
        //设置要显示Swagger的环境
        Profiles profiles = Profiles.of("dev", "test");
        //通过environment.acceptsProfiles判断是否处在自己设定的环境中
        boolean flag = environment.acceptsProfiles(profiles);

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(flag)//enable是否启动Swagger,如果为false,则Swagger-ui不能在浏览器中访问
                .groupName("Shen")
                .select()
                /* RequestHandlerSelectors:配置要扫描的接口的方式
                        .basePackage():指定要扫描的包
                        .any():扫描全部
                        .none():不扫描
                        .withClassAnnotation():扫描类上的注解,参数是一个注解的反射对象
                        .withMethodAnnotation():扫描方法上的注解
                */
                .apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
                /* paths(): 配置过滤的请求
                     .any():不过滤,所有请求都放行,结果就是在swagger-ui.html上显示扫描包的所有的RequestMapping
                     .none():过滤全部,所有请求都不放行,结果就是在swagger-ui.html上什么都不显示
                     .ant():括号里填请求地址,就是过滤其他,只剩下ant()括号里的请求显示在网页上
                 */
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * String title;             标题
     * String description;       描述
     * String termsOfServiceUrl; 服务条款网址
     * Contact contact;          负责这个 api 的人的联系方式
     * String license;           这个 api 的许可证信息
     * String licenseUrl;        这个 api 的许可证地址
     * String version;           Api版本
     *
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("我的Api文档")
                .description("这是一个测试文档")
                .termsOfServiceUrl("https://gitee.com/")
                .contact(new Contact("Shen", "", "***********@qq.com"))
                .license("许可证信息")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .version("1.0x")
                .build();
    }
}

Controller

package shiro.demo.controller;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import shiro.demo.pojo.User;

/**
 * @Auther Shen
 * @Date 2020-07-07
 */
@Controller
public class SwaggerTestController {

    @GetMapping("/user")
    @ApiOperation("User访问控制接口")
    public User getUser(){
        return new User();
    }

    @GetMapping("/test")
    @ApiOperation("test测试注解")
    public String test(@ApiParam("用户名") String username){
        return username;
    }
}

你可能感兴趣的:(Swagger)