[Spring]聊一聊被Springboot废弃的web.xml

3 篇文章 0 订阅
2 篇文章 0 订阅

如果你接触的技术够新,你会发现,原本以前学习web工程时,每个工程的WEB-INF下面的web.xml似乎不见了。
实话说,技术本来更新换代就比较快,有些人甚至都不知道web.xml是做什么的它就被湮没在历史的洪流中了。

For Example

比如,以下是一个web.xml的例子

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring/applicationcontext-*.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/springmvc-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

作用-是对ServletContext进行补充

首先,tomcat等容器启动时(这里以tomcat为例),Servlet容器也随之启动。
然后:
①它会先去读取server.xml,启动里面配置的web应用,并为每个应用创建一个“全局上下文环境(ServletContext)”。
②容器启动时,加载web.xml。web.xml的作用就是对ServletContext进行补充。里面可以为每个工程配置Filter、Listener、Servlet。
因此,我们需要明白的一点是,web.xml并不是必须有。

加载顺序

web.xml中大致会有这么几个主要的标签:
1.<context-param>
2.<listener>
3.<filter>
4.<servlet>
加载的顺序为:
context-param -> listener -> filter -> servlet

各个标签的作用

<context-param>

需要加载的配置项。例如这里指定配置文件,多个配置文件以逗号分隔或者换行分隔。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring/applicationcontext-*.xml</param-value>
</context-param>

<listener>

使用Spring时,我们通常填入的是:

   <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
   </listener>

这个listener会去加载第一步配置的contextConfigLocation。
这里配置的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.监听

这个接口只有一个初始化和销毁的方法,监听ServletContext的状态。ServletContext属于容器对象,在用于在容器开启或关闭时触发事件,执行contextInitialized/contextDestroyed

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 );
}

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.功能

继承的对象ContextLoader中的initWebApplicationContext()方法中会创建WebApplicationContext上下文对象,并将这个对象设置到servletContext中:
①创建IOC容器
initWebApplicationContext调用createWebApplicationContext方法;

–>createWebApplicationContext 调用determineContextClass方法

–> defaultStrategies中加载配置文件:

defaultStrategies.getProperty(WebApplicationContext.class.getName())
在这里插入图片描述
在这里插入图片描述
ContextLoader 类中有段静态代码:
在这里插入图片描述
private static final String DEFAULT_STRATEGIES_PATH = “ContextLoader.properties”;
这个文件中的配置:
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
默认加载的WebApplicationContext是XmlWebApplicationContext,如果不想用默认的,可以在web.xml指定:

<context-param>
    <param-name>contextClass</param-name>
    <param-value>webApplicationContext类全路径名称</param-value>
<context-param>

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

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			// The application context id is still set to its original default value
			// -> assign a more useful id based on available information
			String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
			if (idParam != null) {
				wac.setId(idParam);
			}
			else {
				// Generate default id...
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
						ObjectUtils.getDisplayString(sc.getContextPath()));
			}
		}

		wac.setServletContext(sc);
		String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
		if (configLocationParam != null) {
			wac.setConfigLocation(configLocationParam);
		}

		// The wac environment's #initPropertySources will be called in any case when the context
		// is refreshed; do it eagerly here to ensure servlet property sources are in place for
		// use in any post-processing or initialization that occurs below prior to #refresh
		ConfigurableEnvironment env = wac.getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
		}

		customizeContext(sc, wac);
		wac.refresh();
	}

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

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

未完待续。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值