Git Product home page Git Product logo

log-record's Introduction

So glad you are here.

  • 🔭 I’m a backend engineer.
  • 🔭 I’m currently working at Alibaba Group in Hangzhou, China.
  • 🌱 Focusing on backend, data security and LLM.
  • 🌱 Learning frontend and desire to be a fullstack engineer.
  • 👯 I’m the host of the blog website: @monitor4all
  • 👯 My social media: @WechatOfficialAccount:后端技术漫谈 / Blog / CSDN / Zhihu / Juejin
  • 📫 How to reach me: [email protected]

😄很高兴你点开了我的主页,欢迎与我交流😄

  • 我目前是一名后端开发工程师,主攻Java领域。
  • 目前就职于阿里巴巴。
  • 热爱后端开发,数据安全和大模型方向。
  • 正在好奇并努力地学习前端开发中,努力成为合格的全栈工程师。
  • 你可以通过邮箱联系我:[email protected] 个人微信:yangzd1102(请务必注明来意,例如交流开源等)
  • 我的技术博客:@公众号:后端技术漫谈 / 博客 / CSDN / 知乎 / 掘金

Anurag's github stats

log-record's People

Contributors

dependabot[bot] avatar duanluan avatar gilnatab avatar javaeasyrob avatar oldratlee avatar pumbf avatar qqxx6661 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

log-record's Issues

关于 Diff 根据内容忽略字段的建议

  1. 只修改部分字段时,msg 显示了全部字段。
    编辑接口使用 Diff,msg最终为:“【username】从【xxx】变成了【 】 【xxx】……”。实际上因为 MyBatis 配置的更新策略,是不会更新参数中为 null 的字段(此处即 username)的,但是操作日志中却显示了。
    建议新增一个全局配置,用于 Diff 时忽略 newObj 中为 null 或为空或指定内容的字段。还可以给@LogRecordDiffField新增一个属性用于单独配置。
  2. 感觉@LogRecordDiffIgnoreField这个注解,可以变成@LogRecordDiffField的一个属性。

关于第 1 点,我现在自己的做法是在implements IOperationLogGetService的类中判断diffDTOList是否不为空,如果不为空的话,获取其中 newValue 为 null 的,再去处理 msg。

_DIFF对于对象/对象数组的msg输出

diff函数内,我看作者大大在msg输出时是直接调用 old/newValue.toString()。请问能否支持通过注解别名优化一下输出。

例子:【列表A】从【[TestDiffJob(jobId=22, jobName=222, dutyList=[TestDiffDuty(dutyId=222, dutyName=222)])]】 改为
【列表A】从【[实体A(编号=22, 名字=222, 列表A=[实体B(编号=222, 名=222)])]】

原输出虽然开发人员能够明白,但对于业务人员的查看并不友好

以上效果虽然可以直接通过覆写toString实现,但不算是一个太好的方案,容易干扰用到toString的相关代码。

使用diff场景问题

实际业务中,当修改的对象是复杂对象,里面又包含List对像集合,这种情况时支持吗?我自测没通过

批量操作是如何支持的?

针对业务中的批量操作,比如批量删除、批量新增操作,通过注解的方式记录日志时貌似无法满足业务需求,请问您这种情况有考虑吗?

