All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kim.sesame.framework.serial.service.SerialNumberService Maven / Gradle / Ivy

There is a newer version: 1.21
Show newest version
package kim.sesame.framework.serial.service;

import kim.sesame.framework.lock.service.DistributedLocker;
import kim.sesame.framework.mybatis.dao.BaseDao;
import kim.sesame.framework.serial.dao.SerialNumberRuleDao;
import kim.sesame.framework.serial.define.ISerialNumberService;
import kim.sesame.framework.serial.define.SerialNumberRule;
import kim.sesame.framework.serial.entity.SerialNumberRuleEntity;
import kim.sesame.framework.utils.Argument;
import kim.sesame.framework.utils.DateUtils;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;

/**
 * 序列号Service
 **/
@Service
@CommonsLog
public class SerialNumberService implements ISerialNumberService, InitializingBean {

    /**
     * Redis 锁前缀
     */
    private static final String LOCK_KEY_PREFIX = "serial_number_lock";

    @SuppressWarnings("all")
    @Autowired
    private SerialNumberRuleDao serialNumberRuleDao;
    @Autowired
    private BaseDao baseDao;

    @Autowired
    private DistributedLocker locker;


    @Override
    public void afterPropertiesSet() throws Exception {
        serialNumberRuleDao.check_notExistsCreate();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public String generateSerialNumber(SerialNumberRule serialNumberRule, String... params) {
        Argument.notNull(serialNumberRule, "序号规则不能为空!");
        String lockKey = LOCK_KEY_PREFIX + serialNumberRule.getCode();

        log.info("获取Redis分布式锁:" + serialNumberRule.getCode());
        try {
            locker.lock(lockKey);
            log.info("Redis分布式锁加锁成功:" + lockKey);

            SerialNumberRuleEntity serialNumberRuleEntity = getSerialNumberRule(serialNumberRule);
            SerialNumberEntry result = spliceSerialNumber(serialNumberRule,
                    serialNumberRuleEntity, true, params);
            serialNumberRuleEntity.setCurTime(Calendar.getInstance().getTime());
            serialNumberRuleEntity.setCurNum(result.getNextSequenceValue());
            serialNumberRuleDao.updateSerialNumberRule(serialNumberRuleEntity);
            return result.getSerialNumber();
        } finally {
            locker.unlock(lockKey);
            log.info("Redis分布式锁释放锁成功:" + lockKey);
        }

    }

    /**
     * 获取序号
     *
     * @param serialNumberRule
     * @return
     */
    private SerialNumberRuleEntity getSerialNumberRule(SerialNumberRule serialNumberRule) {
        // 根据业务类型查询序号并添加悲观锁
        SerialNumberRuleEntity serialNumberRuleEntity = serialNumberRuleDao
                .querySerialNumberRuleForUpdate(serialNumberRule.getCode());
        if (serialNumberRuleEntity == null) {
            // 业务类型序号不存在则添加序号信息
            serialNumberRuleEntity = new SerialNumberRuleEntity();
            serialNumberRuleEntity.setId(serialNumberRule.getCode());
            serialNumberRuleEntity.setCode(serialNumberRule.getCode());
            serialNumberRuleEntity.setName(serialNumberRule.getName());
            serialNumberRuleEntity.setCurNum(0L);
            serialNumberRuleEntity.setCurTime(new Date());
            serialNumberRuleDao.addSerialNumberRule(serialNumberRuleEntity);
            // 新增序号后添加悲观锁
            serialNumberRuleEntity = serialNumberRuleDao
                    .querySerialNumberRuleForUpdate(serialNumberRule.getCode());
        }
        return serialNumberRuleEntity;
    }

    /**
     * 拼接序号
     *
     * @param serialNumberRule       序号规则
     * @param serialNumberRuleEntity 序号实体
     * @param params                 参数
     */
    private SerialNumberEntry spliceSerialNumber(
            SerialNumberRule serialNumberRule,
            SerialNumberRuleEntity serialNumberRuleEntity, boolean formal,
            String[] params) {
        StringBuffer newCode = new StringBuffer();
        long newSeq = 0;
        boolean resetNo = false;
        if (serialNumberRule.isNeedParams()) {
            // todo 需要拼接参数待实现

        }
        // 是否需要时间
        if (serialNumberRule.isNeedTime()) {
            // 如果对于上一个已生成的编号已跨天,需重置对应的sequence
            String currentDate = DateUtils.convert(
                    serialNumberRuleEntity.getCurTime(),
                    DateUtils.DATE_FORMAT);
            String nowDate = DateUtils.convert(
                    Calendar.getInstance().getTime(), DateUtils.DATE_FORMAT);
            Long differDayNum = DateUtils.getTimeDiff(currentDate, nowDate);
            if (differDayNum > 0) {
                resetNo = true;
            }
        }
        // 字母前缀
        if (serialNumberRule.isNeedLetterPrefix()) {
            newCode.append(serialNumberRule.getLetterPrefix());
        }
        // 时间前缀
        if (serialNumberRule.isNeedTime()) {
            newCode.append(DateUtils.convert(Calendar.getInstance().getTime(), serialNumberRule.getTimeFormat()));
        }
        // 分隔符
        if (serialNumberRule.isNeedDelimiter()) {
            newCode.append(serialNumberRule.getDelimiter());
        }
        // 数字项
        if (serialNumberRule.isNeedNumber()) {
            // 针对日期+数字情况,如果跨天,则重置为1
            if (resetNo) {
                newSeq = 1;
                // 针对无需重置的情况,使当前值累加1
            } else {
                newSeq = serialNumberRuleEntity.getCurNum() + 1;
            }
            // 数字项是否固定位数
            if (serialNumberRule.isFixedNumLen()) {
                newCode.append(String.format("%0" + serialNumberRule.getNumLen() + "d", newSeq));
            } else {
                newCode.append(String.valueOf(newSeq));
            }
        }
        // 后缀
        if (serialNumberRule.isNeedLetterSuffix()) {
            newCode.append(serialNumberRule.getLetterSuffix());
        }
        return new SerialNumberEntry(newCode.toString(), Long.valueOf(newSeq));
    }

    private class SerialNumberEntry {
        /**
         * 生成的序号
         */
        private String serialNumber;
        /**
         * 下一个序列值
         */
        private Long nextSequenceValue;

        public SerialNumberEntry(String serialNumber, long nextSequenceValue) {
            this.serialNumber = serialNumber;
            this.nextSequenceValue = nextSequenceValue;
        }

        public String getSerialNumber() {
            return serialNumber;
        }

        public void setSerialNumber(String serialNumber) {
            this.serialNumber = serialNumber;
        }

        public long getNextSequenceValue() {
            return nextSequenceValue;
        }

        public void setNextSequenceValue(long nextSequenceValue) {
            this.nextSequenceValue = nextSequenceValue;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy