springboot 记录数据修改前和修改后的记录返回给前端
时间: 2024-05-09 07:21:50 浏览: 95
可以使用 Spring AOP 的方式,在数据更新时拦截相关方法,将数据修改前后的差异信息记录下来,然后将记录返回给前端。以下是简单的代码示例:
首先定义一个切面类,用于拦截数据更新方法:
```java
@Aspect
@Component
public class DataChangeAspect {
@Autowired
private HttpServletRequest request;
@Pointcut("execution(public * com.example.demo.service.*.update*(..))")
public void updatePointcut() {}
@Around("updatePointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法名
String methodName = joinPoint.getSignature().getName();
// 获取参数列表
Object[] args = joinPoint.getArgs();
// 获取被更新的实体对象
Object entityObject = args[0];
// 获取原始实体对象
Object originalObject = getOriginalEntityObject(entityObject);
// 执行方法
Object result = joinPoint.proceed();
// 记录数据差异并返回给前端
recordDataChange(originalObject, entityObject);
return result;
}
/**
* 获取原始实体对象
*/
private Object getOriginalEntityObject(Object entityObject) {
// 根据实体对象的 ID 查询原始实体对象
// 这里需要根据具体业务进行实现
Long entityId = ((BaseEntity) entityObject).getId();
return entityManager.find(entityObject.getClass(), entityId);
}
/**
* 记录数据差异并返回给前端
*/
private void recordDataChange(Object originalObject, Object entityObject) {
// 计算数据差异
Map<String, Object> diffMap = getDiff(originalObject, entityObject);
// 将差异信息记录到日志中
String diffStr = convertDiffMapToString(diffMap);
logService.info("数据修改前后差异:" + diffStr);
// 将差异信息返回给前端
request.setAttribute("dataDiff", diffMap);
}
/**
* 计算实体对象的属性差异信息
*/
private Map<String, Object> getDiff(Object originalObject, Object entityObject) {
Map<String, Object> diffMap = new HashMap<>();
Class<?> clazz = entityObject.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 非持久化字段不参与差异计算
if (!field.isAnnotationPresent(Column.class)) {
continue;
}
String fieldName = field.getName();
Object originalValue = ReflectionUtils.getFieldValue(originalObject, fieldName);
Object newValue = ReflectionUtils.getFieldValue(entityObject, fieldName);
if (originalValue == null || !originalValue.equals(newValue)) {
diffMap.put(fieldName, newValue);
}
}
return diffMap;
}
/**
* 将差异信息转换为字符串
*/
private String convertDiffMapToString(Map<String, Object> diffMap) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> entry : diffMap.entrySet()) {
sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(",");
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
```
然后,使用 AOP 拦截 Spring Data JPA 的 save 或 update 方法:
```java
@Aspect
@Component
public class JpaRepositoryAspect {
@Autowired
private HttpServletRequest request;
@Around("execution(public * org.springframework.data.jpa.repository.JpaRepository+.save(..)) || execution(public * org.springframework.data.jpa.repository.JpaRepository+.saveAndFlush(..))")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取被保存或更新的实体对象
Object entityObject = joinPoint.getArgs()[0];
// 记录数据变化并返回给前端
request.setAttribute("originalData", entityObject);
Object result = joinPoint.proceed();
request.setAttribute("modifiedData", entityObject);
return result;
}
}
```
最后,在 Controller 中获取前面拦截器中记录的数据差异信息和修改前后的实体对象:
```java
@RestController
public class DataController {
@GetMapping("/users/{userId}")
public User getUser(@PathVariable Long userId, HttpServletRequest request) {
// 查询用户
User user = userRepository.findById(userId).orElse(null);
// 获取数据差异信息
Map<String, Object> dataDiff = (Map<String, Object>) request.getAttribute("dataDiff");
// 获取修改前的实体对象
User originalData = (User) request.getAttribute("originalData");
// 获取修改后的实体对象
User modifiedData = (User) request.getAttribute("modifiedData");
// 合并差异信息到修改后的实体对象中
mergeDiffIntoModifiedData(modifiedData, dataDiff);
return modifiedData;
}
/**
* 将数据差异合并到修改后的实体对象中
*/
private void mergeDiffIntoModifiedData(User modifiedData, Map<String, Object> dataDiff) {
if (dataDiff == null || dataDiff.isEmpty()) {
return;
}
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(modifiedData);
beanWrapper.setAutoGrowNestedPaths(true);
for (Map.Entry<String, Object> entry : dataDiff.entrySet()) {
String fieldName = entry.getKey();
Object value = entry.getValue();
beanWrapper.setPropertyValue(fieldName, value);
}
}
}
```
阅读全文