SpringMVC的父子容器问题
在使用SpringMVC 的时候,我们需要对前端控制器进行配置,前端控制器(DispatcherServlet)需要有一个 WebApplicationConetxt作为它的环境配置。
而 SpringMVC 作为 Spring 框架的一个子框架 ,自己拥有一个独立的子容器(Servlet WebApplicationContext),这个容器中应该包含 controller、view resolvers(视图适配器)、handlerMapping(处理器映射器)以及其他的一些和 web 相关的类;
但是如果在这个子容器中没有找到需要的组件(Component),那么SpringMVC 会到一个父容器的环境中(Root WebApplicationContext)去获取。而如果这个时候,父容器没有创建,那么就找不到对应的组件,编译器就会抛出异常,因此在配置前端控制器的时候,应该保证子容器当中可以获取到controller等的一些组件,并且父容器也要被创建。


解决方法
在 springmvc.xml 中配置包扫描,扫描 controller 包
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.alibaba.com/schema/stat"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.alibaba.com/schema/stat
http://www.alibaba.com/schema/stat.xsd">
<context:component-scan base-package="com.sxt.controller"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
情况一:在配置前端控制器的时候,使用通配符( * )来引入两个配置文件(springdao.xml [主容器配置文件]和 springmvc.xml [springMVC配置文件])
这种情况在理论上是可以满足需求的,但是由于使用的是通配符直接加载两个配置文件,不排除在创建的时候父容器之前就已经创建了子容器,这样也会出现错误
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
情况二:在 web.xml 中配置监听器(ContextLoaderListener),这个监听器在 web 启动的时候就会加载对应的 contextConfig 对应的配置文件,来创建父容器
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springdao.xml</param-value>
</context-param>
情况三:前端控制器中配置 springdao.xml 作为它的环境配置(ContextConfiguration),并且在 springdao.xml 中通过 <import> 引入 springmvc.xml,这样来保证两个容器的创建顺序。
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springdao.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
springdao.xml 文件配置: