package com.jilongda.common.swagger; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.reflect.FieldUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 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 org.springframework.context.annotation.Profile; import org.springframework.http.HttpMethod; import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import springfox.documentation.builders.*; import springfox.documentation.oas.annotations.EnableOpenApi; import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import java.lang.reflect.Field; import java.util.*; /** * swagger3 的spring-boot启动器 * * @author ck */ @Configuration @ConditionalOnProperty(name = "web.swagger.enabled") @EnableConfigurationProperties(SwaggerProperties.class) @EnableOpenApi @ConditionalOnClass(Docket.class) @Profile({"dev", "test","prod"}) public class SwaggerAutoConfiguration implements WebMvcConfigurer { private final SwaggerProperties swaggerProperties; @Autowired public SwaggerAutoConfiguration(SwaggerProperties swaggerProperties) { this.swaggerProperties = swaggerProperties; } /** * 文档相关资源路径 */ public static final String[] DOC_LIST = {"/js/**", "/css/**", "/static/**", "/webass/**", "/iconfont/**", "/RFIDR/**", "/tinymce/**", "/img/**", "/images/**", "/fonts/**","/index.html", "/favicon.ico", "/v3/**", "/v2/**", "/error", "/swagger**/**", "/configuration/ui", "/configuration/security", "/webjars/**", "/doc**/**" ,"/swagger-resources/**", "/swagger-ui.html/**" }; /** * 支持的通讯协议集合 * * @return */ private Set protocols() { Set set = new HashSet<>(); set.add("https"); set.add("http"); return set; } /** * 响应状态集合 * * @return */ private List responseList() { List responseList = new ArrayList<>(); Arrays.stream(GlobalResultEnum.values()).forEach(errorEnum -> { responseList.add( new ResponseBuilder().code(String.valueOf(errorEnum.getCode())).description(errorEnum.getMessage()).build() ); }); return responseList; } /** * 设置文档基本信息 * * @return */ private ApiInfo apiInfo(SwaggerProperties.Contact contact) { SwaggerProperties.Contact cont = Objects.isNull(contact) ? swaggerProperties.getContact() : contact; return new ApiInfoBuilder() .title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()) .termsOfServiceUrl(swaggerProperties.getServiceUrl()) .contact(new Contact(cont.getName(), cont.getUrl(), cont.getEmail())) .version(swaggerProperties.getVersion()) .license(swaggerProperties.getLicense()) .licenseUrl(swaggerProperties.getLicenseUrl()) .build(); } /** * 生成全局头部通用参数 * * @return */ private List setFixedParameter(List reqFixedParameters) { List parameters = new ArrayList<>(); List fixedParameters = CollectionUtils.isEmpty(reqFixedParameters) ? swaggerProperties.getReqFixedParameters() : reqFixedParameters; for (SwaggerProperties.ReqFixedParameter reqFixedParameter : fixedParameters) { parameters.add(new RequestParameterBuilder() .name(reqFixedParameter.getParamKey()) .description(reqFixedParameter.getDescription()) .required(reqFixedParameter.isRequired()) .in(ParameterType.HEADER) .build()); } return parameters; } /** * 默认分组 * * @return */ @Bean @ConditionalOnMissingBean public Docket docket() { return new Docket(DocumentationType.OAS_30) .enable(swaggerProperties.isEnabled()) .groupName("全部") .globalResponses(HttpMethod.GET, responseList()) .globalResponses(HttpMethod.POST, responseList()) .globalResponses(HttpMethod.PUT, responseList()) .globalResponses(HttpMethod.DELETE, responseList()) .apiInfo(apiInfo(swaggerProperties.getContact())) .select() // 表示任何包 // 加了ApiOperation注解的类,才生成接口文档 .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) // 避免使用swagger api的默认basic-error-controller // .paths(PathSelectors.regex("(?!/error.*).*")) .build() // .securitySchemes(securitySchemes()) // 支持的通讯协议集合 .protocols(protocols()) //.securityContexts(securityContexts()) .pathMapping(swaggerProperties.getPathMapping()) .globalRequestParameters(setFixedParameter(swaggerProperties.getReqFixedParameters())); } /** * 接口请求拦截配置 * * @param registry */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addRedirectViewController("/swagger", "/swagger-ui/index.html"); } /** * 通用拦截器排除swagger设置,所有拦截器都会自动加swagger相关的资源排除信息 */ @Override public void addInterceptors(InterceptorRegistry registry) { Field registrationsField = FieldUtils.getField(InterceptorRegistry.class, "registrations", true); List registrations = (List) ReflectionUtils.getField(registrationsField, registry); if (!CollectionUtils.isEmpty(registrations)) { for (InterceptorRegistration interceptorRegistration : registrations) { interceptorRegistration .excludePathPatterns(DOC_LIST); } } } }