All Downloads are FREE. Search and download functionalities are using the official Maven repository.

club.zhcs.swagger.SwaggerAutoConfiguration Maven / Gradle / Ivy

package club.zhcs.swagger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.nutz.lang.Lang;
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 com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.service.SecurityReference;
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;

/**
 * @author kerbores
 *
 */
@Configuration
@Import({Swagger2Configuration.class})
public class SwaggerAutoConfiguration implements BeanFactoryAware {

    private BeanFactory beanFactory;

    @Bean
    @ConditionalOnMissingBean
    public SwaggerConfigurationProerties swaggerConfigurationProerties() {
        return new SwaggerConfigurationProerties();
    }

    @Bean
    public UiConfiguration uiConfiguration(SwaggerConfigurationProerties swaggerConfigurationProerties) {
        return UiConfigurationBuilder.builder()
                                     .deepLinking(swaggerConfigurationProerties.getUiConfig().getDeepLinking())
                                     .defaultModelExpandDepth(swaggerConfigurationProerties.getUiConfig().getDefaultModelExpandDepth())
                                     .defaultModelRendering(swaggerConfigurationProerties.getUiConfig().getDefaultModelRendering())
                                     .defaultModelsExpandDepth(swaggerConfigurationProerties.getUiConfig().getDefaultModelsExpandDepth())
                                     .displayOperationId(swaggerConfigurationProerties.getUiConfig().getDisplayOperationId())
                                     .displayRequestDuration(swaggerConfigurationProerties.getUiConfig().getDisplayRequestDuration())
                                     .docExpansion(swaggerConfigurationProerties.getUiConfig().getDocExpansion())
                                     .maxDisplayedTags(swaggerConfigurationProerties.getUiConfig().getMaxDisplayedTags())
                                     .operationsSorter(swaggerConfigurationProerties.getUiConfig().getOperationsSorter())
                                     .showExtensions(swaggerConfigurationProerties.getUiConfig().getShowExtensions())
                                     .tagsSorter(swaggerConfigurationProerties.getUiConfig().getTagsSorter())
                                     .validatorUrl(swaggerConfigurationProerties.getUiConfig().getValidatorUrl())
                                     .build();
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnBean(UiConfiguration.class)
    @ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
    public List createRestApi(SwaggerConfigurationProerties swaggerConfigurationProerties) {
        ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
        List docketList = Lists.newArrayList();

        // 没有分组
        if (swaggerConfigurationProerties.getDocket().size() == 0) {
            return createRestApiWithoutDocket(swaggerConfigurationProerties, configurableBeanFactory, docketList);
        }

        // 分组创建
        return createRestApiWithDocketInfo(swaggerConfigurationProerties, configurableBeanFactory, docketList);
    }

    private List createRestApiWithDocketInfo(SwaggerConfigurationProerties swaggerConfigurationProerties,
                                                     ConfigurableBeanFactory configurableBeanFactory,
                                                     List docketList) {
        for (String groupName : swaggerConfigurationProerties.getDocket().keySet()) {
            SwaggerConfigurationProerties.DocketInfo docketInfo = swaggerConfigurationProerties.getDocket()
                                                                                               .get(groupName);

            ApiInfo apiInfo = createApiInfo(swaggerConfigurationProerties, docketInfo);

            // base-path处理
            // 当没有配置任何path的时候,解析/**
            if (docketInfo.getBasePath().isEmpty()) {
                docketInfo.getBasePath().add("/**");
            }
            List> basePath = new ArrayList();
            for (String path : docketInfo.getBasePath()) {
                basePath.add(PathSelectors.ant(path));
            }

            // exclude-path处理
            List> excludePath = new ArrayList();
            for (String path : docketInfo.getExcludePath()) {
                excludePath.add(PathSelectors.ant(path));
            }

            Docket docketForBuilder = new Docket(DocumentationType.SWAGGER_2)
                                                                             .host(swaggerConfigurationProerties.getHost())
                                                                             .apiInfo(apiInfo)
                                                                             .securitySchemes(Collections.singletonList(apiKey()))
                                                                             .securityContexts(Collections.singletonList(securityContext()))
                                                                             .globalOperationParameters(assemblyGlobalOperationParameters(
                                                                                                                                          swaggerConfigurationProerties.getGlobalOperationParameters(),
                                                                                                                                          docketInfo.getGlobalOperationParameters()));

            // 全局响应消息
            if (Boolean.FALSE.equals(swaggerConfigurationProerties.getApplyDefaultResponseMessages())) {
                buildGlobalResponseMessage(swaggerConfigurationProerties, 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;
    }

    private ApiInfo createApiInfo(SwaggerConfigurationProerties swaggerConfigurationProerties,
                                  SwaggerConfigurationProerties.DocketInfo docketInfo) {
        return new ApiInfoBuilder()
                                   .title(docketInfo.getTitle().isEmpty() ? swaggerConfigurationProerties.getTitle()
                                                                          : docketInfo.getTitle())
                                   .description(docketInfo.getDescription().isEmpty() ? swaggerConfigurationProerties.getDescription()
                                                                                      : docketInfo.getDescription())
                                   .version(docketInfo.getVersion().isEmpty() ? swaggerConfigurationProerties.getVersion()
                                                                              : docketInfo.getVersion())
                                   .license(docketInfo.getLicense().isEmpty() ? swaggerConfigurationProerties.getLicense()
                                                                              : docketInfo.getLicense())
                                   .licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerConfigurationProerties.getLicenseUrl()
                                                                                    : docketInfo.getLicenseUrl())
                                   .contact(new Contact(
                                                        docketInfo.getContact().getName().isEmpty()
                                                                                                    ? swaggerConfigurationProerties.getContact()
                                                                                                                                   .getName()
                                                                                                    : docketInfo.getContact().getName(),
                                                        docketInfo.getContact()
                                                                  .getUrl()
                                                                  .isEmpty() ? swaggerConfigurationProerties.getContact().getUrl()
                                                                             : docketInfo.getContact().getUrl(),
                                                        docketInfo.getContact().getEmail().isEmpty()
                                                                                                     ? swaggerConfigurationProerties.getContact()
                                                                                                                                    .getEmail()
                                                                                                     : docketInfo.getContact().getEmail()))
                                   .termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty()
                                                                                                  ? swaggerConfigurationProerties.getTermsOfServiceUrl()
                                                                                                  : docketInfo.getTermsOfServiceUrl())
                                   .build();
    }

    private List createRestApiWithoutDocket(SwaggerConfigurationProerties swaggerConfigurationProerties,
                                                    ConfigurableBeanFactory configurableBeanFactory,
                                                    List docketList) {
        ApiInfo apiInfo = new ApiInfoBuilder().title(swaggerConfigurationProerties.getTitle())
                                              .description(swaggerConfigurationProerties.getDescription())
                                              .version(swaggerConfigurationProerties.getVersion())
                                              .license(swaggerConfigurationProerties.getLicense())
                                              .licenseUrl(swaggerConfigurationProerties.getLicenseUrl())
                                              .contact(new Contact(swaggerConfigurationProerties.getContact().getName(),
                                                                   swaggerConfigurationProerties.getContact().getUrl(),
                                                                   swaggerConfigurationProerties.getContact().getEmail()))
                                              .termsOfServiceUrl(swaggerConfigurationProerties.getTermsOfServiceUrl())
                                              .build();

        // base-path处理
        // 当没有配置任何path的时候,解析/**
        if (swaggerConfigurationProerties.getBasePath().isEmpty()) {
            swaggerConfigurationProerties.getBasePath().add("/**");
        }
        List> basePath = new ArrayList();
        for (String path : swaggerConfigurationProerties.getBasePath()) {
            basePath.add(PathSelectors.ant(path));
        }

        // exclude-path处理
        List> excludePath = Lists.newArrayList();
        for (String path : swaggerConfigurationProerties.getExcludePath()) {
            excludePath.add(PathSelectors.ant(path));
        }

        Docket docketForBuilder = new Docket(DocumentationType.SWAGGER_2).host(swaggerConfigurationProerties.getHost())
                                                                         .apiInfo(apiInfo)
                                                                         .securitySchemes(Collections.singletonList(apiKey()))
                                                                         .securityContexts(Collections.singletonList(securityContext()))
                                                                         .globalOperationParameters(buildGlobalOperationParametersFromSwaggerConfigurationProerties(
                                                                                                                                                                    swaggerConfigurationProerties.getGlobalOperationParameters()));

        // 全局响应消息
        if (Boolean.FALSE.equals(swaggerConfigurationProerties.getApplyDefaultResponseMessages())) {
            buildGlobalResponseMessage(swaggerConfigurationProerties, docketForBuilder);
        }

        Docket docket = docketForBuilder.select()
                                        .apis(RequestHandlerSelectors.basePackage(swaggerConfigurationProerties.getBasePackage()))
                                        .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath)))
                                        .build();

