Filter

1.Filter是什么?

1)JavaWEB 的一个重要组件,既可以对发送到 Servlet 的请求进行拦截,也可以对 Servlet 返回的响应进行拦截


2)Filter 是实现了 Filter 接口的 Java 类。与 Servlet 程序相似,它由 Servlet 容器进行调用和执行
3)Filter 程序需要在 web.xml 文件中进行注册和设置它所能拦截的资源:Filter 程序可以拦截 Jsp, Servlet, 静态图片文件和静态 html 文件


2.如何创建 Filter ,并运行 Filter

1)创建一个 Filter 类:实现 Filter 接口:public class HelloFilter implements 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;

public class HelloFilter implements Filter {

	@Override
	public void destroy() {
		System.out.println("destroy...");
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		System.out.println("doFilter...");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init...");
	}

}

2)在 web.xml 文件中配置并映射该 Filter,其中 url-pattern 指定了该 Filter 可以拦截哪些资源,既可以通过那些 url 可以访问到该 Filter

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

①REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。

②INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

③FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。

④ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

	<!-- 注册 Filter -->
	<filter>
		<filter-name>helloFilter</filter-name>
		<filter-class>com.javaweb.filter.HelloFilter</filter-class>
		
		<!-- 配置初始化参数 -->
		<init-param>
			<param-name>user</param-name>
			<param-value>root</param-value>
		</init-param>
	</filter>
	<!-- 配置 Filter -->
	<filter-mapping>
		<filter-name>helloFilter</filter-name>
		<url-pattern>/app1/hello.jsp</url-pattern>
	</filter-mapping>

3)Filter 相关的 API

(1)Filter 接口的:

①public void init(FilterConfig arg0):类似与  Servlet 的 init 方法,在创建 Filter 对象(Filter 对象在 Servlet 容器加载当前 WEB 应用时即被创建)后,立即被调用,且只被调用一次。该方法用于对当前的 Filter 进行初始化操作

----a. FilterConfig类似于 ServletConfig  String getFilterName() ServletContext getServletContext()   String getInitParameter(String name)   Enumeration getInitParameterNames()

----b. 可以在 web.xml 文件中配置当前 Filter 初始化参数,配置方式也和 Servlet 方式一致

②public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2):真正 Filter 的逻辑代码需要写在该方法中,每次拦截都会调用该方法。

----a. FilterChain : Filter 链,多个 Filter 可以构成一个 Filter 链。

---------void doFilter(ServletRequest request,ServletResponse response):把请求传给 Filter 链的下一个 Filter,若当前 Filter 是Filter 链的最后一个 Filter,将把请求给目标 Servlet(或JSP)

----b. 多个 Filter 拦截顺序和<filter-mapping> 配置顺序有关,靠前的先被调用。

③public void destroy()

(2)自定义的 HttpFilter

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;
import javax.servlet.http.HttpServletResponse;

public abstract class HttpFilter implements Filter {

	private FilterConfig filterConfig;

	//不建议子类直接覆盖,若直接覆盖可能导致 FilterConfig 对象初始化失败
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		this.filterConfig = filterConfig;
		init();
	}

	/**
	 * 供子类继承的初始化方法,可以通过 getFilterConfig() 方法获取 FilterConfige 对象
	 */
	protected void init() {}

	public FilterConfig getFilterConfig() {
		return filterConfig;
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse rep,
			FilterChain arg2) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) rep;
		doFilter(request, response, arg2);
	}

	public abstract void doFilter(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException;

	@Override
	public void destroy() {
	}
}

3.典型应用

1)使浏览器不缓存页面的过滤器:
(1)有 3 个 HTTP 响应头字段都可以禁止浏览器缓存当前页面,它们在 Servlet 中的示例代码如下:response.setDateHeader("Expires",-1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma","no-cache"); 
(2)并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头

public class NoCache extends HttpFilter  {

	@Override
	public void doFilter(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		response.setDateHeader("Expires",-1);
		response.setHeader("Cache-Control","no-cache");
		response.setHeader("Pragma","no-cache");
		
		chain.doFilter(request, response);
	}
}

2)字符编码的过滤器:通过配置参数encoding指明使用何种字符编码,以处理Html Form请求参数的中文问题

(1)

public class EncodingFilter extends HttpFilter {

	private String encoding;
	
	@Override
	protected void init() {
		encoding = getFilterConfig().getServletContext().getInitParameter("encoding");
	}

	public String getEncoding() {
		return encoding;
	}
	
	@Override
	public void doFilter(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		request.setCharacterEncoding(encoding);
		chain.doFilter(request, response);
	}
}
































“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值