Java tutorial
package cn.howardliu.gear.spring.boot.autoconfigure; import cn.howardliu.gear.spring.boot.autoconfigure.SwaggerProperties.GlobalOperationParameter; import cn.howardliu.gear.spring.boot.autoconfigure.SwaggerProperties.GlobalResponseMessage; import cn.howardliu.gear.spring.boot.autoconfigure.SwaggerProperties.GlobalResponseMessageBody; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMethod; import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; import springfox.documentation.builders.*; import springfox.documentation.schema.ModelRef; 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.swagger.web.ApiKeyVehicle; import springfox.documentation.swagger.web.UiConfiguration; import springfox.documentation.swagger.web.UiConfigurationBuilder; import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration; import java.util.*; import java.util.stream.Collectors; import static com.google.common.collect.Lists.newArrayList; /** * <br>created at 2019-05-22 * * @author liuxh * @since 1.0.0 */ @Configuration @ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true) @Import({ Swagger2DocumentationConfiguration.class, BeanValidatorPluginsConfiguration.class }) public class SwaggerAutoConfiguration implements BeanFactoryAware { private BeanFactory beanFactory; @Bean @ConditionalOnMissingBean public SwaggerProperties swaggerProperties() { return new SwaggerProperties(); } @Bean public UiConfiguration uiConfiguration(SwaggerProperties swaggerProperties) { return UiConfigurationBuilder.builder().deepLinking(swaggerProperties.getUiConfig().getDeepLinking()) .defaultModelExpandDepth(swaggerProperties.getUiConfig().getDefaultModelExpandDepth()) .defaultModelRendering(swaggerProperties.getUiConfig().getDefaultModelRendering()) .defaultModelsExpandDepth(swaggerProperties.getUiConfig().getDefaultModelsExpandDepth()) .displayOperationId(swaggerProperties.getUiConfig().getDisplayOperationId()) .displayRequestDuration(swaggerProperties.getUiConfig().getDisplayRequestDuration()) .docExpansion(swaggerProperties.getUiConfig().getDocExpansion()) .maxDisplayedTags(swaggerProperties.getUiConfig().getMaxDisplayedTags()) .operationsSorter(swaggerProperties.getUiConfig().getOperationsSorter()) .showExtensions(swaggerProperties.getUiConfig().getShowExtensions()) .tagsSorter(swaggerProperties.getUiConfig().getTagsSorter()) .validatorUrl(swaggerProperties.getUiConfig().getValidatorUrl()).build(); } @Bean @ConditionalOnMissingBean @ConditionalOnBean(UiConfiguration.class) @ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true) public List<Docket> createRestApi(SwaggerProperties swaggerProperties) { ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory; List<Docket> docketList = new LinkedList<>(); // if (swaggerProperties.getDocket().size() == 0) { ApiInfo apiInfo = new ApiInfoBuilder().title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()).version(swaggerProperties.getVersion()) .license(swaggerProperties.getLicense()).licenseUrl(swaggerProperties.getLicenseUrl()) .contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail())) .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()).build(); // base-path? // ?path?/** if (swaggerProperties.getBasePath().isEmpty()) { swaggerProperties.getBasePath().add("/**"); } List<Predicate<String>> basePath = new ArrayList<>(); for (String path : swaggerProperties.getBasePath()) { basePath.add(PathSelectors.ant(path)); } // exclude-path? List<Predicate<String>> excludePath = new ArrayList<>(); for (String path : swaggerProperties.getExcludePath()) { excludePath.add(PathSelectors.ant(path)); } Docket docketForBuilder = new Docket(DocumentationType.SWAGGER_2).host(swaggerProperties.getHost()) .apiInfo(apiInfo).securityContexts(Collections.singletonList(securityContext())) .globalOperationParameters(buildGlobalOperationParametersFromSwaggerProperties( swaggerProperties.getGlobalOperationParameters())); if ("BasicAuth".equalsIgnoreCase(swaggerProperties.getAuthorization().getType())) { docketForBuilder.securitySchemes(Collections.singletonList(basicAuth())); } else if (!"None".equalsIgnoreCase(swaggerProperties.getAuthorization().getType())) { docketForBuilder.securitySchemes(Collections.singletonList(apiKey())); } // ?? if (!swaggerProperties.getApplyDefaultResponseMessages()) { buildGlobalResponseMessage(swaggerProperties, docketForBuilder); } Docket docket = docketForBuilder.select() .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())) .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath))) .build(); /* ignoredParameterTypes **/ Class<?>[] array = new Class[swaggerProperties.getIgnoredParameterTypes().size()]; Class<?>[] ignoredParameterTypes = swaggerProperties.getIgnoredParameterTypes().toArray(array); docket.ignoredParameterTypes(ignoredParameterTypes); configurableBeanFactory.registerSingleton("defaultDocket", docket); docketList.add(docket); return docketList; } // for (String groupName : swaggerProperties.getDocket().keySet()) { SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName); ApiInfo apiInfo = new ApiInfoBuilder() .title(docketInfo.getTitle().isEmpty() ? swaggerProperties.getTitle() : docketInfo.getTitle()) .description(docketInfo.getDescription().isEmpty() ? swaggerProperties.getDescription() : docketInfo.getDescription()) .version(docketInfo.getVersion().isEmpty() ? swaggerProperties.getVersion() : docketInfo.getVersion()) .license(docketInfo.getLicense().isEmpty() ? swaggerProperties.getLicense() : docketInfo.getLicense()) .licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl() : docketInfo.getLicenseUrl()) .contact(new Contact( docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(), docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(), docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail())) .termsOfServiceUrl( docketInfo.getTermsOfServiceUrl().isEmpty() ? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl()) .build(); // base-path? // ?path?/** if (docketInfo.getBasePath().isEmpty()) { docketInfo.getBasePath().add("/**"); } List<Predicate<String>> basePath = new ArrayList(); for (String path : docketInfo.getBasePath()) { basePath.add(PathSelectors.ant(path)); } // exclude-path? List<Predicate<String>> excludePath = new ArrayList(); for (String path : docketInfo.getExcludePath()) { excludePath.add(PathSelectors.ant(path)); } Docket docketForBuilder = new Docket(DocumentationType.SWAGGER_2).host(swaggerProperties.getHost()) .apiInfo(apiInfo).securityContexts(Collections.singletonList(securityContext())) .globalOperationParameters( assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(), docketInfo.getGlobalOperationParameters())); if ("BasicAuth".equalsIgnoreCase(swaggerProperties.getAuthorization().getType())) { docketForBuilder.securitySchemes(Collections.singletonList(basicAuth())); } else if (!"None".equalsIgnoreCase(swaggerProperties.getAuthorization().getType())) { docketForBuilder.securitySchemes(Collections.singletonList(apiKey())); } // ?? if (!swaggerProperties.getApplyDefaultResponseMessages()) { buildGlobalResponseMessage(swaggerProperties, docketForBuilder); } Docket docket = docketForBuilder.groupName(groupName).select() .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage())) .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath))) .build(); /* ignoredParameterTypes **/ Class<?>[] array = new Class[docketInfo.getIgnoredParameterTypes().size()]; Class<?>[] ignoredParameterTypes = docketInfo.getIgnoredParameterTypes().toArray(array); docket.ignoredParameterTypes(ignoredParameterTypes); configurableBeanFactory.registerSingleton(groupName, docket); docketList.add(docket); } return docketList; } /** * ? ApiKey ? * * @return */ private ApiKey apiKey() { return new ApiKey(swaggerProperties().getAuthorization().getName(), swaggerProperties().getAuthorization().getKeyName(), ApiKeyVehicle.HEADER.getValue()); } /** * ? BasicAuth ? * * @return */ private BasicAuth basicAuth() { return new BasicAuth(swaggerProperties().getAuthorization().getName()); } /** * ????? ^.*$ ?URL * securityReferences ??? * * @return */ private SecurityContext securityContext() { return SecurityContext.builder().securityReferences(defaultAuth()) .forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex())).build(); } /** * ?? SecurityReference reference ?ApiKey?name????? * * @return */ private List<SecurityReference> defaultAuth() { AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; return Collections.singletonList(SecurityReference.builder() .reference(swaggerProperties().getAuthorization().getName()).scopes(authorizationScopes).build()); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } private List<Parameter> buildGlobalOperationParametersFromSwaggerProperties( List<GlobalOperationParameter> globalOperationParameters) { List<Parameter> parameters = newArrayList(); if (Objects.isNull(globalOperationParameters)) { return parameters; } for (GlobalOperationParameter globalOperationParameter : globalOperationParameters) { parameters.add(new ParameterBuilder().name(globalOperationParameter.getName()) .description(globalOperationParameter.getDescription()) .modelRef(new ModelRef(globalOperationParameter.getModelRef())) .parameterType(globalOperationParameter.getParameterType()) .required(Boolean.parseBoolean(globalOperationParameter.getRequired())).build()); } return parameters; } /** * ?name? * * @param globalOperationParameters * @param docketOperationParameters * @return */ private List<Parameter> assemblyGlobalOperationParameters( List<GlobalOperationParameter> globalOperationParameters, List<GlobalOperationParameter> docketOperationParameters) { if (Objects.isNull(docketOperationParameters) || docketOperationParameters.isEmpty()) { return buildGlobalOperationParametersFromSwaggerProperties(globalOperationParameters); } Set<String> docketNames = docketOperationParameters.stream().map(GlobalOperationParameter::getName) .collect(Collectors.toSet()); List<GlobalOperationParameter> resultOperationParameters = newArrayList(); if (Objects.nonNull(globalOperationParameters)) { for (GlobalOperationParameter parameter : globalOperationParameters) { if (!docketNames.contains(parameter.getName())) { resultOperationParameters.add(parameter); } } } resultOperationParameters.addAll(docketOperationParameters); return buildGlobalOperationParametersFromSwaggerProperties(resultOperationParameters); } /** * ?? * * @param swaggerProperties swaggerProperties ? POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE * @param docketForBuilder swagger docket builder */ private void buildGlobalResponseMessage(SwaggerProperties swaggerProperties, Docket docketForBuilder) { GlobalResponseMessage globalResponseMessages = swaggerProperties.getGlobalResponseMessage(); /* POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE ?? **/ List<ResponseMessage> postResponseMessages = getResponseMessageList(globalResponseMessages.getPost()); List<ResponseMessage> getResponseMessages = getResponseMessageList(globalResponseMessages.getGet()); List<ResponseMessage> putResponseMessages = getResponseMessageList(globalResponseMessages.getPut()); List<ResponseMessage> patchResponseMessages = getResponseMessageList(globalResponseMessages.getPatch()); List<ResponseMessage> deleteResponseMessages = getResponseMessageList(globalResponseMessages.getDelete()); List<ResponseMessage> headResponseMessages = getResponseMessageList(globalResponseMessages.getHead()); List<ResponseMessage> optionsResponseMessages = getResponseMessageList(globalResponseMessages.getOptions()); List<ResponseMessage> trackResponseMessages = getResponseMessageList(globalResponseMessages.getTrace()); docketForBuilder.useDefaultResponseMessages(swaggerProperties.getApplyDefaultResponseMessages()) .globalResponseMessage(RequestMethod.POST, postResponseMessages) .globalResponseMessage(RequestMethod.GET, getResponseMessages) .globalResponseMessage(RequestMethod.PUT, putResponseMessages) .globalResponseMessage(RequestMethod.PATCH, patchResponseMessages) .globalResponseMessage(RequestMethod.DELETE, deleteResponseMessages) .globalResponseMessage(RequestMethod.HEAD, headResponseMessages) .globalResponseMessage(RequestMethod.OPTIONS, optionsResponseMessages) .globalResponseMessage(RequestMethod.TRACE, trackResponseMessages); } /** * ?? * * @param globalResponseMessageBodyList Code?? * @return */ private List<ResponseMessage> getResponseMessageList( List<GlobalResponseMessageBody> globalResponseMessageBodyList) { List<ResponseMessage> responseMessages = new ArrayList<>(); for (GlobalResponseMessageBody globalResponseMessageBody : globalResponseMessageBodyList) { ResponseMessageBuilder responseMessageBuilder = new ResponseMessageBuilder(); responseMessageBuilder.code(globalResponseMessageBody.getCode()) .message(globalResponseMessageBody.getMessage()); if (!StringUtils.isEmpty(globalResponseMessageBody.getModelRef())) { responseMessageBuilder.responseModel(new ModelRef(globalResponseMessageBody.getModelRef())); } responseMessages.add(responseMessageBuilder.build()); } return responseMessages; } }