过滤器及监听器

过滤器及监听器

过滤器

介绍

Filter 即为过滤,用于在 Servlet 之外对 Request 或者 Response 进行修改。它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后处理。使用 Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。

单个过滤器
在这里插入图片描述

多个过滤器

在这里插入图片描述

若是一个过滤器链:先配置先执行(请求时的执行顺序);响应时:以相反的顺序执行。

在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest 。根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据。

在HttpServletResponse 到达客户端之前,拦截 HttpServletResponse。根据需要检查HttpServletResponse,也可以修改 HttpServletResponse 头和数据。

实现

我们可以通过实现一个叫做 javax.servlet.Fileter 的接口来实现一个过滤器,其中定义了三个方 法,init(), doFilter(), destroy() 分别在相应的时机执行。后期观察生命周期。Filter 的实现只需要两步:

Step1: 编写 java 类实现 Filter 接口,并实现其 doFilter 方法。

Step2: 在 web.xml 文件中对编写的 fifilter 类进行注册,并设置它所能拦截的资源。

public class Filter01 implements Filter {
	@Override
	public void destroy() {
		System.out.println("Filter01 destroy...");
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("Filter01...");
		//请求到达资源之前处理的代码
		System.out.println("Filter01请求到达资源之前处理的代码...");
		//放行
		chain.doFilter(request, response);
		//响应客户端之前执行的代码
		System.out.println("Filter01响应到客户端之前执行的代码...");
		
	}
	@Override
	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("Filter01初始化了。。。");
	}
}
<filter>
    <display-name>Filter01</display-name>
    <filter-name>Filter01</filter-name>
    <filter-class>com.mage.filter.Filter01</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Filter01</filter-name>
    <url-pattern>/s01</url-pattern>
  </filter-mapping>

Filter 接口中有一个 doFilter 方法,当开发人员编写好 Filter,并配置对哪个 web 资源进行拦截后,Web 服务器每次在调用 web 资源的 service 方法之前,都会先调用一下 fifilter 的 doFilter 方法。

因此可以达到如下效果:
  调用目标资源之前,让一段代码执行。
  是否调用目标资源(即是否让用户访问 web 资源)。
  
  web 服务器在调用 doFilter 方法时,会传递一个 fifilterChain 对象进来,fifilterChain 对象是 fifilter接口中最重要的一个对象,它提供了一个 doFilter 方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则 web 服务器就会调用 web 资源的 service 方法,即 web 资源就会被访问,否则web 资源不会被访问。(本质是放行,调用 doFilter 方法后,即请求可以到达资源)

web.xml 配置各节点说明:

  • <filter>
    

    指定一个过滤器。

    • <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
    • <filter-class>元素用于指定过滤器的完整的限定类名。
    • <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
    • 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
  • <filter-mapping>
    

    元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径

    • <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字

    • <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)

    • <servlet-name>指定过滤器所拦截的Servlet名称。

    • <dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARDERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。

  • <dispatcher>
    

    子元素可以设置的值及其意义

    • REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
    • INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
    • FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
    • ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

    注意:Tomcat7 及以下的版本:上述解决 GET 乱码的方式不好,不能解决所有的问题,可以借助

HttpServletRequestWrapper 类和过滤器来完成转换乱码的问题:

①在过滤器中判断哪些需要解决

②定义 HttpServletRequestWrapper 的子类,并且重写 getParameter(String name) 方法,在该

方法中实现乱码的处理

③chain.doFilter(自定义类(HttpServletRequestWrapper 的子类),response)

监听器

介绍

web 监听器是一种 Servlet 中的特殊的类,它们能帮助开发者监听 web 中的特定事件,比如ServletContext,HttpSession,ServletRequest 的创建和销毁;变量的创建、销毁和修改等。可以在某些 动作前后增加处理,实现监控。例如可以用来统计在线人数等。

原理

1、存在事件源
2、提供监听器
3、为事件源注册监听器
4、操作事件源,产生事件对象,将事件对象传递给监听器,并且执行监听器相应监听方法

实现

监听器有三类8种:

⑴监听生命周期(三个域对象的创建和销毁):实现接口 ServletRequestListener、 HttpSessionListener 、ServletContextListener

⑵监听值的变化(属性添加,移除,替换):实现接口 ServletRequestAttributeListener、 HttpSessionAttributeListener、ServletContextAttributeListener

⑶针对 session 中的对象:监听 session 中的 java 对象(javaBean),javaBean 直接实现监听器的接口 HttpSessionBindingListener、HttpSessionActivationListener。

假设我们想做一个对在线人数的监控。

​ Step1:创建一个监听器,需要实现某种接口,根据需求选取 HttpSessionListener

Step2:在 web.xml 中配置该监听器

创建一个类,并实现 HttpSessionListener 接口,用来检测 Session 的创建和销毁。在类中定义一 个成员变量用来存储当前的 session 个数。

package com.mage.listener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 监听器  由服务器管理
 * 1、新建普通java类
 * 2、实现相应的接口
 * 3、重写接口
 * 4、配置web.xml
 * 
 *
 */
public class Listener01 implements HttpSessionListener{
	int onlinePeople=0;
	/**
	 * 监听SESSION创建
	 */
	@Override
	public void sessionCreated(HttpSessionEvent se){
		onlinePeople++;
		//不同用户不同session,除非重新创建一个session才是最新的人数
		se.getSession().getServletContext().setAttribute("onlinePeople", onlinePeople);
		System.out.println("session被创建了。。。");
	}
	
	/**
	 * 监听SESSION销毁
	 * 正常关闭服务器不会销毁,因为会自动序列化到本地
	 */
	
	@Override
	public void sessionDestroyed(HttpSessionEvent se){
		onlinePeople--;
		se.getSession().getServletContext().setAttribute("onlinePeople",onlinePeople);
		System.out.println("session被销毁了。。。");
	}

}

在 web.xml 中配置该监听器,让监听器生效

<listener>
    <listener-class>com.mage.listener.Listener01</listener-class>
</listener>

做一个测试的 Servlet 用来访问,和显示当前在线人数

public class Servlet01 extends HttpServlet{
	private static final long serialVersionUID = 1L;
	protected void service(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException, IOException{
		System.out.println("s01....");
		//及时获取也是创建
		int onlinePeople =(int) request.getSession().getServletContext().getAttribute("onlinePeople");
		//输出
		response.getOutputStream().write(("<h1>在线人数</h1>"+onlinePeople).getBytes("GBK"));		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值