一、监听器
Servlet监听器是指这样的实例对象,首先它实现了Servlet规范中定义的某些Listener接口,然后由Servlet容器实例化,并在整个web application生命周期中监听某些事件,对监听到的事件调用相应的方法进行处理。
Servlet监听器主要包括ServletContextListener、HttpSessionListener、ServletRequestListener这三大类监听器。
ServletContextListener 负责监听Servlet上下文(亦即整个web application)的创建/销毁事件
HttpSessionListener 负责监听Session会话的创建/销毁事件
ServletRequestListener 负责监听用户请求的发起/返回事件。
当这些事件发生时,会自动触发已注册的监听器实例来进行相应处理。
Servlet监听器需要在web项目的web.xml文件中注册,或者使用@WebListener注解。
以一个简单例子作为说明:
package com.funway.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class FirstListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { System.out.println("监听到web app销毁"); } @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("监听到web app启动"); } }
<listener> <listener-class>com.funway.listener.FirstListener</listener-class> </listener>
PS: 除了上面的三大类监听器,Servlet API中还定义了其他更细分的监听器,比如HttpSessionActivationListener、ServletContextAttributeListener等等。
二、过滤器
Servlet过滤器负责过滤用户对web资源的请求,并在返回Response前做一些自定义的操作。同监听器一样,Servlet过滤器必须要先实现Filter接口,然后在web.xml中注册,并由Servlet容器来实例化。它的生命周期同样是整个web application的运行时。
过滤用户对web资源的请求,这听起来有点像ServletRequestListener监听器的功能,都是捕获请求并执行处理。但二者要处理的事情其实是不同的,监听器监听到Request请求后,要做的处理是与web application相关的Servlet上下文,并不能处理ServletRequest与ServletResponse;而过滤器则正是对用户的请求与返回进行加工处理。
过滤器需要在web项目的web.xml配置文件中注册,或者使用@WebFilter注解。
以一个简单的例子作为说明:
package com.funway.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class FirstFilter implements Filter { @Override // 随web application的销毁而销毁 public void destroy() { System.out.println("过滤器销毁"); } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) throws IOException, ServletException { System.out.println("doFilter start"); // 执行一些处理(在本例中我们打印请求的URL地址即可) HttpServletRequest request = (HttpServletRequest)req; System.out.println(request.getRequestURL()); // 执行过滤器链中其他过滤器的doFilter方法 fc.doFilter(req, resp); System.out.println("doFilter end"); } @Override // 随web application的启动而启动 public void init(FilterConfig arg0) throws ServletException { System.out.println("过滤器初始化"); } }
<filter> <filter-name>FirstFilter</filter-name> <filter-class>com.funway.filter.FirstFilter</filter-class> </filter> <filter-mapping> <filter-name>FirstFilter</filter-name> <url-pattern>/home.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
另外,除了默认的对用户Request请求进行过滤的过滤器外,根据web.xml中定义的过滤器的<dispatcher>,Servlet过滤器还有如下几种类型:
具体的用法就不细说了。
三、拦截器
拦截器的作用有点类似于过滤器,同样都是在整个web application生命周期内捕获用户请求事件,然后进行处理。他们二者之间的区别在于:
- 检查spring mvc项目的web.xml配置就可以看到,过滤器<filter>跟<servlet>是同级别的,一个web application可以有一个或者多个servlet来负责处理不同的url mapping,spring mvc的基础DispatcherServlet就是一个servlet,拦截器是定义在DispatcherServlet的上下文中的。所以处理顺序是 用户访问 –> 过滤器 –> DispatcherServlet –> 过滤器 –> 返回
- 过滤器的作用范围比拦截器大。
以一个简单地例子作为说明:
package com.funway.firstspringmvc; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class FirstInterceptor implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("afterCompletion: 在请求全部结束后执行该方法(即已经返回response给用户之后)"); } @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("postHandle: 在请求被控制器处理后执行该方法,然后进入视图"); } @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("preHandle: 在请求被控制器处理前执行该方法, 然后进入控制器"); return true; } }
<!-- 注册拦截器 --> <interceptors> <interceptor> <!-- 拦截器映射的URL --> <mapping path="/**"/> <exclude-mapping path="/home" /> <beans:bean class="com.funway.firstspringmvc.FirstInterceptor"></beans:bean> </interceptor> </interceptors>
参考:
http://www.imooc.com/learn/271
http://www.imooc.com/learn/213
http://www.imooc.com/learn/498
经典!!