总览:
关键代码doFIlter,处理逻辑如下:
- 挨个的执行Filter的逻辑;
- 判断pos=n的时候,发现是最后一个FIlter;
- 开始执行servlet的操作,处理request和response;
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if( Globals.IS_SECURITY_ENABLED ) {
// 非关键代码
} else {
// 关键代码
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
// 记录过滤后的请求最后状态
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
// 省略...
} else {
// 执行真正的Servlet
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
addFilter方法,10为步数进行扩容操作
void addFilter(ApplicationFilterConfig filterConfig) {
// Prevent the same filter being added multiple times
for(ApplicationFilterConfig filter:filters) {
if(filter==filterConfig) {
return;
}
}
if (n == filters.length) {
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
手写一个简单的FilterChain模式,应用场景有那些?我想审批是一个比较典型的FilterChian模式,审批需要一个审批再接另外一个审批单子处理。
/**
* 审批信息
*/
public class ApprovalMsg {
public ApprovalMsg(String msg) {
this.msg = msg;
}
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
/**
* 审批节点,对应者审批单据
*/
public class ApprovalNode implements IFilter {
private String author;
public ApprovalNode(String author) {
this.author = author;
}
@Override
public void filter(ApprovalMsg msg, IChain iChain) {
System.out.println("in");
if (msg.getMsg().equalsIgnoreCase(author)) {
iChain.doFilter(msg, iChain);
} else {
System.out.println("审批失败");
throw new RuntimeException("审批失败");
}
}
}
public interface IChain {
void doFilter(ApprovalMsg approvalMsg, IChain iChain);
}
public interface IFilter {
void filter(ApprovalMsg approvalCase, IChain iChain);
}
public class MyChain implements IChain {
private static final IFilter[] node = new IFilter[10];
int pos = 0;
int n = 10;
int cap = 0;
// 审批成功的数量,成功数量对的时候才返回成功
int success = 0;
public void filter(ApprovalMsg msg) {
doFilter(msg, this);
}
@Override
public void doFilter(ApprovalMsg approvalMsg, IChain iChain) {
if (pos < n) {
try {
IFilter filter = node[pos++];
if (filter != null) {
filter.filter(approvalMsg, this);
} else {
System.out.println("审批流处理成功");
}
} catch (Exception e) {
System.out.println("审批失败");
}
} else {
System.out.println("审批成功");
}
}
public void addFilter(ApprovalNode approvalNode) {
node[cap++] = approvalNode;
}
}
/**
* 客户端
*/
public class Server {
public static void main(String[] args) {
ApprovalMsg message = new ApprovalMsg("message");
MyChain myChain = new MyChain();
for (int i = 0; i < 5; i++) {
ApprovalNode message1 = new ApprovalNode("message");
myChain.addFilter(message1);
}
myChain.filter(message);
}
}
这只是最简单的场景,真正的审批是复杂的多了的,比如,需要处理人回复同意或者失败,涉及到很多相关的数据入库操作,审批同样的有很多不同的模式的,比如只要有一个通过,那么认为审批完成,全部审批通过才认为是审批完成等,这个后面有空再套路,本文讨论的范围到此结束。