SystemLogAspect 中 原方法执行异常时的logDTOList 添加数据有问题

    // 原方法执行异常
    catch (Throwable throwable) {
        // 方法异常执行后日志切面
        try {
            if (stopWatch != null) {
                stopWatch.stop();
                executionTime = stopWatch.getTotalTimeMillis();
            }
            // 在LogRecordContext中写入执行后信息
            LogRecordContext.putVariable(LogRecordContext.CONTEXT_KEY_NAME_ERROR_MSG, throwable.getMessage());
            for (OperationLog annotation : annotations) {
                if (!annotation.executeBeforeFunc()) {
                    logDtoMap.put(annotation, resolveExpress(annotation, pjp));
                }
            }
            // 写入异常执行后日志
            logDTOList = new ArrayList<>(logDtoMap.values());
            logDTOList.forEach(logDTO -> {                                      //  此处的是否有问题??
                logDTO.setSuccess(false);
                logDTO.setException(throwable.getMessage());
            });
        } catch (Throwable throwableAfterFuncFailure) {
            log.error("OperationLogAspect doAround after function failure, error:", throwableAfterFuncFailure);
        }
        // 抛出原方法异常
        throw throwable;
    } finally {

有一点小小的建议

作者你好,注解上的SpEL表达式执行顺序总是晚于被注解的整体方法执行的,有一种逻辑就会产生问题。
比如,有个方法是删除数据,参数只有一个ID,这种情况下需要通过id查到这条数据的信息,然后一起记录到日志。
但是现在的结果是,数据先被删除,然后SpEL函数去查数据时数据已经是null了。
看到您有个LogRecordContext的上下文,可以在方法体先查出来,但是这样子的话入侵太严重。
现在入参ID不变,不动入参,不能影响到前端。这种情况怎么处理比较好,后续会优化这种情况吗?

找不到依赖

配置了github生效后,依赖仍爆红。Could not find artifact cn.monitor4all:log-record-starter:pom:1.0.0 in central (https://repo1.maven.org/maven2)

编码文件格式问题

目前看代码是默认按照ISO-8859-1编码格式读取配置文件,但是这个似乎有问题,这种编码不支持配置中文?而且springboot之类的框架目前大多数也是默认按照utf-8来更改读取配置文件,所以目前自定义更改中文提示语是有问题的
image

StopWatch 能否在生产环境使用.

是线程不安全,好像不能在生产环境使用吧?

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/StopWatch.html

Simple stop watch, allowing for timing of a number of tasks, exposing total running time and running time for each named task.
Conceals use of [System.nanoTime()](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html#nanoTime()), improving the readability of application code and reducing the likelihood of calculation errors.

Note that this object is not designed to be thread-safe and does not use synchronization.

This class is normally used to verify performance during proof-of-concept work and in development, rather than as part of production applications.

As of Spring Framework 5.2, running time is tracked and reported in nanoseconds.

CustomFunctionObjectDiff 组件取newData alias使用的是oldObject

CustomFunctionObjectDiff 类里第54行
// 对象类名
51 String oldClassName = oldObject.getClass().getName();
52 String newClassName = newObject.getClass().getName();
53 LogRecordDiff oldClassLogRecordDiff = oldObject.getClass().getDeclaredAnnotation(LogRecordDiff.class);
54 LogRecordDiff newClassLogRecordDiff = oldObject.getClass().getDeclaredAnnotation(LogRecordDiff.class);

项目集成后通过docker部署到服务器javassist.NotFoundException:xxxxx.utils.function.CustomFunctionObjectDiff

tils.function.CustomFunctionObjectDiff
at javassist.ClassPool.get(ClassPool.java:430)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.constructCtClass(CustomFunctionRegistrar.java:122)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.proxy2static(CustomFunctionRegistrar.java:108)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:74)
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.setApplicationContext(CustomFunctionRegistrar.java:45)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:123)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:100)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:415)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1791)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236)
at com.zeekr.speech.config.Application.main(Application.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)

@OperationLog的success参数建议

我有个问题
@OperationLog 这个注解有个success() 的参数 可以判断函数是否执行成功,文档如下图

  • image
    因为我这个项目是已完成的项目,返回的参数都是统一的,如下图
  • image

这样操作的话就侵入了业务逻辑。而且要改很多的接口,我就是想能不能出个接口,让我自己来根据方法的返回参数判断接口是否执行成功,如果方法执行抛出了错误那么自动认为方法执行失败了

请教一个小问题😂

获取请求ip地址或者request对象,您是怎么传递的
我看图片当中也提到了访问ip

MQ支持Kafka吗

我看介绍支持RabbitMQ、RocketMQ、SpringCloud Stream。如果想接入其他MQ,有对应的扩展点嘛?

完善单元测试

需要完善单元测试,用于PR做回归测试,保证代码质量

关于DIFF

作者你好,使用DIFF的时候需要从业务代码中获取原来的值,这个还有调整的空间吗

自定义 log-record.diff-msg-format 结果错误

版本:v1.5.1

application.yml:

log-record:
  # Diff 时忽略新对象中 null 值字段,默认为 false
  diff-ignore-new-object-null-value: true
  # Diff 格式
  diff-msg-format: 【${_fieldName}】:【${_oldValue}】->【${_newValue}】
  # Diff 分隔符
  diff-msg-separator: ;

UserController:

@OperationLog(bizId = "#id", bizType = "'user:update'", msg = "'更新用户:' + #_DIFF(#oldObj, #obj)")
public ApiResponse update(@Min(value = 1, message = "参数错误") @PathVariable Long id, @Validated @RequestBody UserUpdateQO obj) {
  User user = userService.getById(id);
  if (user == null) {
    throw new ServiceException("用户不存在");
  }
  LogRecordContext.putVariable("oldObj", user);
  // ……
}

User:

@LogRecordDiffObject(alias = "用户")
public class User {
  @LogRecordDiffField(alias = "用户名")
  private String username;
  // ……
}

