java 在 Web 应用程序中记录用户活动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6115858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:23:13  来源:igfitidea点击:

Logging user activity in web app

javaservletsloggingspring-securitydwr

提问by James

I'd like to be able to log user activities in a web app. I'm currently using log4j which works well for logging errors etc, but I'm unsure what the best approach is to log the user, executed servlet method, and method params. I'm using spring security for the authentication.

我希望能够在网络应用程序中记录用户活动。我目前正在使用 log4j,它可以很好地记录错误等,但我不确定最好的方法是记录用户、执行的 servlet 方法和方法参数。我正在使用 spring 安全性进行身份验证。

A typical servlet could look like:

典型的 servlet 可能如下所示:

public class BankAccountServlet {
    @RequestMapping("/deposit")
    public void deposit(double amount) {
        ...
    }

    @RequestMapping("/checkBalance")
    public double checkBalance() {
        ...
    }
}

If there are two users, foo and bar, where foo checks his balance and bar deposits two sums of cash 10.00 and 5.00. I'd like the logs to look like:

如果有两个用户,foo 和 bar,其中 foo 检查他的余额,bar 存入两笔现金 10.00 和 5.00。我希望日志看起来像:

01/01/1970 23:59:59 - foo - checkBalance
02/01/1970 23:59:59 - bar - deposit - 10.00
02/01/1970 23:59:59 - bar - deposit - 5.00

If anyone could offer some advice I'd really appreciate their help.

如果有人可以提供一些建议,我将非常感谢他们的帮助。

回答by Tomasz Nurkiewicz

It's actually pretty simple to achieve using MDC/NDC functionality built into Log4J (SLF4J and Logback only support MDC).

使用 Log4J 中内置的 MDC/NDC 功能来实现实际上非常简单(SLF4J 和 Logback 仅支持 MDC)。

Implementing MDC filter

实现 MDC 过滤器

First, implement a servlet filter that will add username to MDC/NDC. Logback provides convenient MDCInsertingServletFilter, Spring framework also adds Log4jNestedDiagnosticContextFilterto the store. Look at them but you will need a custom one like this:

首先,实现一个将用户名添加到 MDC/NDC 的 servlet 过滤器。Logback 提供了方便的MDCInsertingServletFilter,Spring 框架也在store 中添加了Log4jNestedDiagnosticContextFilter。看看它们,但你需要一个像这样的自定义:

public class UserToMdcFilter implements javax.servlet.Filter
{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        MDC.put("user", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
        try {
            chain.doFilter(request, response);
        } finally {
            MDC.remove("user");
        }
    }

    //...
}

Adding MDC value to your logging pattern

将 MDC 值添加到您的日志记录模式

Make sure this filter is applied in web.xmlafter Spring security filter. MDC feature is really slick - it will add all values saved in MDC thread-local map to each and every logging statement if requested. In your case, simply add this:

确保web.xml在 Spring 安全过滤器之后应用此过滤器。MDC 功能非常灵活 - 如果需要,它会将保存在 MDC 线程本地映射中的所有值添加到每个日志记录语句中。在您的情况下,只需添加以下内容:

%X{user}

to your logging pattern.

到您的日志记录模式

Unobtrusive logging method parameters/values

不显眼的记录方法参数/值

Logging method name, parameters and return values is up to you (username will be added automatically), but there are some elegant ways to remove boilerplate logging code completely. Try this Spring built-in aspect:

记录方法名称、参数和返回值由您决定(用户名将自动添加),但有一些优雅的方法可以完全删除样板记录代码。试试这个 Spring 内置方面:

<bean id="customizableTraceInterceptor" class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
    <property name="enterMessage" value="Entering $[methodName]($[arguments])"/>
    <property name="exitMessage" value="Leaving $[methodName](): $[returnValue]"/>
</bean>
<aop:config>
    <aop:advisor advice-ref="customizableTraceInterceptor" pointcut="execution(public * BankAccountServlet.*(..))"/>
</aop:config>

Final thoughts

最后的想法

回答by DouglasHeitner

I have used log4j in the past in order to log more than just errors. I added INFO tags throughout my code and change the logging level. That way if you decide you no longer need to log those activities you can just change the logging level and you are done. I hope that helps.

我过去使用 log4j 来记录的不仅仅是错误。我在整个代码中添加了 INFO 标签并更改了日志记录级别。这样,如果您决定不再需要记录这些活动,您只需更改日志记录级别即可完成。我希望这有帮助。

回答by Ramesh PVK

If you want to log in sever logs, Use ServletContext.log() method which uses the container logging mechanism and logs into container logs..

如果要登录服务器日志,请使用 ServletContext.log() 方法,该方法使用容器日志记录机制并登录到容器日志中。