Spring4MVC(四)整合Spring
1、是否需要进行Spring和SpringMVC的整合?
其实SpringMVC是Spring的一部分,它已经是运行在Spring容器中的,既然如此,还有必要进行Spring和SpringMVC的整合吗在实际开发中,基本上都是会进行整合的,至少我还没看到过没有进行整合的。那么整合操作是必须的吗?答案是否定的。
1.1 需要整合
一般都是会进行两者的整合,因为,类似于数据源,事务,整合其他框架(比如MyBatis)都是放在 Spring 的配置文件中(而不是放在 SpringMVC 的配置文件中)。实际上放入 Spring 配置文件对应的 IOC 容器中的还有 Service 和 Dao。所以不应该把这么的事情都交给SpringMVC来完成。
1.2 不需要整合
其实也可以把所有的配置信息,都放在 SpringMVC 的配置文件中;也可以分多个 Spring 的配置文件,然后使用 import 节点导入其他的配置文件(或者在web.xml中配置DispatchServlet的时候,使用通配符指定配置文件的名称)。
但是,这种方式不推荐,这也不是Spring的初衷。
2、Spring整合SpringMVC
创建一个新的工程SpringMVC_Spring,演示Spring和SpringMVC的整合;
2.1 创建web工程SpringMVC_Spring
创建工程(IDEA创建web工程的方式可以参考第一篇SpringMVC的文章),导入jar包:
jar包不需要这么全,只要有最重要的几个包就可以了,这里是展示了所有的包
2.2 配置Spring的监听器和SpringMVC的servlet
在web.xml中配置Spring的监听器和SpringMVC的servlet:
org.springframework.web.context.ContextLoaderListener contextConfigLocation classpath:spring/applicationContext*.xml dispatcherServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring/springmvc*.xml 1 dispatcherServlet /
web.xml中,使用了通配符的方式来指定配置文件的名称以及位置:
classpath*:spring/applicationContext*.xml classpath*:spring/springmvc*.xml
这样就会去classpath下面去找spring目录下的以applicationContext开头和以springmvc开头的配置文件。
2.3 创建Spring和SpringMVC的配置文件
2.3.1 创建Spring的配置文件
在项目的classpath下面创建目录spring,然后在该目录下创建applicationContext-mvc.xml(因为我们使用了通配符,所以这个命名也是可以的):
2.3.2 创建SpringMVC的配置文件
在项目的目录spring下创建springmvc-spring.xml(因为我们使用了通配符,所以这个命名也是可以的):
3、处理器和业务层编写
3.1 创建业务层Service
在src下面新建包com.springmvc(配置文件中扫描的包路径),下面新建一个TestService
package com.springmvc;import org.springframework.stereotype.Service;@Service
public class TestService {//这个构造方法只是为了显示该类被创建了几次public TestService(){System.out.println("TestService创建了。。。");}public String getName(){return "Spring";}
}
3.2 创建处理器Controller
在包com.springmvc(配置文件中扫描的包路径),下面新建一个TestController
package com.springmvc;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;@Controller
@RequestMapping("springmvc")
public class TestController {//这个构造方法只是为了显示该类被创建了几次public TestController() {System.out.println("TestController被创建了。。。");}@Autowiredprivate TestService testService;@RequestMapping("testSpring")public ModelAndView testSpring(){String name = testService.getName();ModelAndView modelAndView = new ModelAndView("success");modelAndView.addObject("name",name);return modelAndView;}
}
4、前台页面编写
4.1 首页添加超链接
点击获取名称
4.2 创建一个成功页面success.jsp
因为我们的TestController中,请求处理成功,在ModelAndView中设置了名称为success的视图,所以需要在WEB-INF的views目录下面创建success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
成功页面 SUCCESS PAGE
Hello ${name}
5、存在的问题分析
存在的问题:同一个Bean被初始化了两次。
5.1 演示上面的效果
启动项目,在首页点击超链接,页面跳转到success.jsp页面,效果如下:
咋一看,我们发现整合是成功的啊,但是我们查看控制台的打印如下:
这是什么情况,这是在项目启动的时候,我们的处理器和业务类都被初始化了两次啊。因为Spring和SpringMVC都有自己的容器,而且需要注意的是,我们的TestController和TestService都是放在包com.springmvc下面的,并且我们在Spring和SpringMVC的配置文件中,配置的扫描包的路径也都是:com.springmvc
这样就导致:初始化Spring的IOC容器的时候和初始化SpringMVC的IOC容器时,都把这两个类给初始化了。
5.2 解决Bean重复初始化
5.2.1 不要重复扫描
因为之前我们的Handler和Service都是放在同一个包下,这样配置包扫描的时候,就会把该包下面所有的都扫描了。因此我们可以把TestController放到com.springmvc.controller包下,把TestService放到com.springmvc.service包下,配置文件中的包扫描也是各自扫描给自的包:
5.2.2 配置包扫描的时候排除掉某些注解不扫描
5.2.1 的方法虽然也可以解决问题,但是这样也有不便的地方。因为在分模块开发的时候,每个模块下面都有Controller和Service,这样的话,就导致扫描路径不是很好去区分的。
我们可以在
在SpringMVC的配置文件中,可以使用
use-default-filters="false" 这个别忘记改成false,就是不使用默认的扫描规则,默认会扫描所有的注解
在Spring的配置文件中,可以使用
use-default-filters="false" 这个别忘记改成false,就是不使用默认的扫描规则,默认会扫描所有的注解
6、SpringMVC的IOC容器和Spring的IOC容器的关系
servlet:代表的的容器为spring-mvc的子容器,而DispatcherServlet 是前端控制器,该容器专门为前端监听请求的时候所用,就是说当接收到url请求的时候会引用springmvc容器内的对象来处理。
context-param:代表的容器是spring本身的容器,spring-mvc可以理解为一个继承自该容器的子容器,spring容器是最顶层的父类容器,跟java的继承原理一样
SpringMVC 的 IOC 容器中的 bean 可以引用Spring IOC 容器中的 bean;反之, Spring IOC 容器中的bean则不能引用Spring MVC IOC容器中的 bean 。因为:Spring MVC IOC容器是Spring IOC容器的子类,子类可以引用父类,父类不能引用子类。
从软件层面上来说,Spring MVC是展示层可以调用业务层,业务层不能调用展示层。
当服务器解析web.xml的时候由于listener监听的原因,会优先初始化spring容器,之后才初始化spring-mvc容器。
Spring MVC WEB 层容器可作为 “业务层” Spring容器的子容器:即 WEB 层容器可以引用业务层容器的 Bean,而业务层容器却访问不到 WEB 层容器的 Bean(也就是说不能在Service或Dao中注入Controller)。
注意:当Spring的IOC容器和SpringMVC的IOC容器的扫描包,可以扫描到相同的Controller和Service的时候,并且没有使用
标签:
相关文章
-
无相关信息