package com.oying.config.webConfig; import lombok.RequiredArgsConstructor; import com.oying.utils.AnonTagUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.ReflectionUtils; import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.SecurityReference; import springfox.documentation.service.SecurityScheme; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider; import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * api页面 /doc.html * @author Z * @date 2018-11-23 */ @Configuration @EnableSwagger2 @RequiredArgsConstructor public class SwaggerConfig { @Value("${server.servlet.context-path:}") private String apiPath; @Value("${jwt.header}") private String tokenHeader; @Value("${swagger.enabled}") private Boolean enabled; private final ApplicationContext applicationContext; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .enable(enabled) .pathMapping("/") .apiInfo(apiInfo()) .select() .paths(PathSelectors.regex("^(?!/error).*")) .paths(PathSelectors.any()) .build() //添加登陆认证 .securitySchemes(securitySchemes()) .securityContexts(securityContexts()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .description("一个简单且易上手的 Spring boot 后台管理框架") .title("OYING 接口文档") .version("1.1") .build(); } private List securitySchemes() { //设置请求头信息 List securitySchemes = new ArrayList<>(); ApiKey apiKey = new ApiKey(tokenHeader, tokenHeader, "header"); securitySchemes.add(apiKey); return securitySchemes; } private List securityContexts() { //设置需要登录认证的路径 List securityContexts = new ArrayList<>(); securityContexts.add(getContextByPath()); return securityContexts; } private SecurityContext getContextByPath() { Set urls = AnonTagUtils.getAllAnonymousUrl(applicationContext); urls = urls.stream().filter(url -> !url.equals("/")).collect(Collectors.toSet()); String regExp = "^(?!" + apiPath + String.join("|" + apiPath, urls) + ").*$"; return SecurityContext.builder() .securityReferences(defaultAuth()) .operationSelector(o->o.requestMappingPattern() // 排除不需要认证的接口 .matches(regExp)) .build(); } private List defaultAuth() { List securityReferences = new ArrayList<>(); AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes)); return securityReferences; } /** * 解决Springfox与SpringBoot集成后,WebMvcRequestHandlerProvider和WebFluxRequestHandlerProvider冲突问题 * @return / */ @Bean @SuppressWarnings({"unchecked","all"}) public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private void customizeSpringfoxHandlerMappings(List mappings) { List filteredMappings = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(filteredMappings); } private List getHandlerMappings(Object bean) { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); if (field != null) { field.setAccessible(true); try { return (List) field.get(bean); } catch (IllegalAccessException e) { throw new IllegalStateException("Failed to access handlerMappings field", e); } } return Collections.emptyList(); } }; } }