设计模式之责任链模式
初始化
场景描述
存入数据库之前,过滤用户输入的文字。
public class Servlet_Main {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问 ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
String r = msg.getMsg();
r = r.replace("<", "[");
r = r.replace(">", "]");
r = r.replace("996", "955");
msg.setMsg(r);
System.out.println(r);
}
}
class Msg {
String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\'' +
'}';
}
}
- 输出结果
大家好:),[script],欢迎访问 ,大家都是955
经过两步处理, 敏感信息已经过滤掉, 日后如果有过滤非常多的消息, 都写在一块的话, 代码量非常大 , 要修改现有代码 , 可扩展性不好。
过滤器
由于处理字符串的逻辑会变化, 所以封装变化,将变化的代码进行封装处理。
package com.cyc.design.cor.servlet.v1;
public class Servlet_Main {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问 ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
new HtmlFilter().doFilter(msg);
new SensitiveFilter().doFilter(msg);
System.out.println(msg);
}
}
class Msg {
String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\'' +
'}';
}
}
//新建一个filter接口, 所有过滤逻辑实现该接口
interface Filter {
void doFilter(Msg msg);
}
class HtmlFilter implements Filter {
@Override
public void doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace("<", "[");
r = r.replace(">", "]");
msg.setMsg(r);
}
}
class SensitiveFilter implements Filter {
@Override
public void doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace("996", "955");
msg.setMsg(r);
}
}
但是这种依然有问题, 如果有了新的过滤逻辑 , 还是要改动原来的代码
优化过滤器
新建一个Filter的list , 将需要执行的过滤器添加至该list中, 遍历list , 执行过滤逻辑
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问 ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
List<Filter> filterList = new ArrayList<>();
filterList.add(new HtmlFilter());
filterList.add(new SensitiveFilter());
for (Filter filter : filterList) {
filter.doFilter(msg);
}
System.out.println(msg);
}
此时的filter向一个链条 , 每个filter执行各自的逻辑 , 如果有新的filter进来,就可以直接添加该filter,这种就叫责任链模式。
FilterChain
以上只是一个简单的调用链条,距离真正的责任链还有距离。
新建一个FilterChain , 将这些过滤器串成一条链
class FilterChain {
List<Filter> filterList = new ArrayList<>();
public void add(Filter f) {
filterList.add(f);
}
//在这个链条上的所有filter都跑一遍
public void doFilter(Msg msg) {
for (Filter filter : filterList) {
filter.doFilter(msg);
}
}
}
main方法
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问baidu.com ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
FilterChain fc = new FilterChain();
fc.add(new HtmlFilter());
fc.add(new SensitiveFilter());
fc.doFilter(msg);
System.out.println(msg);
}
这里可以优化代码
改造FilterChain
class FilterChain {
List<Filter> filterList = new ArrayList<>();
/**
* 每次调用都返回新的FilterChain
*/
public FilterChain add(Filter f) {
filterList.add(f);
return this;
}
//在这个链条上的所有filter都跑一遍
public void doFilter(Msg msg) {
for (Filter filter : filterList) {
filter.doFilter(msg);
}
}
}
main方法
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问baidu.com ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
FilterChain fc = new FilterChain();
//链式编程
fc.add(new HtmlFilter()).add(new SensitiveFilter());
fc.doFilter(msg);
System.out.println(msg);
}
当写完这个FilterChain之后 , 如果想要和别的FilterChain连起来应该怎么做?
继续新建Filter
/**
* 替换笑脸
*/
class FaceFilter implements Filter {
@Override
public void doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace(":)", "*_*");
msg.setMsg(r);
}
}
/**
* 补全url
*/
class UrlFilter implements Filter {
@Override
public void doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace("baidu.com", "http://www.baidu.com");
msg.setMsg(r);
}
}
为了将两个链条连接借来 , FilterChain同样实现Filter接口。
main 方法如下
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问baidu.com ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
FilterChain fc = new FilterChain();
//链式编程
fc.add(new HtmlFilter()).add(new SensitiveFilter());
//新建一个FilterChain fc2, 将他和fc连接起来
FilterChain fc2 = new FilterChain();
fc2.add(new FaceFilter()).add(new UrlFilter());
//这里直接将fc2加入到fc中, 达到链式调用的目的
fc.add(fc2);
fc.doFilter(msg);
System.out.println(msg);
}
自定义过滤
新需求: 由FilterChain中的某一个Filter决定链条是否继续 , 假如一个有四个Filter, 当执行到了Filter2之后 , 经过处理 , 不再继续执行链条
方案一: 添加if 判断 , 但是这样的话, 每增加一个Filter , 就要加一个if 判断 , 可扩展性较差
方案二: 修改Filter接口, 将doFilter的返回设为booean类型 , 当返回true时, 就继续执行, 当返回为false , 不再执行 , 链条到此结束
完整代码
public class Servlet_Main {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问baidu.com ,大家都是996 ");
//处理msg, 过滤敏感字,<,> 和996
FilterChain fc = new FilterChain();
//链式编程
fc.add(new HtmlFilter()).add(new SensitiveFilter());
//新建一个FilterChain fc2, 将他和fc连接起来
FilterChain fc2 = new FilterChain();
fc2.add(new FaceFilter()).add(new UrlFilter());
//这里直接将fc2加入到fc中, 达到链式调用的目的
fc.add(fc2);
fc.doFilter(msg);
System.out.println(msg);
}
}
class Msg {
String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\'' +
'}';
}
}
//新建一个filter接口, 所有过滤逻辑实现该接口
interface Filter {
boolean doFilter(Msg msg);
}
class HtmlFilter implements Filter {
@Override
public boolean doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace("<", "[");
r = r.replace(">", "]");
msg.setMsg(r);
return true;
}
}
/**
* 替换敏感字996
*/
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace("996", "955");
msg.setMsg(r);
return false;
}
}
/**
* 替换笑脸
*/
class FaceFilter implements Filter {
@Override
public boolean doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace(":)", "*_*");
msg.setMsg(r);
return true;
}
}
/**
* 补全url
*/
class UrlFilter implements Filter {
@Override
public boolean doFilter(Msg msg) {
String r = msg.getMsg();
r = r.replace("baidu.com", "http://www.baidu.com");
msg.setMsg(r);
return true;
}
}
class FilterChain implements Filter{
List<Filter> filterList = new ArrayList<>();
/**
* 每次调用都返回新的FilterChain
*/
public FilterChain add(Filter f) {
filterList.add(f);
return this;
}
//在这个链条上的所有filter都跑一遍
public boolean doFilter(Msg msg) {
for (Filter filter : filterList) {
if (!filter.doFilter(msg)) {
//当某一个Filter返回false后, 就结束该链条, 不再执行
return false;
}
}
return true;
}
}
由于在执行SensitiveFilter后, 返回了false , 所以之后的过滤器应该是都不再执行, 查看输出结果如下
Msg{msg='大家好:),[script],欢迎访问baidu.com ,大家都是955 '}
顺序过滤
需求: 参照javax.servlet.Filter和javax.servlet.FilterChain写一个过滤链路
目前有两个过滤器 , SensitiveFilter和HtmlFilter , 要求是request请求进来之后 , 先经过SensitiveFilter, 再经过HtmlFilter , 处理完成后 , 返回response先经过HtmlFilter ,再经过SensitiveFilter
基础代码
public class Servlet_Main {
public static void main(String[] args) {
Request request = new Request();
request.str = "大家好:),<script>,欢迎访问baidu.com ,大家都是996 ";
//处理msg, 过滤敏感字,<,> 和996
Response response = new Response();
response.str = "";
FilterChain chain = new FilterChain();
chain.add(new HtmlFilter()).add(new SensitiveFilter());
chain.doFilter(request, response);
System.out.println(request.str);
}
}
class Request {
String str;
}
class Response {
String str;
}
//新建一个filter接口, 所有过滤逻辑实现该接口
interface Filter {
boolean doFilter(Request request,Response response);
}
class HtmlFilter implements Filter {
@Override
public boolean doFilter(Request request,Response response) {
request.str = request.str.replaceAll("<", "[").replaceAll(">", "]");
return true;
}
}
/**
* 替换敏感字996
*/
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request,Response response) {
request.str = request.str.replaceAll("996", "955");
return true;
}
}
class FilterChain implements Filter{
List<Filter> filterList = new ArrayList<>();
/**
* 每次调用都返回新的FilterChain
*/
public FilterChain add(Filter f) {
filterList.add(f);
return this;
}
//在这个链条上的所有filter都跑一遍
public boolean doFilter(Request request,Response response) {
for(Filter f : filterList ){
f.doFilter(request, response);
}
return true;
}
}
用最直观的方式处理response
直接将response的处理放在request的下面
public class Servlet_Main {
public static void main(String[] args) {
Request request = new Request();
request.str = "大家好:),<script>,欢迎访问baidu.com ,大家都是996 ";
Response response = new Response();
response.str = "response";
FilterChain chain = new FilterChain();
chain.add(new HTMLFilter()).add(new SensitiveFilter());
chain.doFilter(request, response);
System.out.println(request.str);
System.out.println(response.str);
}
}
interface Filter {
boolean doFilter(Request request, Response response);
}
class HTMLFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
request.str = request.str.replaceAll("<", "[").replaceAll(">", "]");
response.str += "--HTMLFilter()";
return true;
}
}
class Request {
String str;
}
class Response {
String str;
}
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
request.str = request.str.replaceAll("996", "955");
response.str += "--SensitiveFilter()";
return true;
}
}
class FilterChain implements Filter {
List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
public boolean doFilter(Request request, Response response) {
for(Filter f : filters ){
f.doFilter(request, response);
}
return true;
}
}
查看结果
大家好:),[script],欢迎访问baidu.com ,大家都是955
response--HTMLFilter()--SensitiveFilter()
可以看到request请求 , 是按照顺序处理了, 但是response却没有 , response返回应该先经过sensitiveFilter过滤器, 然后再经过HTMLFilter过滤器, 输出结果应为response–SensitiveFilter()–HTMLFilter() 才对
继续优化
在filterChain中处理加入位置的记录
同时在filter中加入第三个参数
package com.cyc.design.cor.servlet.v3;
import java.util.ArrayList;
import java.util.List;
public class Servlet_Main {
public static void main(String[] args) {
Request request = new Request();
request.str = "大家好:),<script>,欢迎访问baidu.com ,大家都是996 ";
Response response = new Response();
response.str = "response";
FilterChain chain = new FilterChain();
chain.add(new HTMLFilter()).add(new SensitiveFilter());
chain.doFilter(request, response, chain);
System.out.println(request.str);
System.out.println(response.str);
}
}
interface Filter {
boolean doFilter(Request request, Response response, FilterChain chain);
}
class HTMLFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replaceAll("<", "[").replaceAll(">", "]") + "HTMLFilter()";
//这里如果调用chain.doFilter, 程序就会继续执行过滤, 否则, 执行到这里就会结束
chain.doFilter(request, response, chain);
//先走完request的请求后 , 才开始执行response的过滤逻辑
response.str += "--HTMLFilter()";
return true;
}
}
class Request {
String str;
}
class Response {
String str;
}
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replaceAll("996", "955") + " SensitiveFilter()";
chain.doFilter(request, response, chain);
response.str += "--SensitiveFilter()";
return true;
}
}
class FilterChain implements Filter {
List<Filter> filters = new ArrayList<>();
int index = 0;
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
public boolean doFilter(Request request, Response response, FilterChain chain) {
if (index == filters.size()) return false;
Filter f = filters.get(index);
index++;
return f.doFilter(request, response, chain);
}
}
这里采用递归的方式
模拟Servlet.Filter
完全模拟Serverlet中的FilterChain
servelet.filter, spring mvc, structs 2 采用的就是这种方式
package com.cyc.design.cor.servlet.v4;
import java.util.ArrayList;
import java.util.List;
public class Servlet_Main {
public static void main(String[] args) {
Request request = new Request();
request.str = "大家好:),<script>,欢迎访问baidu.com ,大家都是996 ";
Response response = new Response();
response.str = "response";
FilterChain chain = new FilterChain();
chain.add(new HTMLFilter()).add(new SensitiveFilter());
chain.doFilter(request, response);
System.out.println(request.str);
System.out.println(response.str);
}
}
interface Filter {
void doFilter(Request request, Response response, FilterChain chain);
}
class HTMLFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replaceAll("<", "[").replaceAll(">", "]") + "HTMLFilter()";
chain.doFilter(request, response);
response.str += "--HTMLFilter()";
}
}
class Request {
String str;
}
class Response {
String str;
}
class SensitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replaceAll("996", "955") + " SensitiveFilter()";
chain.doFilter(request, response);
response.str += "--SensitiveFilter()";
}
}
class FilterChain {
List<Filter> filters = new ArrayList<>();
int index = 0;
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
public void doFilter(Request request, Response response) {
//判断当前执行的阶段
if (index == filters.size()) return;
Filter f = filters.get(index);
index++;
//将this(当前对象)传进去, 继续过滤
f.doFilter(request, response, this);
}
}