Camunda自定义IdGenerator

实现思路

  1. 自定义类custom实现IdGenerator接口

  1. 新增BpmConfiguration,增加ProcessEnginePlugin bean初始化时指定custom。

代码实现

CustomUuidGenerator.java



import com.fasterxml.uuid.EthernetAddress;
import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.impl.TimeBasedGenerator;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.camunda.bpm.engine.impl.cfg.IdGenerator;
import org.camunda.bpm.engine.impl.persistence.StrongUuidGenerator;
import org.springframework.stereotype.Component;

/**
 * 该类实现的功能是在strongUuidGenerator基础上,去除类'-'
 */
@SuppressWarnings("ALL")
@Component
public class CustomUuidGenerator implements IdGenerator {
    
    protected static volatile TimeBasedGenerator timeBasedGenerator;
    
    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    // private long twepoch = 1288834974657L; // Thu, 04 Nov 2010 01:42:54 GMT
    private long workerIdBits = 5L; // 节点ID长度
    private long datacenterIdBits = 5L; // 数据中心ID长度
    private long maxWorkerId = -1L ^ (-1L << workerIdBits); // 最大支持机器节点数0~31,一共32个
    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 最大支持数据中心节点数0~31,一共32个
    private long sequenceBits = 12L; // 序列号12位
    private long workerIdShift = sequenceBits; // 机器节点左移12位
    private long datacenterIdShift = sequenceBits + workerIdBits; // 数据中心节点左移17位
    // private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; //
    // 时间毫秒数左移22位
    private long sequenceMask = -1L ^ (-1L << sequenceBits); // 4095
    private long lastTimestamp = -1L;
    
    public CustomUuidGenerator() {
        ensureGeneratorInitialized(0,0);
    }
    
    protected void ensureGeneratorInitialized(long workerId, long datacenterId) {
        if (timeBasedGenerator == null) {
            synchronized (StrongUuidGenerator.class) {
                if (timeBasedGenerator == null) {
                    timeBasedGenerator = Generators.timeBasedGenerator(EthernetAddress.fromInterface());
    
                    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;
                    
                }
            }
        }
    }
    
    @Override
    public String getNextId() {
        //return timeBasedGenerator.generate().toString().replaceAll("-","");
        //自定义 nextId 保证 趋势 递增
        long timestamp = timeGen(); // 获取当前毫秒数
        // 如果服务器时间有问题(时钟后退) 报错。
        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只有12bit,所以和sequenceMask相与一下,去掉高位
            sequence = (sequence + 1) & sequenceMask;
            // 判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp); // 自旋等待到下一毫秒
            }
        } else {
            sequence = 0L; // 如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加
        }
        lastTimestamp = timestamp;
    
        StringBuilder idStr = new StringBuilder();
        String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHmmssSSS");
        idStr.append(datePrefix);
    
        Long suffix = (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
        int suffixLen = suffix.toString().length();
        if (suffixLen < 4) {
            idStr.append(StringUtils.repeat("0", 4 - suffixLen));
        }
        idStr.append(suffix);
    
        return idStr.toString();
    }
    
    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }
    
    protected long timeGen() {
        return System.currentTimeMillis();
    }
    public long getWorkerId() {
        return workerId;
    }
    
    public void setWorkerId(long workerId) {
        this.workerId = workerId;
    }
    
    public long getDatacenterId() {
        return datacenterId;
    }
    
    public void setDatacenterId(long datacenterId) {
        this.datacenterId = datacenterId;
    }
    
    //自测
    public static void main(String[] args){
        long now = System.currentTimeMillis();
        CustomUuidGenerator uuid = new CustomUuidGenerator();
        CustomUuidGenerator uuid2 = new CustomUuidGenerator();
        uuid2.setWorkerId(1);
        uuid2.setDatacenterId(1);
        
        for(int i = 0;i < 1000;i ++){
            String nextId = uuid.getNextId();
            
            String next2 = uuid2.getNextId();
            System.out.println(i+"nextId1:"+nextId);
            System.out.println(i+"nextId2:"+next2);
            
        }
        
        System.out.println("cost:"+(System.currentTimeMillis()- now));
    }
    
    
}

BpmConfiguration.java


import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.impl.cfg.AbstractProcessEnginePlugin;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
@Slf4j
@Primary
public class BpmConfiguration {
    
    @Autowired
    private CustomUuidGenerator customUuidGenerator;
    
    @Bean
    public ProcessEnginePlugin statusPlugin() {
        return new AbstractProcessEnginePlugin() {
            @Override
            public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
                log.warn("post init");
            }
            
            @Override
            public void postProcessEngineBuild(ProcessEngine processEngine) {
                log.warn("post build");
            }
            
            @Override
            public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
                log.warn("pre init");
                //BPM 部分实体未实现 序列化接口 通过redis 缓存时无法序列化存储 调整为 通过监听MQ 清理本地缓存
                //processEngineConfiguration.setCacheFactory(redisBpm);
                
                // 设置缓存容量 默认为 1000 调整为10000
                processEngineConfiguration.setCacheCapacity(10000);
                //使用自定义生成的ID
                processEngineConfiguration.setIdGenerator(customUuidGenerator);
            }
        };
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值