Git Product home page Git Product logo

log-record's Issues

找不到依赖

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

有一点小小的建议

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

使用diff场景问题

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

编码文件格式问题

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

MQ支持Kafka吗

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

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;
    }
}

自定义 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的内容前后加单引号也没用。

项目集成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

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

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

我在使用过程中自定义了一个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

请教一个小问题😂

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

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

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

项目集成后通过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)

_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的相关代码。

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

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

说明文档里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"
}]

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);

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 {

关于DIFF

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

@OperationLog的success参数建议

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

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

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

关于自定义 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 对象也行。

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

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

关于 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。

完善单元测试

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

批量操作是如何支持的?

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

使用默认_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

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.