Servlet学习笔记(八)—— 自定义过滤器的编写改进:自定义实现FilterChain

笔记六中实现了三种过滤器:字符编码过滤、登录权限过滤、敏感词过滤,但是有个缺陷就是,限定了过滤顺序,而不能实现先进行request过滤,最后response过滤,并且中间几项过滤的顺序不能动态改变。所以这里做个改进,实现一个过滤顺序的FilterChain。

多个Filter的执行顺序在这篇博文中得到很仔细的讲解,总结一点,多个过滤器的执行顺序是根据web.xml中不同<filter-mapping>的顺序来先后执行的,比如:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <filter>
        <filter-name>firstFilter</filter-name>
        <filter-class>com.test.filter.FirstFilter</filter-class>
    </filter>
    <filter>
        <filter-name>secondFilter</filter-name>
        <filter-class>com.test.filter.SecondFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>secondFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>firstFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>   

    <servlet>
        <servlet-name>firstServlet</servlet-name>
        <servlet-class>com.alimama.servlet.FirstServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>firstServlet</servlet-name>
        <url-pattern>/firstServlet</url-pattern>
    </servlet-mapping>
</web-app>   

将会先执行secondFilter,再执行firstFilter。

下面是截取的一段实现Filter接口的doFilter代码,用户自定义的Filter都实现了这个接口:

 public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("before invoke secondFilter's chain.doFilter() ..");
        chain.doFilter(request, response);
        System.out.println("after invoke secondFilter's chain.doFilter() ..");
    }   

可以看到第四行的chain.doFilter(request,response);这句代码是Servlet里的Filter技术的核心,它的主要职能是将请求传递给下一个Filter。不是一下子全部初始化所有的Filter对象。

依据这个思想,我自己定义了一个FilterChain来实现多个过滤器的过滤顺序。

//FilterChain.java
package lewa;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FilterChain {
	//private static final String[] filters={"LoginFilter","WordFilter"};
	private static final Filter[] filters={new LoginFilter(),new WordFilter()};
	private static int count=0;
	public void doFilter(ServletRequest request,ServletResponse response,FilterChain fc) throws InstantiationException, IllegalAccessException, Exception{
		if(count<filters.length){
			//Class<Filter> cls=(Class<Filter>)Class.forName(filters[count]);
			//cls.doFilter(request, response);
			filters[count++].doFilter(request, response, fc);
		}
	}
}

静态成员变量filters里的过滤器实例的顺序可以自行定义,以后想更改过滤顺序只要改这个String数组就可以。

相应的其他Filter也做了更改:

//Filter.java
package lewa;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public interface Filter {
	public void init();
	public void doFilter(ServletRequest reuqest,ServletResponse response,FilterChain fc)throws Exception;
	public void destroy();
}
//EncodingFilter.java
package lewa;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class EncodingFilter implements Filter{

	@Override
	public void init() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest reuqest, ServletResponse response,FilterChain fc)throws InstantiationException, IllegalAccessException, Exception{
		// TODO Auto-generated method stub
		reuqest.setCharacterEncoding("UTF-8");
		fc.doFilter(reuqest, response,fc);
		response.setContentType("text/html;charset=UTF-8");
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}

}
//LoginFilter.java
package lewa;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginFilter implements Filter{
	public LoginFilter(){}

	@Override
	public void init() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest reuqest, ServletResponse response,FilterChain fc)
			throws  Exception {
		// TODO Auto-generated method stub
		HttpServletRequest req=(HttpServletRequest)reuqest;
		HttpServletResponse resp=(HttpServletResponse)response;
		HttpSession session=req.getSession();
		if(session.getAttribute("username")==null){
			resp.sendRedirect("login.html");
		}else{
		fc.doFilter(reuqest, response,fc);//这里必须有一个else,不能直接是执行下一个Filter,因为如果未登陆,
那么敏感词过滤就不必再做,而且可以尝试不加else,你会发现,未登陆前留言会跳转到登陆界面,登陆之后再回到留言界面,
这时候count已经不满足count<filters.length,所以此时敏感词过滤将不会执行。
                }
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}
//WordFilter.java
package lewa;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class WordFilter implements Filter{

	private static Pattern pattern=null;
	public static String str=null;

	private void loadKeyWordProperties(){
		StringBuffer patternBuffer = new StringBuffer();
		try{
			InputStream in =WordFilter.class.getClassLoader().getResourceAsStream("words.properties");
			Properties properties = new Properties();
			properties.load(in);
			Enumeration<?> enu=properties.propertyNames();
			while(enu.hasMoreElements()){
				patternBuffer.append((String)enu.nextElement()+"|");
			}
			patternBuffer.deleteCharAt(patternBuffer.length()-1);
			pattern = Pattern.compile(new String(patternBuffer.toString().getBytes("ISO-8859-1"),"UTF-8"));
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	@Override
	public void init() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest reuqest, ServletResponse response,FilterChain fc)
			throws InstantiationException, IllegalAccessException, Exception {
		// TODO Auto-generated method stub
		loadKeyWordProperties();
		str=reuqest.getParameter("liuyan");
		try{
			Matcher m=pattern.matcher(str);
			str=m.replaceAll("**");
		}catch(Exception e){
			e.printStackTrace();
		}
		fc.doFilter(reuqest, response,fc);
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}
}

最后Servlet里的代码更改:

package lewa;

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

/**
 * Servlet implementation class Summary
 */
public class Summary extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public Summary() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		Filter filter=new EncodingFilter();
		FilterChain  fc=new FilterChain();
		try {
			filter.doFilter(request, response,fc);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		PrintWriter out=response.getWriter();
		HttpSession session=request.getSession();
		String name=(String) session.getAttribute("username");
		if(name!=null&&!"".equals(name)) {
			name=new String(name.getBytes("ISO-8859-1"),"UTF-8");
		}
		out.println("<html><head><title>留言板内容</title></head><body>");
		out.println("用户名:"+name);
		out.println("<br/>"+WordFilter.str+"</body></html>");
	}
}
 

