需求:
WT拼接时间日期再生成两位递增流水号,每天最多添加100份。
格式类似这样
接下来是我的代码实现,一个工具类可以直接引入然后生成,剩下的可以根据自己的需求更改。
public class ApplyOrderNumberUtil {
@Autowired
private DelegateSignSheetMapper delegateSignSheetMapper;
@Autowired
private StringRedisTemplate redisTemplate;
private static final ThreadLocal<SimpleDateFormat> dateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
private static final ThreadLocal<DecimalFormat> decimalFormat = ThreadLocal.withInitial(() -> new DecimalFormat("00"));
public String generateCode() {
String codes = "WT" + dateFormat.get().format(new Date());
String maxCode;
String newCode;
String lockKey = "lock:" + getUuid(); // mac地址作为唯一标识符
boolean locked = false;
try {
locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked", 5, TimeUnit.SECONDS);
if (locked) {
maxCode = delegateSignSheetMapper.maxRoundCode(codes);
if (StringUtils.isEmpty(maxCode)) {
newCode = codes + "01";
} else {
String getMaxCode = maxCode.substring(10, 12);
newCode = codes + getNum(getMaxCode);
int nums = Integer.parseInt(getMaxCode);
if (nums >= 99) {
return null;
}
}
} else {
log.info("获取锁失败");
throw new RuntimeException("获取锁失败");
}
} catch (Exception e) {
log.error("加锁出现异常", e); // 修改日志输出方式
throw new RuntimeException("加锁出现异常", e);
} finally {
if (locked) {
try {
String lockValue = redisTemplate.opsForValue().get(lockKey);
if (lockValue != null && lockValue.equals("locked")) {
redisTemplate.delete(lockKey);
}
} catch (Exception e) {
log.error("删除锁出现异常", e);
}
}
}
return newCode;
}
private static String getNum(String code) {
String roundCode = "01";
if (code != null && !code.isEmpty()) {
int intCode = Integer.parseInt(code) + 1;
if (intCode < 99) {
roundCode = String.format(String.valueOf(intCode));
}
}
String newCode = decimalFormat.get().format(Integer.parseInt(roundCode));
return newCode;
}
private static String getUuid() {
String uuid = "";
try {
InetAddress address = InetAddress.getLocalHost();
NetworkInterface ni = NetworkInterface.getByInetAddress(address);
byte[] mac = ni.getHardwareAddress();
uuid = Arrays.toString(mac);
} catch (Exception e) {
log.error("获取uuid出现异常", e);
throw new RuntimeException("获取uuid出现异常", e);
}
return uuid;
}
}
这里是maxRoundCode()方法的实现sql,我这里用oracle实现的,mysql数据库的话可以对照这个格式转换
SELECT
MAX(application_number)
FROM
delegate_sign_sheet
WHERE
SUBSTR(application_number,3,8) LIKE TO_CHAR(SYSDATE,'YYYYMMDD')
最后说一下我公司并发量很小,所以不确定高并发会出现哪些问题,有经验的同学欢迎留下建议!感谢!