过滤器Filter

过滤器

一、什么是过滤器

Filter译为过滤,是JavaEE的三大组件之一,用于在Servlet之外对Request或者Response进行修改。例如,污水净化设备可以看做现实中的过滤器,它负责将污水中的杂质过滤,从而使进入的污水变成净水。而对于Web应用程序来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器端之间的请求与响应信息。

1.1 作用:

起到过滤的作用

1.2 执行时机:

在执行对应的Servlet之前.(过滤Request对象中的内容)
在执行对应的Servlet之后.(过滤Respons对象中的内容)

1.3 发展历史:

由于Servlet规范是开放的,借助于公众与开源社区的力量,Servlet规范越来越科学,功能也越来越强大。2000年,Sun公司在Servlet2.3规范中添加了Filter功能,并在Servlet2.4中对Filter进行了细节上的补充。目前主流版本为Servlet2.5的Filter。

Filter最早在Servlet 2.3版本提供
Filter在Servlet 2.5版本完善

1.4 运行原理

1.5 如何使用

Filter是JavaEE提供的一个接口.(自定义Filter需要实现该接口,并重写所有方法)
Filter提供的方法:
     * init()
     * doFilter()
     * destroy() 
实现步骤:
     * 创建Java类,实现Filter接口,并且重写所有方法.
     * 在web.xml文件中进行配置.
        <filter>
		<filter-name>MyFilter1</filter-name>
		<filter-class>hcx.java.filter.MyFilter1</filter-class>
	  </filter>
	  <filter-mapping>
		<filter-name>MyFilter1</filter-name>
		<url-pattern>/*</url-pattern>
	  </filter-mapping>
使用注解:
 
@WebFilter("/*")访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

 

二、生命周期

ServletAPI提供的Filter接口中含有三个方法,分别为init()、doFilter()和destroy()方法。该三个方式就是Filter的生命周期方法。

1.Filter的构造函数

在Tomcat服务器启动时执行。

在Filter的生命周期中只执行一次。

2.init(FilterConfig)方法

在Tomcat服务器启动时执行。

在Filter的生命周期中只执行一次。

用于Filter的初始化工作。

3.doFilter(ServletRequest,ServletResponse, FilterChain)方法

在每次拦截时执行。

在Filter的生命周期中只执行多次。

用于Filter的拦截处理工作。

4.destroy()方法

在Tomcat服务器关闭时执行。

在Filter的生命周期中只执行一次。

用于Filter的销毁工作。

package hcx.java.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;

/**
 * 自定义过滤器:
 *  * 实现Filter接口,并且重写该接口提供所有的方法.
 * @author HCX
 *
 */
public class MyFilter1 implements Filter {
	/**
	 * Filter的构造函数:
	 *  * 执行时机:在Tomcat服务器启动时.
	 *  * 执行次数:在Filter的生命周期中只执行一次.
	 *    * Filter与Servlet一样,都是单例多线程的.(线程安全问题)
	 */
	public MyFilter1() {
		System.out.println("这是MyFilter1的构造函数...");
	}
	/**
	 * init(FilterConfig config)方法:
	 *  * 作用:用于过滤器的初始化.
	 *  * 执行时机:在Tomcat服务器启动时.
	 *  * 执行次数:在Filter的生命周期中只执行一次.
	 */
	public void init(FilterConfig config) throws ServletException {
		System.out.println("这是MyFilter1的init()方法...");
		
	}
	/**
	 * doFilter(ServletRequest request, ServletResponse response,FilterChain chain)方法:
	 *  * 作用:用于过滤器的过滤.
	 *  * 执行时机:客户端访问当前Filter拦截的资源路径时.
	 *  * 执行次数:在Filter的生命周期中,每次拦截,每次执行.
	 */
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("这是MyFilter1的doFilter()方法...");
		
		//过滤器的放行
		chain.doFilter(request, response);
	}
	/**
	 * destroy()方法:
	 *  * 作用:用于过滤器的销毁.
	 *  * 执行时机:在Tomcat服务器关闭时.
	 *  * 执行次数:在Filter的生命周期中只执行一次.
	 */
	public void destroy() {
		System.out.println("这是MyFilter1的destroy()方法...");
		
	}

}

扩展:
* 面向对象:这个人就是对象,年龄、性别等是属性,出生、上学、结婚等方法.
       * 类与对象的区别:
         * 类:比作女生.
         * 对象:就是范冰冰.
     * 实现、继承、多态、封装等概念.
* 面向过程:这个人从出生,长大、上学、工作、...、去世.
 

三、过滤器链

