创建两个容器,Spring容器和SpringMVC容器,把controller组件之外的组件单独放到Spring容器中,controller组件单独放到SpringMVC容器中。
以Spring容器为父容器,SpringMVC容器为子容器,父容器不能使用子容器中的组件,子容器可以使用父容器中的组件。
这样,controller组件在第一次访问url的时候才加载,而controller依赖的组件如:service、dao、dataSource、tx这样的组件可以提前完成加载。
在web.xml中配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在application-mvc.xml初始化的时候会判断有无父容器需要加载,所以可以配置一个Listener,再配置context-param
要求每个组件只实例化一次,因此需要在Spring容器注册组件的时候排除掉controller相关组件
在application.xml中做如下配置,排除掉controller注解所对应的组件:
<!-- bean definitions here -->
<!--排除掉controller相关组件 → 注解Controller-->
<context:component-scan base-package="com.cskaoyan">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
JavaConfig需要三个配置类:
- web.xml
- application.xml
- application-mvc.xml
建议结合JavaConfig基础的文章一起看:Spring之JavaConfig
总览:
1️⃣ web.xml
继承AACDSI(啊啊吃到死),AbstractAnnotationConfigDispatcherServletInitializer
原web.xml中的内容在上方
//AACDSI → 啊啊吃到死
//web.xml → 配置类
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//加载Spring的配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfiguration.class};
}
//加载mvc的配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MvcConfiguration.class};
}
//DispatcherServlet的作用范围
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
①配置filter
在原web.xml中配置了filter,因此在配置类中也要配置:
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
2️⃣ Spring配置文件
在@Component注解中利用属性excludeFilters来排除Conroller组件和EnableWebMvc的组件(即SpringMCV的配置类)
@Configuration
@ComponentScan(value = "com.cskaoyan",
excludeFilters = @ComponentScan.Filter(value = {Controller.class, EnableWebMvc.class}))
//excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class))
public class SpringConfiguration {
//可以是@Bean注册组件
}
3️⃣ SpringMVC配置文件
需要将@Configuration注解替换为@EnableWebMvc注解,对应<mvc:annotation-driven/>
标签
实现接口WebMvcConfigurer,提供了mvc开头的标签有的功能
@EnableWebMvc //也包含了@Configuration功能 → 类里可以使用@Bean
@ComponentScan("com.cskaoyan.controller")
public class MvcConfiguration implements WebMvcConfigurer {
}
① 配置multipartResolver
文件上传组件,记得导包commos-fileupload(io)
//mvc配置类
//multipartResolver组件
@Bean
public CommonsMultipartResolver multipartResolver(){//方法名作为组件默认id,该id为固定值
return new CommonsMultipartResolver();
}
② 配置mvc:resources
静态资源处理
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// mapping location
registry.addResourceHandler("/pic1/**").addResourceLocations("/");
registry.addResourceHandler("/pic2/**").addResourceLocations("classpath:/");
registry.addResourceHandler("/pic3/**").addResourceLocations("file:d:/stone/spring/");
}
③配置mvc:interceptors
拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//作用范围 组件是哪个 interceptor之间的顺序
registry.addInterceptor(new CustomInterceptor1());//作用范围是全局
registry.addInterceptor(new CustomInterceptor2()).addPathPatterns("/hello/**");
registry.addInterceptor(new CustomInterceptor3()).addPathPatterns("/hello/**");
}
④ 配置converter
类型转化器,有两种配置方法
- conversionService
- webMvcConfigurer → addFormatter(推荐)
/*@Autowired
ConfigurableConversionService conversionService;
@PostConstruct
public void addConverter() {
conversionService.addConverter(new String2DateConverter());
}
@Bean
@Primary
public ConfigurableConversionService conversionService(){
return conversionService;
}*/
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new String2DateConverter());
}
⑤ 配置validator
参数校验器
@Override
public Validator getValidator() {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
return localValidatorFactoryBean;
}