UserUpdateQO:

@LogRecordDiffObject
public class UserUpdateQO {
  @LogRecordDiffField(alias = "用户名")
  private String username;
  // ……
}

结果:更新用户:?电话?:?18888888887?->?18888888888?;?昵称?:?234?->?23?;?角色?:?2,1671440885033914373?->?2?

我所有的文件编码都是UTF-8
我试过给diff-msg-format的内容前后加单引号也没用。

局部变量有没有优雅方式记录到日志里

大佬你好,感谢提供了这么优秀的日志记录框架
image
我日志中需要记录的bizId是方法中的局部变量,除了通过LogRecordContext.putVariables("id", id),使用函数的spel表达式看样子不太行。

关于自定义 success、exception 和全局异常处理的顺序问题

目前createLog方法中LogDTO.exception获取的仅为e.getMessage(),而我想获取的是e.printStackTrace()的内容。

大多项目都会有一个全局异常处理。
GlobalExceptionHandler:

/**
 * 全局异常处理
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler  {

  @ExceptionHandler(value = Exception.class)
  @ResponseBody
  public ApiResponse<String> handlerException(Exception e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    LogRecordContext.putVariable("exception", sw.toString());

    // ……
  }
  1. 上文代码中的LogRecordContext.putVariable("exception", sw.toString());仅为我的猜想,能否通过这种方式去设置LogDTO.exception的值(put 中可以特殊点叫 $exception 或者加新方法),不然每个@OperationLog都要加属性(当然现在还没有可以配置exception的属性)。

  2. 假设可以自定义LogDTO.exception的值的话,GlobalExceptionHandler.handlerException的执行顺序也总是在createLog方法后,@Order注解无效。或者 LogDTO 可以获取到 Exception 对象也行。

新增常用公共函数和可序列化对象注解的建议

我再提些建议,你别烦我🥺

我在使用过程中自定义了一个toLogString函数,作用是传进去对象或集合,输出有@LogRecordDiffField的属性,而且还和diff-ignore-new-object-null-valuediff-msg-separator结合起来使用了。我觉得将参数属性名转为中文是很常见的需求,可以新增类似的公共函数。

我觉得@LogRecordDiffField注解可以改成@LogRecordField,然后同时适用于 Diff 和其他功能,就像 MyBatis Plus 的@TableField或 Hibernate 的@Column一样。

我很久以前写过一个基于 Hibernate 的注解日志记录,会自动将带有@Column的属性名转为这个注解的 comment 输出,或者将它的属性名、@column 注解的 comment 属性的值、属性值传到一个集合里后续再使用。

我觉得除了新增类似的公共函数之外,也可以给@OperationLog加一个属性,为 true 就直接把属性名转成@LogRecordField的 alias 的值了。

CustomLogFn

/**
 * 日志自定义函数
 */
@Slf4j
@Component
@LogRecordFunc("custom")
public class CustomLogFn {

  private static boolean ignoreNullValues;
  private static String diffMsgSeparator;

  @Value("${log-record.diff-ignore-new-object-null-value}")
  public void setIgnoreNullValues(boolean ignoreNullValues) {
    CustomLogFn.ignoreNullValues = ignoreNullValues;
  }

  @Value("${log-record.diff-msg-separator}")
  public void setDiffMsgSeparator(String diffMsgSeparator) {
    CustomLogFn.diffMsgSeparator = diffMsgSeparator;
  }

  @LogRecordFunc("toLogString")
  public static String toLogString(Object object) {
    List<String> fields = new ArrayList<>();

    // 操作多个对象
    if (object instanceof Iterable<?>) {
      for (Object o : (Iterable<?>) object) {
        fields.add(toLogString(o));
      }
      return StringUtils.join(fields, " | ");
    } else {
      // 遍历对象的所有字段
      for (Field field : object.getClass().getDeclaredFields()) {
        // 跳过没有 @LogRecordDiffField 的字段
        if (!field.isAnnotationPresent(LogRecordDiffField.class)) {
          continue;
        }
        field.setAccessible(true);
        LogRecordDiffField annotation = field.getAnnotation(LogRecordDiffField.class);
        // 跳过忽略的字段
        if (annotation.ignored()) {
          continue;
        }
        try {
          Object value = field.get(object);
          // 是否忽略 null 值
          if (ignoreNullValues && value == null) {
            continue;
          }
          fields.add(annotation.alias() + ":" + (value != null ? value.toString() : "null"));
        } catch (IllegalAccessException e) {
          log.error("获取字段值失败", e);
        }
      }
      return StringUtils.join(fields, diffMsgSeparator);
    }
  }
}
@OperationLog(bizId = "#bizId", bizType = "'user:save'", msg = "'【保存用户】' + #custom_toLogString(#obj)")
// 结果:【保存用户】用户名:test2;昵称:test2;电话:18888888888;角色:3

