SpringBoot Swagger 解决扫描慢带来的启动速度慢的问题
1 痛点:当项目接口多了之后,swagger的扫描时间甚至在整个启动时间占用到三分之二,解决swagger扫描慢的问题,我们将会有更多的时间make bug。2 思路:让swagger异步扫描初始化,不要卡main 线程,这样就不会影响启动速度。优点:启动速度加快, 缺点:启动成功后,刷新swagger ui页面,swagger接口请求不回json来,要等扫描完成后,才能请求回json,swagg
·
1 痛点:
当项目接口多了之后,swagger的扫描时间甚至在整个启动时间占用到三分之二,解决swagger扫描慢的问题,我们将会有更多的时间make bug。
2 思路:
让swagger异步扫描初始化,不要卡main 线程,这样就不会影响启动速度。
优点:启动速度加快, 缺点:启动成功后,刷新swagger ui页面,swagger接口请求不回json来,要等扫描完成后,才能请求回json,swagger才能正常使用。
特殊说明:如果已经打开了swaggerUI,不刷新swagger UI页面的情况下,不需要去后台重新加载swagger json,不耽误我们测试接口。
3 实现步骤:
- 不要使用@EnableSwagger2 注解,我们自己实现一个config类,代替这个注解
package com.fhs.module.base.config;
import com.fasterxml.classmate.TypeResolver;
import com.fhs.module.base.swagger.FhsJsonSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.*;
import org.springframework.plugin.core.config.EnablePluginRegistries;
import springfox.documentation.schema.configuration.ModelsConfiguration;
import springfox.documentation.service.PathDecorator;
import springfox.documentation.spi.service.*;
import springfox.documentation.spi.service.contexts.Defaults;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.spring.web.ObjectMapperConfigurer;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;
import springfox.documentation.spring.web.json.JsonSerializer;
import springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper;
import springfox.documentation.spring.web.plugins.DocumentationPluginsManager;
import springfox.documentation.spring.web.scanners.ApiDocumentationScanner;
import springfox.documentation.swagger.configuration.SwaggerCommonConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import javax.servlet.ServletContext;
import java.util.ArrayList;
import java.util.List;
/**
* 本类代理@EnableSwagger2 注解,可实现swagger异步加载
*/
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "fhs.swagger", name = "enable", havingValue = "true", matchIfMissing = false)
@Import({ SwaggerCommonConfiguration.class,ModelsConfiguration.class })
@ComponentScan(basePackages = {
"springfox.documentation.swagger2.web",
"springfox.documentation.swagger2.mappers",
"springfox.documentation.spring.web.scanners",
"springfox.documentation.spring.web.readers.operation",
"springfox.documentation.spring.web.readers.parameter",
"springfox.documentation.spring.web.plugins",
"springfox.documentation.spring.web.paths"
}, excludeFilters =
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = {DocumentationPluginsBootstrapper.class})})//禁用掉DocumentationPluginsBootstrapper,这样就不会自动扫描,卡主线程
@EnablePluginRegistries({ DocumentationPlugin.class,
ApiListingBuilderPlugin.class,
OperationBuilderPlugin.class,
ParameterBuilderPlugin.class,
ExpandedParameterBuilderPlugin.class,
ResourceGroupingStrategy.class,
OperationModelsProviderPlugin.class,
DefaultsProviderPlugin.class,
PathDecorator.class
})
public class SwaggerSyncConfig implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
private DocumentationPluginsManager documentationPluginsManager;
@Autowired
private RequestHandlerProvider provider;
@Autowired
private DocumentationCache scanned;
@Autowired
private ApiDocumentationScanner resourceListing;
@Autowired
private TypeResolver typeResolver;
@Autowired
private Defaults defaults;
@Autowired
private ServletContext servletContext;
@Bean
public Defaults defaults() {
return new Defaults();
}
@Bean
public DocumentationCache resourceGroupCache() {
return new DocumentationCache();
}
@Bean
public static ObjectMapperConfigurer objectMapperConfigurer() {
return new ObjectMapperConfigurer();
}
/**
* 自定义json序列化,解决value是null的时候依旧序列化问题
* @param moduleRegistrars
* @return
*/
@Bean
public JsonSerializer jsonSerializer(List<JacksonModuleRegistrar> moduleRegistrars) {
return new FhsJsonSerializer(moduleRegistrars);
}
@Bean
public static PropertyPlaceholderConfigurer swaggerProperties() {
PropertyPlaceholderConfigurer properties = new PropertyPlaceholderConfigurer();
properties.setIgnoreUnresolvablePlaceholders(true);
return properties;
}
/**
* 当springboot 项目启动完成后,新启动一个线程去扫描swagger相关注解,生成配置对象
* @param applicationReadyEvent
*/
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
try{
List<RequestHandlerProvider> handlerProviders = new ArrayList<>();
handlerProviders.add(provider);
new Thread(new Runnable() {
@Override
public void run() {
// 手动去扫描
new DocumentationPluginsBootstrapper(documentationPluginsManager,
handlerProviders,scanned,resourceListing,typeResolver,defaults,servletContext).start();
log.info("-------------swagger 异步扫描完成-------------");
}
}).start();
}catch (Exception e){
e.printStackTrace();
}
}
}
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;
import springfox.documentation.spring.web.json.Json;
import springfox.documentation.spring.web.json.JsonSerializer;
import java.util.List;
public class FhsJsonSerializer extends JsonSerializer {
private ObjectMapper objectMapper = new ObjectMapper();
public Json toJson(Object toSerialize) {
try {
return new Json(objectMapper.writeValueAsString(toSerialize));
} catch (JsonProcessingException e) {
throw new RuntimeException("Could not write JSON", e);
}
}
public FhsJsonSerializer(List<JacksonModuleRegistrar> modules) {
super(modules);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)