参考
- difference-between-and-in-servlet-mapping-url-pattern
- how-are-servlet-url-mappings-in-web-xml-used
- OpenFire_- Listener 监听器
- Web.xml配置详解之context-param
- zhxing - web.xml 中的listener、 filter、servlet 加载顺序及其详解
容器加载web.xml的顺序
容器对于web.xml的加载过程是:
- context-param
- listener
- filter
- servlet
Servlet映射规则匹配顺序
跟Nginx的匹配规则有点相似. 根据Servlet 3.0规范
, 匹配顺序如下:
Map exact URL
直接匹配完全一致的URL, 即请求的URL和某条映射规则逐字匹配.
比如说有如下配置:Map the longest path-prefix, using '/' character as a path separator.
匹配最长的前缀(考虑通配符).
比如说对于/path/*
和/path/long/*
这两个映射, 请求/path/long/hello
会匹配到/path/long/*
.match a servlet handles specific extension.
找专门处理某类后缀的servlet.-
If neither of the previous three rules result in a servlet match, the container will attempt to serve content appropriate for the resource requested. If a "default" servlet is defined for the application, it will be used. Many containers provide an implicit default servlet for serving content.
如果以上都不匹配的话, 容器会尝试去找对应的资源文件. 如果
default servlet
被定义了, 那它就会被使用.
以上匹配是大小写敏感的.
对于Web application deployment descriptor
对来说:
In the Web application deployment descriptor, the following syntax is used to define mappings:
- A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used for path mapping.
- A string beginning with a ‘*.’ prefix is used as an extension mapping.
- The empty string ("") is a special URL pattern that exactly maps to the application's context root, i.e., requests of the form http://host:port/
/. In this case the path info is ’/’ and the servlet path and context path is empty string (““). - A string containing only the ’/’ character indicates the "default" servlet of the application. In this case the servlet path is the request URI minus the context path and the path info is null.
- All other strings are used for exact matches only
所以对于SpringMVC
对的org.springframework.web.servlet.DispatcherServlet
来说, 通常定义的是/
. 这其实不是匹配所有URL
的意思, 而是最为一个最后的匹配手段, 即如果没能从其他更具体的映射中匹配, 那最后只能落到/
这里.
一些例子:
定义的规则:
Path Pattern Servlet
/foo/bar/* servlet1
/baz/* servlet2
/catalog servlet3
*.bop servlet4
请求的URL以及匹配情况:
Incoming Path Servlet Handling Request
/foo/bar/index.html servlet1
/foo/bar/index.bop servlet1
/baz servlet2
/baz/index.html servlet2
/catalog servlet3
/catalog/index.html “default” servlet
/catalog/racecar.bop servlet4
/index.bop servlet4
101
oracle documentation
Listener配置信息必须在Filter和Servlet配置之前,Listener的初始化(ServletContentListener初始化)比Servlet和Filter都优先,而销毁比Servlet和Filter都慢。
web.xml
中定义的顺序被调用的.
If the order in which the listeners, servlets, filters are invoked is important to an application then a deployment descriptor must be used. When using annotations to define the listeners, servlets and filters, the order in which they are invoked is unspecified.
The ordering will be based on the order in which they are defined in the descriptor and on the absolute-ordering element in the web.xml or an ordering element in the web-fragment.xml.
Prior to this release of the specification (Java™ Servlet Specification, version 3), context listeners were invoked in random order. As of Servlet 3.0, the listeners are invoked in the order in which they are declared in the web.xml.
Implementations of javax.servlet.ServletContextListener are invoked at their contextInitialized method in the order in which they have been declared, and at their contextDestroyed method in reverse order.
Configuration specified in the main web.xml or a web fragment takes precedence over the configuration specified via annotations.
首先Listener是有几大类的:
- ServletContext
这是针对整个Web程序而言的. - Session
对Session有关的事件进行监听 - Request
对Request有关的事件进行监听
ServletContext
如果需要监听整个Web程序范围内的ServletContext
. 需要实现javax.servlet.ServletContextListener
接口. 接口定义如下:
public interface ServletContextListener extends EventListener {
/**
* Receives notification that the web application initialization
* process is starting.
*
* All ServletContextListeners are notified of context
* initialization before any filters or servlets in the web
* application are initialized.
*
* @param sce the ServletContextEvent containing the ServletContext
* that is being initialized
*/
public void contextInitialized(ServletContextEvent sce);
/**
* Receives notification that the ServletContext is about to be
* shut down.
*
*
All servlets and filters will have been destroyed before any
* ServletContextListeners are notified of context
* destruction.
*
* @param sce the ServletContextEvent containing the ServletContext
* that is being destroyed
*/
public void contextDestroyed(ServletContextEvent sce);
}
可以在web.xml
文件中通过
来传递一些参数给ServletContext
这个供整个Web程序共享的上下文对象.
以Spring
读取配置文件为例, 做一下解析.
web.xml:
contextConfigLocation
classpath:spring/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
看看org.springframework.web.context.ContextLoaderListener
类是如何读取这个参数的:
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
@Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
这个类基本将工作给了其父类, 所以转而去看父类的实现:
org.springframework.web.context.ContextLoader
/**
* Name of servlet context parameter (i.e., {@value}) that can specify the
* config location for the root context, falling back to the implementation's
* default otherwise.
* @see org.springframework.web.context.support.XmlWebApplicationContext#DEFAULT_CONFIG_LOCATION
*/
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
可以看到定义了这样一个字符串contextConfigLocation
, 刚好就是我们通过
传入的名字. 也可以看到有一个默认路径
/** Default config location for the root context */
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
然后定位CONFIG_LOCATION_PARAM
, 可以发现在configureAndRefreshWebApplicationContext
方法中使用了该值.
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
// 为了简便, 删除了前后代码
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
// 为了简便, 删除了前后代码
}
SessionListener
实例 3.1
Java中的Filter 过滤器
The JSP 3.1 spec (JSR 340) says this on page 14-160:
The element load-on-startup indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the Web application. The element content of this element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-startup value.
简单来说就是设置这个参数可以让Servlet
在整个Web程序启动时候就被加载. 而不用等到第一个请求才加载某个Servlet
.
具体来说:
- >= 0
容器需要在启动这个web程序的时候就加载这个servlet, 而且数字小的应该先加载. 如果数字相同, 容器自定义顺序. - < 0
容器自己决定何时加载这个servlet.
&
-
提供的参数存放在ServletContext
中, 全局可见. -
和特定的Servlet
有关, 只能在那个Servlet
中取得.