场景
在一数据库里有几张表,需要在触发字段更新的时候记录下来操作人和更新字段前后的值。不依赖MQ和监听binlog,直接自定义注解,基于AOP功能实现。最简单版本
实现
- 定义注解
@Target({ METHOD })
@Retention(RUNTIME)
public @interface RecordUpdate {
/**
* 对应表名
* @return
*/
String tableName();
/**
* 处理类
* @return
*/
Class<? extends UpdateAspectHandler> handler();
/**
* 表对应实体参数位置
* @return
*/
int tableEntityIndex();
/**
* 操作人ID参数位置
* @return
*/
int operatorIdIndex();
/**
* 操作人类型参数位置
* @return
*/
int operatorTypeIndex();
}
- 定义切面
@Aspect
@Component
public abstract class UpdateAspectHandler implements ApplicationContextAware {
private static Logger logger = LoggerFactory.getLogger(UpdateAspectHandler.class);
private ApplicationContext applicationContext;
@Before(value = "execution(public * com.simon.dataplatform..*(..)) && @annotation(com.simon.dataplatform.userprofile.annotation.RecordUpdate)")
public void before(JoinPoint joinPoint) throws NoSuchMethodException {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取方法
Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
// 获取参数
Object[] args = joinPoint.getArgs();
// 获取注解
RecordUpdate recordUpdate = method.getAnnotation(RecordUpdate.class);
if(ObjectUtil.isNull(recordUpdate)) {
return;
}
// 获取参数
String tableName = recordUpdate.tableName();
Object operatorId = args[recordUpdate.operatorIdIndex()];
Object operatorType = args[recordUpdate.operatorTypeIndex()];
Object tableEntity = args[recordUpdate.tableEntityIndex()];
try {
// 获取处理类代理对象
UpdateAspectHandler updateAspectHandler = applicationContext.getBean(recordUpdate.handler());
updateAspectHandler.processBefore(tableName,tableEntity,operatorId,operatorType);
} catch (Exception e) {
logger.info("UpdateAspectHandler.before tableName:{},operatorId:{},operatorType:{},tableEntity:{}",tableEntity,operatorId,operatorType, JSON.toJSON(tableEntity));
logger.error("UpdateAspectHandler.before error:{}",e);
}
}
/**
* 交由具体实现类处理
* @param tableName 表名
* @param tableEntity 表对应实体
* @param operatorId 操作人ID
* @param operatorType 操作人类型
*/
public abstract void processBefore(String tableName,Object tableEntity, Object operatorId, Object operatorType);
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
- 定义UserBaseExt表对应的处理类
@Component
public class UserBaseExtAspectHandler extends UpdateAspectHandler {
@Resource(name = "userBaseExtService")
private UserBaseExtService userBaseExtService;
@Resource(name = "userUpdateLogService")
private UserUpdateLogService userUpdateLogService;
/**
* 忽略的属性字段
*/
private List<String> ignoreFieldList = Arrays.asList("id,update_time,add_time".split(","));
@Override
public void processBefore(String tableName, Object tableEntity, Object operatorId, Object operatorType) {
UserBaseExt afterUserBaseExt = (UserBaseExt) tableEntity;
UserBaseExt beforeUserBaseExt = userBaseExtService.findByStuId(afterUserBaseExt.getStuId());
if(ObjectUtil.isNull(beforeUserBaseExt)) {
return;
}
Date date = new Date();
Field[] fields = ReflectUtil.getFields(UserBaseExt.class);
List<UserUpdateLog> userUpdateLogList = new ArrayList<>(fields.length);
for (Field field : fields) {
// 驼峰转蛇形工具类:实体userName,数据库user_name
String fieldName = ConvFieldNameUtil.camelToUnderline(field.getName());
if(ignoreFieldList.contains(fieldName) || Modifier.isStatic(field.getModifiers())){
continue;
}
Object afterValue = ReflectUtil.getFieldValue(afterUserBaseExt, field);
// null值底层不更新
Object afterValue = ReflectUtil.getFieldValue(after, field);
if(ObjectUtil.isNull(afterValue)){
continue;
}
Object beforeValue = ReflectUtil.getFieldValue(beforeUserBaseExt,field);
if(!ObjectUtil.equal(afterValue,beforeValue)) {
UserUpdateLog userUpdateLog = new UserUpdateLog();
userUpdateLog.setStuId(afterUserBaseExt.getStuId());
userUpdateLog.setOperatorId(Long.valueOf(String.valueOf(operatorId)));
userUpdateLog.setOperatorType(String.valueOf(operatorType));
userUpdateLog.setTableName(tableName);
userUpdateLog.setUpdateTime(date);
userUpdateLog.setFieldName(field.getName());
// 对于过长字符串进行截取
userUpdateLog.setBeforeValue(StrUtil.sub(beforeValue+"",0,128));
userUpdateLog.setAfterValue(StrUtil.sub(afterValue+"",0,128));
userUpdateLogList.add(userUpdateLog);
}
}
if(CollectionUtil.isNotEmpty(userUpdateLogList)) {
userUpdateLogService.insertBatch(userUpdateLogList);
}
}
}
- 使用
@Override
@Transactional(readOnly = false,rollbackFor = Exception.class)
@RecordUpdate(tableName = "user_base_ext",handler = UserBaseExtAspectHandler.class,tableEntityIndex = 0,operatorIdIndex = 1,operatorTypeIndex = 2)
public void updateByStuId(UserBaseExt userBaseExt,Long operatorId,String operatorType) {
userBaseExt.setUpdateTime(new Date());
userBaseExtDao.updateByStuId(userBaseExt);
}
网友评论