diff --git a/README.md b/README.md index a56fcfe..7c0bc13 100644 --- a/README.md +++ b/README.md @@ -592,9 +592,8 @@ public Result createOrder(Request request) { 有如下注解: -- `@LogRecordDiffField`:在需要对比的字段上申明`@LogRecordDiffField(alias = "用户工号")`,`alias`别名为可选字段。 -- `@LogRecordDiffObject`:在类上也可以申明`@LogRecordDiffObject(alias = "用户信息实体")`,`alias`别名为可选字段,默认类下所有字段会进行`DIFF`,可通过`enableAllFields`手动关闭,关闭后等于该注解只用于获取类别名。 -- `@LogRecordDiffIgnoreField`:申明该字段不参与实体类`DIFF`(用于当类拥有`@LogRecordDiffObject`注解时排除部分字段) +- `@LogRecordDiffField`:在字段上申明`@LogRecordDiffField(alias = "用户工号", ignored = true)`,`alias`别名为可选字段。 `ignored`为可选字段,默认为`false`,若为`true`,则该字段不参与`DIFF`。 +- `@LogRecordDiffObject`:在类上允许可以申明`@LogRecordDiffObject(alias = "用户信息实体")`,`alias`别名为可选字段,默认类下所有字段会进行`DIFF`,可通过`enableAllFields`手动关闭,关闭后等于该注解只用于获取类别名。 类对象使用示例: @@ -603,7 +602,6 @@ public Result createOrder(Request request) { public class TestUser { private Integer id; private String name; - @LogRecordDiffIgnoreField private String job; } ``` @@ -614,6 +612,7 @@ public class TestUser { public class TestUser { @LogRecordDiffField(alias = "用户工号") private Integer id; + @LogRecordDiffField(alias = "用户工号", ignored = true) private String name; } ``` @@ -717,6 +716,13 @@ testService.testObjectDiff(new TestUser(2, "李四")); } ``` +可以通过`Spring`配置,忽略对比的新旧对象中值为null的字段,形如: + +```properties +log-record.diffIgnoreNewObjectNullValue=true # 忽略新对象中null值字段,默认为false +log-record.diffIgnoreOldObjectNullValue=true # 忽略旧对象中null值字段,默认为false +``` + 此外,可以通过`Spring`配置自定义`DIFF`的标准输出格式,形如: ```properties @@ -809,7 +815,8 @@ CREATE TABLE `operation_log` ( `biz_type` varchar(64) DEFAULT NULL COMMENT '业务类型', `tag` varchar(64) DEFAULT NULL COMMENT '标签', `operation_date` datetime DEFAULT NULL COMMENT '操作执行时间', - `msg` varchar(512) COMMENT '操作内容', + `msg` varchar(512) DEFAULT NULL COMMENT '操作内容', + `extra` varchar(512) DEFAULT NULL COMMENT '附加信息', `operation_status` tinyint(4) DEFAULT NULL COMMENT '操作结果状态', `operation_time` int(11) DEFAULT NULL COMMENT '操作耗时', `content_return` varchar(512) COMMENT '方法返回内容', diff --git a/pom.xml b/pom.xml index 24ecb1e..8a2e01f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ cn.monitor4all log-record-starter - 1.5.0 + 1.5.1 diff --git a/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffField.java b/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffField.java index 8a97b81..6c1a58d 100644 --- a/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffField.java +++ b/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffField.java @@ -17,4 +17,9 @@ * 字段的别名:不填则默认字段名 */ String alias() default ""; + + /** + * 字段是否在DIFF中忽略:默认不忽略 + */ + boolean ignored() default false; } diff --git a/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffIgnoreField.java b/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffIgnoreField.java deleted file mode 100644 index be46c85..0000000 --- a/src/main/java/cn/monitor4all/logRecord/annotation/LogRecordDiffIgnoreField.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.monitor4all.logRecord.annotation; - - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 申明该字段不参与实体类DIFF(用于当类拥有@LogRecordDiffObject注解时排除部分字段) - */ -@Target({ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface LogRecordDiffIgnoreField { - -} diff --git a/src/main/java/cn/monitor4all/logRecord/configuration/LogRecordProperties.java b/src/main/java/cn/monitor4all/logRecord/configuration/LogRecordProperties.java index 6d49e23..1bcebdf 100644 --- a/src/main/java/cn/monitor4all/logRecord/configuration/LogRecordProperties.java +++ b/src/main/java/cn/monitor4all/logRecord/configuration/LogRecordProperties.java @@ -25,6 +25,10 @@ public class LogRecordProperties { private RetryProperties retry = new RetryProperties(); + private Boolean diffIgnoreOldObjectNullValue = false; + + private Boolean diffIgnoreNewObjectNullValue = false; + @Data public static class RetryProperties { diff --git a/src/main/java/cn/monitor4all/logRecord/function/CustomFunctionObjectDiff.java b/src/main/java/cn/monitor4all/logRecord/function/CustomFunctionObjectDiff.java index c33023c..7fde78d 100644 --- a/src/main/java/cn/monitor4all/logRecord/function/CustomFunctionObjectDiff.java +++ b/src/main/java/cn/monitor4all/logRecord/function/CustomFunctionObjectDiff.java @@ -2,7 +2,6 @@ import cn.monitor4all.logRecord.annotation.LogRecordDiffField; -import cn.monitor4all.logRecord.annotation.LogRecordDiffIgnoreField; import cn.monitor4all.logRecord.annotation.LogRecordDiffObject; import cn.monitor4all.logRecord.annotation.LogRecordFunc; import cn.monitor4all.logRecord.bean.DiffDTO; @@ -33,10 +32,16 @@ public class CustomFunctionObjectDiff { private static String DIFF_MSG_FORMAT; private static String DIFF_MSG_SEPARATOR; + private static boolean diffIgnoreOldObjectNullValue; + private static boolean diffIgnoreNewObjectNullValue; + public CustomFunctionObjectDiff(LogRecordProperties logRecordProperties){ DIFF_MSG_FORMAT = logRecordProperties.getDiffMsgFormat().equals(DEFAULT_DIFF_MSG_FORMAT) ? DEFAULT_DIFF_MSG_FORMAT : new String(logRecordProperties.getDiffMsgFormat().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); DIFF_MSG_SEPARATOR = logRecordProperties.getDiffMsgSeparator().equals(DEFAULT_DIFF_MSG_SEPARATOR) ? DEFAULT_DIFF_MSG_SEPARATOR : new String(logRecordProperties.getDiffMsgSeparator().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); + diffIgnoreOldObjectNullValue = logRecordProperties.getDiffIgnoreOldObjectNullValue(); + diffIgnoreNewObjectNullValue = logRecordProperties.getDiffIgnoreNewObjectNullValue(); log.info("CustomFunctionObjectDiff init diffMsgFormat [{}] diffMsgSeparator [{}]", DIFF_MSG_FORMAT, DIFF_MSG_SEPARATOR); + log.info("CustomFunctionObjectDiff init diffIgnoreOldObjectNullValue [{}] diffIgnoreNewObjectNullValue [{}]", diffIgnoreOldObjectNullValue, diffIgnoreNewObjectNullValue); } /** @@ -79,10 +84,13 @@ public static String objectDiff(Object oldObject, Object newObject) throws LogRe Field[] fields = oldObject.getClass().getDeclaredFields(); for (Field oldField : fields) { try { + // 获取老字段值 + oldField.setAccessible(true); + Object oldValue = oldField.get(oldObject); + LogRecordDiffField oldFieldLogRecordDiffField = oldField.getDeclaredAnnotation(LogRecordDiffField.class); - LogRecordDiffIgnoreField oldFieldLogRecordIgnoreField = oldField.getDeclaredAnnotation(LogRecordDiffIgnoreField.class); // 根据老字段判断是否需要进行diff - if (!judgeFieldDiffNeeded(oldClassEnableAllFields, oldFieldLogRecordDiffField, oldFieldLogRecordIgnoreField)) { + if (!judgeFieldDiffNeeded(oldValue, false, oldClassEnableAllFields, oldFieldLogRecordDiffField)) { log.debug("oldField [{}] not need to diff, skip", oldField.getName()); continue; } @@ -90,10 +98,11 @@ public static String objectDiff(Object oldObject, Object newObject) throws LogRe // 在新字段中寻找同名字段,若找不到则抛出NoSuchFieldException异常跳过本次遍历 Field newField = newObject.getClass().getDeclaredField(oldField.getName()); LogRecordDiffField newFieldLogRecordDiffField = newField.getDeclaredAnnotation(LogRecordDiffField.class); - LogRecordDiffIgnoreField newFieldLogRecordDiffIgnoreField = newField.getDeclaredAnnotation(LogRecordDiffIgnoreField.class); - + // 获取新字段值 + newField.setAccessible(true); + Object newValue = newField.get(newObject); // 根据新字段判断是否需要进行diff - if (!judgeFieldDiffNeeded(newClassEnableAllFields, newFieldLogRecordDiffField, newFieldLogRecordDiffIgnoreField)) { + if (!judgeFieldDiffNeeded(newValue, true, newClassEnableAllFields, newFieldLogRecordDiffField)) { log.debug("newField [{}] not need to diff, skip", newField.getName()); continue; } @@ -108,10 +117,6 @@ public static String objectDiff(Object oldObject, Object newObject) throws LogRe } // 对比新老字段值 - oldField.setAccessible(true); - newField.setAccessible(true); - Object oldValue = oldField.get(oldObject); - Object newValue = newField.get(newObject); if (!fieldValueEquals(oldValue, newValue)) { log.debug("field [{}] is different between oldObject [{}] newObject [{}]", oldField.getName(), oldValue, newValue); oldValueMap.put(oldField.getName(), oldValue); @@ -167,15 +172,15 @@ public static String objectDiff(Object oldObject, Object newObject) throws LogRe /** * 判断field是否需要进行DIFF * 规则如下: - * 老类开启EnableAllFields并且老字段未开启LogRecordIgnoreField - * 或 - * 老字段开启LogRecordDiffField并且老字段未开启LogRecordIgnoreField + * 1. 类开启EnableAllFields并且字段未开启ignored 或 字段开启LogRecordDiffField并且字段未开启ignored + * 2. 全局配置忽略值为null的字段 * */ - private static boolean judgeFieldDiffNeeded(boolean classEnableAllFields, LogRecordDiffField fieldLogRecordDiffField, - LogRecordDiffIgnoreField fieldLogRecordIgnoreField) { - return (classEnableAllFields && fieldLogRecordIgnoreField == null) - || (fieldLogRecordDiffField != null && fieldLogRecordIgnoreField == null); + private static boolean judgeFieldDiffNeeded(Object objectValue, boolean isNewObject, boolean classEnableAllFields, LogRecordDiffField fieldLogRecordDiffField) { + boolean annotationChecker1 = classEnableAllFields && (fieldLogRecordDiffField == null || !fieldLogRecordDiffField.ignored()); + boolean annotationChecker2 = fieldLogRecordDiffField != null && !fieldLogRecordDiffField.ignored(); + boolean ignoreNullValue = objectValue == null && ((isNewObject && diffIgnoreNewObjectNullValue) || (!isNewObject && diffIgnoreOldObjectNullValue)); + return (annotationChecker1 || annotationChecker2) && !ignoreNullValue; } /** diff --git a/src/test/java/cn/monitor4all/logRecord/test/LogRecordDiffIgnoreNullValueTest.java b/src/test/java/cn/monitor4all/logRecord/test/LogRecordDiffIgnoreNullValueTest.java new file mode 100644 index 0000000..a1d06d9 --- /dev/null +++ b/src/test/java/cn/monitor4all/logRecord/test/LogRecordDiffIgnoreNullValueTest.java @@ -0,0 +1,52 @@ +package cn.monitor4all.logRecord.test; + +import cn.monitor4all.logRecord.bean.LogDTO; +import cn.monitor4all.logRecord.configuration.LogRecordAutoConfiguration; +import cn.monitor4all.logRecord.test.bean.TestComplexUser; +import cn.monitor4all.logRecord.test.service.OperatorIdGetService; +import cn.monitor4all.logRecord.test.service.TestService; +import cn.monitor4all.logRecord.test.utils.TestHelper; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.context.annotation.PropertySource; +import org.springframework.test.context.ContextConfiguration; + +import java.util.Arrays; + +/** + * 单元测试 + */ +@Slf4j +@SpringBootTest +@ContextConfiguration(classes = { + LogRecordAutoConfiguration.class, + OperatorIdGetService.class, + TestService.class,}) +@PropertySource("classpath:testLogRecordDiffIgnoreNullValue.properties") +@EnableAspectJAutoProxy(proxyTargetClass = true) +public class LogRecordDiffIgnoreNullValueTest { + + @Autowired + private TestService testService; + + @Test + public void testLogRecordDiffIgnoreNullValue() { + TestHelper.addLock("testLogRecordDiffIgnoreNewObjectNullValue"); + testService.testLogRecordDiffIgnoreNewObjectNullValue(new TestComplexUser(2, null, 20, Arrays.asList("小李四", "大李四"), "后端")); + TestHelper.await("testLogRecordDiffIgnoreNewObjectNullValue"); + LogDTO logDTO = TestHelper.getLogDTO("testLogRecordDiffIgnoreNewObjectNullValue"); + + Assertions.assertEquals(logDTO.getMsg(), "【用户工号】从【1】变成了【2】 【nickNameList】从【[小张三, 大张三]】变成了【[小李四, 大李四]】"); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getOldClassName(), "cn.monitor4all.logRecord.test.bean.TestComplexUser"); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getOldClassAlias(), "用户信息复杂实体"); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getDiffFieldDTOList().get(0).getFieldName(), "id"); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getDiffFieldDTOList().get(0).getOldFieldAlias(), "用户工号"); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getDiffFieldDTOList().get(0).getNewFieldAlias(), "用户工号"); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getDiffFieldDTOList().get(0).getOldValue(), 1); + Assertions.assertEquals(logDTO.getDiffDTOList().get(0).getDiffFieldDTOList().get(0).getNewValue(), 2); + } +} diff --git a/src/test/java/cn/monitor4all/logRecord/test/OperationLogGetServiceExceptionTest.java b/src/test/java/cn/monitor4all/logRecord/test/OperationLogExceptionTest.java similarity index 96% rename from src/test/java/cn/monitor4all/logRecord/test/OperationLogGetServiceExceptionTest.java rename to src/test/java/cn/monitor4all/logRecord/test/OperationLogExceptionTest.java index 7c07596..4221868 100644 --- a/src/test/java/cn/monitor4all/logRecord/test/OperationLogGetServiceExceptionTest.java +++ b/src/test/java/cn/monitor4all/logRecord/test/OperationLogExceptionTest.java @@ -22,7 +22,7 @@ TestService.class,}) @PropertySource("classpath:testException.properties") @EnableAspectJAutoProxy(proxyTargetClass = true) -public class OperationLogGetServiceExceptionTest { +public class OperationLogExceptionTest { @Autowired private TestService testService; diff --git a/src/test/java/cn/monitor4all/logRecord/test/OperationLogTest.java b/src/test/java/cn/monitor4all/logRecord/test/OperationLogNormalTest.java similarity index 99% rename from src/test/java/cn/monitor4all/logRecord/test/OperationLogTest.java rename to src/test/java/cn/monitor4all/logRecord/test/OperationLogNormalTest.java index 4106869..b573c76 100644 --- a/src/test/java/cn/monitor4all/logRecord/test/OperationLogTest.java +++ b/src/test/java/cn/monitor4all/logRecord/test/OperationLogNormalTest.java @@ -32,7 +32,7 @@ TestService.class,}) @PropertySource("classpath:testNormal.properties") @EnableAspectJAutoProxy(proxyTargetClass = true) -public class OperationLogTest { +public class OperationLogNormalTest { @Autowired private TestService testService; diff --git a/src/test/java/cn/monitor4all/logRecord/test/bean/TestComplexUser.java b/src/test/java/cn/monitor4all/logRecord/test/bean/TestComplexUser.java index aa0e00c..068d1f6 100644 --- a/src/test/java/cn/monitor4all/logRecord/test/bean/TestComplexUser.java +++ b/src/test/java/cn/monitor4all/logRecord/test/bean/TestComplexUser.java @@ -1,7 +1,6 @@ package cn.monitor4all.logRecord.test.bean; import cn.monitor4all.logRecord.annotation.LogRecordDiffField; -import cn.monitor4all.logRecord.annotation.LogRecordDiffIgnoreField; import cn.monitor4all.logRecord.annotation.LogRecordDiffObject; import lombok.AllArgsConstructor; import lombok.Data; @@ -23,7 +22,7 @@ public class TestComplexUser { private List nickNameList; - @LogRecordDiffIgnoreField + @LogRecordDiffField(ignored = true) private String job; } diff --git a/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogGetExceptionService.java b/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogExceptionService.java similarity index 89% rename from src/test/java/cn/monitor4all/logRecord/test/service/OperationLogGetExceptionService.java rename to src/test/java/cn/monitor4all/logRecord/test/service/OperationLogExceptionService.java index 8dd0c42..a8391a3 100644 --- a/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogGetExceptionService.java +++ b/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogExceptionService.java @@ -10,7 +10,7 @@ @Slf4j @TestComponent @ConditionalOnProperty(name = "test.config", havingValue = "exception") -public class OperationLogGetExceptionService implements IOperationLogGetService { +public class OperationLogExceptionService implements IOperationLogGetService { @Override public boolean createLog(LogDTO logDTO) throws Exception { diff --git a/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogGetService.java b/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogNormalService.java similarity index 99% rename from src/test/java/cn/monitor4all/logRecord/test/service/OperationLogGetService.java rename to src/test/java/cn/monitor4all/logRecord/test/service/OperationLogNormalService.java index 907b907..a53e620 100644 --- a/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogGetService.java +++ b/src/test/java/cn/monitor4all/logRecord/test/service/OperationLogNormalService.java @@ -12,7 +12,7 @@ @Slf4j @TestComponent @ConditionalOnProperty(name = "test.config", havingValue = "normal") -public class OperationLogGetService implements IOperationLogGetService { +public class OperationLogNormalService implements IOperationLogGetService { @Override public boolean createLog(LogDTO logDTO) { diff --git a/src/test/java/cn/monitor4all/logRecord/test/service/TestLogRecordDiffIgnoreNullValueService.java b/src/test/java/cn/monitor4all/logRecord/test/service/TestLogRecordDiffIgnoreNullValueService.java new file mode 100644 index 0000000..b4f534b --- /dev/null +++ b/src/test/java/cn/monitor4all/logRecord/test/service/TestLogRecordDiffIgnoreNullValueService.java @@ -0,0 +1,28 @@ +package cn.monitor4all.logRecord.test.service; + +import cn.monitor4all.logRecord.bean.LogDTO; +import cn.monitor4all.logRecord.service.IOperationLogGetService; +import cn.monitor4all.logRecord.test.utils.TestHelper; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.test.context.TestComponent; + +@Slf4j +@TestComponent +@ConditionalOnProperty(name = "test.config", havingValue = "logRecordDiffIgnoreNullValue") +public class TestLogRecordDiffIgnoreNullValueService implements IOperationLogGetService { + + @Override + public boolean createLog(LogDTO logDTO) throws Exception { + + log.info("logDTO: [{}]", JSON.toJSONString(logDTO)); + + if ("testLogRecordDiffIgnoreNewObjectNullValue".equals(logDTO.getBizType())) { + TestHelper.putLogDTO("testLogRecordDiffIgnoreNewObjectNullValue", logDTO); + TestHelper.releaseLock("testLogRecordDiffIgnoreNewObjectNullValue"); + } + + return true; + } +} diff --git a/src/test/java/cn/monitor4all/logRecord/test/service/TestService.java b/src/test/java/cn/monitor4all/logRecord/test/service/TestService.java index a1adf11..433a4a5 100644 --- a/src/test/java/cn/monitor4all/logRecord/test/service/TestService.java +++ b/src/test/java/cn/monitor4all/logRecord/test/service/TestService.java @@ -135,6 +135,12 @@ public void testLogRecordDiffIgnoreField(TestComplexUser testComplexUser) { Arrays.asList("小张三", "大张三"), "前端")); } + @OperationLog(bizId = "'1'", bizType = "'testLogRecordDiffIgnoreNewObjectNullValue'", msg = "#_DIFF(#oldObject, #testComplexUser)") + public void testLogRecordDiffIgnoreNewObjectNullValue(TestComplexUser testComplexUser) { + LogRecordContext.putVariable("oldObject", new TestComplexUser(1, "张三", null, + Arrays.asList("小张三", "大张三"), "前端")); + } + @OperationLog(bizId = "'1'", bizType = "'testLogRecordDiffNestedClass'", msg = "#_DIFF(#oldObject, #testDiffUserParam)") public void testLogRecordDiffNestedClass(TestDiffUserParam testDiffUserParam) { TestDiffUserVO testDiffUserVO = new TestDiffUserVO(); diff --git a/src/test/resources/testException.properties b/src/test/resources/testException.properties index 432dd47..694c494 100644 --- a/src/test/resources/testException.properties +++ b/src/test/resources/testException.properties @@ -1,3 +1,2 @@ test.config=exception -log-record.retry.retry-times=3 -#log-record.thread-pool.enabled=false \ No newline at end of file +log-record.retry.retry-times=3 \ No newline at end of file diff --git a/src/test/resources/testLogRecordDiffIgnoreNullValue.properties b/src/test/resources/testLogRecordDiffIgnoreNullValue.properties new file mode 100644 index 0000000..efe024f --- /dev/null +++ b/src/test/resources/testLogRecordDiffIgnoreNullValue.properties @@ -0,0 +1,3 @@ +test.config=logRecordDiffIgnoreNullValue +log-record.diffIgnoreNewObjectNullValue=true +log-record.diffIgnoreOldObjectNullValue=true \ No newline at end of file diff --git a/src/test/resources/testNormal.properties b/src/test/resources/testNormal.properties index 2663be1..732172a 100644 --- a/src/test/resources/testNormal.properties +++ b/src/test/resources/testNormal.properties @@ -1,2 +1 @@ -test.config=normal -#log-record.thread-pool.enabled=false \ No newline at end of file +test.config=normal \ No newline at end of file