security是一个基于过滤器拦截器实现的框架。它内置了十几个过滤器(看的头大)。所以说过滤器在这个框架中扮演了不可或缺的角色。过滤器链的执行类似于一个净水器,你发的请求就像不干净的水,然后净水器中的每一环都会对水进行过滤,其中有过滤金属的,过滤有害物质的等等,这些过滤组件依照一定的顺序组合起来使用就能达到很好的效果。过滤器的执行逻辑就是基于:责任链模式。
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。它可以使数据的发送者和接收者解耦,数据沿着责任链传递,直到有一个对象处理了它为止。
责任链模式有两种实现方式:一种基于单链表实现,一种依靠集合实现。第一种比较好理解,第二种使用的更广泛,FilterChain也是使用这种方式。光看说明可能会有点懵,上代码。
首先我们需要一个要被处理的数据,这个数据在实际开发中有可能是请求或是其他的。
public interface DataResource {void doSomething();}
public class DataResourceImpl implements DataResource{//业务数据private Integer data = 0;@Overridepublic void doSomething() {data++;}public Integer getData(){return data;}}
一、单链表方式:
当然,用单链表实现的前提需要搞懂单链表这个简单的数据结构~
public abstract class AbstractHandler {private AbstractHandler next;/*** 执行逻辑*/public abstract void handleRequest(DataResource dataResource);public AbstractHandler getNext(){return next;}public void setNext(AbstractHandler next){this.next = next;}}
定义一个抽象类,我定义的过滤节点都会继承它。
public class Handler extends AbstractHandler{@Overridepublic void handleRequest(DataResource dataResource) {dataResource.doSomething();}}
实现类重写处理方法。
public class StrongerHandler extends AbstractHandler{@Overridepublic void handleRequest(DataResource dataResource) {for (int i = 0; i < 5; i++) {dataResource.doSomething();}}}
再搞一个实现类,他会对被处理类的方法执行5次。
public class LinkHandlerUtil {private static AbstractHandler head = new Handler();/*** 功能描述 :遍历链表添加节点* @author HKH* @date* @param* @return*/public static void addHandler(AbstractHandler handler){AbstractHandler temp = head;while(true){if(temp.getNext()==null){temp.setNext(handler);break;}temp = temp.getNext();}}/*** 功能描述 :依次执行所有节点* @author HKH* @date* @param* @return*/public static void HandleAll(DataResource dataResource){AbstractHandler temp ;if(head.getNext()==null){System.out.println("这是个空链表,请先添加节点。");return;}temp = head.getNext();while (true){if(temp==null){System.out.println("所有节点执行完毕,退出。");break;}temp.handleRequest(dataResource);temp = temp.getNext();}}}
由于我没有在过滤节点处实现链表式的调用,所以我这里写了一个工具类,该类包含对过滤链的添加和调用方法。
public class Test {public static void main(String[] args) {AbstractHandler handler = new Handler();AbstractHandler strong = new StrongerHandler();LinkHandlerUtil.addHandler(handler);LinkHandlerUtil.addHandler(strong);DataResourceImpl dataResource = new DataResourceImpl();LinkHandlerUtil.HandleAll(dataResource);System.out.println(dataResource.getData());}}
二、通过处理器集合来定义处理顺序:
这种方法的好处就是可以集中维护所有节点。
/*** @program: JavaSe* @description: 责任链接口,对责任链进行抽象* @author: HKH* @create: 2019-11-28 14:43**/public interface HandlerChain {/*** 功能描述 :增加责任链节点* @author HKH* @date* @param* @return*/void addHandler(Handler handler);/*** 功能描述 :执行责任链* @author HKH* @date* @param* @return*/void doChain(DataResource dataResource);}
对过滤器链进行抽象,其拥有增加节点和执行方法。
public class ListHandlerChainImpl implements HandlerChain{//当前handler的指针private Integer index = 0;//存放handler的集合private List<Handler> handlers = new ArrayList<>();@Overridepublic void addHandler(Handler handler) {handlers.add(handler);}@Overridepublic void doChain(DataResource dataResource) {int size = handlers.size();if(index<size){Handler handler = handlers.get(index++);handler.doHandler(dataResource,this);}}}
ListHandlerChainImpl 负责维护调用链条的顺序,这里实现用List来管理Handler。不过请注意这个Handler跟我之前定义的Handler有所不同,继续往下看。
public interface Handler{void doHandler(DataResource dataResource, HandlerChain handlerChain);}
public class HandlerImpl implements Handler{@Overridepublic void doHandler(DataResource dataResource, HandlerChain handlerChain) {//处理业务DataResourceImpl dataResourceImpl = (DataResourceImpl) dataResource;dataResourceImpl.doSomething();handlerChain.doChain(dataResource);}}
根据代码我们可以看出,该Handler可以决定是否继续向下执行,是不是和我们学过的过滤器越来越像了!而且处理完方法后会调回到HandlerChain处继续遍历下一个节点。我们来测试一下。
public class Test {public static void main(String[] args) {HandlerChain handlerChain = new ListHandlerChainImpl();handlerChain.addHandler(new HandlerImpl());handlerChain.addHandler(new HandlerImpl());DataResourceImpl dataResource = new DataResourceImpl();handlerChain.doChain(dataResource);System.out.println(dataResource.getData());}}