        /* ignoredParameterTypes **/
        Class[] array = new Class[swaggerConfigurationProerties.getIgnoredParameterTypes().size()];
        Class[] ignoredParameterTypes = swaggerConfigurationProerties.getIgnoredParameterTypes().toArray(array);
        docket.ignoredParameterTypes(ignoredParameterTypes);

        configurableBeanFactory.registerSingleton("defaultDocket", docket);
        docketList.add(docket);
        return docketList;
    }

    private ApiKey apiKey() {
        return new ApiKey(swaggerConfigurationProerties().getAuthorization().getName(),
                          swaggerConfigurationProerties().getAuthorization().getKeyName(),
                          ApiKeyVehicle.HEADER.getValue());
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                              .securityReferences(defaultAuth())
                              .forPaths(PathSelectors.regex(swaggerConfigurationProerties().getAuthorization().getAuthRegex()))
                              .build();
    }

    private List defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Collections.singletonList(
                                         SecurityReference.builder()
                                                          .reference(swaggerConfigurationProerties().getAuthorization().getName())
                                                          .scopes(authorizationScopes)
                                                          .build());
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    private List buildGlobalOperationParametersFromSwaggerConfigurationProerties(
                                                                                            List globalOperationParameters) {
        List parameters = Lang.list();

        if (Objects.isNull(globalOperationParameters)) {
            return parameters;
        }
        for (SwaggerConfigurationProerties.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;
    }

    private List assemblyGlobalOperationParameters(
                                                              List globalOperationParameters,
                                                              List docketOperationParameters) {

        if (Objects.isNull(docketOperationParameters) || docketOperationParameters.isEmpty()) {
            return buildGlobalOperationParametersFromSwaggerConfigurationProerties(globalOperationParameters);
        }

        Set docketNames = docketOperationParameters.stream()
                                                           .map(SwaggerConfigurationProerties.GlobalOperationParameter::getName)
                                                           .collect(Collectors.toSet());

        List resultOperationParameters = Lang.list();

        if (Objects.nonNull(globalOperationParameters)) {
            for (SwaggerConfigurationProerties.GlobalOperationParameter parameter : globalOperationParameters) {
                if (!docketNames.contains(parameter.getName())) {
                    resultOperationParameters.add(parameter);
                }
            }
        }

        resultOperationParameters.addAll(docketOperationParameters);
        return buildGlobalOperationParametersFromSwaggerConfigurationProerties(resultOperationParameters);
    }

    private void buildGlobalResponseMessage(SwaggerConfigurationProerties swaggerConfigurationProerties,
                                            Docket docketForBuilder) {

        SwaggerConfigurationProerties.GlobalResponseMessage globalResponseMessages = swaggerConfigurationProerties
                                                                                                                  .getGlobalResponseMessage();

        /* POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE 响应消息体 **/
        List postResponseMessages = getResponseMessageList(globalResponseMessages.getPost());
        List getResponseMessages = getResponseMessageList(globalResponseMessages.getGet());
        List putResponseMessages = getResponseMessageList(globalResponseMessages.getPut());
        List patchResponseMessages = getResponseMessageList(globalResponseMessages.getPatch());
        List deleteResponseMessages = getResponseMessageList(globalResponseMessages.getDelete());
        List headResponseMessages = getResponseMessageList(globalResponseMessages.getHead());
        List optionsResponseMessages = getResponseMessageList(globalResponseMessages.getOptions());
        List trackResponseMessages = getResponseMessageList(globalResponseMessages.getTrace());

        docketForBuilder.useDefaultResponseMessages(swaggerConfigurationProerties.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);
    }

    private List getResponseMessageList(
                                                         List globalResponseMessageBodyList) {
        List responseMessages = Lang.list();
        for (SwaggerConfigurationProerties.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;
    }

    @Bean
    public SwaggerCustomerController swaggerCustomerController() {
        return new SwaggerCustomerController();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy