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

cloud.agileframework.mvc.config.SpringMvcAutoConfiguration Maven / Gradle / Ivy

package cloud.agileframework.mvc.config;

import cloud.agileframework.mvc.container.AgileHandlerMapping;
import cloud.agileframework.mvc.container.AgileHandlerMethodArgumentResolver;
import cloud.agileframework.mvc.container.CustomAsyncHandlerInterceptor;
import cloud.agileframework.mvc.container.CustomHandlerInterceptor;
import cloud.agileframework.mvc.container.CustomHandlerMethodReturnValueHandler;
import cloud.agileframework.mvc.container.FileHandlerMethodReturnValueHandler;
import cloud.agileframework.mvc.container.ReturnHandlerMethodReturnValueHandler;
import cloud.agileframework.mvc.filter.CorsFilter;
import cloud.agileframework.mvc.filter.RequestWrapperFilter;
import cloud.agileframework.mvc.properties.CorsFilterProperties;
import cloud.agileframework.mvc.provider.ArgumentInitHandlerProvider;
import cloud.agileframework.mvc.provider.ArgumentValidationHandlerProvider;
import cloud.agileframework.spring.util.BeanUtil;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
import com.alibaba.fastjson2.support.spring.webservlet.view.FastJsonJsonView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.task.TaskExecutionProperties;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.TimeoutCallableProcessingInterceptor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 佟盟 on 2017/8/22
 */
@Configuration
@EnableConfigurationProperties({TaskExecutionProperties.class, CorsFilterProperties.class, WebMvcProperties.class})
public class SpringMvcAutoConfiguration implements WebMvcConfigurer {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final CorsFilterProperties corsFilterProperties;
    private final WebMvcProperties webMvcProperties;
    private final TaskExecutionProperties taskExecutionProperties;

    @Autowired
    public SpringMvcAutoConfiguration(CorsFilterProperties corsFilterProperties,
                                      WebMvcProperties webMvcProperties,
                                      TaskExecutionProperties taskExecutionProperties) {
        this.corsFilterProperties = corsFilterProperties;
        this.webMvcProperties = webMvcProperties;
        this.taskExecutionProperties = taskExecutionProperties;
    }

    @Bean
    @ConditionalOnClass(CorsFilter.class)
    public FilterRegistrationBean corsFilter() {
        FilterRegistrationBean corsFilter = new FilterRegistrationBean<>();
        corsFilter.setFilter(new CorsFilter());
        corsFilter.addUrlPatterns("/*");
        corsFilter.addInitParameter("allowOrigin", corsFilterProperties.getAllowOrigin());
        corsFilter.addInitParameter("allowMethods", corsFilterProperties.getAllowMethods());
        corsFilter.addInitParameter("allowCredentials", Boolean.toString(corsFilterProperties.isAllowCredentials()));
        corsFilter.addInitParameter("allowHeaders", corsFilterProperties.getAllowHeaders());
        corsFilter.addInitParameter("exposeHeaders", corsFilterProperties.getExposeHeaders());
        logger.debug("完成初始化跨域过滤器");
        return corsFilter;
    }

    @Bean
    @ConditionalOnClass(RequestWrapperFilter.class)
    public FilterRegistrationBean requestWrapperFilter() {
        FilterRegistrationBean requestFilter = new FilterRegistrationBean<>();
        requestFilter.setFilter(new RequestWrapperFilter());
        requestFilter.addUrlPatterns("/*");
        logger.debug("完成初始化Request包装过滤器");
        return requestFilter;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public AgileHandlerMapping agileHandlerMapping() {
        return new AgileHandlerMapping();
    }

    @Bean
    ArgumentInitHandlerProvider argumentInitHandlerProvider() {
        return new ArgumentInitHandlerProvider();
    }

    @Bean
    ArgumentValidationHandlerProvider argumentValidationHandlerProvider() {
        return new ArgumentValidationHandlerProvider();
    }

    @Override
    public void addArgumentResolvers(List resolvers) {
        resolvers.add(agileHandlerMethodArgumentResolver());
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(fastJsonView());
    }

    @Override
    public void configureMessageConverters(List> converters) {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();


        FastJsonConfig config = getFastJsonConfig();
        converter.setFastJsonConfig(config);
        converter.setDefaultCharset(StandardCharsets.UTF_8);
        // 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"
        List mediaTypeList = new ArrayList<>();
        mediaTypeList.add(MediaType.APPLICATION_JSON);
        converter.setSupportedMediaTypes(mediaTypeList);

        converters.add(new ByteArrayHttpMessageConverter());
        // @ResponseBody 解决乱码
        converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        converters.add(new ResourceHttpMessageConverter());
        converters.add(new AllEncompassingFormHttpMessageConverter());
        converters.add(converter);
    }

    private FastJsonConfig getFastJsonConfig() {
        FastJsonConfig config = new FastJsonConfig();
        config.setWriterFeatures(
                JSONWriter.Feature.WriteMapNullValue,
                JSONWriter.Feature.WriteNullListAsEmpty,
                JSONWriter.Feature.WriteLongAsString,
                JSONWriter.Feature.WriteBigDecimalAsPlain,
                JSONWriter.Feature.WriteEnumsUsingName
        );
        config.setDateFormat(webMvcProperties.getFormat().getDateTime());
        return config;
    }

    private FastJsonJsonView fastJsonView() {
        FastJsonJsonView fastJsonView = new FastJsonJsonView();
        FastJsonConfig fastJsonConfig = getFastJsonConfig();
        fastJsonView.setFastJsonConfig(fastJsonConfig);
        return fastJsonView;
    }

    @Bean
    AgileHandlerMethodArgumentResolver agileHandlerMethodArgumentResolver() {
        return new AgileHandlerMethodArgumentResolver();
    }

    @Override
    public void addReturnValueHandlers(List handlers) {

        handlers.add(new CustomHandlerMethodReturnValueHandler());
        handlers.add(new ReturnHandlerMethodReturnValueHandler());
        handlers.add(new FileHandlerMethodReturnValueHandler());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomHandlerInterceptor());
        registry.addInterceptor(customAsyncHandlerInterceptor());
    }

    @Bean
    CustomAsyncHandlerInterceptor customAsyncHandlerInterceptor() {
        return new CustomAsyncHandlerInterceptor();
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        Duration timeout = webMvcProperties.getAsync().getRequestTimeout();
        if (timeout == null) {
            timeout = Duration.ofSeconds(3);
        }
        configurer.setDefaultTimeout(timeout.toMillis());

        CallableProcessingInterceptor timeoutInterceptor = BeanUtil.getBean(CallableProcessingInterceptor.class);
        configurer.registerCallableInterceptors(timeoutInterceptor);

        ThreadPoolTaskExecutor threadPoolTaskExecutor = BeanUtil.getBean(ThreadPoolTaskExecutor.class);
        configurer.setTaskExecutor(threadPoolTaskExecutor);
    }

    @Bean
    @ConditionalOnMissingBean(CallableProcessingInterceptor.class)
    public TimeoutCallableProcessingInterceptor timeoutInterceptor() {
        return new TimeoutCallableProcessingInterceptor();
    }

    @Bean
    @ConditionalOnMissingBean(ThreadPoolTaskExecutor.class)
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor t = new ThreadPoolTaskExecutor();
        t.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());
        t.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());
        t.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity());
        t.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix());
        return t;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy