博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springmvc web.xml配置之 -- ContextLoaderListener
阅读量:6871 次
发布时间:2019-06-26

本文共 6802 字,大约阅读时间需要 22 分钟。

首先回归一下web.xml的常用配置,看一个示例:

contextConfigLocation
classpath*:spring/applicationcontext-*.xml
org.springframework.web.context.ContextLoaderListener
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
/*
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath*:spring/springmvc-context.xml
1
springmvc
/
View Code

了解web.xml的作用之前必须要了解web容器(也称为是servlet容器)这个概念,常用的web容器有Tomcat、Jetty、JBoss等。

使用web容器,就不得不清楚什么是ServletContext。ServletContext中的信息都是由容器提供的,在web容器启动时,它作为为公共环境容器存放公共信息,为各个Servlet提供信息,也可以作为各个Servlet之间通信的桥梁。

将应用部署到web容器中,启动web容器后,web容器会读取web.xml中的配置信息,对ServletContext进行信息补充。

好了,回到本文主题。

ContextLoaderListener

web.xml中的配置文件中ContextLoaderListener作为监听器,会监听web容器相关事件,在web容器启动或者关闭时触发执行响应程序。具体地,ContextLoaderListener继承ContextLoader类并实现了ServletContextListener接口。

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {    public ContextLoaderListener() {    }    public ContextLoaderListener(WebApplicationContext context) {        super(context);    }    public void contextInitialized(ServletContextEvent event) {        this.initWebApplicationContext(event.getServletContext());    }    public void contextDestroyed(ServletContextEvent event) {        this.closeWebApplicationContext(event.getServletContext());        ContextCleanupListener.cleanupAttributes(event.getServletContext());    }}

  

1.关于监听

ServletContextListener接口中只有初始化和销毁的两个方法::

public interface ServletContextListener extends EventListener {    /**     ** Notification that the web application initialization     ** process is starting.     ** All ServletContextListeners are notified of context     ** initialization before any filter or servlet in the web     ** application is initialized.     */    public void contextInitialized ( ServletContextEvent sce );    /**     ** Notification that the servlet context is about to be shut down.     ** All servlets and filters have been destroy()ed before any     ** ServletContextListeners are notified of context     ** destruction.     */    public void contextDestroyed ( ServletContextEvent sce );}

也就是监听ServletContext的状态,ServletContext属于容器对象,在用于在容器开启或关闭时触发事件,执行contextInitialized/contextDestroyed 。如果想了解程序执行原由可以先了解事件监听设计模式。查阅Tomcat源码,tomcat触发ServletContext初始化监听事件的源码如下:

...(部分略)   Object instances[] = getApplicationLifecycleListeners();for (int i = 0; i < instances.length; i++) {    if (!(instances[i] instanceof ServletContextListener))        continue;    ServletContextListener listener = (ServletContextListener) instances[i];    try {        if (noPluggabilityListeners.contains(listener)) {            listener.contextInitialized(tldEvent);        } else {            listener.contextInitialized(event);        }    } catch (Throwable t) {    }} ...(部分略)

也就是,遍历所有ServletContextListener,调用监听方法。

 

2.关于功能

关于功能主要看initWebApplicationContext()方法。 ContextLoader中的initWebApplicationContext()方法中会创建WebApplicationContext上下文对象,并将这个对象设置到servletContext中:

ContextLoaderListener加载过程:

2.1 创建IOC容器

initWebApplicationContext调用createWebApplicationContext方法;

-->createWebApplicationContext 调用determineContextClass方法

--> defaultStrategies中加载配置文件:

defaultStrategies.getProperty(WebApplicationContext.class.getName())

ContextLoader 类中有段静态代码:

static {        try {            ClassPathResource resource = new ClassPathResource(                    "ContextLoader.properties", ContextLoader.class);            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);        } catch (IOException ex) {            throw new IllegalStateException(                    "Could not load 'ContextLoader.properties': "                            + ex.getMessage());        }        currentContextPerThread = new ConcurrentHashMap(1);    }

ContextLoader.properties 文件内容如下:

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

可知,默认加载的WebApplicationContext是XmlWebApplicationContext

题外话,如果你不想使用默认的,在web.xml中配置contextClass即可

protected Class
determineContextClass(ServletContext servletContext) { String contextClassName = servletContext.getInitParameter("contextClass"); if(contextClassName != null) { try { return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); ...(略)

也就是这种形式:

contextClass
webApplicationContext类全路径名称

org.springframework.web.context.support包下查询webApplicationContext。

2.1 IOC容器配置加载,初始化

这一步主要是调用configureAndRefreshWebApplicationContext,可知在上一步中创建了WebApplicationContext对象(ConfigurableApplicationContext类型),也就是创建了IOC容器对象,接着就要给这个对象进行配置参数的设置了。

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {        String configLocationParam;        if(ObjectUtils.identityToString(wac).equals(wac.getId())) {            configLocationParam = sc.getInitParameter("contextId");            if(configLocationParam != null) {                wac.setId(configLocationParam);            } else {                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));            }        }        wac.setServletContext(sc);        configLocationParam = sc.getInitParameter("contextConfigLocation");        if(configLocationParam != null) {            wac.setConfigLocation(configLocationParam);        }        ConfigurableEnvironment env = wac.getEnvironment();        if(env instanceof ConfigurableWebEnvironment) {            ((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null);        }        this.customizeContext(sc, wac);        wac.refresh();    }

可知,首先会给WebApplicationContext对象设置ServletContext全局信息,然后读取><param-name>contextConfigLocation</param-name>对应的.xml中的配置信息,例如:

contextConfigLocation
classpath*:spring/applicationcontext-*.xml

这些applicationcontext-*.xml配置文件中的信息之后再执行ConfigurableApplicationContext.refresh()方法就会被加载到IOC容器中。

IOC容器的初始化过程,参考下一篇文章。

 

转载于:https://www.cnblogs.com/chenjunjie12321/p/9357534.html

你可能感兴趣的文章
cloudera如何在spark-shell命令行执行spark hql
查看>>
拒绝服务***(DDoS)简介、原理和危害
查看>>
python中的有序字典
查看>>
R语言的包管理功能
查看>>
工厂模式
查看>>
JupyterHub on Kubernetes--定制用户环境
查看>>
sed
查看>>
不以成败论战略
查看>>
我的友情链接
查看>>
一个开源系统的架构分析
查看>>
系统基本功能
查看>>
der pem cer crt key pfx等概念及区别
查看>>
我的友情链接
查看>>
flume-ng 1.5.0安装部署
查看>>
http长连接与短连接
查看>>
数据库中快速备份一个表的数据,或者只备份表结构
查看>>
vue-cli
查看>>
文件处理
查看>>
代码调试包Infragistics Windows Forms Test Automation发布v16.1|附下载
查看>>
delete,truncate和drop的区别
查看>>