Java使用更优雅的代码记录操作日志变更记录

场景1

系统中经常会记录数据的更改日志,记录数据的变更前的内容变更后的内容。而且有时候会记录数据的多个字段的变更前和变更后的内容(如状态的变更前后、用户的变更前后、金额的变更前后,而且有的内容不发生变更的时候,不需要进行记录)。

现在有日志记录实体类如下:

package com.wangcp.changelog.entity;

import lombok.Data;

import java.math.BigDecimal;

/**
 * 日志记录实体
 *
 * @author wangcp
 * <br/>date 2021-06-24
 */
@Data
public class RecordChangeLog {
    /**
     * 操作
     */
    private String operate;

    /**
     * 操作人
     */
    private String operateUser;

    /**
     * 操作时间
     */
    private Long operateTime;

    /**
     * “状态”变更前
     */
    private String statusBefore;

    /**
     * ”状态“变更后
     */
    private String statusAfter;

    /**
     * "金额"变更前
     */
    private BigDecimal moneyBefore;

    /**
     * "金额"更能后
     */
    private BigDecimal moneyAfter;
}

此种需求通常的实现方式为:

RecordChangeLog recordChangeLog = new RecordChangeLog();
recordChangeLog.setOperate("xxx操作");
recordChangeLog.setOperateUser("张三");
recordChangeLog.setOperateTime(System.currentTimeMillis());
// 如果“状态Status”变更了,则记录
recordChangeLog.setStatusBefore("变更前状态");
recordChangeLog.setStatusBefore("变更后状态");
// 如果“金额Money”变更了,则记录
recordChangeLog.setMoneyBefore(new BigDecimal(100));
recordChangeLog.setMoneyAfter(new BigDecimal(200));

但采用该种方式,缺点如下:

  • 写set方法设置参数的时候,容易遗漏,或者写错调用的set方法,导致日志记录的错误。
  • 代码冗余量太大,如果日志记录的属性较多时,封装成通用方法也较为复杂
  • 代码不明确,无法明确此次记录到底需要更改记录哪些属性。

2 代码实现

下面优化原代码,对日志实体类进行包装实现。

package com.wangcp.changelog.config;

import com.wangcp.changelog.entity.RecordChangeLog;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;

/**
 * 日志包装器
 *
 * @author wangcp
 * <br/>date 2021-06-24
 */
public class RecordChangeLogWrapper {

    private RecordChangeLog recordChangeLog;


    /**
     * 构造函数
     * @param operate  操作类型(可用枚举代替)
     * @param opearteUser  操作人
     * @return
     * @author wangcp
     * <br/>date 2021-06-24
     */
    public RecordChangeLogWrapper(String operate , String opearteUser) {
        if(StringUtils.isEmpty(operate) || StringUtils.isEmpty(opearteUser)){
            throw new IllegalArgumentException("operate or opearteUser is null");
        }
        recordChangeLog = new RecordChangeLog();
        recordChangeLog.setOperate(operate);
        recordChangeLog.setOperateUser(opearteUser);
        recordChangeLog.setOperateTime(System.currentTimeMillis());
    }

    /**
     * 获取实例
     * @return
     */
    public RecordChangeLog getInstance(){
        return this.recordChangeLog;
    }

    /**
     * 变更状态
     * @param statusBefore 状态  变更前
     * @param statusAfter  状态  变更后
     * @return
     */
    public RecordChangeLogWrapper  changeStatus(String statusBefore , String statusAfter){
        this.recordChangeLog.setStatusBefore(statusBefore);
        this.recordChangeLog.setStatusAfter(statusAfter);
        return this;
    }

    /**
     * 变更金额
     * @param moneyBefore 金额   变更前
     * @param moneyAfter  金额   变更后
     * @return
     */
    public RecordChangeLogWrapper changeMoney(BigDecimal moneyBefore , BigDecimal moneyAfter){
        this.recordChangeLog.setMoneyBefore(moneyBefore);
        this.recordChangeLog.setMoneyAfter(moneyAfter);
        return this;
    }
}

使用方式如下:

/**
  * 调用包装类初始化日志数据
  */
public void testNewLog(){
    // 更改状态与金额
    RecordChangeLogWrapper recordChangeLogWrapper1 = new RecordChangeLogWrapper("新增操作" , "张三")
        .changeMoney(new BigDecimal(100) , new BigDecimal(200))
        .changeStatus("待审核" , "审核通过");
    RecordChangeLog recordChangeLog1 = recordChangeLogWrapper1.getInstance();

    // 更改状态
    RecordChangeLogWrapper recordChangeLogWrapper2 = new RecordChangeLogWrapper("修改操作" , "李四")
        .changeStatus("待审核" , "驳回");
    RecordChangeLog recordChangeLog2 = recordChangeLogWrapper2.getInstance();

    // 更改金额
    RecordChangeLogWrapper recordChangeLogWrapper3 = new RecordChangeLogWrapper("删除操作" , "王大")
        .changeMoney(new BigDecimal(200) , new BigDecimal(500));
    RecordChangeLog recordChangeLog3 = recordChangeLogWrapper3.getInstance();
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容