package com.ruoyi.system.service.impl; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisLock; import com.ruoyi.common.enums.SystemDataNoEnum; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysSerialNumber; import com.ruoyi.system.service.ISysSerialNumberService; import com.ruoyi.system.service.ISystemDataNoService; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.List; import java.util.concurrent.TimeUnit; @Slf4j @Service public class SystemDataNoServiceImpl implements ISystemDataNoService { @Autowired private RedisLock redisLock; @Autowired private RedisCache redisCache; /**流水号启用缓存*/ @Value("${custom.serialNumber.cache.enabled:false}") private boolean serialNumberCache; @Autowired private ISysSerialNumberService serialNumberService; @Override public String getNoByKey(SystemDataNoEnum systemDataNoEnum) { String baseNo = systemDataNoEnum.getNo(); if (StringUtils.isEmpty(baseNo)) { return ""; } String dayKey = DateUtils.dateYYMM(); String fullKey = baseNo + dayKey; RLock lock = redisLock.lock(Constants.SYS_DATASERIALNUMBER_KEYPREFIX + fullKey); try { if (!lock.tryLock(60, TimeUnit.SECONDS)) { throw new RuntimeException("获取锁失败"); } log.info("{}进入", Thread.currentThread().getName()); Integer serial = getOrInitSerialNumber(fullKey, baseNo, dayKey); redisCache.setCacheObject(fullKey, serial, 1000, TimeUnit.DAYS); return formatSerialNumber(fullKey, serial); } catch (InterruptedException e) { throw new RuntimeException("获取锁异常", e); } finally { unlockIfHeld(lock); } } private Integer getOrInitSerialNumber(String fullKey, String baseNo, String dayKey) { Integer serial = serialNumberCache ? redisCache.getCacheObject(fullKey) : null; if (serial != null) { return serial + 1; } SysSerialNumber serialNumber = new SysSerialNumber(); serialNumber.setKeyStr(baseNo); serialNumber.setKeyAuxStr(dayKey); serialNumber.setNo(fullKey); List existingNumbers = serialNumberService.selectSysSerialNumberList(serialNumber); serial = existingNumbers != null && !existingNumbers.isEmpty() ? existingNumbers.get(0).getSerialNumber() : 0; if (serial == 0) { serialNumber.setSerialNumber(1); serialNumberService.insertSysSerialNumber(serialNumber); return 1; } return serial + 1; } private String formatSerialNumber(String prefix, Integer serial) { return prefix + String.format("%04d", serial); } private void unlockIfHeld(RLock lock) { if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } }