Swagger 之 Starter 编写
这里并没有使用 starter 的自定加载而是使用 注解进行开关 Swagger 服务,这样方便选择性的打开或者关闭 Swagger 服务
没有过多的解释,请见谅,直接上代码:
码云中有整合的案例: https://gitee.com/chxlay/be-helpful/tree/master/behelpful-common/behelpful-swagger/src/main
依赖:
<dependencies> <!--swagger 依赖--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>your version</version> </dependency> <!-- swagger Ui页面 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>your version</version> </dependency> <!--knife4j是为Java MVC框架集成Swagger生成Api文档的增强--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-micro-spring-boot-starter</artifactId> <version>your version</version> </dependency> <!-- 文档 Ui页面 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-ui</artifactId> <version>your version</version> </dependency> </dependencies>
属性配置:
swagger: title: Behelpful Swagger API license: Powered By Behelpful licenseUrl: https://www.xxx.com terms-of-service-url: https://www.xxx.com # 文档上下文主体描述属性信息 contact: email: xxx@gmail.com url: https://www.xxx.com # Swagger 权限认证配置 authorization: name: Authorization auth-regex: ^.*$ authorization-scope-list: - scope: server description: server all token-url-list: # 调用权限认证的模块的接口配置 - http://behelpful-gateway:9999/admin/login enabled: true
属性文件配置类:
@Data @ConfigurationProperties("swagger") public class SwaggerProperties { /** * 是否开启swagger */ private Boolean enabled; /** * swagger会解析的包路径 **/ private String basePackage = ""; /** * swagger会解析的url规则 **/ private List<String> basePath = new ArrayList<>(); /** * 在basePath基础上需要排除的url规则 **/ private List<String> excludePath = new ArrayList<>(); /** * 标题 **/ private String title = ""; /** * 描述 **/ private String description = ""; /** * 版本 **/ private String version = ""; /** * 许可证 **/ private String license = ""; /** * 许可证URL **/ private String licenseUrl = ""; /** * 服务条款URL **/ private String termsOfServiceUrl = ""; /** * host信息 **/ private String host = ""; /** * 联系人信息 */ private Contact contact = new Contact(); /** * 全局统一鉴权配置 **/ private Authorization authorization = new Authorization(); @Data @NoArgsConstructor public static class Contact { /** * 联系人 **/ private String name = ""; /** * 联系人url **/ private String url = ""; /** * 联系人email **/ private String email = ""; } @Data @NoArgsConstructor public static class Authorization { /** * 鉴权策略ID,需要和SecurityReferences ID保持一致 */ private String name = "Authorization"; /** * 需要开启鉴权URL的正则 */ private String authRegex = "^.*$"; /** * 鉴权作用域列表 */ private List<AuthorizationScope> authorizationScopeList = new ArrayList<>(); private List<String> tokenUrlList = new ArrayList<>(); } @Data @NoArgsConstructor public static class AuthorizationScope { /** * 作用域名称 */ private String scope = ""; /** * 作用域描述 */ private String description = ""; } }
配置类:
/**官方文档3.0版本@see {https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md} * swagger配置 禁用方法1:使用注解@Profile({"dev","test"}) * 表示在开发或测试环境开启,而在生产关闭。(推荐使用) 禁用方法2:使用注解@ConditionalOnProperty(name = "swagger.enable", * havingValue = "true") 然后在测试配置或者开发配置中添加swagger.enable=true即可开启,生产环境不填则默认关闭Swagger. */ @Configuration @EnableSwagger2 @EnableAutoConfiguration @ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true) public class SwaggerAutoConfiguration { /** * 默认的排除路径,排除Spring Boot默认的错误处理路径和端点 */ private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**"); private static final String BASE_PATH = "/**"; @Autowired private SwaggerProperties swaggerProperties; @Bean public Docket api(SwaggerProperties swaggerProperties) { // base-path处理 if (swaggerProperties.getBasePath().isEmpty()) { swaggerProperties.getBasePath().add(BASE_PATH); } List<Predicate<String>> basePath = new ArrayList(); swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path))); // exclude-path处理 if (swaggerProperties.getExcludePath().isEmpty()) { swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH); } List<Predicate<String>> excludePath = new ArrayList<>(); swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path))); // 版本请求头处理 ParameterBuilder versionPar = new ParameterBuilder(); List<Parameter> pars = new ArrayList<>(); versionPar.name("VERSION").description("灰度路由版本信息").modelRef(new ModelRef("string")).parameterType("header") .required(false).build(); pars.add(versionPar.build()); // noinspection Guava return new Docket(DocumentationType.SWAGGER_2) .host(swaggerProperties.getHost()) // 文档上下文主体描述信息 .apiInfo(this.apiInfo(swaggerProperties)).globalOperationParameters(pars) // 获取Docket 中的选择器,返回ApiSelectorBuilder .select() // Api 的规则,断言 .apis( // 设定扫描那个包(及子包)中的注解 RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()) ) // 类或者方法上含有此直接的不进行文档生成 .apis( // 添加一个断言,Predicates.not()取反的意思, Predicates.not( // 当方法或者类上含有此注解时返回 true 表示隐藏 接口,不生成Api文档及测试,不用自己写,可使用Swagger 注解自带的 hidden=true RequestHandlerSelectors.withClassAnnotation(HideApi.class) ) ) // 路径返回约束 .paths( Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath)) ) // 使用正则表达式匹配,约束生成Api文档的路径地址,.代表任意字符串,*代表 0~n个任意字符 .paths(PathSelectors.regex("/xxx/.*")) .build() // 权限认证配置 .securitySchemes(Collections.singletonList(this.securitySchema())) .securityContexts(Collections.singletonList(this.securityContext())).pathMapping("/"); } /** * 配置默认的全局鉴权策略的开关,通过正则表达式进行匹配;默认匹配所有URL * * @return */ private List<SecurityContext> securityContext() { SecurityContext securityContext = new SecurityContext( this.defaultAuth(), PathSelectors.regex(swaggerProperties.getAuthorization().getAuthRegex()) ); return ICollUtil.asList(securityContext); } /** * 默认的全局鉴权策略 * * @return */ private List<SecurityReference> defaultAuth() { List<AuthorizationScope> authorizationScopeList = new ArrayList<>(); swaggerProperties.getAuthorization() .getAuthorizationScopeList() .forEach(authorizationScope -> authorizationScopeList.add( new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription())) ); AuthorizationScope[] authorizationScopes = new AuthorizationScope[authorizationScopeList.size()]; authorizationScopes = authorizationScopeList.toArray(authorizationScopes); SecurityReference securityReference = new SecurityReference(swaggerProperties.getAuthorization().getName(), authorizationScopes); return ICollUtil.asList(securityReference); } /** * 权限认证 * * @return */ private List<OAuth> securitySchema() { ArrayList<AuthorizationScope> authorizationScopeList = new ArrayList<>(); swaggerProperties.getAuthorization() .getAuthorizationScopeList() .forEach(authorizationScope -> authorizationScopeList.add( new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription()))); List<GrantType> grantTypes = new ArrayList<>(); swaggerProperties.getAuthorization() .getTokenUrlList() // 权限认证调用服务的 Api,如:http://xxx/xxx/login .forEach(tokenUrl -> grantTypes.add(new ResourceOwnerPasswordCredentialsGrant(tokenUrl))); OAuth oAuth = new OAuth(swaggerProperties.getAuthorization().getName(), authorizationScopeList, grantTypes); return ICollUtil.asList(oAuth); } /** * 另一种权鉴认证 * * @return */ private List<ApiKey> securitySchema() { // ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); ApiKey apiKey = new ApiKey("Authorization-Token", "Authorization-Token", "header"); return ICollUtil.asList(apiKey); } /** * 文档上下文主体描述属性信息对象构建 * * @param swaggerProperties * @return */ private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { return new ApiInfoBuilder() .title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()) .license(swaggerProperties.getLicense()) .licenseUrl(swaggerProperties.getLicenseUrl()) .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) .contact( new Contact( swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail() ) ) .version(swaggerProperties.getVersion()) .build(); } } /** * 配置默认的全局鉴权策略的开关,通过正则表达式进行匹配;默认匹配所有URL * * @return */ private List<SecurityContext> securityContext() { SecurityContext securityContext = new SecurityContext( this.defaultAuth(), PathSelectors.regex(swaggerProperties.getAuthorization().getAuthRegex()) ); return ICollUtil.asList(securityContext); } /** * 默认的全局鉴权策略 * * @return */ private List<SecurityReference> defaultAuth() { List<AuthorizationScope> authorizationScopeList = new ArrayList<>(); swaggerProperties.getAuthorization() .getAuthorizationScopeList() .forEach(authorizationScope -> authorizationScopeList.add( new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription())) ); AuthorizationScope[] authorizationScopes = new AuthorizationScope[authorizationScopeList.size()]; authorizationScopes = authorizationScopeList.toArray(authorizationScopes); SecurityReference securityReference = new SecurityReference( swaggerProperties.getAuthorization().getName(), authorizationScopes ); return ICollUtil.asList(securityReference); } /** * 权限认证 * * @return */ private List<OAuth> securitySchema() { ArrayList<AuthorizationScope> authorizationScopeList = new ArrayList<>(); swaggerProperties.getAuthorization() .getAuthorizationScopeList() .forEach(authorizationScope -> authorizationScopeList.add( new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription()))); List<GrantType> grantTypes = new ArrayList<>(); swaggerProperties.getAuthorization() .getTokenUrlList() // 权限认证调用服务的 Api,如:http://xxx/xxx/login .forEach(tokenUrl -> grantTypes.add(new ResourceOwnerPasswordCredentialsGrant(tokenUrl))); OAuth oAuth = new OAuth(swaggerProperties.getAuthorization().getName(), authorizationScopeList, grantTypes); return ICollUtil.asList(oAuth); } /** * 另一种权鉴认证 * * @return */ private List<ApiKey> securitySchema() { // ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); ApiKey apiKey = new ApiKey("Authorization-Token", "Authorization-Token", "header"); return ICollUtil.asList(apiKey); } /** * 文档上下文主体描述属性信息对象构建 * * @param swaggerProperties * @return */ private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { return new ApiInfoBuilder() .title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()) .license(swaggerProperties.getLicense()) .licenseUrl(swaggerProperties.getLicenseUrl()) .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) .contact( new Contact( swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail() ) ) .version(swaggerProperties.getVersion()) .build(); } }
如:项目中实际使用的案例:
@Slf4j @Configuration @EnableSwagger2 @EnableKnife4j @EnableConfigurationProperties(value = SwaggerProperties.class) @ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true) public class SwaggerConfig { /** * 默认的排除路径,排除Spring Boot默认的错误处理路径和端点 */ private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**"); private static final String BASE_PATH = "/**"; @Autowired private SwaggerProperties swaggerProperties; @Bean public Docket docket() { // base-path处理 if (swaggerProperties.getBasePath().isEmpty()) { swaggerProperties.getBasePath().add(BASE_PATH); } List<com.google.common.base.Predicate<String>> basePath = new ArrayList(); swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path))); // exclude-path处理 if (swaggerProperties.getExcludePath().isEmpty()) { swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH); } List<Predicate<String>> excludePath = new ArrayList<>(); swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path))); // 版本请求头处理 ParameterBuilder versionPar = new ParameterBuilder(); List<Parameter> pars = new ArrayList<>(); versionPar .name("VERSION") .description("灰度路由版本信息") .modelRef(new ModelRef("string")) .parameterType("header") .required(false) .build(); pars.add(versionPar.build()); // noinspection Guava Docket docket = new Docket(DocumentationType.SWAGGER_2) .groupName(swaggerProperties.getGroupName()) .host(swaggerProperties.getHost()) // 是否开启文档生成 .enable(swaggerProperties.getEnabled()) .apiInfo(this.apiInfo(swaggerProperties)) .globalOperationParameters(pars) .select() // Api 的规则,断言 .apis( // 设定扫描那个包(及子包)中的注解 RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()) ) // 路径返回约束 .paths( Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath)) ) .build() // 权限认证 .securitySchemes(this.securitySchema()) .securityContexts(this.securityContext()) .pathMapping("/"); log.info("My Swagger | 配置完成"); return docket; } /** * 配置默认的全局鉴权策略的开关,通过正则表达式进行匹配;默认匹配所有URL * * @return */ private List<SecurityContext> securityContext() { SecurityContext securityContext = new SecurityContext( this.defaultAuth(), PathSelectors.regex(swaggerProperties.getAuthorization().getAuthRegex()) ); return ICollUtil.asList(securityContext); } /** * 默认的全局鉴权策略 * * @return */ private List<SecurityReference> defaultAuth() { List<AuthorizationScope> authorizationScopeList = new ArrayList<>(); swaggerProperties.getAuthorization() .getAuthorizationScopeList() .forEach(authorizationScope -> authorizationScopeList.add( new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription())) ); AuthorizationScope[] authorizationScopes = new AuthorizationScope[authorizationScopeList.size()]; authorizationScopes = authorizationScopeList.toArray(authorizationScopes); SecurityReference securityReference = new SecurityReference( swaggerProperties.getAuthorization().getName(), authorizationScopes ); return ICollUtil.asList(securityReference); } /** * 权限认证 * * @return */ /* private List<OAuth> securitySchema() { ArrayList<AuthorizationScope> authorizationScopeList = new ArrayList<>(); swaggerProperties.getAuthorization() .getAuthorizationScopeList() .forEach(authorizationScope -> authorizationScopeList.add( new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription()))); List<GrantType> grantTypes = new ArrayList<>(); swaggerProperties.getAuthorization() .getTokenUrlList() // 权限认证调用服务的 Api,如:http://xxx/xxx/login .forEach(tokenUrl -> grantTypes.add(new ResourceOwnerPasswordCredentialsGrant(tokenUrl))); OAuth oAuth = new OAuth(swaggerProperties.getAuthorization().getName(), authorizationScopeList, grantTypes); return ICollUtil.asList(oAuth); }*/ /** * 另一种权鉴认证 * * @return */ private List<ApiKey> securitySchema() { // ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); ApiKey apiKey = new ApiKey("Authorization-Token", "Authorization-Token", "header"); return ICollUtil.asList(apiKey); } /** * 文档上下文主体描述属性信息对象构建 * * @param swaggerProperties * @return */ private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { return new ApiInfoBuilder() .title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()) .license(swaggerProperties.getLicense()) .licenseUrl(swaggerProperties.getLicenseUrl()) .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) .contact( new Contact( swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail() ) ) .version(swaggerProperties.getVersion()) .build(); } }
自定义注解,不推荐使用,推荐使用 Swagger 内置注解处理 hidden=true
@Target(value = {ElementType.TYPE, ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface HideApi { }
Swagger 启动控制开关注解:
@Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({ SwaggerAutoConfiguration.class }) public @interface EnableMySwagger2 { }
本文来自博客园,作者:Vermeer,转载请注明原文链接:https://www.cnblogs.com/chxlay/p/15170879.html