diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowFlake.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowFlake.java new file mode 100644 index 0000000..9d260c7 --- /dev/null +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowFlake.java @@ -0,0 +1,110 @@ +package cn.estsh.i3plus.pojo.base.codemaker; + +/** + * @Description : 备用算法 + * @Reference : + * @Author : alwaysfrin + * @CreateDate : 2019-01-10 13:11 + * @Modify: + **/ +@Deprecated +public class SnowFlake { + // 起始的时间戳 + private final static long START_STMP = 1480166465631L; + // 每一部分占用的位数,就三个 + private final static long SEQUENCE_BIT = 12;// 序列号占用的位数 + private final static long MACHINE_BIT = 5; // 机器标识占用的位数 + private final static long DATACENTER_BIT = 5;// 数据中心占用的位数 + // 每一部分最大值 + private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); + private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); + private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); + // 每一部分向左的位移 + private final static long MACHINE_LEFT = SEQUENCE_BIT; + private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; + private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; + private long datacenterId; // 数据中心 + private long machineId; // 机器标识 + private long sequence = 0L; // 序列号 + private long lastStmp = -1L;// 上一次时间戳 + + public SnowFlake(long datacenterId, long machineId) { + if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { + throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0"); + } + if (machineId > MAX_MACHINE_NUM || machineId < 0) { + throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); + } + this.datacenterId = datacenterId; + this.machineId = machineId; + } + //产生下一个ID + public synchronized long nextId() { + long currStmp = getNewstmp(); + if (currStmp < lastStmp) { + throw new RuntimeException("Clock moved backwards. Refusing to generate id"); + } + + if (currStmp == lastStmp) { + //if条件里表示当前调用和上一次调用落在了相同毫秒内,只能通过第三部分,序列号自增来判断为唯一,所以+1. + sequence = (sequence + 1) & MAX_SEQUENCE; + //同一毫秒的序列数已经达到最大,只能等待下一个毫秒 + if (sequence == 0L) { + currStmp = getNextMill(); + } + } else { + //不同毫秒内,序列号置为0 + //执行到这个分支的前提是currTimestamp > lastTimestamp,说明本次调用跟上次调用对比,已经不再同一个毫秒内了,这个时候序号可以重新回置0了。 + sequence = 0L; + } + + lastStmp = currStmp; + //就是用相对毫秒数、机器ID和自增序号拼接 + return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分 + | datacenterId << DATACENTER_LEFT //数据中心部分 + | machineId << MACHINE_LEFT //机器标识部分 + | sequence; //序列号部分 + } + + private long getNextMill() { + long mill = getNewstmp(); + while (mill <= lastStmp) { + mill = getNewstmp(); + } + return mill; + } + + private long getNewstmp() { + return System.currentTimeMillis(); + } + + /** 测试 */ + public static void main(String[] args) { + SnowFlake idWorker = new SnowFlake(0, 0); + for (int i = 0; i < 100; i++) { + long id = idWorker.nextId(); + //System.out.println(Long.toBinaryString(id)); + System.out.println(id); + } + + Runnable testRun = new Runnable() { + @Override + public void run() { + SnowFlake idWorker = new SnowFlake(0, 0); + for (int i = 0; i < 10; i++) { + System.out.println(idWorker.nextId()); + } + } + }; + Thread thread1 = new Thread(testRun); + thread1.start(); + Thread thread2 = new Thread(testRun); + thread2.start(); + Thread thread3 = new Thread(testRun); + thread3.start(); + Thread thread4 = new Thread(testRun); + thread4.start(); + Thread thread5 = new Thread(testRun); + thread5.start(); + } +} diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeId.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeId.java new file mode 100644 index 0000000..9ffbab7 --- /dev/null +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeId.java @@ -0,0 +1,123 @@ +package cn.estsh.i3plus.pojo.base.codemaker; + +/** + * @Description : + * @Reference : + * @Author : alwaysfrin + * @CreateDate : 2019-01-10 13:27 + * @Modify: + **/ +@Deprecated +public class SnowflakeId { + private long workerId; + private long datacenterId; + private long sequence = 0L; + + public SnowflakeId(){ + this.workerId = 1; + this.datacenterId = 1; + this.sequence = 0L; + } + + public SnowflakeId(long workerId, long datacenterId){ + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0",maxDatacenterId)); + } + + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + private long twepoch = 1288834974657L; + + private long workerIdBits = 5L; + private long datacenterIdBits = 5L; + private long maxWorkerId = -1L ^ (-1L << workerIdBits); + private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + private long sequenceBits = 12L; + + private long workerIdShift = sequenceBits; + private long datacenterIdShift = sequenceBits + workerIdBits; + private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + private long sequenceMask = -1L ^ (-1L << sequenceBits); + + private long lastTimestamp = -1L; + + private long getWorkerId(){ + return workerId; + } + + private long getDatacenterId(){ + return datacenterId; + } + + public synchronized long nextId() { + long timestamp = timeGen(); + + if (timestamp < lastTimestamp) { + System.err.printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp); + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", + lastTimestamp - timestamp)); + } + + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + + lastTimestamp = timestamp; + return ((timestamp - twepoch) << timestampLeftShift) | + (datacenterId << datacenterIdShift) | + (workerId << workerIdShift) | + sequence; + } + + private long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private long timeGen(){ + return System.currentTimeMillis(); + } + + //---------------测试--------------- + public static void main(String[] args) { + SnowflakeId worker = new SnowflakeId(); + Runnable testRun = new Runnable() { + @Override + public void run() { + + for (int i = 0; i < 10; i++) { + System.out.println(i + "=" + worker.nextId()); + } + } + }; + Thread thread1 = new Thread(testRun); + thread1.start(); + Thread thread2 = new Thread(testRun); + thread2.start(); + Thread thread3 = new Thread(testRun); + thread3.start(); + Thread thread4 = new Thread(testRun); + thread4.start(); + Thread thread5 = new Thread(testRun); + thread5.start(); + + System.out.println(new SnowflakeId().nextId()); + + for (int i = 0; i < 10; i++) { + //System.out.println(worker.nextId()); + } + } +} diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdMaker.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdMaker.java index ca4ca1b..eff481b 100644 --- a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdMaker.java +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdMaker.java @@ -10,30 +10,27 @@ package cn.estsh.i3plus.pojo.base.codemaker; * @Modify: **/ public class SnowflakeIdMaker { + private long workerId; private long datacenterId; - private long sequence; + private long sequence = 0L; public SnowflakeIdMaker(){ this.workerId = 1; this.datacenterId = 1; - this.sequence = 1; + this.sequence = 0L; } - public SnowflakeIdMaker(long workerId, long datacenterId, long sequence){ - // sanity check for workerId + public SnowflakeIdMaker(long workerId, long datacenterId){ if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0",maxDatacenterId)); } -// System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", -// timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId); this.workerId = workerId; this.datacenterId = datacenterId; - this.sequence = sequence; } private long twepoch = 1288834974657L; @@ -59,10 +56,6 @@ public class SnowflakeIdMaker { return datacenterId; } - private long getTimestamp(){ - return System.currentTimeMillis(); - } - public synchronized long nextId() { long timestamp = timeGen(); @@ -102,13 +95,26 @@ public class SnowflakeIdMaker { //---------------测试--------------- public static void main(String[] args) { - System.out.println(new SnowflakeIdMaker().nextId()); SnowflakeIdMaker worker = new SnowflakeIdMaker(); - for (int i = 0; i < 10; i++) { - System.out.println(worker.nextId()); - } + Runnable testRun = new Runnable() { + @Override + public void run() { + for (int i = 0; i < 10; i++) { + System.out.println(worker.nextId()); + } + } + }; + Thread thread1 = new Thread(testRun); + thread1.start(); + Thread thread2 = new Thread(testRun); + thread2.start(); + Thread thread3 = new Thread(testRun); + thread3.start(); + Thread thread4 = new Thread(testRun); + thread4.start(); + Thread thread5 = new Thread(testRun); + thread5.start(); - worker = new SnowflakeIdMaker(1,1,1); for (int i = 0; i < 10; i++) { System.out.println(worker.nextId()); } diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdWorker.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdWorker.java new file mode 100644 index 0000000..03e1078 --- /dev/null +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/codemaker/SnowflakeIdWorker.java @@ -0,0 +1,161 @@ +package cn.estsh.i3plus.pojo.base.codemaker; + +/** + * @Description : 备用算法 + * @Reference : + * @Author : alwaysfrin + * @CreateDate : 2019-01-10 13:07 + * @Modify: + **/ +@Deprecated +public class SnowflakeIdWorker { + + /** 开始时间截 (2015-01-01) */ + private final long twepoch = 1420041600000L; + + /** 机器id所占的位数 */ + private final long workerIdBits = 5L; + + /** 数据标识id所占的位数 */ + private final long datacenterIdBits = 5L; + + /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** 支持的最大数据标识id,结果是31 */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** 序列在id中占的位数 */ + private final long sequenceBits = 12L; + + /** 机器ID向左移12位 */ + private final long workerIdShift = sequenceBits; + + /** 数据标识id向左移17位(12+5) */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** 时间截向左移22位(5+5+12) */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** 工作机器ID(0~31) */ + private long workerId; + + /** 数据中心ID(0~31) */ + private long datacenterId; + + /** 毫秒内序列(0~4095) */ + private long sequence = 0L; + + /** 上次生成ID的时间截 */ + private long lastTimestamp = -1L; + + //==============================Constructors===================================== + /** + * 构造函数 + * @param workerId 工作ID (0~31) + * @param datacenterId 数据中心ID (0~31) + */ + public SnowflakeIdWorker(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + // ==============================Methods========================================== + /** + * 获得下一个ID (该方法是线程安全的) + * @return SnowflakeId + */ + public synchronized long nextId() { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new RuntimeException( + String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + //时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) // + | (datacenterId << datacenterIdShift) // + | (workerId << workerIdShift) // + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } + + //==============================Test============================================= + /** 测试 */ + public static void main(String[] args) { + SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0); + for (int i = 0; i < 100; i++) { + long id = idWorker.nextId(); + //System.out.println(Long.toBinaryString(id)); + System.out.println(id); + } + + Runnable testRun = new Runnable() { + @Override + public void run() { + SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0); + for (int i = 0; i < 10; i++) { + System.out.println(idWorker.nextId()); + } + } + }; + Thread thread1 = new Thread(testRun); + thread1.start(); + Thread thread2 = new Thread(testRun); + thread2.start(); + Thread thread3 = new Thread(testRun); + thread3.start(); + Thread thread4 = new Thread(testRun); + thread4.start(); + Thread thread5 = new Thread(testRun); + thread5.start(); + } +} diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/enumutil/ImppEnumUtil.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/enumutil/ImppEnumUtil.java index 464bf8f..6f0233f 100644 --- a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/enumutil/ImppEnumUtil.java +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/enumutil/ImppEnumUtil.java @@ -158,11 +158,11 @@ public class ImppEnumUtil { @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum LOG_LEVEL{ - DEBUG(1,"DEBUG","调试程序信息"), - INFO(2,"INFO","程序运行信息"), - WARN(3,"WARN","具有潜在危害的信息"), - ERROR(4,"ERROR","错误信息但允许程序继续运行"), - FATAL(5,"FATAL","非常严重的错误,可能导致程序中止"); + DEBUG(1,"DEBUG","调试"), + INFO(2,"INFO","信息"), + WARN(3,"WARN","注意"), + ERROR(4,"ERROR","错误"), + FATAL(5,"FATAL","严重"); private int value; private String name; diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseMongoRepositoryImpl.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseMongoRepositoryImpl.java index 425b983..3ccc1c8 100644 --- a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseMongoRepositoryImpl.java +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseMongoRepositoryImpl.java @@ -16,6 +16,7 @@ import org.bson.json.JsonMode; import org.bson.json.JsonWriterSettings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DuplicateKeyException; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -110,8 +111,26 @@ public class BaseMongoRepositoryImpl extends SimpleM } } - this.mongoOperations.insert(item, this.entityInformation.getCollectionName()); - if(idField!=null){ +// try { + this.mongoOperations.insert(item, this.entityInformation.getCollectionName()); +// }catch (DuplicateKeyException dke){ +// LOGGER.error("【出现重复主键】"); +// //出现重复主键,再次插入 +// if(idField != null){ +// Class type = idField.getType(); +// Object val = idField.get(item); +// if((type == long.class || type == Long.class) && (val == null || Long.parseLong(val.toString()) == 0)){ +// // long类型主键,以snowflake为主键 +// idField.set(item, snowflakeIdMaker.nextId()); +// } else if(type == String.class && (val==null || "".equals(val))){ +// // String类型主键,以UUID为主键 +// idField.set(item, UUID.randomUUID().toString().replace("-", "").toLowerCase()); +// } +// } +// +// this.mongoOperations.insert(item, this.entityInformation.getCollectionName()); +// } + if(idField != null){ return item; }else { return null; diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseRepositoryImpl.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseRepositoryImpl.java index a867bba..9ede73d 100644 --- a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseRepositoryImpl.java +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/daoimpl/BaseRepositoryImpl.java @@ -37,11 +37,11 @@ public class BaseRepositoryImpl extends SimpleJpaRep private Class persistentClass; private SnowflakeIdMaker snowflakeIdMaker; - public BaseRepositoryImpl(Class clz, EntityManager em) { + public BaseRepositoryImpl(Class clz, EntityManager em,SnowflakeIdMaker snowflakeIdMaker) { super(clz, em); this.entityManager = em; this.persistentClass = clz; - this.snowflakeIdMaker = new SnowflakeIdMaker(); + this.snowflakeIdMaker = snowflakeIdMaker; } private void setParameter(Query query, String[] propName, Object[] propValue) { diff --git a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/factory/BaseRepositoryFactoryBean.java b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/factory/BaseRepositoryFactoryBean.java index f94c46e..912705d 100644 --- a/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/factory/BaseRepositoryFactoryBean.java +++ b/modules/i3plus-pojo-base/src/main/java/cn/estsh/i3plus/pojo/base/jpa/factory/BaseRepositoryFactoryBean.java @@ -1,8 +1,10 @@ package cn.estsh.i3plus.pojo.base.jpa.factory; +import cn.estsh.i3plus.pojo.base.codemaker.SnowflakeIdMaker; import cn.estsh.i3plus.pojo.base.jpa.daoimpl.BaseRepositoryImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; @@ -23,6 +25,9 @@ import java.io.Serializable; public class BaseRepositoryFactoryBean, T, I extends Serializable> extends JpaRepositoryFactoryBean { public static final Logger LOGGER = LoggerFactory.getLogger(BaseRepositoryFactoryBean.class); + @Autowired + public SnowflakeIdMaker snowflakeIdMaker; + public BaseRepositoryFactoryBean(Class repositoryInterface) { super(repositoryInterface); } @@ -30,22 +35,24 @@ public class BaseRepositoryFactoryBean, T, I exten @Override protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) { //LOGGER.info("【初始JPA持久仓】"); - return new BaseRepositoryFactory(em); + return new BaseRepositoryFactory(em,snowflakeIdMaker); } //创建一个内部类,该类不用在外部访问 private static class BaseRepositoryFactory extends JpaRepositoryFactory { private final EntityManager em; + private final SnowflakeIdMaker snowflakeIdMaker; - public BaseRepositoryFactory(EntityManager em) { + public BaseRepositoryFactory(EntityManager em,SnowflakeIdMaker snowflakeIdMaker) { super(em); this.em = em; + this.snowflakeIdMaker = snowflakeIdMaker; } //设置具体的实现类是BaseRepositoryImpl @Override protected Object getTargetRepository(RepositoryInformation information) { - return new BaseRepositoryImpl((Class) information.getDomainType(), em); + return new BaseRepositoryImpl((Class) information.getDomainType(), em,snowflakeIdMaker); } //设置具体的实现类的class