前面在使用Swagger2時遇到的坑中簡單介紹了Swagger的使用。html
不過默認狀況下,Swagger2會把項目中的全部接口都展現在列表裏,特別是你用了Springboot/SpringCloud以後,各類內部health check的接口,但其實這些都不必展現出來。java
這時候,你就須要限定接口的範圍了。spring
增長一個配置類,簡要代碼以下:api
@Configuration @EnableSwagger2 public class Swagger2Config { @Bean public Docket buildDocket() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() .apis(RequestHandlerSelectors.basePackage("com.yejg")).paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("接口文檔").description("描述文字...").termsOfServiceUrl("https://yejg.top").version("V1.0").build(); } }
有了這個【RequestHandlerSelectors.basePackage("com.yejg")】限定以後,就只會展現【com.yejg】包下的接口了。so easy…app
不過,這時候,有個新問題,若是要增長展現 com.springXXX 的接口,怎麼辦呢?ide
直接上代碼以前,先看下優化方案怎麼來的。優化
從代碼看,跟目錄範圍相關的就是apis方法了,源碼以下:ui
// 此Predicate是com.google.common.base.Predicate,不是jdk8的那個,不過原理相似 都是判斷的謂詞 public ApiSelectorBuilder apis(Predicate<RequestHandler> selector) { requestHandlerSelector = and(requestHandlerSelector, selector); return this; }
想要支持配置多個目錄,就得從這個Predicate下手了。this
先看下RequestHandlerSelectors.basePackage是怎麼返回Predicate的:google
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); } }; } private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) { return new Function<Class<?>, Boolean>() { @Override public Boolean apply(Class<?> input) { return input.getPackage().getName().startsWith(basePackage); } }; }
重點關注上面的handlerPackage方法,它的邏輯就是:判斷項目的包路徑是否以設定的basePackage開頭。
若是改變這裏的判斷邏輯,判斷項目的包路徑是否以設定的basePackage1 或者 basePackage2 開頭,那就達到同時指定多個目錄的效果了。
實現代碼以下:
@Configuration @EnableSwagger2 public class Swagger2Config { // 定義分隔符 private static final String SEPARATOR = ","; @Bean public Docket buildDocket() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() .apis(basePackage("com.yejg" + SEPARATOR + "com.springXXX")) .paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("接口文檔").description("描述文字...") .termsOfServiceUrl("https://yejg.top").version("V1.0").build(); } /** * @param basePackage * @return * @see RequestHandlerSelectors#basePackage(String) */ 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); } }; } private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) { return input -> { // 循環判斷匹配 for (String strPackage : basePackage.split(SEPARATOR)) { boolean isMatch = input.getPackage().getName().startsWith(strPackage); if (isMatch) { return true; } } return false; }; } private static Optional<? extends Class<?>> declaringClass(RequestHandler input) { return Optional.fromNullable(input.declaringClass()); } }