CAT源码分析之过滤器

CATweb.xml 中配置的2个过滤器

<filter>
    <filter-name>cat-filter</filter-name>
    <filter-class>com.dianping.cat.servlet.CatFilter</filter-class>
</filter>
<filter>
    <filter-name>domain-filter</filter-name>
    <filter-class>com.dianping.cat.report.view.DomainFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>cat-filter</filter-name>
    <url-pattern>/r/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>domain-filter</filter-name>
    <url-pattern>/r/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>cat-filter</filter-name>
    <url-pattern>/s/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>cat-filter</filter-name>
    <url-pattern>/jsp/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

其中

  • domain-filter 根据 domain 设置 cookie 有效期
    • 只针对报表请求, url-pattern/r/*
  • cat-filter 处理 请求信息

值得学习点

  • 枚举实现接口和循环操作

    
    package com.dianping.cat.servlet;
    public class CatFilter implements Filter {
    private List<Handler> m_handlers = new ArrayList<Handler>();
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
    ServletException {
    Context ctx = new Context((HttpServletRequest) request, (HttpServletResponse) response, chain, m_handlers);
    ctx.handle(); // for 循环即 分步处理
    }
    ....
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    // 处理化 分步步骤
    m_handlers.add(CatHandler.ENVIRONMENT);
    m_handlers.add(CatHandler.LOG_SPAN);
    m_handlers.add(CatHandler.LOG_CLIENT_PAYLOAD);
    m_handlers.add(CatHandler.ID_SETUP);
    }
    // 枚举 实现接口
    private static enum CatHandler implements Handler {
    ENVIRONMENT {
    @Override
    public void handle(Context ctx) throws IOException, ServletException {
    HttpServletRequest req = ctx.getRequest();
    boolean top = !Cat.getManager().hasContext();
    ctx.setTop(top);
    if (top) {
    ctx.setType(CatConstants.TYPE_URL);
    setTraceMode(req);
    } else {
    ctx.setType(CatConstants.TYPE_URL_FORWARD);
    }
    ctx.handle();
    }
    ....
    },
    ID_SETUP {
    ....
    @Override
    public void handle(Context ctx) throws IOException, ServletException {
    boolean isTraceMode = Cat.getManager().isTraceMode();
    HttpServletResponse res = ctx.getResponse();
    if (isTraceMode) {
    String id = Cat.getCurrentMessageId();
    res.setHeader("X-CAT-ROOT-ID", id);
    res.setHeader("X-CAT-SERVER", getCatServer());
    }
    ctx.handle();
    }
    },
    LOG_CLIENT_PAYLOAD {
    @Override
    public void handle(Context ctx) throws IOException, ServletException {
    HttpServletRequest req = ctx.getRequest();
    String type = ctx.getType();
    if (ctx.isTop()) {
    logRequestClientInfo(req, type);
    logRequestPayload(req, type);
    } else {
    logRequestPayload(req, type);
    }
    ctx.handle();
    }
    ....
    },
    LOG_SPAN {
    .....
    @Override
    public void handle(Context ctx) throws IOException, ServletException {
    HttpServletRequest req = ctx.getRequest();
    Transaction t = Cat.newTransaction(ctx.getType(), getRequestURI(req));
    try {
    ctx.handle();
    customizeStatus(t, req);
    } catch (ServletException e) {
    t.setStatus(e);
    Cat.logError(e);
    throw e;
    } catch (IOException e) {
    t.setStatus(e);
    Cat.logError(e);
    throw e;
    } catch (Throwable e) {
    t.setStatus(e);
    Cat.logError(e);
    throw new RuntimeException(e);
    } finally {
    customizeUri(t, req);
    t.complete();
    }
    }
    ....
    };
    }
    protected static class Context {
    private FilterChain m_chain;
    private List<Handler> m_handlers;
    private int m_index;
    private HttpServletRequest m_request;
    private HttpServletResponse m_response;
    private boolean m_top;
    private String m_type;
    public Context(HttpServletRequest request, HttpServletResponse response, FilterChain chain, List<Handler> handlers) {
    m_request = request;
    m_response = response;
    m_chain = chain;
    m_handlers = handlers;
    }
    ....
    // Context 封装 Handler 逻辑
    public void handle() throws IOException, ServletException {
    if (m_index < m_handlers.size()) {
    Handler handler = m_handlers.get(m_index++);
    handler.handle(this);
    } else {
    m_chain.doFilter(m_request, m_response);
    }
    }
    ....
    }
    // Handler 接口定义
    protected static interface Handler {
    public void handle(Context ctx) throws IOException, ServletException;
    }
    }
posted @ 2021-02-04 18:13  可可逗豆  阅读(214)  评论(0)    收藏  举报