You've already forked FrameTour-BE
fix(pricing): 优化优惠券打印流水号生成逻辑
-引入 AtomicLong 作为原子计数器,确保流水号的唯一性 - 修改生成流水号的方法,使用毫秒级时间戳和原子计数器组合 - 新方案解决了原方法在高并发情况下可能出现的重复流水号问题 - 优化了 FaceEntity 查询逻辑,确保 faceId 属于当前用户
This commit is contained in:
@@ -23,6 +23,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* 优惠券打印服务实现
|
||||
@@ -44,7 +45,9 @@ public class VoucherPrintServiceImpl implements VoucherPrintService {
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
private static final String PRINT_LOCK_KEY = "voucher_print_lock:%s:%s:%s"; // faceId:brokerId:scenicId
|
||||
private static final String CODE_PREFIX = "VT"; // Voucher Ticket
|
||||
|
||||
// 原子计数器,确保流水号唯一性
|
||||
private static final AtomicLong counter = new AtomicLong(0);
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -56,9 +59,11 @@ public class VoucherPrintServiceImpl implements VoucherPrintService {
|
||||
if (request.getBrokerId() == null) {
|
||||
throw new BaseException("经纪人ID不能为空");
|
||||
}
|
||||
if (request.getScenicId() == null) {
|
||||
throw new BaseException("景区ID不能为空");
|
||||
FaceEntity face = faceRepository.getFace(request.getFaceId());
|
||||
if (face == null) {
|
||||
throw new BaseException("请上传人脸");
|
||||
}
|
||||
request.setScenicId(face.getScenicId());
|
||||
|
||||
Long currentUserId = Long.valueOf(BaseContextHandler.getUserId());
|
||||
|
||||
@@ -149,13 +154,16 @@ public class VoucherPrintServiceImpl implements VoucherPrintService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成流水号
|
||||
* 生成流水号(优化版本)
|
||||
* 使用原子计数器确保唯一性,解决原方法在高并发下的重复问题
|
||||
*/
|
||||
private String generateCode() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
// 方案:使用毫秒级时间戳 + 原子计数器
|
||||
// 格式:5位计数器 + SSS
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("SSS");
|
||||
String timestamp = sdf.format(new Date());
|
||||
String randomSuffix = String.valueOf((int)(Math.random() * 1000)).formatted("%03d");
|
||||
return CODE_PREFIX + timestamp + randomSuffix;
|
||||
long count = counter.incrementAndGet() % 100000; // 5位计数,循环使用
|
||||
return String.format("%05d", count) + timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user