Camunda自定义IdGenerator

news/2024/7/3 2:42:10

实现思路

  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);
            }
        };
    }
    
}

http://lihuaxi.xjx100.cn/news/663721.html

相关文章

从Deepmind最新成果DreamerV3启发的通用AI技术分析

一、背景 本文系个人观点&#xff1a;错漏在所难免&#xff0c;仅供参考 北京时间 1 月 12 日&#xff0c;DeepMind 官方推特发文&#xff0c;正式官宣 DreamerV3&#xff0c;这是首个能在游戏「我的世界」(Minecraft) 中不参考人类数据&#xff0c;就能从头开始收集钻石的通…

智慧水务能效管理平台在污水处理厂电气节能中的应用

摘要&#xff1a;污水处理属于高能耗行业&#xff0c;会消耗大量的电能、燃料和药剂等&#xff0c;高能耗不仅会提升污水处理成本&#xff0c;还会加剧能源危机。所以&#xff0c;本文首先探究了污水处理厂耗能的原因&#xff0c;分析了污水处理与节能降耗的关系&#xff0c;然…

Cookie的相关操作

1. Cookie处理 Cookie定义:是储存在用户本地终端上的数据,实际上是一小段的文本信息。 1. Cookie作用 帮助 Web 站点保存有关访问者的信息,方便用户的访问。如记住用户名密码实现自动登录。 案例:查看访问我要自学网时的Cookie内容 # Webdriver中操作cookie的方法包括: # g…

GraphQL(二)- Schema 和 Resolver

在GraphQL中,Schema和Resolver是两个非常重要的概念,是编写GraphQL Server的2个基本单元 本文介绍GraphQL中的Schema和Resolver。 Schema Schema定义了GraphQL中基于graph的数据格式 参考: https://graphql.org/learn/schema/ Type语言 GraphQL 服务可以用任何语言编写。由于…

2022.12 青少年机器人技术等级考试理论综合试卷(三级)

2022年12月 青少年机器人技术等级考试理论综合试卷&#xff08;三级&#xff09; 分数&#xff1a; 100 题数&#xff1a; 30 一、 单选题(共 20 题&#xff0c; 共 80 分) 1.舵机接到 Arduino UNO/Nano 主控板的 2 号引脚&#xff0c; 下列选项中&#xff0c; 实现舵机在 0 度…

mysql快速生成100W条测试数据(8)全球各城市人口及经济增长速度并存入mysql数据库

这是之前的文章里面包含一些以前的一些操作流程可以进行参考学习 更加详细操作步骤在第一篇文章里面 mysql快速生成100W条测试数据&#xff08;1&#xff09;&#xff1a;游戏人物数据 mysql快速生成100W条测试数据&#xff08;2&#xff09;公司员工信息 mysql快速生成100W条测…

实时即未来,大数据项目车联网之Flink Watermark(水位线)【十四】

文章目录 1 Flink Watermark(水位线)1 事件时间(event time)2 Flink Window Assigners(窗口分配器)2.1 Tumbling Windows(翻滚窗口)2.2 Sliding Windows(滑动窗口)2.3 Session Windows(会话窗口)2.4 Global Windows(全局窗口)2.5 窗口函数(Window Function)1 Fli…

【C语言】自定义类型

前言男孩子在外面要保护好自己~一、结构体为什么会有结构体呢&#xff1f;但要描述一个复杂对象时&#xff0c;仅用之前学过的基本数据类型表达不了&#xff08;如&#xff1a;我要描述一个人&#xff0c;仅靠基本数据类型只能说定义他的一种属性<如用 int 定义他的年龄>…