了解

責任鍊的執行序列是一環連着一環,後一環的執行依賴前一環的執行,層層遞進.
流程圖
組成部分
- 鍊條:負責承前啟後;
- 鍊條上的環:執行業務邏輯,決定是否繼續執行下一個環(有的情況由鍊條決定);
- 執行流:
- 前期:由外層到裡層;
- 後期:由裡層到外層
特點
- 鍊條上相鄰的環之間會影響,影響入參和出參;
- 每個環負責相對獨立的任務,比如有的負責字元編碼設定,有的負責流的編碼和解碼(比如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
感想
- 責任鍊模式,依然符合開閉原則,比如由于業務的發展,需要添加新的邏輯,那麼就可以增加一個過濾器,而不用修改原來的邏輯處理;
- 對于邏輯比較複雜,且容易變動的邏輯,可以充分使用責任鍊模式,把相對聚合的邏輯抽取出來,作為一個個環,後面增加新的邏輯隻需要增加新的環即可,也可以根據實際需求修改鍊條上環的順序。