From 3d5d86584b04d06b39389f4227421cc8ebcb0262 Mon Sep 17 00:00:00 2001 From: Administrator Date: Thu, 1 Dec 2022 23:13:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=86=E9=A2=91056~(=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E9=9B=AA=E8=8A=B1=E7=AE=97=E6=B3=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mashibing/api/ApiStarterApp.java | 5 ++ .../api/controller/SmsController.java | 8 +++ .../common/enums/ExceptionEnums.java | 3 +- .../mashibing/common/util/SnowFlakeUtil.java | 66 +++++++++++++++---- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/beacon-api/src/main/java/com/mashibing/api/ApiStarterApp.java b/beacon-api/src/main/java/com/mashibing/api/ApiStarterApp.java index ddc220e..9f73030 100644 --- a/beacon-api/src/main/java/com/mashibing/api/ApiStarterApp.java +++ b/beacon-api/src/main/java/com/mashibing/api/ApiStarterApp.java @@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.ComponentScan; /** * @author zjw @@ -12,6 +13,10 @@ import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients +@ComponentScan(basePackages = { + "com.mashibing.api", + "com.mashibing.common" +}) public class ApiStarterApp { public static void main(String[] args) { diff --git a/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java b/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java index e171502..df34920 100644 --- a/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java +++ b/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java @@ -6,6 +6,7 @@ import com.mashibing.api.util.R; import com.mashibing.api.vo.ResultVO; import com.mashibing.common.enums.ExceptionEnums; import com.mashibing.common.model.StandardSubmit; +import com.mashibing.common.util.SnowFlakeUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -30,6 +31,10 @@ import javax.servlet.http.HttpServletRequest; @RefreshScope public class SmsController { + @Autowired + private SnowFlakeUtil snowFlakeUtil; + + /** * 客户端IP地址的请求头信息,多个用','隔开。 */ @@ -80,6 +85,9 @@ public class SmsController { //=========================调用策略模式的校验链========================================= checkFilterContext.check(submit); + //========================基于雪花算法生成唯一id,并添加到StandardSubmit对象中========================================= + submit.setSequenceId(snowFlakeUtil.nextId()); + //=========================发送到MQ,交给策略模块处理========================================= return R.ok(); } diff --git a/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java b/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java index 769a06b..31ee049 100644 --- a/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java +++ b/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java @@ -16,7 +16,8 @@ public enum ExceptionEnums { ERROR_MOBILE(-5,"手机号格式不正确"), BALANCE_NOT_ENOUGH(-6,"客户余额不足"), PARAMETER_ERROR(-10,"参数不合法!"), - SNOWFLAKE_OUT_OF_RANGE(-11,"雪花算法的机器id或服务id超出最大范围!") + SNOWFLAKE_OUT_OF_RANGE(-11,"雪花算法的机器id或服务id超出最大范围!"), + SNOWFLAKE_TIME_BACK(-12,"雪花算法的服务器出现时间回拨问题!"), ; private Integer code; diff --git a/beacon-common/src/main/java/com/mashibing/common/util/SnowFlakeUtil.java b/beacon-common/src/main/java/com/mashibing/common/util/SnowFlakeUtil.java index c56178d..f6caa8f 100644 --- a/beacon-common/src/main/java/com/mashibing/common/util/SnowFlakeUtil.java +++ b/beacon-common/src/main/java/com/mashibing/common/util/SnowFlakeUtil.java @@ -2,15 +2,10 @@ package com.mashibing.common.util; import com.mashibing.common.enums.ExceptionEnums; import com.mashibing.common.exception.ApiException; -import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import java.util.Date; /** * 雪花算法生成全局唯一ID @@ -24,7 +19,6 @@ import java.util.Date; * @description */ @Component -@Slf4j public class SnowFlakeUtil { /** @@ -98,16 +92,64 @@ public class SnowFlakeUtil { /** * 时间戳需要位移的位数 */ - private long timestampShift = sequenceBits + serviceIdBits + maxMachineId; - - - - - + private long timestampShift = sequenceBits + serviceIdBits + machineIdBits; + /** + * 序列的最大值 + */ + private long maxSequenceId = -1 ^ (-1 << sequenceBits); + /** + * 记录最近一次获取id的时间 + */ + private long lastTimestamp = -1; + /** + * 获取系统时间毫秒值 + * @return + */ + private long timeGen(){ + return System.currentTimeMillis(); + } + public synchronized long nextId(){ + //1、 拿到当前系统时间的毫秒值 + long timestamp = timeGen(); + // 避免时间回拨造成出现重复的id + if(timestamp < lastTimestamp){ + // 说明出现了时间回拨 + System.out.println("当前服务出现时间回拨!!!"); + throw new ApiException(ExceptionEnums.SNOWFLAKE_TIME_BACK); + } + //2、 判断当前生成id的时间和上一次生成的时间 + if(timestamp == lastTimestamp){ + // 同一毫秒值生成id + sequence = (sequence + 1) & maxSequenceId; + // 0000 10100000 :sequence + // 1111 11111111 :maxSequenceId + if(sequence == 0){ + // 进到这个if,说明已经超出了sequence序列的最大取值范围 + // 需要等到下一个毫秒再做回来生成具体的值 + timestamp = timeGen(); + while(timestamp <= lastTimestamp){ + // 时间还没动。 + timestamp = timeGen(); + } + } + }else{ + // 另一个时间点生成id + sequence = 0; + } + //3、重新给lastTimestamp复制 + lastTimestamp = timestamp; + + //4、计算id,将几位值拼接起来。 41bit位的时间,5位的机器,5位的服务 ,12位的序列 + return ((timestamp - timeStart) << timestampShift) | + (machineId << machineIdShift) | + (serviceId << serviceIdShift) | + sequence & + Long.MAX_VALUE; + } }