@OperationLog(bizId = "#ids", bizType = "'user:remove'", msg = "'【删除用户】' + #custom_toLogString(#removedList)")
// 结果:【删除用户】用户名:test1;电话:18888888888;昵称:test1;角色:2 | 用户名:test2;电话:18888888888;昵称:test2;角色:3

项目集成log-record通过k8s发布启动后报javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff异常

项目集成log-record通过k8s发布启动后报javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff异常
但是本地通过idea启动是没问题的,以下是详细的错误日志,希望作者帮忙看一下

DEBUG 2022-12-20 10:50:39:929 main AgentPackagePath : The beacon class location is jar:file:/skywalking-agent/skywalking-agent.jar!/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.class.
INFO 2022-12-20 10:50:39:932 main SnifferConfigInitializer : Config file found in /skywalking-agent/config/agent.config.

. ____ _ __ _ _
/\ / ' __ _ () __ __ _ \ \ \
( ( )_
_ | '_ | '| | ' / ` | \ \ \
\/ )| |)| | | | | || (| | ) ) ) )
' |
| .__|| ||| |_, | / / / /
=========|
|==============|/=////
:: Spring Boot :: (v2.5.1)

10:51:23.614 [main] INFO [TID:N/A] com.toplion.download.DownloadCenterApplication - The following profiles are active: pre
10:53:03.515 [main] ERROR [TID:N/A] cn.monitor4all.logRecord.function.CustomFunctionRegistrar - cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at javassist.ClassPool.get(ClassPool.java:430)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.constructCtClass(CustomFunctionRegistrar.java:118)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.proxy2static(CustomFunctionRegistrar.java:104)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:72)
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.setApplicationContext(CustomFunctionRegistrar.java:43)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:128)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:102)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
at com.toplion.download.DownloadCenterApplication.main(DownloadCenterApplication.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
10:53:04.323 [main] ERROR [TID:N/A] org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'registrar' defined in class path resource [cn/monitor4all/logRecord/configuration/LogRecordConfiguration.class]: Initialization of bean failed; nested exception is java.lang.RuntimeException: javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:610)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
at com.toplion.download.DownloadCenterApplication.main(DownloadCenterApplication.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: java.lang.RuntimeException: javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:85)
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.setApplicationContext(CustomFunctionRegistrar.java:43)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:128)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:102)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
... 23 common frames omitted
Caused by: javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at javassist.ClassPool.get(ClassPool.java:430)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.constructCtClass(CustomFunctionRegistrar.java:118)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.proxy2static(CustomFunctionRegistrar.java:104)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:72)
... 30 common frames omitted

LogRecordFunc 注解是否只支持标注static方法

大多情况下自定义的函数为了查old的值都会调用spring容器中的方法去获取,在@component注解标记的类中使用LogRecordFunc注解会报空指针,代理类获取不到Annotation,微调后发现非静态方法无法放到StandardEvaluationContext里

关于 @LogRecordDiffObject 和 @LogRecordDiffField 的一些建议

  1. diff 时,oldObj 和 obj 必须都要加 @LogRecordDiffObject 注解,否则 diff 内容为空。我觉得这个注解可以不加,主要只用 @LogRecordDiffField 的 alias。或者没有都加 @LogRecordDiffObject 的时候报错提醒下。
  2. diff 时,oldObj 和 obj 的字段都得写 @LogRecordDiffField(alias = "用户名"),结果才会有中文,否则就是字段名,我觉得其中一个加就行了,根据字段名来判断。

使用默认_DIFF方法对日期进行比对的时候会出现异常

报错内容如下,原因是因为Date转JSONObject的时候出错,建议进行优化一下默认的_DIFF方法

