概述:责任链模式,我们最常见的就是拦截器、过滤器。其中:拦截器、过滤器实现方式一样,并无本质区别,换汤不换药的。
举例说明:
String msg="大家好:),<script> 被就业,敏感,一个人学习到深夜";
要求:
1、把上面这句话中的特殊字符(前后尖括号)、笑脸:)、特殊敏感词汇(“敏感”),分别用不同的过滤器给过滤掉,并输出到控制台。
2、在实现上述功能的基础上,逆向调用责任链中的方法,逆向处理服务器响应数据。例如:服务器返回的信息是“response”。
即是:处理request时,依次调用 过滤器 A ---> B ----> C.处理Response时,依次调用 过滤器 C ---> B ----> A
具体实现如下:
一:先实现第一个Demo (代码都写在 包com.xp.chain.responsibility.demo1 中)
1、创建过滤类接口,及其实现类:
//过滤类/拦截器超类
interface SuperFilter {
public String doFilter(String str);
}
public class SonHtmlFilter implements SuperFilter {
@Override
public String doFilter(String str) {
return str.replace("<", "[").replace(">", "]");
}
}
public class SonFaceFilter implements SuperFilter {
@Override
public String doFilter(String str) {
return str.replace(":)", "^_^");
}
}
public class SonSensitiveFilter implements SuperFilter {
@Override
public String doFilter(String str) {
return str.replace("敏感", "**");
}
}
2、创建过滤类的容器,也就是所谓的责任链容器,并让容器本身也实现SuperFilter接口。
//过滤链条类(名字是汉语拼音,为了区分版本二的ChainFilter)
//该类即是过滤器接口和拦截器子类(实现类)的中间人,该类也继承了过滤器接口。(本身即是过滤器,同时还可以作为过滤器的容器)
public class LianTiaoFilter implements SuperFilter {
List<SuperFilter> filters=new ArrayList<SuperFilter>();
@Override
public String doFilter(String str) {
//循环遍历出各个过滤类的具体实现类,并执行过滤方法
for (SuperFilter superFilter : filters) {
str=superFilter.doFilter(str);
}
return str;
}
//提供容器扩展方法,remove暂不考虑
public LianTiaoFilter addFilter(SuperFilter filter) {
filters.add(filter);
return this;//返回过滤器本身
}
}
3、创建测试类,并在Main方法中,测试Demo结果
public class MainTest {
public static void main(String[] args) {
String msg="大家好:),<script> 被就业,敏感,一个人学习到深夜";
LianTiaoFilter filters=new LianTiaoFilter();
filters.addFilter(new SonHtmlFilter()).addFilter(new SonFaceFilter()).addFilter(new SonSensitiveFilter());//正因为容器本身实现了过滤器父类接口,所以可以连着写
String string=filters.doFilter(msg);
System.out.println(string);
}
}
4、控制台输出结果如下:
大家好^_^,[script] 被就业,**,一个人学习到深夜
二:第二个Demo (代码都写在 包com.xp.chain.responsibility.demo2 中)。
注:前几个步骤和Demo1非常类似,比较难以理解的是,在同一个过滤器内,同时处理请求数据和返回数据。这个比较难,拿到代码后,打断点,就可以发现其中的奥妙。
1、创建Request类和Response类,为了模拟servler的底层实现。
//请求类
public class Request {
public String requestStr;
public String getRequestStr() {
return requestStr;
}
public void setRequestStr(String requestStr) {
this.requestStr = requestStr;
}
}
//响应类
public class Response {
public String responseStr;
public String getResponseStr() {
return responseStr;
}
public void setResponseStr(String responseStr) {
this.responseStr = responseStr;
}
}
2、创建过滤类父类和其实现类(代码看着长,里面的逻辑比较简单,自己打断点尝试一下)
interface Filter {
void doFilter(Request request,Response response,ChainFilter chain);
}
//Html标签过滤类
public class HtmlFilter implements Filter {
@Override
public void doFilter(Request request, Response response, ChainFilter chain) {
request.requestStr=request.requestStr.replace("<", "[").replace(">", "]")+"---HtmlFiter()";//添加尾巴为了方便看执行结果
//循环调用,处理request信息,直至结束后,才会执行下面response的代码。通过打断点调试可以看一下
chain.doFilter(request, response, chain);
response.responseStr+="---HtmlFiter()";//添加尾巴为了方便看执行结果
}
}
//特殊符号过滤类
public class FaceFilter implements Filter {
@Override
public void doFilter(Request request, Response response, ChainFilter chain) {
request.requestStr=request.requestStr.replace(":)", "^_^")+"---FaceFilter()";
//循环调用,处理request信息,直至结束后,才会执行下面response的代码。通过打断点调试可以看一下
chain.doFilter(request, response, chain);
response.responseStr+="---FaceFilter()";
}
}
//敏感词汇过滤类
public class SensitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response, ChainFilter chain) {
request.requestStr=request.requestStr.replace("敏感", "**")+"---SensitiveFilter()";
//循环调用,处理request信息,直至结束后,才会执行下面response的代码。通过打断点调试可以看一下
chain.doFilter(request, response, chain);
response.responseStr+="---SensitiveFilter()";
}
}
注:细心的小伙伴,会很好奇(自己可以尝试调换顺序后运行一下):
chain.doFilter(request, response, chain);
response.responseStr+="---HtmlFiter()";
上述这两行代码调换顺序后,会发生什么后果。(后果是:达不到逆向调用过滤类处理相应数据)
3、创建过滤器容器,下面这段代码比较绕口。可以打断点看一下。
public class ChainFilter implements Filter {
List<Filter> filters=new ArrayList<Filter>();
int index = 0;
@Override
public void doFilter(Request request, Response response, ChainFilter chain) {
if (index==filters.size()) {
return;
}
Filter filter = filters.get(index);
index ++;
filter.doFilter(request, response, chain);
}
public ChainFilter addFilter(Filter filter) {
this.filters.add(filter);
return this;
}
}
4、创建测试类,测试Demo运行结果。
public class MainFilter {
/**
* 该测试方法目的,正向过滤请求数据的同时,反向处理响应数据
* @param args
*/
public static void main(String[] args) {
String msg="大家好:),<script> 被就业,敏感,一个人学习到深夜";
ChainFilter filters=new ChainFilter();
filters.addFilter(new HtmlFilter()).addFilter(new FaceFilter()).addFilter(new SensitiveFilter());
Request request=new Request();
Response response=new Response();
request.setRequestStr(msg);
response.setResponseStr("response");
filters.doFilter(request, response, filters);
System.out.println(request.getRequestStr());
System.out.println(response.getResponseStr());
}
}
5、运行结果如下:
大家好^_^,[script] 被就业,**,一个人学习到深夜---HtmlFiter()---FaceFilter()---SensitiveFilter()
response---SensitiveFilter()---FaceFilter()---HtmlFiter()
后记:
这个例子,即使听马士兵老师的视频课,也比较生涩难懂。拿到代码后,自己多琢磨一下,打断点运行一下。并参考下图,领会其中的精髓。