(三)Swagger配置多项目共用

重构了多个项目后,在联调接口时,查看api会发现Swagger在几个项目可用,有几个不可用,配置都一样,扫描也充分,那问题出在哪里呢?先仔细找了下Docket的源码,发现有这么个方法:

/**
   * Predicate that matches RequestHandler with given base package name for the class of the handler method.
   * This predicate includes all request handlers matching the provided basePackage
   *
   * @param basePackage - base package of the classes
   * @return this
   */
  public static Predicate<RequestHandler> basePackage(final String basePackage) {
    return new Predicate<RequestHandler>() {
      @Override
      public boolean apply(RequestHandler input) {
        return declaringClass(input).transform(handlerPackage(basePackage)).or(true);
      }
    };
  }

而我们在配置中,就用到这个方法:

return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder()
                        .title("some title")
                        .description("some description")
                        .termsOfServiceUrl("this is url")
                        .version("0.01")
                        .build())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.***.qaqc"))
                .paths(PathSelectors.any())
                .build();

由于整合了多个项目,每个项目的包命名规则不一致扫描的包的规则没有完全匹配所有项目,导致有些可以访问Swagger有些不能访问,问题迎刃而解。


项目中是用JWT作为整个spring cloud项目的单点登录Token,如何让Swagger也可以支持,让我们在每次mock中都添加Authentication呢?遵循上面解决问题的思路,我们又找到了这个方法:

/**
   * Adds default parameters which will be applied to all operations.
   *
   * @param operationParameters parameters which will be globally applied to all operations
   * @return this Docket
   */
  public Docket globalOperationParameters(List<Parameter> operationParameters) {
    this.globalOperationParameters.addAll(nullToEmptyList(operationParameters));
    return this;
  }

只要按照方法添加合理的参数,功能就可以实现:

ParameterBuilder authParam = new ParameterBuilder();
List<Parameter> paramList = new ArrayList<>();
authParam.name(authHeader).description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false);
paramList.add(authParam.build());
docket.globalOperationParameters(paramList);

但还有部分项目是不需要做token校验的,也要保证其兼容性,那么我们可以稍微改造一下:

/**
 * @author zhangqiuyang
 * Created on 2018/4/21.
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Value("${system.auth.header:null}")
    private String authHeader;

    /**
     * 初始化api
     *
     * @return Docket
     */
    @Bean
    public Docket createRestApi() {
        List<Parameter> paramList = null;

        if (!"null".equals(authHeader)) {
            paramList = new ArrayList<>();
            ParameterBuilder authParam = new ParameterBuilder();
            authParam.name(authHeader).description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false);
            paramList.add(authParam.build());
        }
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder()
                        .title("**************")
                        .description("************")
                        .termsOfServiceUrl("http://www.komect.com/")
                        .version("0.01")
                        .build())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.cmhi.qaqc"))
                .paths(PathSelectors.any())
                .build();
        if (paramList != null) {
            docket.globalOperationParameters(paramList);
        }
        return docket;
    }
}