自定义过滤器链的编写这个是源码的下载地址。

希望大家多多指教~~

Servlet学习笔记(八)—— 自定义过滤器的编写改进:自定义实现FilterChain,布布扣,bubuko.com

时间: 2024-10-13 11:22:45

Servlet学习笔记(八)—— 自定义过滤器的编写改进:自定义实现FilterChain的相关文章

Servlet学习笔记(六)—— 自定义过滤器的编写

Boss今天让我写一个类似BBS留言板的过滤器,要求对字符编码.登录权限.敏感词进行过滤操作. 总体分两模块: 一.过滤器 //Filter.java package lewa; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public interface Filter { public void init(); public void doFilter(ServletRequest reu

JavaWeb 后端 &lt;二&gt; 之 Servlet 学习笔记

JavaWeb 后端 <二> 之 Servlet 学习笔记 一.Servlet概述 1.什么是Servlet Servlet是一个运行在服务器端的Java小程序,通过HTTP协议用于接收来自客户端请求,并发出响应. 2.Servlet中的方法 public void service(ServletRequest req,ServletResponse res) throws ServletException,java.io.IOException ServletRequest req:代表着请

SERVLET 学习笔记

SERVLET 学习笔记 一.Servlet基本定义 Servlet是服务器端上面运行的一段小的java程序,一个servlet就是一个简答的java类.通常servlet都是通过请求和返回的模式来被访问的,客户端通过resuest请求,servlet则通过response来返回需要的内容. 二.Tomcat容器等级 Tomcat容器等级分为四个等级,由内向外分别是:context容器àSERVLET容器àHOST(主机)容器àENGINE(引擎)容器.其中,CONTEXT容器,一个CONTEX

Servlet学习笔记(七)—— JSP概述

1.Servlet两个缺陷: ①所有HTML标签必须包在Java字符串中,使得发送HTTP响应十分繁琐: ②所有文本和HTML标签都必须进行硬编码,即使对表示层做极其微小的修改,也需要重新编译. 2.注释: (1)JSP备注:<% %>,不会发送到浏览器,不能嵌套 (2)HTML备注:<!-- -->,不被容器处理,直接发送到浏览器,用途之一是标识JSP页面.在处理带有许多JSP片段的应用程序时,开发者通过查看HTML源代码,可以轻松查出某个HTML代码部分生成了那个JSP页面.

测试servlet学习笔记

操作方法: 1.新建工程: File-->new-->Java Project-->TestServlet(工程名称)-->Finish. 2.加载servlet-api.jar类包: TestServlet(右键)-->Build Path-->Configure Build Path-->Library -->Add External JAR Selection-->(浏览在tomcat的lib目录下找到servlet-api.jar选中后点击打开

angular学习笔记(八)

本篇介绍angular控制视图的显示和隐藏: 通过给元素添加ng-show属性或者ng-hide属性来控制视图的显示或隐藏: ng-show: 绑定的数据值为true时,显示元素,值为false时,隐藏元素 ng-hide: 绑定的数据值为true时,隐藏元素,值为false时,显示元素 (其实只要用到其中一个就可以了) 下面来看个简单的例子,点击按钮可以显示/隐藏元素: <!DOCTYPE html> <html ng-app> <head> <title>

Linux System Programming 学习笔记(八) 文件和目录管理

1. 文件和元数据 每个文件都是通过inode引用,每个inode索引节点都具有文件系统中唯一的inode number 一个inode索引节点是存储在Linux文件系统的磁盘介质上的物理对象,也是LInux内核通过数据结构表示的实体 inode存储相关联文件的元数据 ls -i 命令获取文件的inode number /* obtaining the metadata of a file */ #include <sys/types.h> #include <sys/stat.h>

马哥学习笔记八——LAMP编译安装之PHP及xcache

1.解决依赖关系: 请配置好yum源(可以是本地系统光盘)后执行如下命令: # yum -y groupinstall "X Software Development" 如果想让编译的php支持mcrypt扩展,此处还需要下载如下两个rpm包并安装之: libmcrypt-2.5.7-5.el5.i386.rpm libmcrypt-devel-2.5.7-5.el5.i386.rpm 2.编译安装php-5.4.13 首先下载源码包至本地目录. # tar xf php-5.4.13

Lua学习笔记(八):数据结构

table是Lua中唯一的数据结构,其他语言所提供的数据结构,如:arrays.records.lists.queues.sets等,Lua都是通过table来实现,并且在Lua中table很好的实现了这些数据结构. 1.数组 在Lua中通过整数下标访问table中元素,既是数组,并且数组大小不固定,可动态增长.通常我们初始化数组时,就间接地定义了数组的大小,例如: 1 a = {} -- new array 2 for i=1, 1000 do 3 a[i] = 0 4 end 5 6 --数