0

我在我的应用程序中使用 j2se 记录器。有什么方法可以在不修改当前日志语句的情况下使用日志文件中的每个日志条目记录 jSessionId。

4

1 回答 1

0

我得到了解决方案。这可以通过 ThreadLocal、一个 servlet 过滤器和一个日志过滤器来完成。步骤如下:

使用 ThreadLocal 变量创建会话 id 持有者类:

public abstract class SessionUtil {
      private static final ThreadLocal<String> sessionIdThreadLocal = new ThreadLocal<String>();
      public static String getSessionId() {
            return sessionIdThreadLocal.get();
      }
      public static void setSessionId(String jSessionId) {
            sessionIdThreadLocal.set(jSessionId);
      }
      public static void removeSessionId() {
            sessionIdThreadLocal.remove();
      }
}

创建一个 ServletFilter 并在 ServletFilter 类的 init() 方法中,将日志过滤器与日志处理程序连接起来:

Handler[] handlers = Logger.getLogger("").getHandlers();
for (Handler handler : handlers) {
LogFilter logFilter = new MyLogFilter();
handler.setFilter(logFilter);
}

在 ServletFilter 类的 doFilter() 方法中,添加以下行以将 JSessionId 添加到 ThreadLocal:

SessionUtil.setSessionId(request.getSession(false).getId());

在 ServletFilter 类的 doFilter() 方法的 finally 块中,添加以下行以在处理请求后从 ThreadLocal 中删除 JSessionId:

SessionUtil.removeSessionId();

定义日志过滤器类:

public class MyLogFilter implements LogFilter {
    public boolean isLoggable(LogRecord record) {
    if (SessionUtil.getSessionId() != null && 
            !SessionUtil.getSessionId().toString().equals("")) {
        StringBuilder sessId = new StringBuilder(SessionUtil.getSessionId().toString());
        String methodName = record.getSourceMethodName();
            if (methodName != null && !methodName.equals("")) {
            if (!methodName.endsWith(sessId.toString())) {
                    record.setSourceMethodName(sessId.insert(0, " ").insert(0, methodName).toString());
            }
            } else {
            record.setSourceMethodName(sessId.toString());
            }
    }
        return true;
    }
}

现在示例日志条目将如下所示:

[4/12/13 10:00:46:685 EDT] 00000020 SampleClass    I com.example.SampleClass sampleMethod() [ROatVgqdnLd-ls3_ONvXcXU] Sample message
于 2013-04-12T16:12:29.380 回答