责任链学习笔记


对于一个一些逻辑操作如敏感字符的过滤,可以写在一个java类中完成,对对于敏感词汇过滤的规则也是在不断增加和变化的,如果写在一个类中就要不断的修改这个类,维护难度是相当巨大的。对于这个问题可以是责任链模式进行很好的解决,对于一个过滤规则就建立一个类,过滤完之后,就交给下一个类的规则进行过滤,这样做的好处是,对于字符的过滤规则可以在配置文件中指定,对于一些规则的修改不会影响到其他的规则,若要添加新的规则只需添加新的过滤类即可。可以通过以下简图描述。下图是对请求和返回都进行了过滤,关键是chain.doFilter要放在请求和返回之间,在请求过滤完成后再过滤返回。


一、主要抽象出来的元素。

1、Handler(责任链中具体的责任处理,可以是filter等)

2、chain使责任可以向下传递的链


二 、实现

对于这个模式以java web中的filter进行一个简单的实现

1、定义 filter接口,使每个过滤器有共同的行为。

package com.akwolf.chain;

public interface Filter {
	
	// 每个filter都有过滤的行为
	public void doFilter(Request request,Response response,FilterChain chain) ;
}



2、定义chain,使责任操作(过滤能够传递下去)

package com.akwolf.chain;

public interface FilterChain {
	// 传递
	public void doFilter(Request request,Response response) ;
}


3、对于chain肯定有其具体的实现类,以完成具体的链式传递规则,javaweb中filter的实现可参看ApplicationFilterChain
package com.akwolf.chain;

import java.util.ArrayList;
import java.util.List;

public class FilterChainImpl implements FilterChain {
	private int index ;
	
	private List<Filter> list ;
	
	public FilterChainImpl(){
		list = new ArrayList<Filter>() ;
	}
	
	// 添加需要传递的链项目
	public FilterChainImpl addFilter(Filter filter){
		list.add(filter) ;
		return this ;
	}

	@Override
	public void doFilter(Request request, Response response) {
		if(index>=list.size()) return ;
		// 取得链中的过滤器
		Filter filter = list.get(index++) ;
		// 委派到具体的过滤器进行过滤,filter 具体的过滤逻辑
		filter.doFilter(request, response, this) ;
	}

}

4、模拟web中request,response,这里进行编码的设置(很常用的操作)。

package com.akwolf.chain;

public class Request {
	private String encoding ;

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
	
}


package com.akwolf.chain;

public class Response {
	private String encoding ;

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
	
	
}

5、编写两个模拟编码设置的过滤器
package com.akwolf.chain.custom;

import com.akwolf.chain.Filter;
import com.akwolf.chain.FilterChain;
import com.akwolf.chain.Request;
import com.akwolf.chain.Response;

public class GBKFilter implements Filter {

	@Override
	public void doFilter(Request request, Response response, FilterChain chain) {
		request.setEncoding("GBK") ;
		System.out.println("GBK-1");
		chain.doFilter(request, response) ;
		// 在过滤完请求后,在服务器返回时对返回进行过滤的操作
		response.setEncoding("GBK") ;
		System.out.println("GBK-2");

	}

}

package com.akwolf.chain.custom;

import com.akwolf.chain.Filter;
import com.akwolf.chain.FilterChain;
import com.akwolf.chain.Request;
import com.akwolf.chain.Response;

public class UTF8Filter implements Filter {

	@Override
	public void doFilter(Request request, Response response, FilterChain chain) {
		request.setEncoding("UTF-8") ;
		System.out.println("UTF-8-1");
		chain.doFilter(request, response) ;
		response.setEncoding("UTF-8") ;
		System.out.println("UTF-8-2");
	}

}

6、测试。起始测试中的这些操作在tommat中随着server的启动自动完成,如filter的初始化,是通过查找web.xml中的配置文件进行相应的初始化并设置到FilterChain中。

package com.akwolf.chain;

import com.akwolf.chain.custom.UTF8Filter;
import com.akwolf.chain.custom.GBKFilter;

public class Main {

	// 充当服务器启动时,加载web.xml初始化filterchain的实现类设置filter
	public static void main(String[] args) {
		UTF8Filter encodingFilter = new UTF8Filter() ;
		GBKFilter gbkFilter = new GBKFilter() ;
		
		FilterChainImpl chain = new FilterChainImpl() ;
		chain.addFilter(encodingFilter) ;
		chain.addFilter(gbkFilter) ;
		
		Request request = new Request() ;
		Response response = new Response() ;
		
		chain.doFilter(request, response) ;
		System.out.println(request.getEncoding());
		System.out.println(response.getEncoding());
	}

}

看一下结果,大功告成,解释这个结果,顺序是    [UTF-8-1--->GBK-1--->GBK-2--->UTF-8-2],请求时过滤的顺序与返回时过滤的顺序刚好相反。结合一下队列的原理(Queue)就很好理解。就到这,睡觉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值