예제 #1
0
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    // 设定请求开始时间
    FilterHelpers.getRequestTime(req);

    if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(req)) {
      // Proceed without invoking this filter...
      chain.doFilter(request, response);
    } else {
      // Do invoke this filter...
      request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
      CharsetDetectRequestWrapper reqWrapper = new CharsetDetectRequestWrapper(req);
      boolean gzip = false;
      // 是否启用GZip压缩
      if (enableGZip) {
        String encoding = req.getHeader("Accept-Encoding");
        if (encoding != null && encoding.contains("gzip")) {
          gzip = true;
        }
      }
      BufferedResponseWrapper resWrapper = new BufferedResponseWrapper(res, gzip);
      try {
        // XXX: 生成traceId,需要请求_traceId的参数,所以必须放到CharsetEncodingHandler后面
        fillTraceContext(reqWrapper);
        chain.doFilter(reqWrapper, resWrapper);
        if (TraceContext.get().isColor()) {
          Cookie cookie = new Cookie("_color", "1");
          cookie.setMaxAge(3600);
          cookie.setPath("/");
          resWrapper.addCookie(cookie);
        }
      } catch (Exception e) {
        LOG.error("{}", req.getRequestURL(), e);
        resWrapper.setStatus(500);
        // 这里把异常抛出去,针对服务端异常,接入层nginx可以统计到,否则就统计不到
        throw new ServletException(
            req.getRequestURL() + ", message: " + e.getMessage(), e.getCause());
      } finally {
        request.removeAttribute(alreadyFilteredAttributeName);
        try {
          if (resWrapper.getLocation() != null) {
            res.sendRedirect(resWrapper.getLocation());
          } else {
            setContentType(res);
            try {
              copyResponse(res, resWrapper);
            } catch (Exception e) {
              long cost = FilterHelpers.getCostTime(req);
              LOG.error("{}, cost={}ms", req.getRequestURL(), cost, e);
            }
          }
        } finally {
          TraceContext c = TraceContext.get();
          TraceContext.remove();
          // 染色日志发送到总线上
          if (c.isColor()) {
            sendTrace(req, c, resWrapper);
          }
          // 统计页面状态信息
          PageStatusReporter.getInstance().stat(req, c.getCost(), res.getStatus(), c.isSpider());
        }
      }
    }
  }