| | |
| | | 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 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 |
| | |
| | | @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 |
| | |
| | | return ""; |
| | | } |
| | | |
| | | String dayKey = DateUtils.dateYYMM(); |
| | | String dayKey = DateUtils.dateTime(); |
| | | String fullKey = baseNo + dayKey; |
| | | RLock lock = redisLock.lock(Constants.SYS_DATASERIALNUMBER_KEYPREFIX + fullKey); |
| | | RLock lock = redisLock.getRLock(Constants.SYS_DATASERIALNUMBER_KEYPREFIX + fullKey); |
| | | |
| | | boolean locked = false; |
| | | try { |
| | | if (!lock.tryLock(60, TimeUnit.SECONDS)) { |
| | | throw new RuntimeException("获取锁失败"); |
| | | 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, 1000, TimeUnit.DAYS); |
| | | redisCache.setCacheObject(fullKey, serial, 1, TimeUnit.DAYS); |
| | | |
| | | return formatSerialNumber(fullKey, serial); |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | throw new RuntimeException("获取锁异常", e); |
| | | } finally { |
| | | unlockIfHeld(lock); |
| | | 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; |
| | | |
| | |
| | | return prefix + String.format("%04d", serial); |
| | | } |
| | | |
| | | private void unlockIfHeld(RLock lock) { |
| | | if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) { |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | |
| | | } |