当前位置: 首页 > 知识库问答 >
问题:

在json文件中登录

羊舌阎宝
2023-03-14

我的应用程序使用angular 7和spring boot 2运行。每次用户与应用程序交互(单击一些按钮或链接)时,我都需要在json文件中存储一些数据。json应该如下所示(只是一个示例):

[
 "event": {

   userid : 1
   ipAddress : x.x.x.x
   lastConnectionDateTime : ...,
   action : "click on link 1"
 },
 "event": {

   userid : 2
   ipAddress : y.y.y.y
   lastConnectionDateTime : ...,
   action : "click on button THE_BUTTON" 
 },
 ...
]

>

  • 使用异步调用webservice的角度拦截器手动执行此操作。然后,webservice将调用一个异步spring服务,该服务将数据追加到json文件中。使用这个解决方案,我将不得不擦除一周以上的数据,这感觉就像重新创建轮子一样。

    使用log4j2或logback之类的日志库。在log4j2中,有一个JsonLayout,它可以帮助我使用“loggerfields”来实现这一点,该“loggerfields”包含一个“KeyValuePairs”列表来将自定义字段放入我的json中,但是我有三个问题:

    >

  • 如何将我自己的值放入不是预定义的%c、%t……等。可能是这样的:logger.info(“event”、“userid”、“1”、“ipaddress”、“x.x.x.x”等);?
  • 使用该方法似乎会生成一个带有“message”字段的json,其中包含我的自定义值。如何将它们放在我的事件对象的根级别,就像我上面给出的示例一样?

    提前谢谢你

  • 共有1个答案

    乐正光誉
    2023-03-14

    关于你问题的这一部分:

    • 使用log4j2或logback等日志库。在log4j2中,有一个JsonLayout,它可以帮助我使用“loggerfields”来实现这一点,该“loggerfields”包含一个“KeyValuePairs”列表来将自定义字段放入我的json中,但是我有三个问题:
      • 如何将我自己的值放入不是预定义的%c、%t……等。可能是这样的:logger.info(“event”、“userid”、“1”、“ipaddress”、“x.x.x.x”等);?

      我想在这个要点中,您是在询问如何将动态变量的值注入JSONLayoutKeyValuePair元素。答案是,您将使用类似于JSOLayout文档末尾示例中的查找-类似于

      • 使用该方法似乎会生成一个带有“message”字段的json,其中包含我的自定义值。如何将它们放在事件对象的根级别,就像我上面给出的示例一样?

      我让您回到上面--如果使用查找,数据将放在生成的JSON中它自己的键下。

      • 恐怕这会与我默认的spring boot logger配置冲突,因为我还需要使用默认的日志系统,在普通日志文件中写入日志。我可以创建一个记录器吗?其他级别的ThanfoDebugerrorWarn(“”,“);?

      有几种方法可以处理将其他日志事件与JSON事件分离的问题。我建议您考虑将标记与MarkerFilter一起使用,或者使用特殊名称创建记录器配置(我建议您仔细阅读log4j2手册中的体系结构页,以了解记录器名称是如何工作的)。例如,如果要创建一个具有特殊名称的记录器配置,可以执行如下操作:

      private static final Logger JSON_EVENT_LOGGER = LogManager.getLogger("JSON_EVENT_LOGGER");
      

      这将在您的配置中定义,如下所示(假设是XML配置):

      <Logger name="JSON_EVENT_LOGGER" additivity="false">
          ...
      </Logger>
      

      我建议您阅读有关可加性属性的内容,以便您能够很好地理解为什么在这里将其设置为false。基本上,您不希望这些json日志事件转到任何父记录器的追加器。

      下面是一个非常简单的示例,它使用第二种方法创建具有特殊名称的记录器配置:

      首先,一个java类生成一些日志事件:

      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.Logger;
      import org.apache.logging.log4j.ThreadContext;
      
      
      public class SomeClass {
      
          private static final Logger log = LogManager.getLogger();
          private static final Logger JSON_EVENT_LOGGER = LogManager.getLogger("JSON_EVENT_LOGGER");
      
          public static void main(String[] args){
              ThreadContext.put("userid", "1");
              ThreadContext.put("ipAddress", "127.0.0.1");
              ThreadContext.put("lastConnectionDateTime", "...timestamp...");
              ThreadContext.put("action", "click link 1");
              JSON_EVENT_LOGGER.info("A JSON message uses the special logger");
      
              log.info("A non-json message uses the normal logger");
          }
      }
      

      现在是定义记录器和追加器的log4j2.xml配置文件:

      <?xml version="1.0" encoding="UTF-8"?>
      <Configuration status="WARN">
          <Appenders>
              <Console name="Console" target="SYSTEM_OUT">
                  <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
              </Console>
              <Console name="ConsoleJSON" target="SYSTEM_OUT">
                  <JsonLayout compact="false" eventEol="true" stacktraceAsString="true">
                      <KeyValuePair key="userid" value="$${ctx:userid}"/>
                      <KeyValuePair key="ipAddress" value="$${ctx:ipAddress}"/>
                      <KeyValuePair key="lastConnectionDateTime" value="$${ctx:lastConnectionDateTime}"/>
                      <KeyValuePair key="action" value="$${ctx:action}"/>
                  </JsonLayout>
              </Console>
      
          </Appenders>
      
          <Loggers>
              <Root level="INFO">
                  <AppenderRef ref="Console"/>
              </Root>
              <Logger name="JSON_EVENT_LOGGER" level="ALL" additivity="false">
                  <Appenderref ref="ConsoleJSON"/>
              </Logger>
          </Loggers>
      </Configuration>
      

      当java类执行时,控制台中会生成以下日志:

      {
        "thread" : "main",
        "level" : "INFO",
        "loggerName" : "JSON_EVENT_LOGGER",
        "message" : "A JSON message uses the special logger",
        "endOfBatch" : false,
        "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
        "instant" : {
          "epochSecond" : 1576215690,
          "nanoOfSecond" : 541000000
        },
        "threadId" : 1,
        "threadPriority" : 5,
        "userid" : "1",
        "ipAddress" : "127.0.0.1",
        "lastConnectionDateTime" : "...timestamp...",
        "action" : "click link 1"
      }
      23:41:30.653 [main] INFO  example.SomeClass - A non-json message uses the normal logger
      
      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.Logger;
      import org.apache.logging.log4j.Marker;
      import org.apache.logging.log4j.MarkerManager;
      import org.apache.logging.log4j.ThreadContext;
      
      public class SomeClass2 {
      
          private static final Logger log = LogManager.getLogger();
          private static final Marker JSON_EVENT = MarkerManager.getMarker("JSON_EVENT");
      
          public static void main(String[] args){
              ThreadContext.put("userid", "1");
              ThreadContext.put("ipAddress", "127.0.0.1");
              ThreadContext.put("lastConnectionDateTime", "...timestamp...");
              ThreadContext.put("action", "click link 1");
              log.info(JSON_EVENT, "A JSON message uses the special logger");
      
              log.info("A non-json message uses the normal logger");
          }
      }
      

      注意这里的区别--两种类型的消息都只有一个记录器对象,对记录器的一次调用包括标记来指示它是一个JSON事件。

      接下来是log4j2.xml配置:

      <?xml version="1.0" encoding="UTF-8"?>
      <Configuration status="WARN">
          <Appenders>
              <Console name="Console" target="SYSTEM_OUT">
                  <MarkerFilter marker="JSON_EVENT" onMatch="DENY" onMismatch="NEUTRAL"/>
                  <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
              </Console>
              <Console name="ConsoleJSON" target="SYSTEM_OUT">
                  <MarkerFilter marker="JSON_EVENT" onMatch="ACCEPT" onMismatch="DENY"/>
                  <JsonLayout compact="false" eventEol="true" stacktraceAsString="true">
                      <KeyValuePair key="userid" value="$${ctx:userid}"/>
                      <KeyValuePair key="ipAddress" value="$${ctx:ipAddress}"/>
                      <KeyValuePair key="lastConnectionDateTime" value="$${ctx:lastConnectionDateTime}"/>
                      <KeyValuePair key="action" value="$${ctx:action}"/>
                  </JsonLayout>
              </Console>
      
          </Appenders>
      
          <Loggers>
              <Root level="INFO">
                  <AppenderRef ref="Console"/>
                  <Appenderref ref="ConsoleJSON"/>
              </Root>
          </Loggers>
      </Configuration>
      

      再次注意这里的区别--有2个追加器,但只有一个记录器配置(root)。根记录器指定两个追加器,然后追加器负责使用markerfilter过滤事件。

      最后,运行java代码的结果输出:

      {
        "thread" : "main",
        "level" : "INFO",
        "loggerName" : "example.SomeClass2",
        "marker" : {
          "name" : "JSON_EVENT"
        },
        "message" : "A JSON message uses the special logger",
        "endOfBatch" : false,
        "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
        "instant" : {
          "epochSecond" : 1576275417,
          "nanoOfSecond" : 684000000
        },
        "threadId" : 1,
        "threadPriority" : 5,
        "userid" : "1",
        "ipAddress" : "127.0.0.1",
        "lastConnectionDateTime" : "...timestamp...",
        "action" : "click link 1"
      }
      16:16:57.756 [main] INFO  example.SomeClass2 - A non-json message uses the normal logger
      

      注意:我使用的是log4j2版本2.11.1,如果使用更新的版本,可能会看到不同的结果。当我在2.12.1中尝试这些相同的示例时,JSON输出非常不同。

     类似资料:
    • 问题内容: 我有以下json文件。我想知道我应该将json文件放在我的项目中的位置以及如何读取和存储它。 问题答案: 将该文件放入资产中 。 对于在Android Studio项目中创建的项目,您需要在主文件夹下创建资产文件夹。 将该文件读取为: 然后您可以简单地通过此函数读取此返回 有关JSON的更多详细信息,请参见 http://www.vogella.com/articles/Android

    • 问题内容: 我有一个如下文件: 我正在尝试将其导入文件。为此,我将其添加到类型定义中: 我正在这样导入。 在文件中,我将颜色用作。但是我得到一个错误: 属性’primaryMain’在类型’typeof“ * .json”上不存在 问题答案: 导入表单和模块声明需要就模块的形状,导出的内容达成一致。 编写时(自TypeScript 2.9导入JSON时,针对兼容模块格式的一种次佳实践, 请参见no

    • 问题内容: 我是React的新手,正在尝试从外部文件导入JSON 变量。我收到以下错误: 找不到模块“ ./customData.json” 有人可以帮我吗?如果我的变量位于外部JSON文件中,但没有该变量,则它可以工作。 index.js hobbies.js profile.js customData.json 问题答案: 一种不错的方法(不添加伪造的.js扩展名,用于代码而不用于数据和配置)

    • 我想保存JSch日志文件,因为它不显示任何东西在控制台。 这是我的代码: 把jsch记录器放在哪里来获取文件中的一些信息。我试过了,但从来没有成功过: D

    • 问题内容: 我正在尝试在React组件中加载language.json文件。当我想导入json文件时,第一步出现以下错误。这是错误: 我正在使用webpack,这是配置文件: 并且我已经安装了以下软件包: 这就是我尝试导入文件(ES6格式)的方式: 另外,我检查了json文件格式并进行了验证!那么,您认为问题出在哪里? 问题答案: azium是正确的,需要加载程序,但这是很好的配置: npm命令

    • 和 因为该类在JDBC包中。那我就这么做 Edit2:因为我在控制台中获得的日志消息看起来与logback.xml中的日志消息不同,所以它看起来完全忽略了我的logback.xml。