web.xml中四种配置参数的执行顺序是:context-param ---> Listener ---> Filter ---> Servlet;
1. web容器首先会读取位于web.xml中的两个节点<context-param>和<listener>;
2. 然后去创建一个ServletContext上下文,被所有的组件共享;
3. 将web.xml中配置的<context-param>转化为键值对,存放于servletContext中;
4. web容器负责实例化监听器并注册监听器以用来监听各种事件,由于可以配置多个监听器,所以监听器本身的注册及执行也是有顺序的:
web容器是根据监听器实现的接口以及在web.xml中的顺序注册的,在web应用程序执行的时候,监听器执行的顺序和它们的注册顺序是一致的;在容器关闭的时候,监听器是按照和注册顺序相反的顺序被通知调用;监听器可以按照如下进行分类:
Object |
Event |
Listener Interface and Event Class |
---|---|---|
Web context |
Initialization and destruction |
javax.servlet.ServletContextListener and ServletContextEvent |
Attribute added, removed, or replaced |
javax.servlet.ServletContextAttributeListener and ServletContextAttributeEvent |
|
Session |
Creation, invalidation, activation, passivation, and timeout |
javax.servlet.http.HttpSessionListener , javax.servlet.http.HttpSessionActivationListener , and HttpSessionEvent |
Attribute added, removed, or replaced |
javax.servlet.http.HttpSessionAttributeListener and HttpSessionBindingEvent |
|
Request |
A servlet request has started being processed by web components |
javax.servlet.ServletRequestListener and ServletRequestEvent |
Attribute added, removed, or replaced |
javax.servlet.ServletRequestAttributeListener and ServletRequestAttributeEvent |
监听器是设计模式中观察者模式的一种应用,容器维护了对某种事件的一个监听器列表,当事件被触发的时侯,响应的监听器就会被按一定的顺序调用. Spring中的ContextLoaderListener实现了ServletContextListener,在ServletContext初始化的时候,就会去初始化webapplicationcontext,从而完成spring IOC中bean的注册;
5. web容器通过调用Filter的init方法初始化Filter,Filter主要用于在请求被处理之前和之后拦截并作出响应;Filter可以通过<filter-mapping>对特定的资源进行处理;当一个请求到来时,针对某种资源的filter会被组织成一个filterChain,filter可以通过调用filterChanin.dofilter()调用后面的filter;如果在一个filter的doFilter方法中调用filterChain.doFilter(),那么filterChian.doFilter()之后的代码将会在response返回的时候才会被执行;如下段代码,当程序进入到filterChain.doFilter(request, response)时,下一个filter的doFilter方法会被调用,如果下一个filter的doFilter方法中也有filterChain.doFilter(request, response),将会继续对下下一个filter的doFilter方法,直到针对当前请求的最后一个filter,然后进入Servlet进行应用逻辑的处理,待处理结束后,会按照刚才调用filter相反的顺序逐一执行filterChain.doFilter(request, response)之后的代码.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; if(!INITIAL_PAGE.equals(req.getServletPath()) && !LOGIN_ACTION.equals(req.getServletPath())){ Object user = req.getSession().getAttribute(WebConstants.USER_INFO); if(user == null){ req.getRequestDispatcher(LOGIN_PAGE_PATH).forward(request, response); }else{ log.info("pre filterChain doFiler in LoginCheckFilter"); filterChain.doFilter(request, response); log.info("post filterChain doFiler in LoginCheckFilter"); } }else{ log.info("pre filterChain doFiler in LoginCheckFilter"); filterChain.doFilter(request, response); log.info("post filterChain doFiler in LoginCheckFilter"); } }
以下是在我的应用程序中的输出:
2010-08-15 14:22:29,948 [http-8080-Processor25] INFO org.mywork.web.utils.LoginCheckFilter - pre filterChain doFiler in LoginCheckFilter 2010-08-15 14:22:29,948 [http-8080-Processor25] INFO org.mywork.web.actions.LoginAction 2010-08-15 14:22:30,212 [http-8080-Processor25] WARN org.apache.struts2.components.Form - No configuration found for the specified action: 'userQueryAction.action' in namespace: '/basic'. Form action defaulting to 'action' attribute's literal value. 2010-08-15 14:22:30,252 [http-8080-Processor25] WARN org.apache.struts2.components.Form - No configuration found for the specified action: 'userQueryAction.action' in namespace: '/basic'. Form action defaulting to 'action' attribute's literal value. 2010-08-15 14:22:30,299 [http-8080-Processor25] INFO org.mywork.web.utils.LoginCheckFilter - post filterChain doFiler in LoginCheckFilter
6. 在filterChain中的filter方法执行完毕的时候,相应的servlet会被调用,sevlet可以通过<servlet-mapping>进行配置使其对特定的url进行处理;在sevlet处理完成后,应用程序可能会再次进入filter,执行某个filter内doFilter()方法中filterChain.doFilter()之后的代码.