spring整合springmvc
需要整合吗?
有的人也许有些疑问,springmvc已经有IOC容器,那么我们还需要使用spring吗?对于这个问题,两种观点各有道理
观点一:需要。因为在实际开发中,我们还需要整合hibernate等其他框架,还需要用到事务等,这些需要使用spring来整合配置
观点二:因为springmvc已经有IOC容器了。。不需要spring =。=
很显然,观点一更合理
整合后遇到的问题
我们先来整合看看会遇到什么问题
在web.xml中配置
<!-- 配置启动 Spring IOC 容器的 Listener -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在src下创建beans.xml
<?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-4.0.xsd">
<context:component-scan base-package="com.zj">
</context:component-scan>
<!-- 配置数据源, 整合其他框架, 事务等. -->
</beans>
这样就完成了简单的整合。关于spring,我后续还会更新相关博客。
为了能够看到整合后出现的问题,我们现在来写一个service
package com.zj.service;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
//构造函数
public HelloService(){
System.out.println("hello service");
}
}
在controller中也加上构造函数
package com.zj.controller;
import org.springframework.stereotype.Controller;
@Controller
public class HelloCtrl {
public HelloCtrl(){
System.out.println("hello controller");
}
}
将程序跑起来,我们看到控制台输出这样的结果
没错,由于spring和springmvc都有IOC容器,他们两都帮我们创建了实例,这让人十分不爽
如何解决这个问题
解决方案一(不推荐)
IOC容器创建哪些实例,取决于我们在配置文件中配置的扫描的包
<context:component-scan base-package="com.zj">
</context:component-scan>
这个配置在springmvc配置文件中有,在spring配置文件中也有。他们有重复的部分,因此实例都创建了两次。
- 只要spring和springmvc扫描的包不重合,就能解决这个问题。比如springmvc只扫描controller的包,spring扫描其他的包。
- 但是这样有一个缺点。在实际项目中,包的划分也有可能是按照模块来划分,而不是所有controller都放在同一个包里,这种情况下,这个解决方案就不行了。
解决方案二(推荐)
使用include-filter节点和exclude-filter节点来配置只扫描的注解,和不扫描的注解。
在springmvc配置文件中只扫描@Controller和@ControllerAdvice注解。ControllerAdvice是处理异常的注解
<!-- 自动扫描的包名 -->
<context:component-scan base-package="com.zj">
<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>
spring扫描剩余所有的注解
<context:component-scan base-package="com.zj">
<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>
注意,spring中用的是exclude-filter,springmvc配置的是include-filter。两个长得有点像,别看错了。
问题就这样轻松的解决了。