spring 框架与 Springmvc 框架概述
现在做为java开发的程序员,我相信基本上每个人都听说过Spring框架,而SpringMVC框架也逐渐的替代了原来的一些MVC框架,成为了Web层框架的佼佼者,但是SpringMVC框架其实本身也是Spring 框架的一个后续产品,这两个框架在结合到一起使用的时候Spring会有自己的IOC容器,而Springmvc也会有自己的ioc容器,两个框架一起使用的时候会有一些什么样的问题,或者两个框架的容器直接是一种什么样的关系,今天我们一起来讨论一下
spring 框架与 Springmvc 框架整合使用的细节
Springmvc 框架的基本使用
在理解spring框架与Springmvc框架一起使用时的两个容器关系之前,我们先对SpringMVC框架的使用步骤做一个简单介绍,以下是SpringMVC在使用的时候的基本代码
1. 在web项目的web.xml文件中配置Springmvc前端控制器
2. 在项目中创建springmvc的配置文件
3. 当做了前面两个配置之后就能直接在项目中创建Controller类和方法去接收请求
Springmvc 的基本执行过程
当我们做了上面的一些事情之后,服务器在启动的时候就会去创建Springmvc的前端控制器(DispatcherServlet),这个Servlet一创建就会帮助我们去加载Springmvc的配置文件,从而初始化Springmvc的容器,创建所有的Controller。以后发送请求的时候,执行的过程会经过Springmvc的各个组件,大致流程如下图
spring 框架与 Springmvc 框架整合使用
1. spring 框架与 Springmvc 框架整合使用的思路
当我们在实际案例中去使用SpringMVC的时候由于我们需要在Controller中注入Service,所以我们必须要保证Controller对象创建之前Service对象要创建,而我们都知道Service最终都会交给Spring去管理,所以Spring的容器应该要先于Springmvc的容器创建才行
2. 具体代码实现
代码实现很简单,想要web项目在加载Springmvc的配置之前先加载Spring的配置,只需要在web.xml文件中配置一下Spring的监听器和配置文件位置就可以
spring 框架与 Springmvc 框架一起使用后两个容器的关系
spring框架与Springmvc框架一起使用后Spring会有Spring的容器,在Spring容器中会创建Service,Dao层的对象,当然也会有SpringMVC的容器,SpringMVC容器会创建Controller对象,那么当我们去发送请求到Controller中去的时候,Controller中会注入Service对象,SpringMVC容器中的Controller对象是如何去注入Spring容器中的service对象的,相信部分刚接触SpringMVC框架的学者会在这个地方有疑问,那么接下来我们就一起去跟着Spring和SpringMVC源码一起来揭秘一下这个问题:
Spring 容器加载
首先我们都知道,服务器一启动会去去执行Spring监听器中的代码加载Spring配置文件初始化容器,我们先去看看这一部分Spring是如何去完成的。
通过这一部分源码我们发现,服务器已启动,listener中确实会帮我们去创建Spring容器,但是他还会做一件事情,就是将容器保存到ServletContext域对象中
SpringMVC 容器加载
从Springmvc源代码中可以看到SpringMVC容器初始化的过程如下图:
SpringMVC的容器在初始化的时候,会把原来已经保存在ServletContext中的Spring容器设置成SpringMVC的父容器,也就是说 Spring 容器和 SpringMVC 容器直接是一种逻辑上的父子关系, SpringMVC 容器是子容器, Spring 容器是父容器 ,所以在SpringMVC容器中的Controller能注入Spring容器中的service对象
总结
通过前面的分析,这样我们在清楚了spring和springMVC的父子容器关系;所以在项目中当我们同时去使用Spring框架和Springmvc框架的时候,Springmvc中的Controller能够访问到Springmvc父容器(Spring容器)中的对象
来源:http://bbs.itheima.com/thread-443226-1-1.html
转载自:https://my.oschina.net/jast90/blog/282773#
要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的。spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。
说完了spring上下文的初始化过程,这三个上下文的关系应该就了解了。如还是不太清楚,我就爱莫能助了,只能自行看代码去了。
===============================================================================================================
最近在做项目时牵扯到有关父子上下文的概念。
何为父子上下文呢?
父上下文:
使用listener监听器来加载配置文件,如下:
<
listener
>
<
listener-class
>org.springframework.web.context.ContextLoaderListener</
listener-class
>
</
listener
>
Spring 会创建一个WebApplicationContext上下文,称为父上下文(父容器),保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。
可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);
子上下文:
使用Spring MVC 来处理拦截相关的请求时,会配置DispatchServlet:
<
servlet
>
<
servlet-name
>dispatcherServlet</
servlet-name
>
<
servlet-class
>org.springframework.web.servlet.DispatcherServlet
</
servlet-class
>
<
init-param
>
<
param-name
>contextConfigLocation</
param-name
>
<
param-value
>/WEB-INF/applicationContext-mvc.xml</
param-value
>
</
init-param
>
<
load-on-startup
>1</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>dispatcherServlet</
servlet-name
>
<
url-pattern
>/</
url-pattern
>
</
servlet-mapping
>
每个DispatchServlet会有一个自己的上下文,称为子上下文,它也保存在 ServletContext中,key 是”org.springframework.web.servlet.FrameworkServlet.CONTEXT”+Servlet名称。当一 个Request对象产生时,会把这个子上下文对象(WebApplicationContext)保存在Request对象中,key是 DispatcherServlet.class.getName() + “.CONTEXT”。
可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);
父上下文(父容器)和子上下文(子容器)的访问权限:
子上下文可以访问父上下文中的bean,但是父上下文不可以访问子上下文中的bean。
父上下文使用与否
方案一,传统型:
父上下文容器中保存数据源、服务层、DAO层、事务的Bean。
子上下文容器中保存Mvc相关的Action的Bean.
事务控制在服务层。
由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。
当然,做为“传统型”方案,也没有必要这要做。
方案二,激进型:
Java世界的“面向接口编程”的思想是正确的,但在增删改查为主业务的系统里,Dao层接口,Dao层实现类,Service层接口,Service层实现类,Action父类,Action。再加上众多的O(vo/po/bo)和jsp页面。写一个小功能 7、8个类就写出来了。 开发者说我就是想接点私活儿,和PHP,ASP抢抢饭碗,但我又是Java程序员。最好的结果是大项目能做好,小项目能做快。所以“激进型”方案就出现了—–没有接口、没有Service层、还可以没有众多的O(vo/po/bo)。那没有Service层事务控制在哪一层?只好上升的Action层。
本文不想说这是不是正确的思想,我想说的是Spring不会限制你这样做。
由于有了父子上下文,你将无法实现这一目标。解决方案是只使用子上下文容器,不要父上下文容器 。所以数据源、服务层、DAO层、事务的Bean、Action的Bean都放在子上下文容器中。就可以实现了,事务(注解事务)就正常工作了。这样才够激进。
总结:不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet,事情就简单了,什么麻烦事儿也没有了。