actitivi自定义属性(二)

news2025/4/14 7:55:03

声明:此处activiti版本为6.0

此文章介绍后端自定义属性解析,前端添加自定义属性方法连接:activiti自定义属性(一)_ruoyi activiti自定义标题-CSDN博客

1、涉及到的类如下:

简介:DefaultXmlParser :xml自定义属性解析类 :实现解析指定节点下扩展字段xml节点

CustomBpmnJsonConverter:用于转换BPMN与JSON供activiti解析界面属性并应用,在ActivitiConfig中引入使用

CustomBpmnXmlConverter:用于xml与BPMN转换

CustomUserTaskJsonConverter:用户节点自定义扩展属性解析(xml与json互转)

CustomUserTaskXmlConverter:用户节点自定义扩展属性解析xml

ActivitiConfig:springboot整合activiti配置类

代码如下:

DefaultXmlParser :

import org.activiti.bpmn.converter.child.BaseChildElementParser;
import org.activiti.bpmn.model.*;

import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * xml自定义属性解析类 :实现解析指定节点下扩展字段xml节点
 *
 */
public class DefaultXmlParser extends BaseChildElementParser {

    //元素名称
    private String elementName;

    public DefaultXmlParser() {
    }

    public DefaultXmlParser(String elementName) {
        this.elementName = elementName;
    }

    public String getElementName() {
        return elementName;
    }

    /**
     * 解析指定节点下扩展字段xml节点
     * @param xtr               xml字节流读取器
     * @param parentElement     父节点对象
     * @param model             流程图模型对象
     * @throws Exception
     */
    public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception {
        Map<String, List<ExtensionElement>> map = parentElement.getExtensionElements();
        List<ExtensionElement> extensionElementList = new ArrayList<>();
        ExtensionElement extensionElement = new ExtensionElement();
        extensionElement.setName(getElementName());
        extensionElement.setElementText(xtr.getElementText());
        extensionElement.setNamespacePrefix("activiti");
        extensionElement.setNamespace("http://activiti.org/bpmn");
        extensionElementList.add(extensionElement);
        map.put(getElementName(), extensionElementList);

    }
}

CustomBpmnJsonConverter:

import org.activiti.bpmn.model.BaseElement;
import org.activiti.editor.language.json.converter.BaseBpmnJsonConverter;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;

import java.util.Map;

/**
 * 自定义bpmn解析,用于转换BPMN与JSON供activiti解析界面属性并应用
 *
 */
public class CustomBpmnJsonConverter extends BpmnJsonConverter {

    /**
     * 获取bpmn组件解析map
     * @return
     */
    public static Map<String,Class<? extends BaseBpmnJsonConverter>> getConvertersToBpmnMap(){
        return convertersToBpmnMap;
    }

    /**
     * 获取bpmn组件解析map
     * @return
     */
    public static Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>>  getConvertersToJsonMap(){
        return convertersToJsonMap;
    }

}

CustomBpmnXmlConverter:

import org.activiti.bpmn.converter.BpmnXMLConverter;

/**
 * 自定义bpmn解析,用于xml转换成BPMN
 *
 */
public class CustomBpmnXmlConverter extends BpmnXMLConverter {

    static {
        // 添加自定义用户节点xml解析器
        addConverter(new CustomUserTaskXmlConverter());
    }
}

CustomUserTaskJsonConverter:用户节点自定义扩展属性解析(xml与json互转)

用到的常量为自定义属性名

import com.self.common.constant.activiti.ActivitiNodeConstant;
import com.self.common.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.model.*;
import org.activiti.editor.language.json.converter.BaseBpmnJsonConverter;
import org.activiti.editor.language.json.converter.UserTaskJsonConverter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 用户节点自定义扩展属性解析(xml与json互转)
 */
public class CustomUserTaskJsonConverter extends UserTaskJsonConverter {

