SpringBoot扩展自定义SringMVC配置需要继承WebMvcConfigurer接口,并添加@Configuration注解,可以让SpringBoot自动将我们自定义的MVC配置纳入Spring管理。如果添加@@EnableWebMvc注解,则SpringBoot不会导入它自身的自动配置功能。
1、自定义属性编辑器(PropertyEditor)的配置方法参考SpringBoot 自定义ConfigurableWebBindingInitializer(可配置web初始化绑定器)
2、我们详解WebMvcConfigurer接口的方法使用:
package com.iclnetwork.springboot.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 自定义MVC配置
*/
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
/** 引入环境变量 */
@Autowired
private Environment environment;
/** 信息源 */
@Autowired
private MessageSource messageSource;
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
/**
* 配置异步执行器
* @param configurer
*/
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
ThreadPoolTaskExecutor asyncTaskExecutor = new ThreadPoolTaskExecutor();
// 线程分组名称
asyncTaskExecutor.setThreadGroupName(environment.getProperty("async.task.threadGroupName", String.class, "AsyncTask"));
// 核心线程的数量,初始化不会创建线程
asyncTaskExecutor.setCorePoolSize(environment.getProperty("async.task.corePoolSize", Integer.class, 5));
// 线程的最大数量,包括闲空与活动的线程
asyncTaskExecutor.setMaxPoolSize(environment.getProperty("async.task.maxPoolSize", Integer.class, 100));
// 线程队列的容量,少于“核心数量”时首选创建线程,大于“核心数量”时首选加入队列,其次再继续创建线程直到等于“最大数量”
asyncTaskExecutor.setQueueCapacity(environment.getProperty("async.task.queueCapacity", Integer.class, 20));
// 空闲线程存在的秒数,大于“核心数量”时监控,配合“AllowCoreThreadTimeOut”配置
asyncTaskExecutor.setKeepAliveSeconds(environment.getProperty("async.task.keepAliveSeconds", Integer.class, 300));
// 等待线程任务的最大秒数,容器关闭前触发,配合“WaitForTasksToCompleteOnShutdown”配置
asyncTaskExecutor.setAwaitTerminationSeconds(environment.getProperty("async.task.awaitTerminationSeconds", Integer.class, 60));
// 禁用核心线程超时,即允许核心线程永久空闲
asyncTaskExecutor.setAllowCoreThreadTimeOut(false);
// 启用容器关闭前等待线程任务完成
asyncTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
// 异常拒绝处理策略,无线程可用时抛“RejectedExecutionException”异常
asyncTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
asyncTaskExecutor.initialize();
configurer.setTaskExecutor(asyncTaskExecutor);
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
/**
* 添加类型转换器和格式化器
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
}
/**
* 增加拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(new AdminInterceptor()).addPathPatterns("/admin/**");
}
/**
* 添加静态资源处理
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//从配置文件中读取enabledDevelopment属性值
boolean enabledDevelopment = environment.getProperty("enabledDevelopment", Boolean.class, false);
if (enabledDevelopment) {
// 资源处理器
registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html").setCachePeriod(0);
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(0);
}
}
/**
* 跨域支持
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods("GET", "POST", "DELETE", "PUT").maxAge(3600 * 24);
}
/**
* 增加视图控制器
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//当请求/时,spring MVC会自动返回home模板。
registry.addViewController("/").setViewName("home");
//当求/index时,spring MVC会自动从定向到/home地址上。
registry.addRedirectViewController("/index", "/home");
}
/**
* 配置视图解析器
* SpringBoot 可以通过我们导入的模板启动器类型来自动配置,
* 如果您使用的是Thymeleaf或者Freemarker启动器,SpringBoot会给我们讲此功能自动配置好,这里无需配置。
* 可以参考WebMvcProperties和View在配置文件(application.properties)中修改参数
* @param registry
* @see org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
* @see org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.View
* @see org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
//freemarker配置样例
// ViewResolver viewResolver = new FreeMarkerViewResolver();
// // 内容类型,解决中文乱码
// viewResolver.setContentType("text/html; charset=UTF-8");
// // 后缀
// viewResolver.setSuffix(".ftl");
// registry.viewResolver(viewResolver);
// // BeanName视图解析器
// registry.beanName();
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
/**
* 消息转换器 将请求参数转换成特定的类
* SpringBoot的自动配置功能已经将这块功能自动配置了,可以通过WebMvcProperties的属性在配置文件(application.properties)中设置
* dateFormat日期转换格式
* @param converters
* @see org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
* @see org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// ObjectMapper objectMapper = new ObjectMapper().setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// for (HttpMessageConverter<?> messageConverter : converters) {
// if (messageConverter instanceof MappingJackson2HttpMessageConverter) {
// // 对象映射器
// ((MappingJackson2HttpMessageConverter) messageConverter).setObjectMapper(objectMapper);
// }
// }
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
/**
* 配置异常处理
* @param resolvers
*/
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
// 是否启用开发模式
boolean enabledDevelopment = environment.getProperty("enabledDevelopment", Boolean.class, false);
// 异常映射
Properties exceptionMappings = new Properties();
// 状态码映射
Properties statusCodes = new Properties();
if (!enabledDevelopment) {
exceptionMappings.setProperty("org.apache.shiro.authz.UnauthorizedException", "/unauthorized");
statusCodes.setProperty("/unauthorized", String.valueOf(HttpServletResponse.SC_FORBIDDEN));
}
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
// 默认错误视图
if (enabledDevelopment) {
exceptionResolver.setDefaultErrorView("/exception");
} else {
exceptionResolver.setDefaultErrorView("/error");
}
// 默认状态代码
exceptionResolver.setDefaultStatusCode(500);
// 阻止响应缓存
exceptionResolver.setPreventResponseCaching(true);
// 警告日志类型
exceptionResolver.setWarnLogCategory("org.springframework.web.servlet.handler.SimpleMappingExceptionResolver");
exceptionResolver.setExceptionMappings(exceptionMappings);
exceptionResolver.setStatusCodes(statusCodes);
resolvers.add(exceptionResolver);
}
@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
/**
* 验证器,SpringBoot已自动配置,这里无需配置,以下是配置实例
* @return
*/
@Override
public Validator getValidator() {
// LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
// // 生产者类
// validator.setProviderClass(HibernateValidator.class);
// validator.setValidationMessageSource(messageSource);
// return validator;
return null;
}
@Override
public MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
还有一些方法后续会持续更新。
注:SpringBoot对以上的所有功能都有一个默认配置(WebMvcAutoConfiguration),如果它给定的默认配置不能满足我们的需求,我们可以根据以上的方法进行扩展。