本地項目作了Swagger2的配置,在啓動時報以下錯誤:html
DocumentationPluginsBootstrapper : Unable to scan documentation context default
測試的Controller文件:java
package com.quantsmart.controller; import com.quantsmart.model.R; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.Authorization; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author: kaiyi * @Date 2021/5/21 13:57 */ @RestController @Api(tags = "CoinCommon裏面的測試接口") public class TestController { @GetMapping("/common/test") @ApiOperation(value = "測試方法", authorizations = {@Authorization("Authorization")}) @ApiImplicitParams({ @ApiImplicitParam(name = "param", value = "參數1", dataType = "String", paramType = "query", example = "paramValue"), @ApiImplicitParam(name = "param1", value = "參數2", dataType = "String", paramType = "query", example = "paramValue") }) public R<String> testMethod(String param, String param2){ return R.ok("ok,哈哈哈,測試哇"); } }
/config/swagger/SwaggerProperties.java
web
package com.quantsmart.config.swagger; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author: kaiyi * @Date 2021/5/20 16:50 */ @Data @ConfigurationProperties(prefix = "swagger2") public class SwaggerProperties { /** * 是否開啓swagger */ private Boolean enabled; /** * 包掃描的路徑 */ private String basePackage; /** * 聯繫人的名稱 */ private String name ; /** * 聯繫人的主頁 */ private String url ; /** * 聯繫人的郵箱 */ private String email ; /** * API的標題 */ private String title ; /** * API的描述 */ private String description ; /** * API的版本號 */ private String version ; /** * API的服務團隊 */ private String termsOfServiceUrl ; }
/config/swagger/SwaggerAutoConfiguration.java
spring
package com.quantsmart.config.swagger; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; 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.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.Arrays; import java.util.List; /** * @author: kaiyi * @Date 2021/5/20 16:50 */ @Configuration @EnableSwagger2 // 開啓swagger2自動生成api文檔的功能 @EnableConfigurationProperties(SwaggerProperties.class) public class SwaggerAutoConfiguration { private SwaggerProperties swaggerProperties; public SwaggerAutoConfiguration(SwaggerProperties swaggerProperties) { this.swaggerProperties = swaggerProperties; } @Bean public Docket docket() { Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())) .paths(PathSelectors.any()) .build(); // 安全的配置 docket.securitySchemes(securitySchemes()) // 安全規則 .securityContexts(securityContexts()); // 安全配置的上下問 return docket; } /** * api 信息的簡介 * * @return */ private ApiInfo apiInfo() { return new ApiInfoBuilder().contact( new Contact(swaggerProperties.getName(), swaggerProperties.getUrl(), swaggerProperties.getEmail()) ) .title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()) .version(swaggerProperties.getVersion()) .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) .build(); } /** * 安全的規則配置 * * @return */ private List<SecurityScheme> securitySchemes() { return Arrays.asList(new ApiKey("Authorization", "Authorization", "Authorization")); } /** * 安全的上下文 * * @return */ private List<SecurityContext> securityContexts() { return Arrays.asList(new SecurityContext( Arrays.asList(new SecurityReference("Authorization", new AuthorizationScope[]{new AuthorizationScope("global", "accessResource")})), PathSelectors.any() )); } }
注意這裏的apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
掃描的是 controller包,是產生下面錯誤的緣由:api
ERROR 4928 --- [ main] d.s.w.p.DocumentationPluginsBootstrapper : Unable to scan documentation context default java.lang.NullPointerException: null at java.lang.String.startsWith(String.java:1405) ~[na:1.8.0_131] at java.lang.String.startsWith(String.java:1434) ~[na:1.8.0_131] at springfox.documentation.builders.RequestHandlerSelectors$4.apply(RequestHandlerSelectors.java:98) ~[springfox-core-2.9.2.jar:null] at springfox.documentation.builders.RequestHandlerSelectors$4.apply(RequestHandlerSelectors.java:95) ~[springfox-core-2.9.2.jar:null] at com.google.common.base.Present.transform(Present.java:75) ~[guava-20.0.jar:na] at springfox.documentation.builders.RequestHandlerSelectors$5.apply(RequestHandlerSelectors.java:114) ~[springfox-core-2.9.2.jar:null] at springfox.documentation.builders.RequestHandlerSelectors$5.apply(RequestHandlerSelectors.java:111) ~[springfox-core-2.9.2.jar:null] at com.google.common.base.Predicates$AndPredicate.apply(Predicates.java:384) ~[guava-20.0.jar:na] at com.google.common.base.Predicates$AndPredicate.apply(Predicates.java:384) ~[guava-20.0.jar:na] at com.google.common.collect.Iterators$6.computeNext(Iterators.java:617) ~[guava-20.0.jar:na] at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145) ~[guava-20.0.jar:na] at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140) ~[guava-20.0.jar:na] at springfox.documentation.spring.web.scanners.ApiListingReferenceScanner.scan(ApiListingReferenceScanner.java:48) ~[springfox-spring-web-2.9.2.jar:null] at springfox.documentation.spring.web.scanners.ApiDocumentationScanner.scan(ApiDocumentationScanner.java:67) ~[springfox-spring-web-2.9.2.jar:null] at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.scanDocumentation(DocumentationPluginsBootstrapper.java:101) [springfox-spring-web-2.9.2.jar:null] at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:167) [springfox-spring-web-2.9.2.jar:null] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) [spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.7.RELEASE.jar:2.2.7.RELEASE] at com.coin.TestCommonApplication.main(TestCommonApplication.java:12) [classes/:na]
上邊已經發現了問題了,若是我此時將apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
改成我具體要掃描的包安全
apis(RequestHandlerSelectors.basePackage(「com.quantsmart.controller」))
app
此時重啓,能夠發現打印的日誌中沒出現上面的錯誤了,且DocumentationPluginsBootstrapper 中打印掃描到一個controller接口了。spring-boot
上邊的修改方法是直接寫死的,因此,咱們能夠在配置文件中配置swaggerProperties.getBasePackage()這個controller包路徑(即SwaggerProperties類中的basePackage屬性),例如在 application.yml
配置文件中添加controller包路徑測試
# Swagger2屬性配置 swagger2: base-package: com.quantsmart.controller # 須要指定掃描的包的路徑
而後訪問 http://localhost:8989/swagger-ui.html
頁面,能夠看到能夠成功看到接口文檔頁面了:ui