spring boot雪花算法

原文地址

首先生成雪花id,这样虽然可以直接调用也就是通过new这个类的对象来生成,但是因为使用了spring框架,交给容器管理更好,所以下面就通过配置来实现将类注入到容器中:

import java.security.SecureRandom;

public class SnowflakeManager {
    private static final long EPOCH_STAMP = 1262275200000L;//开始时间戳,可自定义
    private static final long SEQUENCE_BIT = 12L;//序号位 12
    private static final long MACHINE_BIT = 5L;//机器码位 5
    private static final long DATA_CENTER_BIT = 5L;//数据中心 5
    private static final long MAX_SEQUENCE_NUM = -1L ^ (-1L << SEQUENCE_BIT);
    private static final long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    private static final long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);
    private static final long MACHINE_LEFT = SEQUENCE_BIT;
    private static final long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
    private static final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT + DATA_CENTER_BIT;
    private final long machineId;//机器ID
    private final long dataCenterId;//数据中心ID
    private long sequence = 0L;
    private long lastTimestamp = -1L;//上次生成ID的时间戳

    public SnowflakeManager(long machineId, long dataCenterId) {
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException(String.format("machine id can't be greater than %d or less than 0", MAX_MACHINE_NUM));
        }
        if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {
            throw new IllegalArgumentException(String.format("data center id can't be greater than %d or less than 0", MAX_DATA_CENTER_NUM));
        }
        this.machineId = machineId;
        this.dataCenterId = dataCenterId;
    }

    public synchronized long nextValue() throws Exception {
        String os = System.getProperty("os.name");
        SecureRandom secureRandom;
        if (os.toLowerCase().startsWith("win")) {
            // windows机器用
            secureRandom = SecureRandom.getInstanceStrong();
        } else {
            // linux机器用
            secureRandom = SecureRandom.getInstance("NativePRNGNonBlocking");
        }
        //SecureRandom secureRandom = SecureRandom.getInstanceStrong();
        long currentTimeMillis = this.currentTimeMillis();
        if(currentTimeMillis < this.lastTimestamp) {
            throw new Exception(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", (this.lastTimestamp-currentTimeMillis)));
        }

        if(this.lastTimestamp == currentTimeMillis) {
            this.sequence = (this.sequence+1) & MAX_SEQUENCE_NUM;
            if (this.sequence == 0) {
                this.sequence = secureRandom.nextInt(Long.valueOf(SEQUENCE_BIT).intValue());
                currentTimeMillis = this.tilNextMillis(this.lastTimestamp);
            }
        } else {
            this.sequence = secureRandom.nextInt(Long.valueOf(SEQUENCE_BIT).intValue());
        }
        this.lastTimestamp = currentTimeMillis;

        // 64 Bit ID (42(Millis)+5(Data Center ID)+5(Machine ID)+12(Repeat Sequence Summation))
        long nextId = ((currentTimeMillis-EPOCH_STAMP) << TIMESTAMP_LEFT)
                | (this.dataCenterId << DATA_CENTER_LEFT)
                | (this.machineId << MACHINE_LEFT)
                | this.sequence;

        return nextId;
    }

    private long tilNextMillis(long lastTimestamp) {
        long currentTimeMillis = this.currentTimeMillis();
        while (currentTimeMillis <= lastTimestamp) {
            currentTimeMillis = this.currentTimeMillis();
        }
        return currentTimeMillis;
    }

    private long currentTimeMillis() {
        return System.currentTimeMillis();
    }

    public static void main(String[] args) throws Exception {
        SnowflakeManager snowflakeManager = new SnowflakeManager(0L,0L);
        long l = snowflakeManager.nextValue();
        System.out.println(l);
    }
}

  • 1、因为生成雪花id时要传入两个long型的参数,所以将这两个参数提到配置文件中来
    application.yml
  • com:
      linshan:
        demo1:
          snowflake:
            machine-id: 1
            data-center-id: 1
    

    我的包结构如下:

  • 2、创建一个类 TestProperties ,来获取配置文件中的信息,一个类 SnowflakeProperties 来存需要传入的两个参数。
    TestProperties
  • import com.linshan.demo1.entity.SnowflakeProperties;
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @Data
    @ConfigurationProperties(prefix = "com.linshan.demo1")
    public class TestProperties {
    
        private SnowflakeProperties snowflake;
    
    }
    

    SnowflakeProperties

  • import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class SnowflakeProperties {
        private long machineId;
        private long dataCenterId;
    }
    

  • 3、创建 BossAutoConfiguration 类
  • 这里注意的是@EnableConfigurationProperties注解的作用是:使使用 @ConfigurationProperties 注解的类生效。
  • import com.linshan.demo1.entity.SnowflakeManager;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @EnableConfigurationProperties(TestProperties.class)
    public class BossAutoConfiguration {
        @Autowired
        private TestProperties properties;
    
        @Bean
        @ConditionalOnMissingBean
        public SnowflakeManager snowflakeManager() {
            return new SnowflakeManager(this.properties.getSnowflake().getMachineId(), this.properties.getSnowflake().getDataCenterId());
        }
    }
    

  • 4、最后就是直接在需要使用的类中注入即可
  • //注入
    @Autowired
    private SnowflakeManager snowflakeManager;
    //调用
    long snowflakeID = snowflakeManager.nextValue();
    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中使用雪花算法的工具类可以通过创建一个SnowflakeManager类来实现。首先,你需要创建一个SnowflakeProperties类,该类使用lombok注解@Getter和@Setter来自动生成getter和setter方法,并定义了machineId和dataCenterId两个属性。\[1\]然后,你可以创建一个BossAutoConfiguration类,该类使用@EnableConfigurationProperties注解来使@ConfigurationProperties注解的类生效。在BossAutoConfiguration类中,你可以使用@Autowired注解来注入TestProperties类,并使用@Bean注解和@ConditionalOnMissingBean注解来创建一个SnowflakeManager的bean。在SnowflakeManager的构造函数中,你可以使用properties对象获取machineId和dataCenterId的值,并将其传递给SnowflakeManager的实例化对象。\[3\]这样,你就可以在Spring Boot中使用雪花算法的工具类了。 #### 引用[.reference_title] - *1* *3* [spring boot雪花算法](https://blog.csdn.net/qq_33327680/article/details/125599943)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Spring Boot项目下JPA自定义雪花算法ID生成器详解](https://blog.csdn.net/wjw465150/article/details/125301120)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值