    /**
     * xml => json
     * 将 xml格式的模型数据解析出来放入到节点的json自定义扩展属性中
     *
     * @param propertiesNode
     * @param baseElement
     */
    @Override
    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement) {
        super.convertElementToJson(propertiesNode, baseElement);
        //获取扩展属性并进行设置
        UserTask userTask = (UserTask) baseElement;

        Map<String, List<ExtensionElement>> map = userTask.getExtensionElements();
        for(String key : map.keySet()){
            List<ExtensionElement> extensionElementList = map.get(key);
            if (extensionElementList != null && extensionElementList.size() > 0) {
                propertiesNode.put(extensionElementList.get(0).getName(), extensionElementList.get(0).getElementText());
            }
        }
    }

    /**
     * json => xml
     * 将 json格式的模型数据解析出来放入到节点的自定义扩展属性中
     *
     * @param elementNode
     * @param modelNode
     * @param shapeMap
     * @return
     */
    @Override
    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap) {
        FlowElement flowElement = super.convertJsonToElement(elementNode, modelNode, shapeMap);
        //解析
        UserTask userTask = (UserTask) flowElement;
        List<CustomProperty> cpList = new ArrayList<>();
        //是否为并行节点,常量为自定义属性名
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_PARALLEL);
        //是否可以AA跳
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK);
        //节点审批人为空是否跳过
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK);
        //跳过节点时意见
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK_OPINION);
        //是否可以修改表单
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACTMODIFY_FROM);
        //附件是否必填
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_FILE_REQUIRED);
        //是否可以查看流转记录
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD);
        //是否可配置审批记录查看权限
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS);
        //抄送用户
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_CC_USERS);
        //是否显示流程图
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_PNG);
        userTask.setCustomProperties(cpList);
        return userTask;
    }

    public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
                                 Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {

        fillJsonTypes(convertersToBpmnMap);
        fillBpmnTypes(convertersToJsonMap);
    }

    public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {
        convertersToBpmnMap.put(STENCIL_TASK_USER, CustomUserTaskJsonConverter.class);
    }

    public static void fillBpmnTypes(Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
        convertersToJsonMap.put(UserTask.class, CustomUserTaskJsonConverter.class);
    }

    /**
     * 处理自定义属性
     *
     * @param cpList      自定义属性列表
     * @param elementNode 任务节点
     * @param key         自定义属性key
     */
    private void handleCustomProperties(List<CustomProperty> cpList, JsonNode elementNode, String key) {
        String value = getPropertyValueAsString(key, elementNode);
        if (StringUtils.isNotBlank(value)) {
            CustomProperty cp = new CustomProperty();
            cp.setName(key);
            cp.setSimpleValue(value);
            cpList.add(cp);
        }
    }

}

CustomUserTaskXmlConverter:用户节点自定义扩展属性解析xml

用到的常量为自定义属性名

import com.self.activiti.config.extension.DefaultXmlParser;
import com.self.common.constant.activiti.ActivitiNodeConstant;
import org.activiti.bpmn.converter.UserTaskXMLConverter;

/**
 * 用户节点自定义扩展属性解析xml
 */
public class CustomUserTaskXmlConverter extends UserTaskXMLConverter {

    public CustomUserTaskXmlConverter() {
        super();
        //是否为并行节点
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_PARALLEL, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_PARALLEL));
        //是否可以AA跳
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK));
        //节点审批人为空是否跳过
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK));
        //跳过节点时意见
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK_OPINION, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK_OPINION));
        //是否可以修改表单
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACTMODIFY_FROM, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACTMODIFY_FROM));
        //附件是否必填
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_FILE_REQUIRED, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_FILE_REQUIRED));
        //是否可以查看流转记录
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD));
        //是否可配置审批记录查看权限
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS));
        //抄送用户
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_CC_USERS, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_CC_USERS));
        //是否显示流程图
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_PNG, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_PNG));

    }
}

ActivitiConfig:

重点在于下面这句:

import com.self.activiti.id.MyIdGenerator;
import org.activiti.engine.*;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * acitiviti配置类
 */
@Configuration
public class ActivitiConfig  {
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PlatformTransactionManager transactionManager;

    //流程配置,与spring整合采用SpringProcessEngineConfiguration这个实现
    @Bean
    public SpringProcessEngineConfiguration processEngineConfiguration(){
        SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
        processEngineConfiguration.setDataSource(dataSource);
        processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfigurationImpl.DB_SCHEMA_UPDATE_TRUE);
        processEngineConfiguration.setDatabaseType(ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL);
        processEngineConfiguration.setIdGenerator(new MyIdGenerator());
        processEngineConfiguration.setTransactionManager(transactionManager);
        processEngineConfiguration.setJobManager(new MyJobManager());//自定义任务管理

