JavaWeb中的监听器、过滤器、拦截器

监听器Listener

  • web监听器是Servlet中一种特殊的类,能监听web中的特定时间,比如ServletContext,HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。
  • 监听事件自身的创建和销毁
    1. ServletContext监控:对应监控application内置对象的创建和销毁。当web容器开启时,执行contextInitialized方法;当容器关闭或重启时,执行contextDestroyed方法。
      实现方式:直接实现ServletContextListener接口
    2. HttpSession监控:对应监控session内置对象的创建和销毁。当打开一个新的页面时,开启一个session会话,执行sessionCreated方法;当页面关闭session过期时,或者容器关闭销毁时,执行sessionDestroyed方法。
      实现方式:直接实现HttpSessionListener接口
    3. ServletRequest监控:对应监控request内置对象的创建和销毁。当访问某个页面时,出发一个request请求,执行requestInitialized方法;当页面关闭时,执行requestDestroyed方法。
      实现方式,直接实现ServletRequestListener接口
  • 监听对象属性的新增、删除和修改
    1. 实现ServletContextAttributeListener接口:通过调用ServletContextAttribtueEvent的getName方法可以得到属性的名称。
    2. 实现HttpSessionAttributeListener接口
    3. 实现ServletRequestAttributeListener接口
  • 监听对象的状态
    1. 针对某些POJO类,可以通过实现HttpSessionBindingListener接口,监听POJO类对象的事件。
      HttpSessionBindingListener虽然叫做监听器,但使用方法与HttpSessionListener完全不同。我们实际看一下它是如何使用的。
      新建类OnlineUserBindingListener,实现HttpSessionBindingListener接口,HttpSessionBindingListener内有两个方法valueBound(HttpSessionBindingEvent event)和valueUnbound(HttpSessionBindingEvent event),前者为数据绑定,后者为取消绑定
      所谓对session进行数据绑定,就是调用session.setAttribute()把HttpSessionBindingListener保存进session中。
      HttpSessionListener只需要设置到web.xml中就可以监听整个应用中的所有session。HttpSessionBindingListener必须实例化后放入某一个session中,才可以进行监听
  • 监听Session数据的钝化与活化
    1. 由于session中保存大量访问网站相关的重要信息,因此过多的session数据就会服务器性能的下降,占用过多的内存。因此类似数据库对象的持久化,web容器也会把不常使用的session数据持久化到本地文件或者数据中。这些都是有web容器自己完成,不需要用户设定。
      不用的session数据序列化到本地文件中的过程,就是钝化;
      当再次访问需要到该session的内容时,就会读取本地文件,再次放入内存中,这个过程就是活化。
      类似的,只要实现HttpSeesionActivationListener接口就是实现钝化与活化事件的监听
  • 代码实现
  1. 自定义监听器类
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener{

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println(sce.getServletContext().getContextPath() + "  " + "ServletContext对象创建");
		sce.getServletContext().setAttribute("path", sce.getServletContext().getContextPath());
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("ServletContext对象销毁");
	}
}
  1. web.xml配置
	<!-- 自定义servletContext监听器 -->
	<listener>
		<listener-class>zjq.listener.MyServletContextListener</listener-class>
	</listener>

参考文章1 参考文章2

过滤器Filter

  • 过滤器是一个服务器端的组件,它可以拦截客户端的请求和响应信息,并对这些信息进行过滤。
    Servlet API中提供了一个Filter接口,如果编写类实现了这个接口,则称这个类为过滤器。
  • 定义一个Filter类,需要继承javax.servlet.Filter类,重写其init、doFilter、destroy方法。init()方法会在Filter初始化后进行调用,在init()方法里面我们可以通过FilterConfig访问到初始化参数( getInitParameter()或getInitParameters() )、ServletContext (getServletContext)和当前Filter部署的名称( getFilterName() )等信息。destroy()方法将在Filter被销毁之前调用。而doFilter()方法则是真正进行过滤处理的方法,在doFilter()方法内部,我们可以过滤请求的request和返回的response,同时我们还可以利用FilterChain把当前的request和response传递给下一个过滤器或Servlet进行处理。
  • 代码实现
  1. 自定义过滤器类
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;

public class FirstFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//做相应操作
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
	}
}
  1. web.xml
	<!-- 自定义过滤器1 -->
	<filter>
		<filter-name>firstFilter</filter-name>
		<filter-class>zjq.filter.FirstFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>firstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

参考文章1 参考文章2

拦截器Interceptor

  • SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间。
  • SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式:
    1. 第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;
    2. 第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。
  • 代码实现
  1. 自定义拦截器类
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class FirstInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		//请求处理之前进行调用
		HttpSession session = request.getSession();
		String userName = (String) session.getAttribute("userName");
		if (userName == null) {
			response.sendRedirect("/ssm_demo/welcome.html");
			//当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行
			return false;			
		} else {
			//当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法
			return true;
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		//在当前请求进行处理之后,也就是Controller 方法调用之后执行
		//但是它会在DispatcherServlet 进行视图返回渲染之前被调用
		//可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		//该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行
		//这个方法的主要作用是用于进行资源清理工作的
	}
}
  1. spring.xml配置文件
	<!-- 配置拦截器1 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/testController/toTest"/>
			<mvc:exclude-mapping path="/welcome.html"/>
			<bean id="firstInterceptor" class="zjq.interceptor.FirstInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

过滤器和拦截器的区别

  1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调
  2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器
  3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
  4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问
  5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
  6. 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

过滤器和拦截器的顺序

  1. 先过滤再做实际的拦截操作
  2. 过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理
  3. 拦截器是被包裹在过滤器之中的
    在这里插入图片描述
    在这里插入图片描述
    参考文章1 参考文章2 参考文章3
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章