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

你可能感兴趣的:(Java架构专栏,深蓝计划,spring,spring,boot,数据库)