SpringMVC的运行流程图
Spring整合SpringMVC
Spring整合SpringMVC的原因
通常情况下,类似于数据源、事务、整合其他框架都是放在Spring的配置文件中,而不是放在SpringMVC的配置文件中。实际上放入Spring配置文件对应的IOC容器中的还有Service和Dao等。
Spring整合SpringMVC中出现的问题
我们现在创建两个类,一个让SpringMVC初始化,另一个用Spring初始化。
package com.cerr.springmvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloWorld {
@Autowired
private UserService userService;
public HelloWorld() {
System.out.println("HelloWorld");
}
@RequestMapping(value = "/helloWorld")
public String hello(){
System.out.println("success");
return "success";
}
}
package com.cerr.springmvc;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public UserService() {
System.out.println("UserService");
}
}
SpringMVC的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置自动扫描的包-->
<context:component-scan base-package="com.cerr.springmvc"/>
<!-- 配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
Spring的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.cerr.springmvc"/>
<!-- 配置数据源,整合其他框架,事务等 -->
</beans>
然后开启Tomcat后发现,这两个类会被初始化两次。因为Spring的IOC容器扫描的包和SpringMVC的IOC容器扫描的包有融合的部分,这就会导致有的bean会被创建2次。
那么如何解决呢?有两种解决方案
- 使Spring的IOC容器和SpringMVC的IOC容器扫描的包没有重合部分,即合理规划好包,使其的包明显分开,然后就可以设置了
- 可以在自动扫描包的节点中使用
exclude-filter
和include-filter
子节点来规定只能扫描的注解。
下面我们来说明第二种解决方案:
例如在这个例子中,对于SpringMVC,我们只让扫描Controller
和ControllerAdvice
注解的类。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置自动扫描的包-->
<context:component-scan base-package="com.cerr.springmvc" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>
<!-- 配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
对于Spring配置文件,我们让它不扫描Controller
和ControllerAdvice
注解的类。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.cerr.springmvc" >
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
<!-- 配置数据源,整合其他框架,事务等 -->
</beans>
这样即可解决该问题。
Spring的IOC容器与SpringMVC的IOC容器的关系
多个Spring IOC容器之间可以设置为父子关系,以实现良好的解耦,SpringMVC WEB层容器可作为“业务层”Spring容器的子容器。即SpringMVC的IOC容器中的bean可以引用Spring IOC容器中的bean,但是Spring IOC容器中的bean却不能引用SpringMVC IOC容器的bean。