2023-05-19 11:49:21.555 [http-nio-8080-exec-5] ERROR c.m.logRecord.function.CustomFunctionObjectDiff:124 - objectDiff error
cn.monitor4all.logRecord.exception.LogRecordException: fieldValueEquals error
	at cn.monitor4all.logRecord.function.CustomFunctionObjectDiff.fieldValueEquals(CustomFunctionObjectDiff.java:228)
	at cn.monitor4all.logRecord.function.CustomFunctionObjectDiff.objectDiff(CustomFunctionObjectDiff.java:115)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.expression.spel.ast.FunctionReference.executeFunctionJLRMethod(FunctionReference.java:121)
	at org.springframework.expression.spel.ast.FunctionReference.getValueInternal(FunctionReference.java:80)
	at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117)
	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:308)
	at cn.monitor4all.logRecord.aop.SystemLogAspect.resolveExpress(SystemLogAspect.java:259)
	at cn.monitor4all.logRecord.aop.SystemLogAspect.doAround(SystemLogAspect.java:118)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at org.jeecg.common.aspect.PrintLogAspect.doAround(PrintLogAspect.java:155)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at org.jeecg.common.aspect.DictAspect.doAround(DictAspect.java:56)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at org.jeecg.common.aspect.AutoLogAspect.around(AutoLogAspect.java:57)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at org.jeecg.modules.sys.controller.SysConfigController$$EnhancerBySpringCGLIB$$d91be327.edit(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.jeecg.common.config.mqtoken.TransmitUserTokenFilter.doFilter(TransmitUserTokenFilter.java:26)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:450)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: java.util.Date cannot be cast to com.alibaba.fastjson.JSONObject
	at cn.monitor4all.logRecord.function.CustomFunctionObjectDiff.fieldValueEquals(CustomFunctionObjectDiff.java:214)
	... 150 common frames omitted

Null return value from advice does not match primitive return type for: public abstract boolean cn.monitor4all.logRecord.service.IOperationLogGetService.createLog(cn.monitor4all.logRecord.bean.LogDTO)

org.springframework.aop.AopInvocationException: Null return value from advice does not match primitive return type for: public abstract boolean cn.monitor4all.logRecord.service.IOperationLogGetService.createLog(cn.monitor4all.logRecord.bean.LogDTO) throws java.lang.Exception
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:229)
	at com.sun.proxy.$Proxy259.createLog(Unknown Source)
	at cn.monitor4all.logRecord.aop.SystemLogAspect.createLog(SystemLogAspect.java:323)
	at cn.monitor4all.logRecord.aop.SystemLogAspect.lambda$doAround$2(SystemLogAspect.java:167)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at cn.monitor4all.logRecord.aop.SystemLogAspect.doAround(SystemLogAspect.java:175)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
	at com.hiifans.brick.spring.framework.logging.RequestLogInterceptor.invoke(RequestLogInterceptor.java:44)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
	at com.hiifans.crm.admin.controller.ReportController$$EnhancerBySpringCGLIB$$773e8852.reportViewLog(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:891)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1784)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:750)

使用方式:

@PostMapping("/view-log")
    @OperationLog(bizId = "", bizType = "'VIEW'", msg = "'菜单名称:' + #reportViewLogDTO.menuName + ',进入时间:' + #enterTime")
    @ApiOperation("浏览日志上报")
    public DataResponse<?> reportViewLog(@RequestBody @Valid ReportViewLogDTO reportViewLogDTO) {
        LogRecordContext.putVariable("enterTime", LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
        return DataResponse.ok();
    }
@Slf4j
@Service
public class OperationLogGetServiceImpl implements IOperationLogGetService {

    @Async
    @Override
    public boolean createLog(LogDTO logDTO) throws Exception {
        try {
            log.error("{}", JSONUtil.toJsonStr(logDTO));
        } catch (Exception e) {

        }
        return true;
    }
}

说明文档里diffDTOList数组为什么同样的数据存储两条,没理解

testService.testObjectDiff(new TestUser(2, "李四"));

===========================
"diffDTOList":[
{
"diffFieldDTOList":[
{
"fieldName":"id",
"newFieldAlias":"用户工号",
"newValue":2,
"oldFieldAlias":"用户工号",
"oldValue":1
},
{
"fieldName":"name",
"newValue":"李四",
"oldValue":"张三"
}],
"newClassAlias":"用户信息实体",
"newClassName":"cn.monitor4all.logRecord.test.bean.TestUser",
"oldClassAlias":"用户信息实体",
"oldClassName":"cn.monitor4all.logRecord.test.bean.TestUser"
},
{
"diffFieldDTOList":[
{
"fieldName":"id",
"newFieldAlias":"用户工号",
"newValue":2,
"oldFieldAlias":"用户工号",
"oldValue":1
},
{
"fieldName":"name",
"newValue":"李四",
"oldValue":"张三"
}],
"newClassAlias":"用户信息实体",
"newClassName":"cn.monitor4all.logRecord.test.bean.TestUser",
"oldClassAlias":"用户信息实体",
"oldClassName":"cn.monitor4all.logRecord.test.bean.TestUser"
}]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.