1、责任链模式是适用于对一个对象的链式加工处理,在处理的链中可以随时按需终止。非常使用处理http请求。
2、模式优点
易于扩展:这点对于设计框架特别重要,spring框架给客户提供了Filter接口,客户实现并注册,spring框架启动的时候就可以将客户的实现扫描加载到框架中。
结构清晰,方便理解,易于阅读:这点特别有利于项目的维护。
3、实现方法
先看在java扩展包中servert定义的责任链接口和Filter接口
package javax.servlet;
public interface FilterChain {
//request:http请求 response: http响应
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
public interface Filter {
public void init(FilterConfig filterConfig) throws ServletException;
//业务逻辑实现函数
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public void destroy();
}
通过idea工具查看FilterChain的实现类:
先看在Tomcat 中的实现类ApplicationFilterChain:
class ApplicationFilterChain implements FilterChain {
//使用threadlocal可以看出ApplicationFilterChain是线程共享的,是线程安全的
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
//Filter配置数组,ApplicationFilterConfig组合Filter相关的功能,提供了Filter的功能
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
//每次Filter数组增加的数量,addFilter当fiter数组容量不够的时候,先扩容,再copy,再加入新filter
public static final int INCREMENT = 10;
//当前处理Filter的位置索引
private int pos = 0;
责任链Fiters的数量
private int n = 0;
//实际工作的doFilter函数,删除业务代码,保留责任链处理流程
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
//如果pos<n,表示还有Filter处理request
if (pos < n) {
//获取对应的Filter,位置指数加1,然后调用Filter的doFilter业务处理函数
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = filterConfig.getFilter();
filter.doFilter(request, response, this);
}
//责任链执行完毕,最后还要调用servlet处理request请求
//这里的servlet,根据request中的url映射到常见的有DispathcherServlet,DruidViewServlet
servlet.service(request, response);
}
// 增加filter函数
void addFilter(ApplicationFilterConfig filterConfig) {
//避免加入重复的filter
for (ApplicationFilterConfig filter : filters)
if (filter == filterConfig)
return;
//如果filter数组已经满了,怎执行扩容,复制原filters数组到新数组,最后将新filter加到数组末尾
if (n == filters.length) {
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
}
1、从上面代码可以看出,ApplicationFilterChain用动态数组保存Filter,按实际需要扩展数组,可以减少内存资源的消耗。
4、进阶:
用链表实现,并给filter添加排序功能,不是简单的将新Filter加入到尾部。
另外也可以用链表实现:想比较与动态数组扩容方式,避免了数组扩容带来的复制时间开销。
package com.dengfangwen.org;
public class FilterChain {
Filter header;
public void doFilter(Object o) {
Filter f = header;
while (f != null) {
f.doFilter(o);
f = f.next;
}
}
public void addFilter(Filter f) {
if (header == null) {
f.next = null;
header = f;
} else if (f.order <= header.order) {
//需要插入到头节点位置
f.next = header;
header = f;
} else {
Filter pre = header;
Filter cur = pre.next;
while (cur != null) {
if (f.order <= cur.order) {
//插入到当前位置
pre.next = f;
f.next = cur;
} else {
pre = cur;
cur = pre.next;
}
}
//需要加到尾部
if (cur == null) {
f.next = null;
pre.next = f;
}
}
}
public static void main(String[] argc) {
FilterChain fc = new FilterChain();
fc.addFilter(new FilterImpl("Filter 2", 2, null));
fc.addFilter(new FilterImpl("Filter 3", 3, null));
fc.addFilter(new FilterImpl("Filter 1", 1, null));
fc.doFilter(new Object());
}
}
abstract class Filter {
protected Filter next;
protected String filterName;
protected int order;
abstract void doFilter(Object o);
Filter(String name, int order, Filter next) {
filterName = name;
this.next = next;
this.order = order;
}
}
class FilterImpl extends Filter {
FilterImpl(String name, int order, Filter next) {
super(name, order, next);
}
public void doFilter(Object o) {
System.out.println("filter " + (filterName != null ? filterName : "null") + " order: " + order + " in process");
}
}
filter 按照order 顺序处理: