• Swagger


    1、Swagger的诞生

    前后端分离

    • 后端团队:

      • 控制层、服务层、数据访问层

    • 前端团队:

      • 控制层、视图层

      • 伪造测试数据,数据类型为json,不需要后端提供数据,前端工程也能正常运行

    • 前后端交互:

      • 通过API接口,后端提供正确的json类型的数据以及能访问这个数据的API接口,前端通过接口访问数据

    • 前后端分离产生的问题:

      • 前后端集成联调,需求发生变化无法做到即时协商,及时解决

    • 问题解决办法:

      • 后端:

        提供接口,实时更新最新的消息及改动

      • 前端:

        测试后端生成的API是否可以连接成功

      • 前端测试工具:

        • postman

        • Swagger

          世界上最流行的API框架

          Restful API文档在线自动生成工具

          API文档与API定义实时同步更新

          直接运行,可以在线测试API

     

    2、SpringBoot集成Swagger

    • 新建一个SpringBoot的web项目

    • 导入swagger的依赖

      <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>
    • 编写一个hello工程

      @RestController
      public class HelloController {

         @GetMapping("/hello")
         public String hello(){
             return "hello";
        }
      }
    • 集成Swagger

      @Configuration
      //启动Swagger2的相关功能
      @EnableSwagger2
      public class SwaggerConfig {
      }
    • 测试运行

      启动项目,访问:http://localhost:8080/swagger-ui.html,出现以下页面

     

    2.1 Docket构造方法

    public Docket(DocumentationType documentationType) {
       //Swagger基本信息
       this.apiInfo = ApiInfo.DEFAULT;
       //Swagger文档的分组
       this.groupName = "default";
       //Swagger的开关控制
       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;
    }

     

     

    2.2 配置Swagger的基本信息

    • 1、配置Swagger的Bean实例:Docket

      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {

         //配置了Swagger的Docket的Bean实例
         @Bean
         public Docket docket(){
             return new Docket(DocumentationType.SWAGGER_2);
        }
      }
      • 查看ApiInfo的源码:

        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;

           /** @deprecated */
           @Deprecated
           public ApiInfo(String title, String description, String version, String termsOfServiceUrl, String contactName, String license, String licenseUrl) {
               this(title, description, version, termsOfServiceUrl, new Contact(contactName, "", ""), license, licenseUrl, new ArrayList());
          }

           //ApiInfo的有参构造方法
           public ApiInfo(String title, String description, String version, String termsOfServiceUrl, Contact contact, String license, String licenseUrl, Collection<VendorExtension> vendorExtensions) {
               this.title = title;
               this.description = description;
               this.version = version;
               this.termsOfServiceUrl = termsOfServiceUrl;
               this.contact = contact;
               this.license = license;
               this.licenseUrl = licenseUrl;
               this.vendorExtensions = Lists.newArrayList(vendorExtensions);
          }

           public String getTitle() {
               return this.title;
          }

           public String getDescription() {
               return this.description;
          }

           public String getTermsOfServiceUrl() {
               return this.termsOfServiceUrl;
          }

           public Contact getContact() {
               return this.contact;
          }

           public String getLicense() {
               return this.license;
          }

           public String getLicenseUrl() {
               return this.licenseUrl;
          }

           public String getVersion() {
               return this.version;
          }

           public List<VendorExtension> getVendorExtensions() {
               return this.vendorExtensions;
          }

           //ApiInfo的默认信息;
           static {
               DEFAULT = new ApiInfo("Api Documentation", "Api Documentation", "1.0", "urn:tos", DEFAULT_CONTACT, "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList());
          }
        }
    • 自定义ApiInfo,并使用

      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {

         //自定义ApiInfo
         Contact contact = new Contact("hmx", "", "");
         ApiInfo apiInfo = new ApiInfo(
                 "hmx的Swagger笔记",
                 "Api 文档",
                 "1.0",
                 "urn:tos",
                 contact,
                 "Apache 2.0",
                 "http://www.apache.org/licenses/LICENSE-2.0",
                 new ArrayList());

         //配置了Swagger的Docket的Bean实例
         @Bean
         public Docket docket(){
             return new Docket(DocumentationType.SWAGGER_2)
                //自定义ApiInfo的使用
                    .apiInfo(apiInfo);
        }
      }
    • 启动项目,访问:http://localhost:8080/swagger-ui.html,出现以下页面

     

    2.3 配置Swagger的扫描接口

    • 使用 Docket 的 select() 方法

      • select()源码:

        public ApiSelectorBuilder select() {
           return new ApiSelectorBuilder(this);
        }
      • ApiSelectorBuilder的源码的核心代码如下:

        public class ApiSelectorBuilder {

           //ApiSelectorBuilder.api方式:要扫描的
           public ApiSelectorBuilder apis(Predicate<RequestHandler> selector) {
               this.requestHandlerSelector = Predicates.and(this.requestHandlerSelector, selector);
               return this;
          }

           //ApiSelectorBuilder.paths方式:要过滤的
           public ApiSelectorBuilder paths(Predicate<String> selector) {
               this.pathSelector = Predicates.and(this.pathSelector, selector);
               return this;
          }

           public Docket build() {
               return this.parent.selector(new ApiSelector(this.combine(this.requestHandlerSelector, this.pathSelector), this.pathSelector));
          }

           private Predicate<RequestHandler> combine(Predicate<RequestHandler> requestHandlerSelector, Predicate<String> pathSelector) {
               return Predicates.and(requestHandlerSelector, this.transform(pathSelector));
          }

           private Predicate<RequestHandler> transform(final Predicate<String> pathSelector) {
               return new Predicate<RequestHandler>() {
                   public boolean apply(RequestHandler input) {
                       return Iterables.any(input.getPatternsCondition().getPatterns(), pathSelector);
                  }
              };
          }
        }
    • 1、ApiSelectorBuilder.api方式

      • RequestHandlerSelectors 类源码的核心代码如下:

        public class RequestHandlerSelectors {
           private RequestHandlerSelectors() {
               throw new UnsupportedOperationException();
          }

           //扫描任何包
           public static Predicate<RequestHandler> any() {
               return Predicates.alwaysTrue();
          }

           //所有包都不扫描
           public static Predicate<RequestHandler> none() {
               return Predicates.alwaysFalse();
          }

           //扫描有指定注解的方法
           public static Predicate<RequestHandler> withMethodAnnotation(final Class<? extends Annotation> annotation) {
               return new Predicate<RequestHandler>() {
                   public boolean apply(RequestHandler input) {
                       return input.isAnnotatedWith(annotation);
                  }
              };
          }

           //扫描有指定注解的类
           public static Predicate<RequestHandler> withClassAnnotation(final Class<? extends Annotation> annotation) {
               return new Predicate<RequestHandler>() {
                   public boolean apply(RequestHandler input) {
                       return (Boolean)RequestHandlerSelectors.declaringClass(input).transform(RequestHandlerSelectors.annotationPresent(annotation)).or(false);
                  }
              };
          }

           //扫描指定包
           public static Predicate<RequestHandler> basePackage(final String basePackage) {
               return new Predicate<RequestHandler>() {
                   public boolean apply(RequestHandler input) {
                       return (Boolean)RequestHandlerSelectors.declaringClass(input).transform(RequestHandlerSelectors.handlerPackage(basePackage)).or(true);
                  }
              };
          }
           
        }
      • 在SwaggerConfig中实现

        @Bean
        public Docket docket(){
           return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(apiInfo)
              .select()
               //五种方式选其一
              .apis(RequestHandlerSelectors.basePackage(""))
              .apis(RequestHandlerSelectors.any())
              .apis(RequestHandlerSelectors.none())
              .apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
              .apis(RequestHandlerSelectors.withClassAnnotation(Configuration.class))
              .build();
        }
    • 2、ApiSelectorBuilder.paths方式

      • PathSelectors类的源码如下:

        public class PathSelectors {
           private PathSelectors() {
               throw new UnsupportedOperationException();
          }

        //过滤所有包
           public static Predicate<String> any() {
               return Predicates.alwaysTrue();
          }

           //所有包都不过滤
           public static Predicate<String> none() {
               return Predicates.alwaysFalse();
          }

           //正则表达式
           public static Predicate<String> regex(final String pathRegex) {
               return new Predicate<String>() {
                   public boolean apply(String input) {
                       return input.matches(pathRegex);
                  }
              };
          }

           //路径匹配
           public static Predicate<String> ant(final String antPattern) {
               return new Predicate<String>() {
                   public boolean apply(String input) {
                       AntPathMatcher matcher = new AntPathMatcher();
                       return matcher.match(antPattern, input);
                  }
              };
          }
        }
      • 在SwaggerConfig中实现

        @Bean
        public Docket docket(){
           return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(apiInfo)
              .select()
               //4中方式选其一
              .paths(PathSelectors.none())
              .paths(PathSelectors.any())
              .paths(PathSelectors.regex(""))
              .paths(PathSelectors.ant(""))
              .build();
        }

     

    2.4 配置Swagger的开关

    • 使用 Docket 里的 Enable 方法

    • 在SwaggerConfig中实现

      • true:表示开启

      • false表示关闭

      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {

         @Bean
         public Docket docket(){
             return new Docket(DocumentationType.SWAGGER_2)
                    .enable(true);
        }
      }
    • enable = false 时,启动项目,访问:http://localhost:8080/swagger-ui.html,出现以下页面

    • 在开发时,开启Swagger,上线时,关闭Swagger

      • 1、配置多环境

        spring:
        profiles:
          active: dev
        ---
        spring:
        profiles: dev

        server:
        port: 8081
        ---
        spring:
        profiles: test

        server:
        port: 8082
        ---
        spring:
        profiles: prod

        server:
        port: 8083
      • 2、获取项目的环境并且运用

        @Configuration
        @EnableSwagger2
        public class SwaggerConfig {

           //配置了Swagger的Docket的Bean实例
           @Bean
           public Docket docket(Environment environment){

               //设置要显示Swagger的环境
               Profiles profiles = Profiles.of("dev","test");
               //通过environment.acceptsProfiles(profiles)判断当前是否处于我们设定的环境中
               boolean acceptsProfiles = environment.acceptsProfiles(profiles);

               return new Docket(DocumentationType.SWAGGER_2)
                      .enable(acceptsProfiles);
          }

        }
      • 3、启动项目测试

        • 当前环境是dev,启动可以正常显示Swagger

        • 改动环境在prod,再次启动项目,Swagger显示不出来

     

    2.5 配置API文档的分组

    • Docket 的 groupName方法

    • 在SwaggerConfig中实现

      @Bean
      public Docket docket(){
         return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo)
            .groupName("hmx");
      }
    • 启动项目,查看效果:

    • 分多个组协同开发

      • 在SwaggerConfig中实现

      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {
         
         @Bean
         public Docket docket(){
             return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("hmx");
        }

         @Bean
         public Docket docketAAA(){
             return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("AAA");
        }

         @Bean
         public Docket docketBBB(){
             return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("BBB");
        }
      }
    • 启动项目,查看效果

      • 选择框里有三个分组

      • 点击分组名可以调到对应的分组

     

    2.6 实体类配置

    • 1、创建实体类

      public class User {
         public String userName;
         public String passWord;
      }
    • 2、在Controller中配置接口

      @RestController
      public class HelloController {

         //只要接口中的返回值存在实体类,就会被Swagger扫描
         @PostMapping(value = "/user")
         public User user(){
             return new User();
        }
      }
    • 3、启动项目测试

    • 4、给实体类加注释

      @ApiModel("用户实体类")
      public class User {
         @ApiModelProperty("用户名")
         public String userName;
         @ApiModelProperty("密码")
         public String passWord;
      }
    • 5、再次启动项目测试

     

    2.7 Swagger测试

    测试过程如下:

     

    2.8 Swagger 的 API注解

    • 给实体类加注释

      • 类:@ApiModel("用户实体类")

      • 属性:@ApiModelProperty("用户名")

    • 给接口加注释

      • Controller中的方法:@ApiOperation("user接口")

      • 方法的参数:@ApiParam("用户名")

  • 相关阅读:
    Synchronized和Lock的实现原理和锁升级
    如何禁止CPU指令重排
    MESI缓存一致性
    归并排序
    强软弱虚四种引用和ThreadLocal内存泄露
    VINS-Mono代码分析与总结(完整版)
    IMU误差模型与校准
    小感
    K8S conul部署
    Centos Consul集群及Acl配置
  • 原文地址:https://www.cnblogs.com/LittleSkinny/p/13697083.html
Copyright © 2020-2023  润新知