        // 将自定义用户任务组件bpmn解析替换activiti中用户任务组件默认解析
        CustomUserTaskJsonConverter.fillTypes(CustomBpmnJsonConverter.getConvertersToBpmnMap(), CustomBpmnJsonConverter.getConvertersToJsonMap());

//        processEngineConfiguration.setJobExecutorActivate(true);//JobExecutor是管理几个线程计时器的组成部分,JobExecutor对多线程的处理较为笨重缓慢
//        processEngineConfiguration.setAsyncExecutorEnabled(true);//定义为true,使用AsyncExecutor代替默认的JobExecutor;
        processEngineConfiguration.setAsyncExecutorActivate(true);//定义为true,工作流引擎在启动时就建立启动AsyncExecutor线程
        //流程图字体
        processEngineConfiguration.setActivityFontName("宋体");
        processEngineConfiguration.setAnnotationFontName("宋体");
        processEngineConfiguration.setLabelFontName("宋体");

        return processEngineConfiguration;
    }

    //流程引擎,与spring整合使用factoryBean
    @Bean
    public ProcessEngineFactoryBean processEngine(ProcessEngineConfiguration processEngineConfiguration){
        ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
        processEngineFactoryBean.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
        ((ProcessEngineConfigurationImpl) processEngineConfiguration).setIdGenerator(new MyIdGenerator());
        return processEngineFactoryBean;
    }
    //八大接口
    @Bean
    public RepositoryService repositoryService(ProcessEngine processEngine){
        return processEngine.getRepositoryService();
    }

    @Bean
    public RuntimeService runtimeService(ProcessEngine processEngine){
        return processEngine.getRuntimeService();
    }

    @Bean
    public TaskService taskService(ProcessEngine processEngine){
        return processEngine.getTaskService();
    }

    @Bean
    public HistoryService historyService(ProcessEngine processEngine){
        return processEngine.getHistoryService();
    }

    @Bean
    public FormService formService(ProcessEngine processEngine){
        return processEngine.getFormService();
    }

    @Bean
    public IdentityService identityService(ProcessEngine processEngine){
        return processEngine.getIdentityService();
    }

    @Bean
    public ManagementService managementService(ProcessEngine processEngine){
        return processEngine.getManagementService();
    }

    @Bean
    public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine){
        return processEngine.getDynamicBpmnService();
    }

}

ActivitiNodeConstant:常量表

/**
 * activiti节点类型常量表
 *
 */
public class ActivitiNodeConstant {

    //会签节点名称后缀
    public static final String NODE_NAME_COUNTERSIGN_SUFFIX = "-会签";


    //流程节点类型 -- 互斥网关
    public static final String NODE_NAME_EXCLUSIVE_GATEWAY = "exclusiveGateway";
    //流程节点类型 -- 并行网关
    public static final String NODE_NAME_PARALLEL_GATEWAY = "parallelGateway";
   //流程节点类型 -- 包容网关
    public static final String NODE_NAME_INCLUSIVE_GATEWAY = "inclusiveGateway";
    //流程节点类型 -- 开始事件
    public static final String NODE_NAME_START_EVENT = "startEvent";
    //流程节点类型 -- 结束事件
    public static final String NODE_NAME_END_EVENT = "endEvent";
    //流程节点类型 -- 边界事件
    public static final String NODE_NAME_BOUNDARY_EVENT = "boundaryEvent";
    //流程节点类型 -- 用户任务
    public static final String NODE_NAME_USER_TASK = "userTask";
    //流程节点类型 -- 服务任务
    public static final String NODE_NAME_SERVICE_TASK = "serviceTask";

    //节点自定义属性 -- 是否为并行节点
    public static final String CUSTOM_PROPERTIES_PARALLEL = "isparallel";
    //节点自定义属性 -- 是否可以AA跳
    public static final String CUSTOM_PROPERTIES_SKIP_TASK = "skiptask";
    //节点自定义属性 -- 节点审批人为空是否跳过
    public static final String CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK = "approvalnullskiptask";
    //节点自定义属性 -- 跳过节点时意见
    public static final String CUSTOM_PROPERTIES_SKIP_TASK_OPINION = "skiptaskopinion";
    //节点自定义属性 -- 是否可以修改表单
    public static final String CUSTOM_PROPERTIES_ACTMODIFY_FROM = "actmodifyfrom";
    //节点自定义属性 -- 附件是否必填
    public static final String CUSTOM_PROPERTIES_FILE_REQUIRED = "filerequired";
    //节点自定义属性 -- 是否可以查看流转记录
    public static final String CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD = "actapprovalrecord";
    //节点自定义属性 -- 是否可配置审批记录查看权限
    public static final String CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS = "actrecordpermissions";
    //节点自定义属性 -- 抄送用户
    public static final String CUSTOM_PROPERTIES_CC_USERS = "ccusers";
    //节点自定义属性 -- 是否显示流程图
    public static final String CUSTOM_PROPERTIES_ACT_APPROVAL_PNG = "actapprovalpng";



}