在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。
 问题:
     * 如何定义过滤器被执行的先后顺序?(创建方法的执行不分顺序)
     * Filter的doFilter()方法具有一个参数FilterChain,通过调用chain.doFilter()方法可以放行.
       * 在过滤器链中,执行chain.doFilter()方法,是否还是放行的作用?
       * 如果是,应该被放行到哪里去了?(单个Filter时,直接被放行到对应的Web资源[Servlet、JSP])
   * 解决以上问题:
     * chain.doFilter()方法依旧是放行方法.
     * 如果执行的不是过滤器链中最后一个过滤器的话,执行chain.doFilter()方法,会被放行到下一个过滤器里.
     * 如果执行的是过滤器链中最后一个过滤器的话,chain.doFilter()方法,才会被放行到对应Web资源中.
     * 过滤器链中的过滤器执行的先后顺序由web.xml文件中的<filter-mapping>标签定义的先后顺序决定.
   * 实际开发的意义:
     * 单个Filter完成单个任务.

FilterChain的doFilter()方法执行时,如果只有一个过滤器的话,执行该方法会将请求发送给服务器端的动态或静态资源。如果是过滤器链的话,只有在执行过滤器链的最后一个过滤器的FilterChain的doFilter()方法时,才会将请求发送给服务器端的动态或静态资源。如果不是在过滤器链的最后一个过滤器的FilterChain的doFilter()方法时,将请求发送给下一个过滤器进行拦截。

 

过滤器先后顺序问题:
1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
       * 如: AFilter 和 BFilter,AFilter就先执行了。
2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行

 

三、过滤器配置FilterConfig

读取web.xml文件中的初始化参数.
在web.xml文件中是如何配置的:
<filter>
		<filter-name>MyFilter2</filter-name>
		<filter-class>hcx.java.filter.MyFilter2</filter-class>
		<init-param>
			<param-name>mingjiao</param-name>
			<param-value>zhangwuji</param-value>
		</init-param>
</filter>
FilterConfig的用法与ServletConfig一致.
在web.xml文件中配置全局初始化参数<context-param>,通过ServletContext对象读取.

需要注意的是,通过getInitParameter()方法获取的初始化参数是私有参数。只有当前过滤器才能获取到,而其他过滤器并不能访问。如果配置全局初始化参数,可以使用<context-param>来配置,并使用ServletContext对象获取。

 

1.Filter的映射配置:

wbe.xml:<url-pattern>

注解:@WebFilter("xxx")

  1. 完全匹配:/xxxx  具体资源路径: /index.jsp   只有访问index.jsp资源时,过滤器才会被执行
  2. 目录匹配:/aaaa/  拦截目录: /user/*    访问/user下的所有资源时,过滤器都会被执行
  3. 扩展名匹配:*.do  *.jsp     访问所有后缀名为jsp资源时,过滤器都会被执行
 
优先级别:完全匹配 -> 目录匹配 -> 扩展名匹配
 

如果当前Filter拦截对应Servlet的话:还可以使用<servlet-name>标签
<filter>
  	<filter-name>MyFilter2</filter-name>
  	<filter-class>hcx.java.filter.MyFilter2</filter-class>
  	<init-param>
  		<param-name>mingjiao</param-name>
  		<param-value>zhangwuji</param-value>
  	</init-param>
</filter>
<filter-mapping>
  	<filter-name>MyFilter2</filter-name>
  	<servlet-name>MyServlet2</servlet-name>
  	<dispatcher>REQUEST</dispatcher>
  	<dispatcher>FORWARD</dispatcher>
</filter-mapping>


Filter拦截Servlet默认情况是拦截直接请求.
在web.xml文件中配置<filter-mapping>标签中具有<dispatcher>
<dispatcher>标签在同一个Filter的配置中,可以配置多个.


<dispatcher>标签的值:

  • REQUEST:是默认值,表示一次请求. 表示仅当直接请求Servlet时才生效。
  • FORWARD:表示请求转发到.   表示仅当某Servlet通过FORWARD到该Servlet时才生效。
  • INCLUDE:表示包含(例如JSP包含另一个JSP等)    JSP中可以通过<jsp:include>标签请求某Servlet或调用RequestDispatcher的include()方法请求某Servlet,仅这种情况下有效。
  • ERROR:表示JSP的<%@ page errorPage=""%>   JSP中可以通过<%@ pageerrorPage=”error.jsp”>标签指定错误处理页面,仅这种情况下有效。
  • ASYNC:异步访问资源

<url-pattern>标签与<dispatcher>标签的关系是“且”的关系。只有满足<url-pattern>标签的条件,且满足<dispatcher>标签的条件时,当前过滤器才能生效。

注解:@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)

package hcx.java.filter; 

import java.io.IOException;
import java.util.Enumeration;

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 MyFilter2 implements Filter {

	public void destroy() {
		
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("这是MyFilter2的doFilter()方法...");
		
		chain.doFilter(request, response);
	}

	public void init(FilterConfig config) throws ServletException {
		System.out.println("这是MyFilter2的init()方法...");
		
		Enumeration enums = config.getInitParameterNames();
		
		while (enums.hasMoreElements()) {
			String name = (String) enums.nextElement();
			String value = config.getInitParameter(name);
			
			System.out.println(name+" : "+value);
		}
	}

}
MyServlet1:
package hcx.java.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		request.getRequestDispatcher("/servlet2").forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}
MyServlet2:
package hcx.java.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		System.out.println("这是Servlet2.........");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值