Spring Boot 功能代码:基于注解+Spring AOP 记录业务数据修改前后记录。
Posted 在奋斗的大道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot 功能代码:基于注解+Spring AOP 记录业务数据修改前后记录。相关的知识,希望对你有一定的参考价值。
功能需求:今天在禅道上收到产品经理的新提功能需求:要求保存业务记录数据的前后变更情况。
核心功能点: 业务数据变更记录表、自定义注解、Spring AOP 。
数据库设计:
DROP TABLE IF EXISTS DATA_DEAL_RECORD;
CREATE TABLE DATA_DEAL_RECORD(
ID VARCHAR(64) NOT NULL COMMENT '主键' ,
TID VARCHAR(100) COMMENT '地市代码' ,
REGION_CODE VARCHAR(100) COMMENT '区域编码' ,
DATA_TABLE_NAME VARCHAR(100) COMMENT '数据类型表名' ,
DATA_ORIGIN_ID VARCHAR(100) COMMENT '数据项Id' ,
RECORD_TYPE VARCHAR(10) COMMENT '记录类型' ,
DEAL_TYPE VARCHAR(10) COMMENT '处理类型' ,
YWBH VARCHAR(100) COMMENT '业务编号/主键' ,
YWBJSJ DATETIME COMMENT '业务办结时间' ,
SJCRSJ DATETIME COMMENT '数据存入时间' ,
SOURCE_TYPE VARCHAR(10) COMMENT '来源渠道' ,
DATA_CONTENT VARCHAR(2000) COMMENT '数据内容' ,
ORI_DATA_CONTENT VARCHAR(2000) COMMENT '源数据内容' ,
SYS_CREATE_TIME DATETIME COMMENT '创建时间' ,
SYS_CREATE_ID VARCHAR(32) COMMENT '创建人id' ,
ORG_ID VARCHAR(64) COMMENT '创建者机构id' ,
SYS_CREATE_ORG_TYPE VARCHAR(10) COMMENT '创建者机构类型' ,
SYS_UPDATE_TIME DATETIME COMMENT '修改时间' ,
SYS_UPDATE_ID VARCHAR(32) COMMENT '修改人id' ,
SYS_DELETE_TIME DATETIME COMMENT '删除时间' ,
SYS_DELETE_ID VARCHAR(32) COMMENT '删除人id' ,
IS_DELETE VARCHAR(10) COMMENT '逻辑删除标志' ,
PRIMARY KEY (ID)
) COMMENT = '数据的处理记录';
Java 核心功能代码设计
自定义注解:RecordChange
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
improt com.zzg.common.dao.BaseDao;
import com.zzg.common.enums.DealType
import com.zzg.common.model.po.BasePO;
@Documented
@RetentionPolicy(value =RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD, ElementType.TYPE)
public @interface RecordChange
/**
* 操作类型:1 新增, 2 修改
**/
DealType opera();
/**
* dao 接口实现
**/
Class<? extends BaseDao<? extends BasePO> mapper();
Spring AOP代码:RecordChangeAspectj
@Component
@Aspect
public class RecordChangeAspectj
public static final Logger LOG = LoggerFactory.getLogger(RecordChangeAspectj.class);
@Resource
private IDataDealRecordDao dataDealRecordDao;
public RecordChangeAspectj()
@Point("annotation(com.zzg.common.annotation.RecordChange)")
public void around()
@Around("around()")
public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable
LOG.info("开始处理@RecordChange注解")
// 获取请求参数
Object obj = getArg(joinPoint);
// 获取RecordChange 注解
RecordChange recordChange = getRecordChange(joinPoint);
if(ObjectUtils.isNull(recordChange))
throw new CommonException("缺少RecordChange 注解标签")
// 获取操作类型
DealType operate = getOpera(recordChange);
// 获取Dao接口定义
Class dao = getDao(recordChange);
// 上次指定记录变更内容
BasePo oriDataContent = null;
// 请求参数BO 转PO
BasePO basePO = BeanCopierUtil.copy(obj, BasePO.class);
// 通过Spring 容器工具类, 获取Dao接口实现类, 通过Class Dao接口名
BaseDao baseDao = (BaseDao) SpringContextUtil.getBean(dao);
if(ObjectUtils.isNull(baseDao ))
throw new CommonException("为找到指定Dao接口实现类")
// 获取操作业务实体表面
String tableName = baseDao.getTableName();
// 新增
if(operate.equal(DealType.Add))
addRecord(tableName, DealType.Add.getCode(), SourceType.Two.getCode(), obj, oriDataContent);
// 变更
if(operate.equal(DealType.Update))
String id = basePO.getId();
if(StringUtils.isEmpty(id))
throw new CommonException("缺少Id 参数")
oriDataContent =(BasePO)baseDao.selectById(id);
addRecord(tableName, DealType.Add.getCode(), SourceType.Two.getCode(), obj, oriDataContent);
// 继续执行方法请求
return joinPoint.proceed();
private Object getArg(ProceedingJoinPoint joinPoint)
Object[] args = joinPoint.getArgs();
if(ObjectUtils.isNull(args) || args.length < 1)
// 抛出自定义异常
throw new CommonException("请求参数缺失");
return args[0];
private RecordChange getRecordChange(ProceedingJoinPoint joinPoint)
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature )signature;
Method method = methodSignature.getMethod();
if(ObjectUtils.nonNull(method ))
return method.getAnnotation(RecordChange.class);
return null;
private DealType getOpera(RecordChange recordChange)
return recordChange.opera();
private Class getDao(RecordChange recordChange)
return recordChange.mapper();
private void addRecord(String tableName, String dealType, String sourceType, BasePO basePO, Object dataContent, BasePO oriDataContent )
DataDealRecordPO dataDealRecordPO = new DataDealRecordPO ();
dataDealRecordPO.setDataTableName(tableName);
dataDealRecordPO.setDataOriginId(basePO.getId());
dataDealRecordPO.setRecordType(RecordType.Two.getCode());
dataDealRecordPO.setDealType(dealType);
dataDealRecordPO.setYwbjsj(basePO.getYwbjsj());
dataDealRecordPO.setSjcrsj(basePO.getSjcrsj());
dataDealRecordPO.setSourceType(sourceType);
dataDealRecordPO.setTid(basePO.getTid());
dataDealRecordPO.setRegionCode(basePO.getRegionCode());
if(Objects.nonNull(dataContent))
dataDealRecordPO.setDataContent(JacksonUtil.fromObjectToJson(dataContent))
if(Objects.nonNull(oriDataContent ))
dataDealRecordPO.setOriDataContent(JacksonUtil.fromObjectToJson(oriDataContent ))
dataDealRecordDao.insert(dataDealRecordPO);
在业务服务实现类中添加RecordChange 注解,重点关注新增方法和修改方法
在房屋业务服务实现类:HouseServiceImpl.java
@Override
@Transactional(rollbackFor = Exception.class)
@RecordChange(opera = DealType.Update, mapper=IHouseDao.class)
public boolean updateById(HouseBO houseBO)
return houseDao.updateById(BeanCopierUtil.copy(houseBO, HousePO.class));
@Override
@Transactional(rollbackFor = Exception.class)
@RecordChange(opera = DealType.Add, mapper=IHouseDao.class)
public String saveGeneratedId(HouseBO houseBO)
return houseDao.insertGeneratedId(BeanCopierUtil.copy(houseBO, HousePO.class));
以上是关于Spring Boot 功能代码:基于注解+Spring AOP 记录业务数据修改前后记录。的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 中使用 @Transactional 注解配置事务管理
Spring Boot 中使用 @Transactional 注解配置事务管理
Spring Boot 中使用 @Transactional 注解配置事务管理