使用方法:

1、读取xml文件,转为bpmnModel

private BpmnModel inputStream2Xml(InputStream inputStream) throws Exception {
        //读取xml文件
        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLStreamReader reader = factory.createXMLStreamReader(new InputStreamReader(inputStream, "UTF-8"));
        BpmnModel bpmnModel = new CustomBpmnXmlConverter().convertToBpmnModel(reader);
        // bpmnModel转json
        BpmnJsonConverter converter = new BpmnJsonConverter();
        converter.convertToJson(bpmnModel);

        return bpmnModel;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296549.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年江西省“振兴杯”网络信息行业(信息安全测试员)职业技能竞赛 Write UP

文章目录 一、2023csy-web1二、2023csy-web2三、2023csy-web3四、2023csy-web4五、2023csy-misc1六、2023csy-misc2七、2023csy-crypto1八、2023csy-re1 一、2023csy-web1 该题提供一个web靶场&#xff0c;《伟大的挑战者》&#xff0c;分值&#xff1a;5分 web页面一直在播放c…

nodejs+vue+微信小程序+python+PHP的智能停车系统-计算机毕业设计推荐django

随着网络技术的不断发展&#xff0c;多媒体技术应用渐渐的出现在教育领域中&#xff0c;智能停车算法研究管理已经成为社会的一个热门话题。互联网应用在全球范围内日益普及&#xff0c;在许多的网络服务中&#xff0c;Web给人耳目一新的感觉。在这其中&#xff0c;网络平台开展…

unity 2d 入门 飞翔小鸟 小鸟碰撞 及死亡(九)

1、给地面&#xff0c;柱体这种添加2d盒装碰撞器&#xff0c;小鸟移动碰到就不会动了 2、修改小鸟的脚本&#xff08;脚本命名不规范&#xff0c;不要在意&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine;public class Fly : Mo…

【hugging face】bitsandbytes中8 bit量化的理解

8 位量化使数十亿参数规模的模型能够适应更小的硬件&#xff0c;而不会降低性能。 8 位量化的工作原理如下&#xff1a; 1.从输入隐藏状态中按列提取较大值&#xff08;离群值&#xff09;。 2.对 FP16 中的离群值和 int8 中的非离群值执行矩阵乘法。 3.改变非异常值结果以将值…

SAP UI5 walkthrough step6 Modules

在SAPUI5 中&#xff0c;资源通常用作Modules&#xff0c;这个我们将用Message Toast 来实现告警功能 修改controller.js webapp/controller/App.controller.js sap.ui.define(["sap/ui/core/mvc/Controller","sap/m/MessageToast" ], (Controller, Mes…

running小程序重要技术流程文档

一、项目文件说明&#xff1a; &#xff08;注&#xff1a;getMyMoney无用已删除&#xff09; 二、重要文件介绍 1.reinfo.js&#xff1a;位于utils文件下&#xff0c;该文件封装有统一的请求URL&#xff0c;和请求API同意封装供页面调用&#xff1b;调用时候需要在页面上先…

算法Day26 数位统计

数位统计 Description 给你一个整数n&#xff0c;统计并返回各位数字都不同的数字x的个数&#xff0c;其中0 ≤ x < 10^n。 Input 输入整数n 0≤n≤13 Output 输出整数个数 Sample 代码 import java.util.Scanner;public class Main {public static void main(String[] ar…

鸿蒙方舟开发框架ArkUI简介

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 嗨&#xff0c;各位别来无恙呐&#xff0c;我是小白 众所周知&#xff0c;华为在今年推出了 HarmonyOS 4.0 版本&#xff0c;而在此之前的版本中&#xff0c;HarmonyOS 应用的 …

TCP一对一聊天

客户端 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io…

【web安全】文件读取与下载漏洞

前言 菜某整理仅供学习&#xff0c;有误请赐教。 概念 个人理解&#xff1a;就是我们下载一个文件会传入一个参数&#xff0c;但是我们可以修改参数&#xff0c;让他下载其他的文件。因为是下载文件&#xff0c;所以我们可以看到文件里面的源码&#xff0c;内容。 文件读取…

MindOpt APL:一款适合优化问题数学建模的编程语言

什么是建模语言 建模语言是一种描述信息或模型的编程语言&#xff0c;在运筹优化领域&#xff0c;一般是指代数建模语言。 比如要写一个线性规划问题的建模和求解&#xff0c;可以采用C、Python、Java等通用编程语言来实现计算机编程&#xff08;码代码&#xff09;&#xff0…

JavaScript常用技巧专题一

文章目录 一、前言二、生成随机颜色的两种方式2.1、生成RandomHexColor2.2、生成随机RGBA 三、复制内容到剪贴板的两种方式3.1、方式13.2、方式2 四、获取URL中的查询参数五、打乱数组六、深拷贝一个对象七、确保元素在可见区域内八、获取当前选中的文本九、浏览器cookie9.1、获…

深入了解数据库锁:类型、应用和最佳实践

目录 1. 引言 2. 数据库锁的基本概念 2.1 悲观锁和乐观锁 2.2 排他锁和共享锁 3. 悲观锁的应用场景 3.1 长事务和大事务 3.2 并发修改 3.3 数据库死锁 4. 悲观锁的最佳实践 4.1 精细控制锁的粒度 4.2 避免死锁 4.3 考虑乐观锁 5. 案例分析 5.1 银行系统的转账操作…

搭乘“低代码”快车,引领食品行业数字化转型全新升级

数字化技术作为重塑传统行业重要的力量&#xff0c;正以不可逆转的趋势改变着企业经营与客户消费的方式。 在近些年的企业数字化服务与交流过程中&#xff0c;织信团队切实感受到大多数企业经营者们从怀疑到犹豫再到焦虑最终转为坚定的态度转变。 在这场数字化转型的竞赛中&a…

Could not resolve all dependencies for configuration ‘:app:androidApis‘.

android studio出现Could not resolve all dependencies for configuration ‘:app:androidApis’. 试过很多种方法&#xff0c;但是都不好使&#xff0c;不管怎么样都是提示如下报错&#xff1a; Using insecure protocols with repositories, without explicit opt-in, is un…

Unity中Batching优化的GPU实例化整理总结

文章目录 前言一、GPU Instancing的支持1、硬件支持2、Shader支持3、脚本支持 二、我们来顺着理一下GPU实例化的使用步骤1、GPU实例化前的C#代码准备2、在 appdata 和 v2f 中定义GPU实例化ID3、在顶点着色 和 片元着色器 设置GPU Instance ID&#xff0c;使实例化对象顶点位置正…

RK3588平台开发系列讲解(hardware)reference-ril源码分析

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、reference-ril目录介绍二、支持的功能三、Android RIL 框架沉淀、分享、成长,让自己和他人都能有所收获!😄 一、reference-ril目录介绍 目录:3588-android12/hardware/ril/reference-ril

做数据分析为何要学统计学(5)——什么问题适合使用t检验?

t检验&#xff08;Students t test&#xff09;&#xff0c;主要依靠总体正态分布的小样本&#xff08;例如n < 30&#xff09;对总体均值水平进行差异性判断。 t检验要求样本不能超过两组&#xff0c;且每组样本总体服从正态分布&#xff08;对于三组以上样本的&#xff0…

降维技术——PCA、LCA 和 SVD

一、说明 降维在数据分析和机器学习中发挥着关键作用&#xff0c;为高维数据集带来的挑战提供了战略解决方案。随着数据集规模和复杂性的增长&#xff0c;特征或维度的数量通常变得难以处理&#xff0c;导致计算需求增加、潜在的过度拟合和模型可解释性降低。降维技术通过捕获数…

Docker, Docker-compose部署Sonarqube

参考文档 镜像地址: https://hub.docker.com/_/sonarqube/tags Docker部署文档地址 Installing from Docker | SonarQube Docs Docker-compose文档部署地址&#xff1a; Installing from Docker | SonarQube Docs 部署镜像 2.1 docker部署 # 宿主机执行 $. vi /etc/sysctl.conf…