DispatcherServlet和ContextLoaderListener

DispatcherServlet和ContextLoaderListener

DispatcherServlet的上下文仅仅是Spring MVC的上下文,而Spring加载的上下文是通过ContextLoaderListener来加载的。因此在/WEB-INF/[server-name]-servlet.xml中配置的Bean一般只针对Spring MVC有效,而在ContextLoaderListener配置文件下配置的bean则对整个spring有效。

上下文创建完后会放在ServletContext对象中,其中ContextLoaderListener加载的上下文放在ServletContext的key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中,而DispatcherServlet加载的上下文在每次请求时会放一份在request对象的key为WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中。

DispatcherServlet中的initWebApplicationContext()方法是容器启动时自动调用的方法,在此方法中会进行bean的加载以及servlet初始化等一系列动作。

在初始化的最后,会调用getServletContext()方法将加载的WebApplicationContext对象作为一个属性放入到ServletContext中。

if (this.publishContext) {
            // Publish the context as a servlet context attribute.
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
                        "' as ServletContext attribute with name [" + attrName + "]");
            }
}

在ContextLoaderListener中也时一样,容器启动的时候调用initWebApplicationContext(ServletContext servletContext)方法,传入一个ServletContext对象,并将最后初始化生成的WebApplicationContext对象放入到ServletContext中。

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

这两个方法中的ServletContext对象是相同的。

DispatcherServlet中使用的特殊的Bean

DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean:

1、Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;

2、HandlerMapping:请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;

3、HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理;

4、ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;

5、LocalResover:本地化解析,因为Spring支持国际化,因此LocalResover解析客户端的Locale信息从而方便进行国际化;

6、ThemeResovler:主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

7、MultipartResolver:文件上传解析,用于支持文件上传;

8、HandlerExceptionResolver:处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);

9、RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;

10、FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景

WebApplicationContext获取方式:
1.DispatcherServlet:

RequestContextUtils.getWebApplicationContext(request)或
WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法来获取对应的applicationContext.

2.ContextLoaderListener:

WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)或
WebApplicationContextUtils.getWebApplicationContext(servletContext)或
WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法来获取对应的applicationContext,

加载顺序

根据web.xml的加载顺序,listener总是先于servlet进行加载,因此虽然DispatcherServlet和ContextLoaderListener的WebApplicationContext不同,但是ContextLoaderListener的WebApplicationContext总是DispatcherServlet的父ApplicationContext

在DisPatcherServlet的initWebApplicationContext()方法中。

WebApplicationContext rootContext =
                WebApplicationContextUtils.getWebApplicationContext(getServletContext());

获取ContextLoaderListener的WebApplicationContext对象,最后将其放入变量中。

createWebApplicationContext(ApplicationContext parent) {
    wac.setParent(parent);
}
bean查找顺序

由于二者生成的WebApplicationContext不同,因而这两个WebApplicationContext会分别去加载它们的配置,生成不同的BeanFactory;获取Spring Bean时,会先从DispatcherServlet的WebApplicationContext中查找,若不存在再通过父ApplicationContext,即ContextLoaderListener的WebApplicationContext,进行查找。

注意:同一个web容器中,只允许存在一个ContextLoaderListener,但可以存在多个DispatcherServlet。

本篇文章参考网上资料。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值