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

cn.kduck.core.configuration.WebMvcConfiguration Maven / Gradle / Ivy

Go to download

The core of the K-Duck development framework encompasses all the featured components of the framework.

There is a newer version: 2.0.0
Show newest version
package cn.kduck.core.configuration;

import cn.kduck.core.utils.ConversionUtils.DateConverter;
import cn.kduck.core.web.GlobalErrorController;
import cn.kduck.core.web.interceptor.DataSourceSwitchInterceptor;
import cn.kduck.core.web.interceptor.OperateIdentificationInterceptor;
import cn.kduck.core.web.interceptor.OperateInterceptor;
import cn.kduck.core.web.interceptor.ValidationInterceptor;
import cn.kduck.core.web.interceptor.operateinfo.OperateInfoHandler;
import cn.kduck.core.web.resolver.PageMethodArgumentResolver;
import cn.kduck.core.web.resolver.ValidErrorArgumentResolver;
import cn.kduck.core.web.resolver.ValueMapMethodArgumentResolver;
import cn.kduck.core.web.resource.ModelResourceLoader;
import cn.kduck.core.web.resource.ModelResourceProcessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
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.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.filter.FormContentFilter;
import org.springframework.web.method.annotation.MapMethodProcessor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
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 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import java.util.Arrays;
import java.util.List;

/**
 * LiuHG
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnMissingClass("org.springframework.web.reactive.config.WebFluxConfigurer")
public class WebMvcConfiguration implements WebMvcConfigurer, ApplicationContextAware {

    @Autowired(required = false)
    private OperateInfoHandler operateInfoHandler;

    private ApplicationContext applicationContext;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new DataSourceSwitchInterceptor());
        registry.addInterceptor(new OperateIdentificationInterceptor(50));
        registry.addInterceptor(new ValidationInterceptor(applicationContext));
        if(operateInfoHandler != null){
            registry.addInterceptor(new OperateInterceptor(operateInfoHandler));
        }
    }

    @Override
    public void addArgumentResolvers(List argumentResolvers) {
//        argumentResolvers.batchAdd(new ValueMapMethodArgumentResolver());
//        argumentResolvers.add(new ValueBeanMethodArgumentResolver(beanDefDepository,messageConverters));
        argumentResolvers.add(new PageMethodArgumentResolver(500));
        argumentResolvers.add(new ValidErrorArgumentResolver());
    }

//    protected void addFormatters(FormatterRegistry registry) {
//        registry.addFormatter();
//    }


    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateConverter());
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    }

//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        registry.addMapping("/**")
//                .allowedOrigins("*")
//                .allowCredentials(false)
//                .allowedMethods("GET","POST");
//    }

    /**
     * 配置一个视图解析器,用来显示比如oauth2的用户授权页面,否则因为均是json请求,此视图解析器无需配置
     * @param registry
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(new InternalResourceViewResolver());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//        handlerAdapter = applicationContext.getBean(ObjectProvider);
        this.applicationContext = applicationContext;
    }



    @Configuration
    @EnableCaching
    public static class KduckWebConfiguration {

        private final List errorViewResolvers;

        public KduckWebConfiguration(ObjectProvider> errorViewResolversProvider) {
            this.errorViewResolvers = errorViewResolversProvider.getIfAvailable();
        }

        @Bean
        @ConditionalOnMissingBean(value = ErrorController.class)
        public ErrorController errorController(ErrorAttributes errorAttributes) {
            return new GlobalErrorController(errorAttributes, this.errorViewResolvers);
        }

        @Bean
        @ConditionalOnMissingBean(value = ErrorAttributes.class)
        public ErrorAttributes webErrorAttributes() {
            return new DefaultErrorAttributes();
        }

        @Bean
        @ConditionalOnBean(ModelResourceProcessor.class)
        @ConditionalOnProperty(prefix = "kduck.resource",value = "enabled",havingValue = "true",matchIfMissing = true)
        public ModelResourceLoader modelResourceLoader(ObjectProvider resourceProcessorList){
            return new ModelResourceLoader(resourceProcessorList);
        }

        //构造Json的转换器,否则会由JacksonHttpMessageConvertersConfiguration加入默认的转换器,导致转换的日期格式不是long
        @Bean
        public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
            Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
            ObjectMapper objectMapper = builder.build();
            objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
            return new MappingJackson2HttpMessageConverter(objectMapper);
        }

        @Bean
        public FormContentFilter httpPutFormContentFilter() {
            return new FormContentFilter();
        }

        @Bean
        @ConditionalOnMissingBean(value=RestTemplate.class)
        public RestTemplate commonRestTemplate (@Autowired(required = false) RequestMappingHandlerAdapter handlerAdapter){

            RestTemplate restTemplate = new RestTemplate();

            List> messageConverters = restTemplate.getMessageConverters();
            //删除默认的Json转换器,后续会加入自定义的。
            for (HttpMessageConverter messageConverter : messageConverters) {
                if(messageConverter instanceof MappingJackson2HttpMessageConverter){
                    messageConverters.remove(messageConverter);
                    break;
                }
            }
            messageConverters.add(mappingJackson2HttpMessageConverter());

            if(handlerAdapter!=null){
                processHandlerAdapter(handlerAdapter,messageConverters);
            }

            restTemplate.setMessageConverters(messageConverters);
            return restTemplate;
        }

        private void processHandlerAdapter(RequestMappingHandlerAdapter handlerAdapter,List> messageConverters) {
            List argumentResolvers = handlerAdapter.getArgumentResolvers();
            HandlerMethodArgumentResolver[] resolversArray = new HandlerMethodArgumentResolver[argumentResolvers.size() + 1];

            int j =0;
            for (int i = 0; i < argumentResolvers.size(); i++,j++) {
                HandlerMethodArgumentResolver resolver = argumentResolvers.get(i);
                if(resolver.getClass() == MapMethodProcessor.class){
                    resolversArray[j] = new ValueMapMethodArgumentResolver(messageConverters);
                    j++;
                }
                resolversArray[j] = resolver;

            }
            handlerAdapter.setArgumentResolvers(Arrays.asList(resolversArray));
        }

//        @Override
//        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//            RequestMappingHandlerAdapter handlerAdapter = applicationContext.getBeanProvider(RequestMappingHandlerAdapter.class).getIfAvailable();
//
//            if(handlerAdapter == null){
//                return;
//            }
//
//            ObjectProvider messageConverters = applicationContext.getBeanProvider(HttpMessageConverter.class);
//
//            List argumentResolvers = handlerAdapter.getArgumentResolvers();
//            HandlerMethodArgumentResolver[] resolversArray = new HandlerMethodArgumentResolver[argumentResolvers.size() + 1];
//
//            int j =0;
//            for (int i = 0; i < argumentResolvers.size(); i++,j++) {
//                HandlerMethodArgumentResolver resolver = argumentResolvers.get(i);
//                if(resolver.getClass() == MapMethodProcessor.class){
//                    resolversArray[j] = new ValueMapMethodArgumentResolver(messageConverters.stream().collect(Collectors.toList()));
//                    j++;
//                }
//                resolversArray[j] = resolver;
//
//            }
//            handlerAdapter.setArgumentResolvers(Arrays.asList(resolversArray));
//        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy