javaweb开发之Filter

1、简介

在Servlet2.3规范中定义了过滤器,它对servlet容器调用servlet的过程进行拦截,从而在servlet进行响应处理的先后实现一些特殊的功能。 java

过滤器实现了一个责任链的模式。多个过滤器造成一个过滤器链,过滤器链中不一样过滤器的前后顺序由部署文件web.xml中过滤器映射<filter-mapping>的顺序决定。 web

最早截获客户端请求的过滤器将最后截获Servlet/JSP的响应信息。 浏览器

Servlet过滤器能够过滤的Web组件包括Servlet,JSP和HTML等文件。 缓存

Servlet过滤器能够应用在客户端和servlet之间、servlet和servlet或JSP页面之间,以及所包括的每一个JSP页面之间。 tomcat

2、原理

在Servlet中使用过滤器时,过滤器能够对客户端的请求进行处理。处理完成后,它会交给下一个过滤器处理,这样,客户的请求在过滤链里逐个处理,直到请求发送到目标为止。在目标处理结束后,会沿着最后一个过滤器反向一个个进行处理直至返回到客户端。

3、Filter相关接口

1. Filter接口

全部的Servlet过滤器都必须实现javax.servlet.Filter接口,并实现该接口中的三个方法: app

init(FilterConfig filterConfig) jsp

Servlet过滤器的初始化方法,Servlet容器建立Servlet过滤器实例后将调用该方法。该方法将读取web.xml文件中Servlet过滤器的初始化参数。 ide

该方法在tomcat启动的时候执行。


doFilter(ServletRequest request, ServletResponse response, FilterChain chain) ui

该方法完成实际的过滤操做,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。 编码

这里的ServletRequest和ServletResponse通常须要转换成具体的Servlet实现对于的对象,如:HttpServletRequest和HttpServletResponse。

有些过滤器比较消耗资源,因此须要防止重复过滤,能够在doFilter()方法中判断。



destroy()

Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。

2. FilterConfig接口

Filter的init方法中提供了一个FilterConfig对象,提供相关的操做:

如获取Filter中配置的初始化参数:
<filter>
      <filter-name>LoginFilter</filter-name>
      <filter-class>cn.heimar.LoginFilter</filter-class>
      <init-param>
          <param-name>username</param-name>
          <param-value>admin</param-value>
      </init-param>
</filter>
在init方法中获取:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
    //获取Filter初始化参数
    String username = filterConfig.getInitParameter("username");
}

3. 在Filter中访问application

ServletContext context = filterConfig.getServletContext();
或者在doFilter方法中根据转换好的request获取:
HttpServletRequest req = (HttpServletRequest)request;
ServletContext context = req.getSession().getServletContext();

4、定义过滤器

public class MyFilter implements Filter {

    public void init(FilterConfig fc) {
        //过滤器初始化代码
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){
        //在这里能够对客户端请求进行检查
        //沿过滤器链将请求传递到下一个过滤器。
        chain.doFilter(request, response);
        //在这里能够对响应进行处理
    }

    public void destroy( ) {
        //过滤器被销毁时执行的代码
    }

}

5、过滤器映射

在web.xml文件中添加以下代码来声明Filter:
<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>
        cn.edu.uibe.webdev.MyFilter
    </filter-class>
    <init-param>
        <param-name>developer</param-name>
        <param-value>TongQiang</param-value>
    </init-param>
</filter>
<!--针对一个Servlet作过滤-->
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <servlet-name>MyServlet</servlet-name>
</filter-mapping>
<!--针对URL Pattern作过滤-->
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/book/*</url-pattern>
</filter-mapping>

/* 拦截全部资源及不存在的资源

*.jsp 拦截全部jsp文件

默认状况下forward方式不会被过滤。通常是须要过滤的,方式是在filter-mapping中添加<dispatcher>FORWARD</dispatcher>,该值默认是request,添加时为了防止覆盖request,须要把该值也添加。

6、常见应用

能够对客户提交的数据进行从新编码。
使浏览器不缓存页面。
过滤不和谐的文字。

能够验证用户是否登陆。


对客户端提交的数据进行从新编码示例:

EncodingFilter.java

package cn.heimar.filter.encoding;

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 class EncodingFilter implements Filter {
	/**
	 * 设置编码格式
	 */
	private String encoding;

	/**
	 * 是否须要强制转码
	 */
	private boolean forceEncoding = false;

	@Override
	public void init(FilterConfig config) throws ServletException {
		encoding = config.getInitParameter("ENCODING");
		String force = config.getInitParameter("FORCE_ENCODING");
		if (force != null)
			forceEncoding = Boolean.valueOf(force);
	}

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

		if ((request.getCharacterEncoding() == null || forceEncoding)
				&& encoding != null){
			request.setCharacterEncoding(encoding);
                }
		response.setCharacterEncoding(encoding);
		chain.doFilter(req, resp);
	}

	@Override
	public void destroy() {

	}

}
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">

	<filter>
		<filter-name>EncodingFilter</filter-name>
		<filter-class>cn.heimar.filter.encoding.EncodingFilter</filter-class>
		<!-- 配置编码格式 -->
		<init-param>
			<param-name>ENCODING</param-name>
			<param-value>utf-8</param-value>
		</init-param>
		<!-- 配置是否强转 -->
		<init-param>
			<param-name>FORCE_ENCODING</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	
	<servlet>
		<servlet-name>LoginServlet</servlet-name>
		<servlet-class>cn.heimar.filter.encoding.LoginServlet</servlet-class>
	</servlet>
	
	<filter-mapping>
		<filter-name>EncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet-mapping>
		<servlet-name>LoginServlet</servlet-name>
		<url-pattern>/login</url-pattern>
	</servlet-mapping>

</web-app>
相关文章
相关标签/搜索