javalite Activeweb 如何在 HttpSupportFilter 中获取用于记录目的的响应正文字符串

javalite Activeweb how to get response body string for logging purpose in HttpSupportFilter

如何在 HttpSupportFilter 中获取用于记录目的的 responseBody 字符串?

常见的日志解决方案是创建包装器并将其插入标准过滤器

如果我们使用标准过滤器,我们将无法访问 activejdbc 数据库连接层

我尝试应用包装器但它不起作用,字符串仍然是空的

public class HTTPLogFilter extends HttpSupportFilter {

    private static ThreadLocal<Long> start = new ThreadLocal<>();
    
    @Override
    public void before() {
        start.set(System.currentTimeMillis());
    }

    @Override
    public void after() {

        if(Configuration.HTTPLOGS_ENABLE) {

            Registry.instance().getStatisticsQueue().enqueue(
                    new QueryExecutionEvent(getRoute().getController().getClass().getName() +
                            "#" + getRoute().getActionName() + ":" + method(), System.currentTimeMillis() - start.get()));

            HttpLog httpLog = new HttpLog();

            String username ="TEST";

            Map request = new HashMap<String, Object>();
            request.put("requestUrl", url());
            request.put("contextPath", context());
            request.put("uriFullPath", uri());
            request.put("uriPath", path());
            request.put("method", method());
            request.put("requestHeaders", headers());
            request.put("requestParams", params());
            request.put("queryString", queryString());
            request.put("requestBody", getRequestString());

            Map response = new HashMap<String, Object>();
            response.put("responseHeaders", getResponseHeaders());
            try {
                // BUG ! this responseBody still empty
                response.put("responseBody", getHttpServletResponse().getWriter().toString());
            } catch (IOException e) {
                e.printStackTrace();
            }

            httpLog.setCreatedby(username);
            httpLog.setCreateddt(new Date());
            httpLog.setUsername(username);
            String remoteAddr = ipForwardedFor() != null ? ipForwardedFor() : remoteAddress();
            httpLog.setIpaddress(remoteAddr );
            httpLog.setUseragent(userAgent());
            httpLog.setControllername(getRoute().getController().getClass().getName() + "." + getRoute().getActionName());
            httpLog.setHttpmethod(method());
            httpLog.setHttpexceptions("");
            httpLog.setExecutiondt(new Date(start.get()));
            httpLog.setExecutiondur(System.currentTimeMillis() - start.get());
            httpLog.setHttpurl(url());
            httpLog.setHttprequest(JsonHelper.toJson(request));
            httpLog.setHttpresponse(JsonHelper.toJson(response));
            httpLog.setHttpstatuscode(getHttpServletResponse().getStatus());
            httpLog.saveIt();
        }
    }

}

总的来说,您的方向是正确的。据我了解,HttpLog 是一个模型,您想将请求值存储到数据库中,对吗?

你写:

如果我们使用标准过滤器,我们将无法访问 activejdbc 数据库连接层

因此,ActiveWeb 过滤器有顺序,记录在此处:https://javalite.io/controller_filters#filter-ordering

这意味着如果你想要在HTTPLogFilter中可用的数据库连接,你必须在HTTPLogFilter之前注册DBConnectionFilter,例如:

public class AppControllerConfig extends AbstractControllerConfig {
    public void init(AppContext appContext) {
        add(new DBConnectionFilter(), new HTTPLogFilter());
    }
}

这样,DBConnectionFilter.before() 将在 HTTPLogFilter.before() 之前被调用,并相应地打开一个数据库连接。

旁注:您将很快填满数据库,建议将所有这些数据简单地记录到日志文件中,并使用 Splunk 或 Graylog 等日志分析器。