2

背景

有问题的应用程序是部署在 Tomcat 中的 Java Web 应用程序,并使用 Apache CXF 公开 REST 服务。我找到了 Spring 配置,但不确定它与 CXF 基础设施的连接情况。

每次发生重要事件时,例如更新或删除实体,我想记录信息,包括(但不限于):

  1. 发生了什么
  2. 谁提出了请求
  3. 改变了什么实体
  4. 实体的新状态(如果适用)
  5. 有关发送的任何通知电子邮件的信息
  6. ETC...

当前设置和挑战

我们有几个层,调用看起来像这样:控制器 > 服务 > 数据层 > 实用程序(电子邮件、SMS 发送等......)。

问题是,我想要收集和记录的数据开始可用并且仅在单独的层中可用。有时数据通过参数传递到下一层,但有时它们没有传递,因为其他层不需要数据。这里有些例子:

  • 一些 HTTP 请求相关数据仅用于一些验证,并不会发送到服务层。
  • 有时,核心实体数据仅在服务层和数据层可用,而对控制器不可用。
  • Utils 的各个层会生成一些其他层不知道的最终数据片段(如链接、代码、最终电子邮件内容)。

但我需要从所有层收集此类信息并将它们记录为审计目的,作为单个日志行。

约束

  • 代码在尊重层边界方面设计得不好。所以,有时事情会在不应该的地方传递。但我不能继续这样做。
  • 我无法将所有需要的数据返回到控制器并最终将它们记录在那里,因为中间层的方法在很多地方都被调用,并且全部重构它们是不切实际的。
  • 我不能将它们分别记录在不同的地方,因为要求不允许这样做。如果没有其他方法,我可以推送这个策略,并有一个共同的请求 ID 或其他东西和多个日志行,以将它们关联起来。

我的问题是,我应该如何以及在哪里收集所有这些数据并将它们写入审计日志?在 Java Web 应用程序中执行上述操作的最佳实践是什么?

4

1 回答 1

0

听起来你的应用程序是一团糟。

但是,只要所有内容都是根据请求触发的,就应该仍然可以执行此操作。

这里有两种方法:

1) 使用来自 Logback 等日志框架的 MDC 对象。这个对象可以在请求的基础上使用键来填充,您可以在其中附加任意信息,这些信息可以在以后提取用于记录(或者它可以作为附加字段自动附加到您的日志消息中)。在此处阅读:https ://logback.qos.ch/manual/mdc.html

这将是我推荐的解决方案,因为它与您想要实现的目标非常匹配。如果那不可能,那么:

2) 创建一个对 ThreadLocal 具有静态访问权限的对象,该对象用于跟踪各个层的信息。请求完成时将其记录在 HTTP 过滤器中。并确保再次清除信息,以免与使用同一线程的下一个请求混淆。

如果您不想使用审计日志来污染您的代码,您可以考虑使用 Aspects(面向方面​​的编程)将此功能添加到您的类中。

于 2017-02-21T14:51:15.947 回答