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 mvc的依赖 springmvc必须依赖spring吗_spring

没错,由于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。两个长得有点像,别看错了。

问题就这样轻松的解决了。