refactor: extract common utilities to manage-common
This commit is contained in:
-25
@@ -1,25 +0,0 @@
|
||||
package cn.novalon.manage.sys.core.constants;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 数据库字段名常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class FieldConstants {
|
||||
|
||||
public static final String USERNAME = "username";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String EMAIL = "email";
|
||||
public static final String PHONE = "phone";
|
||||
public static final String STATUS = "status";
|
||||
public static final String ROLE_NAME = "roleName";
|
||||
public static final String ROLE_KEY = "roleKey";
|
||||
public static final String MENU_NAME = "menuName";
|
||||
public static final String MENU_TYPE = "menuType";
|
||||
public static final String ROLE_ID = "roleId";
|
||||
public static final String PARENT_ID = "parentId";
|
||||
|
||||
private FieldConstants() {
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package cn.novalon.manage.sys.core.constants;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 菜单类型常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class MenuTypeConstants {
|
||||
|
||||
public static final String DIRECTORY = "M";
|
||||
public static final String MENU = "C";
|
||||
public static final String BUTTON = "F";
|
||||
|
||||
private MenuTypeConstants() {
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package cn.novalon.manage.sys.core.constants;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 状态常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class StatusConstants {
|
||||
|
||||
public static final Integer DISABLED = 0;
|
||||
public static final Integer ENABLED = 1;
|
||||
public static final Integer DELETED = 2;
|
||||
|
||||
private StatusConstants() {
|
||||
}
|
||||
}
|
||||
-220
@@ -1,220 +0,0 @@
|
||||
package cn.novalon.manage.sys.core.utils;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* Twitter的Snowflake算法实现(性能优化版)
|
||||
*
|
||||
* 优化点:
|
||||
* 1. 使用自适应等待策略,减少CPU空转
|
||||
* 2. 时间戳缓存机制,降低系统调用频率
|
||||
* 3. 增强CAS重试策略,提升并发性能
|
||||
* 4. 完善异常处理和资源管理
|
||||
*
|
||||
* @author zhangxiang
|
||||
* @version 2.0
|
||||
* @date 2026/03/11
|
||||
*/
|
||||
public final class SnowflakeId {
|
||||
|
||||
private static final int DEFAULT_WORKER_BITS = 10;
|
||||
private static final int DEFAULT_SEQ_BITS = 12;
|
||||
private static final long DEFAULT_EPOCH = 1582136402000L;
|
||||
private static final int MAX_RETRIES = 10;
|
||||
private static final long MAX_BACKWARD_MS = 50;
|
||||
private static final int SPIN_THRESHOLD = 5;
|
||||
private static final long TIME_CACHE_DURATION_MS = 16;
|
||||
|
||||
private static final AtomicLong lastTimestamp = new AtomicLong(-1L);
|
||||
private static final AtomicLong sequence = new AtomicLong(0);
|
||||
private static volatile SnowflakeConfig config;
|
||||
private static volatile long workerId;
|
||||
private static volatile long lastTimeCacheMs;
|
||||
private static volatile int timeCacheHits;
|
||||
|
||||
static {
|
||||
configure(DEFAULT_WORKER_BITS, DEFAULT_SEQ_BITS, DEFAULT_EPOCH);
|
||||
}
|
||||
|
||||
private static void configure(int workerBits, int seqBits, long epoch) {
|
||||
validateBits(workerBits, seqBits);
|
||||
config = new SnowflakeConfig(epoch, workerBits, seqBits);
|
||||
workerId = resolveWorkerId(config.maxWorkerId);
|
||||
lastTimeCacheMs = 0;
|
||||
timeCacheHits = 0;
|
||||
}
|
||||
|
||||
public static long nextId() {
|
||||
for (int i = 0; i < MAX_RETRIES; i++) {
|
||||
try {
|
||||
return nextIdInternal();
|
||||
} catch (ClockBackwardException e) {
|
||||
long backwardMs = e.getBackwardMs();
|
||||
if (backwardMs > MAX_BACKWARD_MS) {
|
||||
throw e;
|
||||
}
|
||||
if (i < SPIN_THRESHOLD) {
|
||||
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1));
|
||||
} else {
|
||||
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10));
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to generate ID after " + MAX_RETRIES + " retries");
|
||||
}
|
||||
|
||||
private static long nextIdInternal() {
|
||||
long currentTs = timeGen();
|
||||
long lastTs;
|
||||
long seq;
|
||||
|
||||
do {
|
||||
lastTs = lastTimestamp.get();
|
||||
|
||||
if (currentTs < lastTs) {
|
||||
long backwardMs = lastTs - currentTs;
|
||||
if (backwardMs <= MAX_BACKWARD_MS) {
|
||||
lastTimestamp.set(currentTs);
|
||||
lastTs = currentTs;
|
||||
} else {
|
||||
throw new ClockBackwardException(backwardMs);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentTs == lastTs) {
|
||||
seq = sequence.incrementAndGet() & config.sequenceMask;
|
||||
if (seq == 0) {
|
||||
currentTs = waitNextMillis(currentTs);
|
||||
}
|
||||
} else {
|
||||
seq = 0;
|
||||
}
|
||||
} while (!lastTimestamp.compareAndSet(lastTs, currentTs));
|
||||
|
||||
return ((currentTs - config.epoch) << config.timestampShift)
|
||||
| (workerId << config.workerShift)
|
||||
| seq;
|
||||
}
|
||||
|
||||
private static long waitNextMillis(long currentTs) {
|
||||
long deadline = currentTs + 2;
|
||||
int spinCount = 0;
|
||||
|
||||
while (currentTs <= lastTimestamp.get()) {
|
||||
if (currentTs >= deadline) {
|
||||
return currentTs;
|
||||
}
|
||||
|
||||
if (spinCount < 10) {
|
||||
spinCount++;
|
||||
} else if (spinCount < 50) {
|
||||
LockSupport.parkNanos(100_000);
|
||||
spinCount++;
|
||||
} else {
|
||||
LockSupport.parkNanos(500_000);
|
||||
}
|
||||
currentTs = timeGen();
|
||||
}
|
||||
return currentTs;
|
||||
}
|
||||
|
||||
private static long timeGen() {
|
||||
long now = System.currentTimeMillis();
|
||||
long cached = lastTimeCacheMs;
|
||||
|
||||
if (now - cached < TIME_CACHE_DURATION_MS) {
|
||||
timeCacheHits++;
|
||||
return cached;
|
||||
}
|
||||
|
||||
synchronized (SnowflakeId.class) {
|
||||
cached = lastTimeCacheMs;
|
||||
if (now - cached < TIME_CACHE_DURATION_MS) {
|
||||
timeCacheHits++;
|
||||
return cached;
|
||||
}
|
||||
lastTimeCacheMs = now;
|
||||
return now;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTimeCacheHits() {
|
||||
return timeCacheHits;
|
||||
}
|
||||
|
||||
public static void resetTimeCache() {
|
||||
synchronized (SnowflakeId.class) {
|
||||
lastTimeCacheMs = 0;
|
||||
timeCacheHits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateBits(int workerBits, int seqBits) {
|
||||
if (workerBits < 0 || workerBits > 22) {
|
||||
throw new IllegalArgumentException("WorkerID位数必须在0-22之间");
|
||||
}
|
||||
if (seqBits < 0 || seqBits > 22) {
|
||||
throw new IllegalArgumentException("序列号位数必须在0-22之间");
|
||||
}
|
||||
if (workerBits + seqBits > 22) {
|
||||
throw new IllegalArgumentException("WorkerID和序列号位数总和不能超过22位,当前为: " + (workerBits + seqBits));
|
||||
}
|
||||
if (workerBits + seqBits == 0) {
|
||||
throw new IllegalArgumentException("WorkerID和序列号位数总和不能为0");
|
||||
}
|
||||
}
|
||||
|
||||
private static long resolveWorkerId(long maxWorkerId) {
|
||||
long id = generateNewId();
|
||||
if (id < 0 || id > maxWorkerId) {
|
||||
throw new IllegalStateException("WorkerID超出有效范围: " + id + " (有效范围: 0-" + maxWorkerId + ")");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private static long generateNewId() {
|
||||
long newId = ThreadLocalRandom.current().nextLong(config.maxWorkerId + 1);
|
||||
return newId;
|
||||
}
|
||||
|
||||
public static void config(int workerBits, int seqBits, long epoch) {
|
||||
configure(workerBits, seqBits, epoch);
|
||||
}
|
||||
|
||||
public static long getWorkerId() {
|
||||
return workerId;
|
||||
}
|
||||
|
||||
private static class SnowflakeConfig {
|
||||
final long epoch;
|
||||
final int timestampShift;
|
||||
final int workerShift;
|
||||
final long sequenceMask;
|
||||
final long maxWorkerId;
|
||||
|
||||
SnowflakeConfig(long epoch, int workerBits, int seqBits) {
|
||||
this.epoch = epoch;
|
||||
this.timestampShift = workerBits + seqBits;
|
||||
this.workerShift = seqBits;
|
||||
this.sequenceMask = ~(-1L << seqBits);
|
||||
this.maxWorkerId = ~(-1L << workerBits);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ClockBackwardException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long backwardMs;
|
||||
|
||||
ClockBackwardException(long backwardMs) {
|
||||
super("Clock moved backwards by " + backwardMs + "ms");
|
||||
this.backwardMs = backwardMs;
|
||||
}
|
||||
|
||||
public long getBackwardMs() {
|
||||
return backwardMs;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user