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.exception.ServiceException; 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.HashSet; import java.util.List; import java.util.Set; 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; private static final long LOCK_WAIT_TIME = 5; // 尝试获取锁最大等待时间(秒) private static final long LOCK_LEASE_TIME = 10; // 锁的自动释放时间(秒) @Override public String getNoByKey(SystemDataNoEnum systemDataNoEnum) { String baseNo = systemDataNoEnum.getNo(); if (StringUtils.isEmpty(baseNo)) { return ""; } String dayKey = DateUtils.dateTime(); String fullKey = baseNo + dayKey; RLock lock = redisLock.getRLock(Constants.SYS_DATASERIALNUMBER_KEYPREFIX + fullKey); boolean locked = false; try { locked = lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, TimeUnit.SECONDS); if (!locked) { throw new RuntimeException("获取锁失败,请稍后重试"); } log.info("{}进入", Thread.currentThread().getName()); Integer serial = getOrInitSerialNumber(fullKey, baseNo, dayKey); redisCache.setCacheObject(fullKey, serial, 1, TimeUnit.DAYS); return formatSerialNumber(fullKey, serial); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("获取锁异常", e); } finally { if (locked) { unlockIfHeld(lock); } } } private void unlockIfHeld(RLock lock) { try { if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } catch (Exception e) { log.warn("释放锁异常: {}", e.getMessage(), e); } } // 以下方法保持原样 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); } }