如图所示,消息在进入数据库之前,会进过多层过滤器,我们可以在过滤器中对消息进行数据处理
或者拦截
。而这每一个Filter都有自己的责任,串成了一个链条就是责任链。数据按照顺序一层层经过这些过滤器。
直接上代码
简单说一下需求:有一个消息经过filter1,filter2. filter1和filter2都为该消息添加一些自己的字符串。
import java.util.ArrayList;
import java.util.List;
public class FilterMain {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("hello world");
// 通过集合存储,将过滤器组合成一条责任链
List<Filter> filters = new ArrayList<>();
filters.add(new Filter1());
filters.add(new Filter2());
for (Filter f : filters) {
f.doFilter(msg);
}
System.out.println(msg); // hello world--经过filter1--经过filter2
}
}
class Msg{
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return msg;
}
}
interface Filter{
void doFilter(Msg m);
}
class Filter1 implements Filter{
@Override
public void doFilter(Msg m) {
m.setMsg(m.getMsg()+"--filter1");
}
}
class Filter2 implements Filter{
@Override
public void doFilter(Msg m) {
m.setMsg(m.getMsg()+"--filter2");
}
}
然后我们可以将Main方法中的
// 通过集合存储,将过滤器组合成一条责任链
List<Filter> filters = new ArrayList<>();
filters.add(new Filter1());
filters.add(new Filter2());
for (Filter f : filters) {
f.doFilter(msg);
}
抽离出来封装成一个FilterChain
具体代码如下
import java.util.ArrayList;
import java.util.List;
//使用FilterChain
public class FilterMain {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("hello world");
FilterChain fc = new FilterChain();
fc.add(new Filter1())
.add(new Filter2());
fc.doFilter(msg);
System.out.println(msg);
}
}
class Msg{
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return msg;
}
}
interface Filter{
void doFilter(Msg m);
}
class Filter1 implements Filter{
@Override
public void doFilter(Msg m) {
m.setMsg(m.getMsg()+"--filter1");
}
}
class Filter2 implements Filter{
@Override
public void doFilter(Msg m) {
m.setMsg(m.getMsg()+"--filter2");
}
}
class FilterChain implements Filter{
List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f){
filters.add(f);
return this;
}
public void doFilter(Msg m){
for (Filter f : filters) {
f.doFilter(m);
}
}
}
当然有时候我们并不需要,消息经过整个责任链,有可能在第一个过滤器就因为数据不符合直接返回了。这种情况该如何实现呢?
我们需要修改一下Filter的doFilter
,void
->boolean
具体代码如下
import java.util.ArrayList;
import java.util.List;
public class FilterMain {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("hello world");
FilterChain fc = new FilterChain();
fc.add(new Filter1()).add(new Filter2());
fc.doFilter(msg);
System.out.println(msg);
}
}
class Msg{
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return msg;
}
}
interface Filter{
boolean doFilter(Msg m);
}
class Filter1 implements Filter{
@Override
public boolean doFilter(Msg m) {
m.setMsg(m.getMsg()+"--filter1");
return true;
}
}
class Filter2 implements Filter{
@Override
public boolean doFilter(Msg m) {
m.setMsg(m.getMsg()+"--filter2");
return false;
}
}
class FilterChain implements Filter{
List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f){
filters.add(f);
return this;
}
public boolean doFilter(Msg m){
for (Filter f : filters) {
if(!f.doFilter(m)){ // 重点:判断只要有一个doFilter返回false就直接return false,不在继续执行下面的Filter
return false;
}
}
return true;
}
}
最后是模拟Servlet
的Filter
的实现:
首先需要了解一下java中的Filter帮我们做了哪些事。
首先是request
进来会经过Filter1,Filter2,Filter3然后进入到Servlet。而Servlet返回的时候会经过Filter3,FIlter2,Filter1,最终返回给客户端。这里很关键的一件事是,我们只写了一个过滤器链,确能够以123的顺序对request进行过滤,以321的顺序对response进行过滤。这是如何做到的呢?
直接上代码
package com.zxh.design.filter;
import java.util.ArrayList;
import java.util.List;
/**
* Created by zxh on 2022/1/10
*/
public class ServletFilterMain {
public static void main(String[] args) {
Request request = new Request();
request.str = "request";
Response response = new Response();
response.str = "response";
FilterChain chain = new FilterChain();
chain.add(new Filter1())
.add(new Filter2())
.add(new Filter3());
chain.doFilter(request,response);
System.out.println(request.str); // request--Filter1--Filter2--Filter3
System.out.println(response.str); // response--Filter3--Filter2--Filter1
}
}
interface Filter{
void doFilter(Request request,Response response,FilterChain filterChain);
}
class Request{
String str;
}
class Response{
String str;
}
class Filter1 implements Filter{
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str+"--Filter1";
// 这里进行一个递归调用,为了保证request是正序,response是倒叙。
// 对request的处理要放在chain.doFilter之前,对response的处理要放在之后
chain.doFilter(request,response);
response.str += "--Filter1"; // chain.doFilter执行结束后,response才有值,如果要对返回值进行处理需要在这里进行
}
}
class Filter2 implements Filter{
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str += "--Filter2";
chain.doFilter(request,response);
response.str += "--Filter2";
}
}
class Filter3 implements Filter{
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str += "--Filter3";
chain.doFilter(request,response);
response.str += "--Filter3";
}
}
// 该类封装了过滤器链由doFilter方法进控制调用
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 filter = filters.get(index);
index++;
filter.doFilter(request,response,this);
}
}
在Filter接口的doFilter的中新增了FilterChain 参数取消了返回值。我们将过滤器链的调用全部交给FilterChain。当我们调用chain.doFilter(request,response);
该方法就会帮我们调用当前Filter,并且index++将下标指向下一个Filter.