对于一个一些逻辑操作如敏感字符的过滤,可以写在一个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) ;
}
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)就很好理解。就到这,睡觉了。