前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从0.5到1写个rpc框架 - 4:request filter

从0.5到1写个rpc框架 - 4:request filter

作者头像
acupt
发布2019-08-26 15:04:13
4190
发布2019-08-26 15:04:13
举报
文章被收录于专栏:一杯82年的JAVA一杯82年的JAVA

为了后续扩展方便,搞个filter支持,就抄一个servlet的filter吧。

servlet filter 分析

在写mvc项目时,经常会用到filter,可以给一个请求做前置或者后置处理。如下:

代码语言:javascript
复制
@WebFilter(filterName = "requestFilter", urlPatterns = "/*")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("filter init");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
        System.out.println("我进来了");
        chain.doFilter(request, response);
        System.out.println("我要走了");
    }

    @Override
    public void destroy() {
        System.out.println("filter destroy");
    }
}

这是一种责任链模式的实现,debug看下调用栈可以了解框架是怎么实现的。

  • 每次请求生成一个FilterChain对象,并使其持有所有filter的数组,初始化成员变量pos=0(表示应该执行第几个filter)
  • 从FilterChain.doFilter开始调用整个链路,从第一个filter开始,调用时会把chain本身传给filter,pos自增
  • 某个filter如果不拦截这个请求,则调用FilterChain.doFilter,由于pos已经自增,则会调用下一个filter
  • filter全部调用后(pos=filters.length),开始真正执行请求
  • 请求返回后会依次再经过之前经过的所有filter(倒序)

rpc filter 实现

定义filter接口,使用者如果要添加过滤逻辑需要集成这个接口。

代码语言:javascript
复制
public interface RpcFilter {
    void doFilter(RpcRequest request, RpcResponse response, RpcFilterChain filterChain);
}

filter持有者

代码语言:javascript
复制
public class RpcFilterChain implements RpcCode {
    private RpcFilter[] filters = new RpcFilter[0];
    private int pos;
    private RpcServiceInfo serviceInfo;
    private RpcServiceExecutor serviceExecutor;//最终要执行请求的处理器

    public RpcFilterChain(List<RpcFilter> filterList, RpcServiceInfo serviceInfo, RpcServiceExecutor serviceExecutor) {
        if (filterList != null && !filterList.isEmpty()) {
            this.filters = new RpcFilter[filterList.size()];
            this.filters = filterList.toArray(this.filters);
        }
        this.serviceInfo = serviceInfo;
        this.serviceExecutor = serviceExecutor;
    }

    public void doFilter(RpcRequest request, RpcResponse response) {
        if (pos < filters.length) {
            RpcFilter filter = filters[pos++];
            filter.doFilter(request, response, this);
            return;
        }
        if (serviceExecutor == null) {
            response.error(SERVICE_NOT_FOUND, "service not exist: " + serviceInfo);
            return;
        }
        serviceExecutor.execute(request, response);
    }

}

rpc server 接收到请求后先初始化一个责任链,然后触发。

代码语言:javascript
复制
public RpcResponse execute(RpcRequest rpcRequest) {
        RpcServiceInfo rpcServiceInfo = new RpcServiceInfo(rpcRequest.getAppName(), rpcRequest.getServiceName());
        RpcFilterChain chain = new RpcFilterChain(filters, rpcServiceInfo, serviceExecutorMap.get(rpcServiceInfo));
        RpcResponse rpcResponse = new RpcResponse();
        try {
            chain.doFilter(rpcRequest, rpcResponse);
        } catch (Exception e) {
            rpcResponse.error(e);
        }
        return rpcResponse;
    }
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一杯82年的JAVA 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • servlet filter 分析
  • rpc filter 实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档