责任链模式,以ApplicationFilterChain类为例

文章介绍了Servlet中的FilterChain模式,通过关键代码`doFilter`展示了如何逐个执行Filter并处理请求和响应。同时,提供了一个审批流程的简化示例,说明了FilterChain如何在审批场景中工作,如何添加新的审批节点以及如何处理审批结果。审批流程可以有多种模式,如单一通过即完成或全部通过才算完成。
摘要由CSDN通过智能技术生成

总览:

关键代码doFIlter,处理逻辑如下:

  1. 挨个的执行Filter的逻辑;
  2. 判断pos=n的时候,发现是最后一个FIlter;
  3. 开始执行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);
    }
}

这只是最简单的场景,真正的审批是复杂的多了的,比如,需要处理人回复同意或者失败,涉及到很多相关的数据入库操作,审批同样的有很多不同的模式的,比如只要有一个通过,那么认为审批完成,全部审批通过才认为是审批完成等,这个后面有空再套路,本文讨论的范围到此结束。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值