理解
责任链的执行序列是一环连着一环,后一环的执行依赖前一环的执行,层层递进.
流程图
组成部分
- 链条:负责承前启后;
- 链条上的环:执行业务逻辑,决定是否继续执行下一个环(有的情况由链条决定);
- 执行流:
- 前期:由外层到里层;
- 后期:由里层到外层
特点
- 链条上相邻的环之间会影响,影响入参和出参;
- 每个环负责相对独立的任务,比如有的负责字符编码设置,有的负责流的编码和解码(比如gzip),有的负责记录日志等
实例
一个简单的 demo
项目代码
链条类
public class DaoFilterChain {
private List<IFilter> filterList = new ArrayList<>();
private int index = 0;
private boolean hasAddDefaultFilter = false;
public DaoFilterChain addFilter(IFilter filter) {
if (hasAddDefaultFilter) {
throw new RuntimeException("自定义过滤器必须在默认过滤器之前添加");
}
this.filterList.add(filter);
return this;
}
/***
* 专门添加最基础的DaoFilter
* @param filter
* @return
*/
public DaoFilterChain addDefaultFilter(IFilter filter) {
this.filterList.add(filter);
hasAddDefaultFilter = true;
return this;
}
public void reset() {
this.index = 0;
}
private IFilter next() {
if (index == filterList.size()) {
return null;
}
IFilter filter = filterList.get(index);
index++;
return filter;
}
public void doFilter(DaoRequest request, DaoResponse response) {
IFilter filter = next();
if (null == filter) {
System.out.println("结束 index :" + index);
return;
}
filter.doFilter(request, response, this);
}
}
过滤器接口
public interface IFilter {
/***
* 最后一个过滤器一定是DefaultDaoFilter
* @param request
* @param response
* @param filterChain
*/
void doFilter(DaoRequest request, DaoResponse response, DaoFilterChain filterChain);
}
javax.servlet.Filter
过滤器核心方法 :
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException;
链条:org.apache.catalina.core.ApplicationFilterChain
源码见:
http://www.docjar.com/html/api/org/apache/catalina/core/ApplicationFilterChain.java.htmldoFilter 核心代码 (去掉了其他代码):
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
filter = filterConfig.getFilter();
filter.doFilter(request, response, this);
过滤器实例 :支持跨域
其他过滤器实例
租户拦截器
接口:
public interface IRequestFilter {
void doFilter(HttpFormContentRequestWrapper request, HttpServletResponse response, RequestFilterChain filterChain) throws IOException, ServletException;
}
链条类 RequestFilterChain
public class RequestFilterChain {
private List<IRequestFilter> filterList = new ArrayList<>();
private final static Logger logger = LoggerFactory.getLogger(RequestFilterChain.class);
private ThreadLocal<Integer> indexLocal = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
private ThreadLocal<Boolean> hasAddDefaultFilter = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return Boolean.FALSE;
}
};
public RequestFilterChain addFilter(IRequestFilter filter) {
if (hasAddDefaultFilter.get()) {
throw new RuntimeException("自定义过滤器必须在默认过滤器之前添加");
}
this.filterList.add(filter);
return this;
}
public RequestFilterChain removeFilter(IRequestFilter filter) {
this.filterList.remove(filter);
return this;
}
public RequestFilterChain addDefaultFilter(IRequestFilter filter) {
this.filterList.add(filter);
hasAddDefaultFilter.set(true);
// DefaultFormRequestWrapperFilter defaultDaoFilter = (DefaultFormRequestWrapperFilter) filter;
return this;
}
public void reset() {
indexLocal.set(0);
}
private IRequestFilter next() {
if (indexLocal.get() == filterList.size()) {
return null;
}
IRequestFilter filter = filterList.get(indexLocal.get());
// index++;
indexLocal.set(indexLocal.get() + 1);
return filter;
}
public void doFilter(HttpFormContentRequestWrapper request, HttpServletResponse response) throws IOException, ServletException {
IRequestFilter filter = next();
if (null == filter) {
return;
}
try {
filter.doFilter(request, response, this);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
MultipleTenantsFilter 做了什么
适用场景
- 同时有请求和应答的场景,例如HTTP请求,数据库查询;
- 映射层转化
- 需要决定是否中断流程的执行;
- 业务的执行分为多个中间环节,中间环节的个数可以定制;
和aop的区别
aop体现的是代理模式,实际是动态代理或 cglib
感想
- 责任链模式,依然符合开闭原则,比如由于业务的发展,需要添加新的逻辑,那么就可以增加一个过滤器,而不用修改原来的逻辑处理;
- 对于逻辑比较复杂,且容易变动的逻辑,可以充分使用责任链模式,把相对聚合的逻辑抽取出来,作为一个个环,后面增加新的逻辑只需要增加新的环即可,也可以根据实际需求修改链条上环的顺序。