多IOC容器整合
SSM整合方式
Spring、SpringMVC、MyBatis
SpringMVC的核心Servlet会启动一个IOC容器,而ContextLoaderListener也会启动一个IOC容器。
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 在Servlet的上下文参数中指定Spring配置文件的配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-tx.xml</param-value> </context-param> <listener> <!-- 配置ContextLoaderListener监听器,初始化WebApplicationContext这个类型的IOC容器 --> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
对象重复创建为问题
两个IOC容器分别扫描不同的包时不会有重复创建对象问题[推荐]
SpringMVC扫描:com.ioc.component.handler
Spring扫描:
com.ioc.component.service
com.ioc.component.dao
特定情况下两个IOC容器都扫描同一个包
com.ioc.component
不做特殊处理会存在对象重复创建问题
在实际开发中我们通常还是需要将二者分开。
1.同时配置两个IOC容器
为了实现更好的解耦,我们在实际开发中往往还是需要将数据源、Service、Dao等组件配置到传统的Spring配置文件中,并通过ContextLoaderListener启动这个IOC容器。 而在表述层负责处理请求的handler组件则使用SpringMVC自己来启动。 这会导致一个问题:同样的组件会被创建两次。
2.两个IOC容器的各自配置
Spring的IOC容器 将标记了@Controller注解的bean排除
Spring配置文件:spring-tx.xml
<context:component-scan base-package="com.ioc.component.*"> <!-- 将@Controller注解标记的类从自动扫描的包中排除 --> <!-- 效果:当前IOC容器不会创建@Controller注解标记的类的bean --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
仅包含标记了@Controller等注解的bean
SpringMVC配置文件:spring-mvc.xml
<!-- 关键:仅 --> <!-- 配置use-default-filters="false"将默认的扫描包规则取消,参考include-filter仅创建@Controller注解标记的类的bean --> <context:component-scan base-package="com.ioc.component.*" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
这两个IOC容器中,先启动的那个将成为后启动的IOC容器的父容器。
小结:
DispatcherServlet读取spring-mvc.xml配置文件
ContextLoaderListener读取spring-tx.xml配置文件
过滤规则
exclude-filter
include-filter
异常映射
SpringMVC配置文件
<!-- 配置异常映射关系 --> <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 将异常类型和视图名称关联起来 --> <!-- 这个机制工作后会自动将捕获到的异常对象存入请求域,默认属性名是exception --> <prop key="java.lang.RuntimeException">error</prop> </props> </property> <!-- 指定将异常对象存入请求域时使用的属性名 --> <property name="exceptionAttribute" value="exception"></property> </bean>
页面上:
exception:${requestScope.exception}