当前位置: 首页 > news >正文

camunda流程引擎基本使用(笔记)

文章目录

  • 一、camunda基础
    • 1.1 安装与部署流程引擎
    • 1.2 流程引擎结构
    • 1.3 流程引擎的基本使用
      • 1.3.1 创建一个BPMN Diagram
      • 1.3.2 实现一个外部工作者
      • 1.3.3 部署流程
      • 1.3.4 创建一个流程实例并消费
      • 1.3.5 向流程中添加用户任务
      • 1.3.6 添加网关
      • 1.3.7 业务规则
  • 二、Java 集成流程引擎
    • 2.1 为项目引入Platform
      • 2.1.1 页面配置
    • 2.2 简单使用
      • 2.2.1 引入API
      • 2.2.2 服务
      • 2.2.3 部署流程
    • 2.3 流程部署详细介绍
  • 附录

一、camunda基础

Camunda介绍 Camunda是一种工作流引擎,是由Java开发的一个纯Java库。

通常集成在我们的服务中,作为其中一块功能。

1.1 安装与部署流程引擎

官方-下载引导地址

  • Camunda Platform 和 Camunda Modeler是必要的文件。
    • Camunda Platform:这里是流程引擎的用户、租户等部分的管理界面
    • Camunda Modeler:流程引擎的核心,即流程相关的部分

  • docker安装
docker pull camunda/camunda-bpm-platform:run-latest
docker run -d --name camunda -p 8080:8080 camunda/camunda-bpm-platform:run-latest
  • 非docker安装

Camunda Platform 下载地址

我们下载好后,需要到这个路径下。这里是创建表的sql语句,选择自己的数据库运行语句,来创建对应的表。
在这里插入图片描述

修改default.yml 中数据源和JDBC 替换为自己使用的数据库的配置

然后把对应的JDBC放入标注上面的userlib之中即可。

在这里插入图片描述

Camunda Modeler 下载地址
我们在点击运行后可以直接使用。
在这里插入图片描述

1.2 流程引擎结构

在这里插入图片描述

在这里插入图片描述

1.3 流程引擎的基本使用

我们创建在Camunda Modeler中创建一个流程,然后我们可以用Java或者JS,按照流程去执行它。

本篇使用Java处理。

1.3.1 创建一个BPMN Diagram

首先,我们可以创建一个BPMN Diagram。

Business Process Modeling Notation,简称BPMN

它的事件包含

  • 开始(Start)
  • 中间(Intermediate)
  • 边界(Boundary)
  • 结束(End)

根据触发方式不同,可以分为

  • 捕获事件(Catching Event)
  • 抛出事件(Throwing Event)

具体的使用方式请参考:参考-Executing automated steps 、Service tasks

我们准备一个简易的流程,如下图(与官方例子一致)。
这里可以直接下载官方的例子下载避免繁琐的配置操作
在这里插入图片描述
注意一下,最新版的是可集群的版本(版本8)
在这里插入图片描述
我们使用的是如下的版本(版本7)
在这里插入图片描述

1.3.2 实现一个外部工作者

换言之就是创建一个Java程序,用它以处理BPMN Diagram

这里是官方的写的依赖,依据自己的需要改动即可。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.camunda.bpm.getstarted</groupId><artifactId>charge-card-worker</artifactId><version>0.0.1-SNAPSHOT</version><properties><camunda.external-task-client.version>7.17.0</camunda.external-task-client.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.camunda.bpm</groupId><artifactId>camunda-external-task-client</artifactId><version>${camunda.external-task-client.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.6.1</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency></dependencies>
</project>

笔者改为Spring Boot(Java11)

	<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.6</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId></dependency><dependency><groupId>org.camunda.bpm</groupId><artifactId>camunda-external-task-client</artifactId><version>7.18.0</version></dependency></dependencies>

该程序连接的是 Camunda Platform 系统注意端口和IP。
在这里插入图片描述

import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.client.ExternalTaskClient;import java.awt.*;
import java.net.URI;@Slf4j
public class ChargeCardWorker {public static void main(String[] args) {ExternalTaskClient client = ExternalTaskClient.create()// 依据实际情况填写程序的IP和端口.baseUrl("http://localhost:8080/engine-rest")// 异步相应超时时间.asyncResponseTimeout(10000) // long polling timeout.build();// subscribe to an external task topic as specified in the process// 订阅流程中指定的外部任务主题,与活动ID对应client.subscribe("charge-card")// 默认锁的持续时间为20秒.lockDuration(1000) // the default lock duration is 20 seconds, but you can override this// 处理内容// externalTask:任务,externalTaskService:处理服务.handler((externalTask, externalTaskService) -> {// Put your business logic here// Get a process variableString item = externalTask.getVariable("item");Integer amount = externalTask.getVariable("amount");log.info("Charging credit card with an amount of '{}'€ for the item '{}'...",amount,item);try {// 打开页面并挂起Desktop.getDesktop().browse(new URI("https://docs.camunda.org/get-started/quick-start/complete"));} catch (Exception e) {e.printStackTrace();}// Complete the task// 任务完成externalTaskService.complete(externalTask);}).open();}
}

在这里插入图片描述
这里的活动的Topic与我们的工作者一致。因而可以知道活动有对应的工作者去处理。

通过改变活动以及活动的顺序来改变流程,而活动自己被不同的工作者处理后继续流转因而不受影响,以此完成流程。

1.3.3 部署流程

也就是将BPMN Diagram 与 Platform关联,然后让我们的工作者去处理它。
我们将流程部署过去
在这里插入图片描述
成功后,我们进入platform登陆后(默认账号密码均为demo),可以看到流程已经在这里了

http://localhost:8080/camunda/app/cockpit/default/#/processes
在这里插入图片描述
在这里插入图片描述

1.3.4 创建一个流程实例并消费

我们接下来可以使用postman
向这个地址发送Post请求

http://localhost:8080/engine-rest/process-definition/key/payment-retrieval/start

同时在body里面发送如下json参数

{"variables": {"amount": {"value":555,"type":"integer"},"item": {"value": "item-xyz"}}
}

在这里插入图片描述

当我们在工作者的后台看到如下数据,并且成功打开了一个页面,就说明成功消费了
在这里插入图片描述

在这里插入图片描述
此处的key就是我们process的ID:payment-retrieval

1.3.5 向流程中添加用户任务

当然这里只是最简单的使用。参考-Add a User Task to the Process

依据类似的操作,我们添加一个
在这里插入图片描述
我们把任务分配给demo用户
下面的候选组、人、到期日期请自行参考文档
在这里插入图片描述
我们接着在这个活动的Forms添加如下属性,来向流程中加一个表单
在这里插入图片描述
选择 File > New File > Form(版本7)创建如下表单

并把ID和我们payment-form设置为一样的,来关联起来。
在这里插入图片描述
我们接下来创建一个Amount项目,使用Number类型
在这里插入图片描述
再创建一个文本框,如下设置
在这里插入图片描述
再加一个是否同意
在这里插入图片描述

完成回到流程然后部署,记得加入我们的表单
在这里插入图片描述
来到这个页面,点击框住的按钮

http://localhost:8080/camunda/app/tasklist/

在这里插入图片描述
选择我们创建的流程,开启一个流程

在这里插入图片描述

输入一个业务流程号后,我们可以找到我们的流程以及表格

在这里插入图片描述

同时可以看到流程位置

在这里插入图片描述
填写完成后,我们继续,则会流转到我们前面写的消费者处。

1.3.6 添加网关

也就是类似if-else的方式,来确定流向。

我们先搭出如下内容

网关1

  1. 如果金额小于 1000 就直接处理
  2. 如果大等于 1000 就需要处理

网关2

  1. 判断是否同意
    在这里插入图片描述

我们的判断是加在箭头上的
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
接下来我们部署该流程,按照1.3.5中流程开始一个流程,或者通过PostMan请求,可以看到流程流转到了不同地方。

platform 创建流程
在这里插入图片描述

我们查看,可以看到流程到了这里
在这里插入图片描述
启动我们的外部工作者,即可完成处理。

postman 创建流程
发送的也是和之前一样的请求
在这里插入图片描述

在这里插入图片描述
可以看到我们这里的流程到了1.3.5的部分,在tasklist中我们处理是否同意即可。

1.3.7 业务规则

我们在这里加入业务规则
在这里插入图片描述

在这里插入图片描述

随后我们创建一个新的DMN流程(依然是版本7)。
在这里插入图片描述
我们这里直接把Decision1的ID(决策表)和我们业务规则输入的reference关联起来
在这里插入图片描述

点击框住部分
在这里插入图片描述

创建如下内容

标题我们是Item大写,Expression我们是小写让变量与之后流程一致
在这里插入图片描述
制作如下表格
在这里插入图片描述
到现在为止,我们完成了决策表的制作。

  • 如果我们的item是"item-xyz"决策就是赞成
  • 若果不是,则结果就是不赞成

关于决策表,可以参考Camunda DMN

我们接下来把它部署即可,名字可以取框住的
在这里插入图片描述
随后我们可以在决策里面找到
在这里插入图片描述

在重新部署我们的流程

在这里插入图片描述
然后我们开始流程

在这里插入图片描述
在这里插入图片描述

二、Java 集成流程引擎

我们用SpringBoot集成流程引擎。

可以参考-Camunda-Spring Boot 集成

相关的SpringBoot配置可以参考-流程引擎配置

2.1 为项目引入Platform

<properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><camunda.spring-boot.version>7.18.0</camunda.spring-boot.version><spring-boot.version>2.7.3</spring-boot.version><xml-bind.version>2.3.6</xml-bind.version><maven.compiler.target>11</maven.compiler.target><mybatis-plus.version>3.5.1</mybatis-plus.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId><version>${camunda.spring-boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter</artifactId><version>${camunda.spring-boot.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-extension</artifactId><version>${mybatis-plus.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>

yml

server:port: 8080
spring:datasource:url: jdbc:mysql://IP:Port/DataBase?useUnicode=true&NamePatternMatchesAll=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=falseusername: usernamepassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverapplication:name:   applicationName
camunda:bpm:admin-user:id: demopassword: demo
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true
package camunda;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class CamundaApplication {public static  void main(String[] args){SpringApplication.run(CamundaApplication.class,args);}
}

在数据库中我们可以看到我们配置的默认用户。
在这里插入图片描述

启动后我们访问

http://localhost:8080/camunda/app/welcome/default/#!/login

出现如下页面就说明成功了。
在这里插入图片描述
页面和地址的使用方式和我们之前的使用方式是一致的。

2.1.1 页面配置

有页面是因为我们引入了,不需要页面的时候,我们可以不引入它即可。

<dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId><version>${camunda.spring-boot.version}</version>
</dependency>

此外,我们可以配置yml,来修改路径以及是否重定向到默认的index.html.

camunda:bpm:webapp:application-path: 路径index-redirect-enabled: false

2.2 简单使用

2.2.1 引入API

可以参考-Camunda BPM Javadocs 7.9.19-ee

要使用类似于我们之前用的API,我们可以引入如下依赖:

<dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter-rest</artifactId><version>${camunda.spring-boot.version}</version>
</dependency>

默认API地址为

http://localhost:8080/engine-rest

Camunda使用的是jersey,因而一些配置需要jersey配置方式。

也可以通过修改spring boot的通用应用程序属性来改变API访问地址:

spring:jersey:application-path=地址

为了修改配置或注册额外的资源,可以提供一个集成自如下的配置类:

org.camunda.bpm.spring.boot.starter.rest.CamundaJerseyResourceConfig 
@Component
@ApplicationPath("/engine-rest")
public class JerseyConfig extends CamundaJerseyResourceConfig {@Overrideprotected void registerAdditionalResources() {register(...);}
}

中心起点是ProcessEngine(流程引擎),可以通过配置部分中描述的几种方式创建ProcessEngine。

从ProcessEngine中,可以获得包含 工作流/BPM 方法的各种服务。

ProcessEngine和服务对象是 线程安全 的。所以可以为整个服务器保留对其中一个的引用。
在这里插入图片描述
actiti.cfg.xml文件:

  • 对于所有的actiti.cfg.xml文件,流程引擎将以Spring方式构建:首先创建Spring应用程序上下文,然后从该应用程序上下文获得流程引擎。
  • 如何书写,可参考-activiti配置文件activiti.cfg.xml

服务都是无状态的:

  • 可以在集群中的多个节点上运行Camunda BPM,每个节点都访问同一个数据库,而不必担心哪台机器实际执行了前面的调用。对任何服务的任何调用都是幂等的,无论它在哪里执行。

2.2.2 服务

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

将在第一次调用流程引擎时初始化并构建流程引擎,之后总是返回相同的流程引擎.
可以使用ProcessEngines.init()和ProcessEngines.destroy()来正确地创建和关闭所有的流程引擎


RepositoryService repositoryService = processEngine.getRepositoryService();

RepositoryService可能是使用Camunda引擎时需要的第一个服务。此服务提供用于管理和操作部署和流程定义的操作。

部署 部署内容 意味着将其上传到引擎,在将所有进程存储到数据库之前,都将会对其进行检查和解析。

完成后,系统就知道部署了,之后就可以启动部署中包含的任何进程。

通过该服务,可以:

  • 查询引擎已知的部署和流程定义。
  • 挂起并激活流程定义。挂起意味着不能对它们进行进一步的操作,而激活则是相反的操作。
  • 检索引擎自动生成的部署图或流程图中包含的文件等各种资源

RuntimeService runtimeService = processEngine.getRuntimeService();

RuntimeService处理启动流程定义的新流程实例。

流程定义定义了流程中不同步骤的结构和行为,流程实例是此类流程定义的一次执行。对于每个流程定义,通常都有多个实例同时运行。

RuntimeService也是用于检索和存储流程变量的服务。这是特定于给定流程实例的数据,可以由流程中的各种构造使用(例如,独占网关通常使用流程变量来确定选择哪条路径来继续流程)。

RuntimeService还允许对流程实例和执行进行查询。基本上,执行就是指向流程实例当前位置的指针。

最后,当流程实例等待外部触发器且流程需要继续时,将使用RuntimeService。流程实例可以有各种等待状态,该服务包含各种“通知”实例接收到外部触发器并可以继续该流程实例的操作。


TaskService taskService = processEngine.getTaskService();

需要展示给实际用户执行的任务是流程引擎的核心。

围绕任务的所有内容都分组在TaskService中,例如

  • 查询已分配给用户/组的任务。
  • 创建新的独立任务。这些任务与流程实例无关。
  • 操作将任务分配给哪个用户,或者哪些用户以某种方式参与了任务。
  • 申请并完成一项任务。声明意味着某人决定成为任务的受让人,这意味着该用户将完成任务。完成的意思是“完成任务的工作”。这通常是填写某种表单。

IdentityService identityService = processEngine.getIdentityService();

IdentityService允许对组和用户进行管理(创建、更新、删除、查询等)。

但是,核心引擎在运行时实际上不会对用户进行任何检查。


FormService formService = processEngine.getFormService();

FormService是一个可选服务。

此服务引入了启动表单和任务表单的概念。

  • 启动表单是在流程实例启动之前向用户显示的表单
  • 任务表单是在用户希望完成表单时显示的表单

该服务以一种易于使用的方式公开此数据。但同样,这是可选的,因为表单不需要嵌入到流程定义中。


HistoryService historyService = processEngine.getHistoryService();

HistoryService公开引擎收集的所有历史数据。

在执行流程时,引擎可以保存大量数据(这是可配置的),例如流程实例的开始时间、谁执行了哪些任务、完成任务所需的时间、每个流程实例遵循的路径等等。

该服务主要提供访问此数据的查询功能。


ManagementService managementService = processEngine.getManagementService();

在编写自定义应用程序时,通常不需要ManagementService。

它允许检索关于数据库表和表元数据的信息。此外,它还公开了作业的查询功能和管理操作。作业在引擎中用于各种用途,如计时器、异步延续、延迟挂起/激活等。稍后,我们将更详细地讨论这些主题。


FilterService filterService = processEngine.getFilterService();

FilterService允许创建和管理过滤器。过滤器是像任务查询一样存储的查询。

例如,Tasklist使用过滤器来过滤用户任务。

camunda-Filters


ExternalTaskService externalTaskService = processEngine.getExternalTaskService();

ExternalTaskService提供对外部任务实例的访问。外部任务表示在外部独立于流程引擎处理的工作项。


CaseService caseService = processEngine.getCaseService();

CaseService类似于RuntimeService,但用于案例实例。它处理启动用例定义的新用例实例和管理用例执行的生命周期。该服务还用于检索和更新案例实例的流程变量。


DecisionService decisionService = processEngine.getDecisionService();

DecisionService允许评估部署到引擎的决策。它是在独立于流程定义的业务规则任务中评估决策的一种替代方法。

2.2.3 部署流程

我们在启动类上添加@EnableProcessApplication注释,并将空的processes.xml文件放在src/main/resources/META-INF文件夹中。
在这里插入图片描述

@SpringBootApplication
@EnableProcessApplication
public class CamundaApplication {public static  void main(String[] args){SpringApplication.run(CamundaApplication.class,args);}
}

Camunda Engine的每个流程应用程序都需要该文件,此处我们始终将它保持为空(它会使用默认配置)

这里我们仍然从Modeler处创建一个流程。

在这里插入图片描述
然后保存在如下位置
在这里插入图片描述
启动后,我们可以看到已经成功部署
在这里插入图片描述
在流程定义中可以找到
在这里插入图片描述
此处也可以找到
在这里插入图片描述
如下就是部署与移除的流程,默认的配置下,即使删除bpmn,流程仍然存在于数据库中
在这里插入图片描述

我们可以创一个用于创建实例的类,这里的key就是我们流程的key,至此该监听器监听该流程。
在这里插入图片描述
可以完成部署后立即创建一个实例(重启也会)

@Service
@Slf4j
public class TestCamunda {@Autowiredprivate RuntimeService runtimeService;@EventListenerprivate void processPostDeploy(PostDeployEvent event) {log.info("{}",event);runtimeService.startProcessInstanceByKey("Process_028ntv2");}
}

可以在这个位置找到
在这里插入图片描述

我们可以做一个接口,通过接受服务ID,然后用RuntimeService去创建。

消费服务我们之前就写给过了,这里就跳过。

2.3 流程部署详细介绍

默认情况下,camunda-spring-boot-starter 使用SpringProcessEngineConfiguration 配置自动部署功能。

从1.2.0开始,可以通过 SpringBootProcessApplication 配置。这将禁用SpringProcessEngineConfiguration 的自动部署功能。

自动部署功能,用如下路径作为资源扫描的目录。

 META-INF/processes.xml 

允许使用的所有 processes.xml 配置项在这里列出。

在这里插入图片描述
如果是空的,就会用默认配置,如下:

<process-applicationxmlns="http://www.camunda.org/schema/1.0/ProcessApplication"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><process-archive><properties><property name="isDeleteUponUndeploy">false</property><property name="isScanForProcessDefinitions">true</property></properties></process-archive></process-application>

官方给出的配置样例:

<process-applicationxmlns="http://www.camunda.org/schema/1.0/ProcessApplication"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><process-archive name="loan-approval"><process-engine>default</process-engine><properties><property name="isDeleteUponUndeploy">true</property><property name="isScanForProcessDefinitions">true</property></properties></process-archive></process-application>

我们在这里声明了一个单个部署(流程存档),流程存档的名称为loan-approval,并部署到名称为default的流程引擎。

  • isDeleteUponUndeploy:此属性控制流程应用程序的取消部署是否需要从数据库中删除流程引擎部署。

    • 默认设置为false。
    • 如果将此属性设置为true,则取消部署流程应用程序将导致从数据库中删除部署(包括流程实例)。
  • isScanForProcessDefinitions:如果此属性设置为true,则会自动扫描流程应用程序的类路径以查找可部署资源。

配置文件的基本设置,可参考-The processes.xml Deployment Descriptor

配置参数可查阅

  • Process Engine Configuration
  • Process Archive Configuration

只需要添加@EnableProcessApplication注解到SpringBootapplication类即可:


@SpringBootApplication
@EnableProcessApplication
public class CamundaApplication{}

由于使用@EnableProcessApplication时,没有扩展ProcessApplication类,所以我们不能使用@PostDeploy和@PreUndeploy方法注释。

相反,这些回调是通过Spring事件发布机制提供的。所以可以使用以下事件监听器。


@SpringBootApplication
@EnableProcessApplication
public class CamundaApplication{//...
}@EventListener
public void onPostDeploy(PostDeployEvent event) {//...
}@EventListener
public void onPreUndeploy(PreUndeployEvent event) {//...
}

通过监听器,我们可以完成如下操作。
在这里插入图片描述

附录

camunda中文-官方文档
camunda内部构造
camunda英文-官方文档

相关文章:

camunda流程引擎基本使用(笔记)

文章目录一、camunda基础1.1 安装与部署流程引擎1.2 流程引擎结构1.3 流程引擎的基本使用1.3.1 创建一个BPMN Diagram1.3.2 实现一个外部工作者1.3.3 部署流程1.3.4 创建一个流程实例并消费1.3.5 向流程中添加用户任务1.3.6 添加网关1.3.7 业务规则二、Java 集成流程引擎2.1 为…...

JS之数据结构与算法

前言数据结构是计算机存储、组织数据的方式,算法是系统描述解决问题的策略。了解基本的数据结构和算法可以提高代码的性能和质量。也是程序猿进阶的一个重要技能。手撸代码实现栈,队列,链表,字典,二叉树,动态规划和贪心算法1.数据结构篇1.1 栈栈的特点&#xff1a;先进后出clas…...

CnOpenData·A股上市企业数字化转型指数数据

一、数据简介 企业数字化转型是近年来中国社会各界重点关注的领域&#xff0c;但基础数据的不完善在很大程度上制约了相关科学研究的开展。构建合理、科学的数字化转型指标体系有利于学者定量地研究企业数字化的相关问题&#xff0c;也有利于衡量企业的数字化水平。广东金融学院…...

VMware16pro虚拟机安装全过程

很多时候需要用到Linux系统&#xff0c;简单的一种方式可以是&#xff1a;Windows系统运行Linux&#xff08;Windows Subsystem for Linux&#xff09;不过有些时候还是需要虚拟机来运行Linux&#xff0c;也更方便点&#xff0c;比如在做嵌入式系统的烧录等操作都需要Linux环境…...

阿里云第六代云服务器最新价格表(计算型c6、通用型g6和内存型r6)

目前阿里云第六代云服务器有计算型c6、通用型g6和内存型r6实例。计算型c6实例有2核4G、4核8G、8核16G配置可选&#xff0c;主要适用于网站应用、批量计算、视频编码等场景。通用型g6实例有2核8G、4核16G、8核32G配置可选&#xff0c;适用于各种类型的企业级应用&#xff0c;网站…...

微小目标识别研究(2)——基于K近邻的白酒杂质检测算法实现

文章目录实现思路配置opencv位置剪裁实现代码自适应中值滤波实现代码动态范围增强实现代码形态学处理实现代码图片预处理效果计算帧差连续帧帧差法原理和实现代码实现代码K近邻实现基本介绍实现代码这部分是手动实现的&#xff0c;并没有直接调用相关的库完整的代码——调用ope…...

2022-06-14至2022-08-11 关于复现MKP算法的总结与反思

Prerequisite 自2022年6月14日至2022年8月11日的时间内&#xff0c;我致力于完成A Hybrid Approach for the 0–1 Multidimensional Knapsack problem 论文的复现工作&#xff0c;此次是我第一次进行组合优化方向的学习工作&#xff0c;下面介绍该工作内容发展过程以及该工作结…...

IBMMQ教程二(window版安装)

下载下载地址&#xff1a;https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/我这里选择的是9.1.0.0版本安装将下载完成的压缩包解压双击Setup.exe直接运行点击软件需求查看系统配置是否满足&#xff0c;右边绿色的对号说明满足需求&#xff0c…...

Java | HashSet 语法

HashSet 基于 HashMap 来实现的&#xff0c;是一个不允许有重复元素的集合。 HashSet 允许有 null 值。 HashSet 是无序的&#xff0c;即不会记录插入的顺序。 HashSet 不是线程安全的&#xff0c; 如果多个线程尝试同时修改 HashSet&#xff0c;则最终结果是不确定的。 您必须…...

js学习4(运算符)

### 1.算数运算符&#xff1a; 、-、*、\、%&#xff08;取余&#xff09;、**&#xff08;幂方&#xff09; ## 优先级 同数学课程&#xff0c;可以加括号 ### 2.自增和自减 、--&#xff08;即数值变量加一或减一&#xff09; ### 3.赋值运算符 、、-、*、/、... ### 4.比较运…...

2月更新 | Visual Studio Code Python

我们很高兴地宣布&#xff0c;2023年2月版 Visual Studio Code Python 和 Jupyter 扩展现已推出&#xff01;此版本包括以下改进&#xff1a;从激活的终端启动 VS Code 时的自动选择环境 使用命令 Python: Create Environmen 时可选择需求文件或可选依赖项 预发布&#xff1a;改…...

C++回顾(十八)—— 文件操作

18.1 I/O流概念和流类库结构 1 概念 程序的输入指的是从输入文件将数据传送给程序&#xff0c;程序的输出指的是从程序将数据传送给输出文件。 C输入输出包含以下三个方面的内容&#xff1a; &#xff08;1&#xff09;对系统指定的标准设备的输入和输出。即从键盘输入数据&am…...

以java编写员工管理系统(测试过 无问题)

一、系统结果的部分展示 二、题目以及相关要求 三、组成 1.该系统由 Employee 类 、commonEmployee类、Testemd类和managerEmployee类组成 2.Employee实现的代码 public class Employee {private String id;private String name;private String job;private int holiday…...

单例模式之懒汉式

在上篇文章中&#xff0c;我们讲了单例模式中的饿汉式&#xff0c;今天接着来讲懒汉式。 1.懒汉式单例模式的实现 public class LazySingleton {private static LazySingleton instance null;// 让构造函数为private&#xff0c;这样该类就不会被实例化private LazySingleto…...

1638_chdir函数的功能

全部学习汇总&#xff1a;GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 今天看一个半生不熟的小函数&#xff0c;chdir。说半生不熟&#xff0c;是因为这个接口一看就知道是什么功能。然而&#xff0c;这个接口如何用可真就没啥想法了。 …...

使用CEF 获得某头条请求,并生成本地文件的方法

目录 一、获得网站请求响应信息 1、响应过滤 2、匹配过滤URL的函数 3、获得请求响应后的处理...

二十、Django-restframework之视图集和路由器

一、视图集和路由器 REST框架包含了一个处理视图集的抽象&#xff0c;它允许开发人员集中精力建模API的状态和交互&#xff0c;并根据通用约定自动处理URL构造。 视图集类与视图类几乎相同&#xff0c;不同之处在于它们提供的是retrieve或update等操作&#xff0c;而不是get或…...

[深入理解SSD系列 闪存实战2.1.2] SLC、MLC、TLC、QLC、PLC NAND_固态硬盘闪存颗粒类型

闪存最小物理单位是 Cell, 一个Cell 是一个晶体管。 闪存是通过晶体管储存电子来表示信息的。在晶体管上加入了浮动栅贮存电子。数据是0或1取决于在硅底板上形成的浮动栅中是否有电子。有电子为0,无电子为1. SSD 根据闪存颗粒区分,固态硬盘有SLC、MLC、TLC、QLC、PLC 五种类型…...

论文阅读-MGTAB: A Multi-Relational Graph-Based Twitter Account DetectionBenchmark

目录 摘要 1. 引言 2. 相关工作 2.1. 立场检测 2.2.机器人检测 3.数据集预处理 3.1.数据收集和清理 3.2.专家注释 3.3. 质量评估 3.4.特征分析 4. 数据集构建 4.1.特征表示构造 4.2.关系图构建 5. 实验 5.1.实验设置 5.2.基准性能 5.3训练集大小的研究 5.4 社…...

基于libco的c++协程实现(时间轮定时器)

在后端的开发中&#xff0c;定时器有很广泛的应用。 比如&#xff1a; 心跳检测 倒计时 游戏开发的技能冷却 redis的键值的有效期等等&#xff0c;都会使用到定时器。 定时器的实现数据结构选择 红黑树 对于增删查&#xff0c;时间复杂度为O(logn)&#xff0c;对于红黑…...

java多线程与线程池-04线程池与AQS

第7章 线程池与AQS java.util.concurrent包中的绝大多数同步工具,如锁(locks)和屏障(barriers)等,都基于AbstractQueuedSynchronizer(简称AQS)构建而成。这个框架提供了一套同步管理的通用机制,如同步状态的原子性管理、线程阻塞与解除阻塞,还有线程排队等。 在JD…...

优化模型验证关键代码25:样本均值近似技术处理两阶段随机旅行商问题及Gurobipy代码验证

大多数数学规划模型都会考虑到研究问题中存在的不确定性,针对这些不确定性,两种常用的处理方法是鲁棒优化和随机规划。这篇论文我们关注后者,也就是两阶段随机旅行商问题;利用套期保值算法计算不同规模TSP的可行解,同时比较了样本均值近似技术的解的情况,并计算了该问题的…...

老爸:“你做的什么游戏测试简直是不务正业!”——我上去就是一顿猛如虎的解释。

经常有人问我&#xff1a;游戏测试到底是干什么呢&#xff1f;是游戏代练&#xff1f;每天玩游戏&#xff1f;装备随便造&#xff0c;怪物随便秒&#xff0c;线上GM指令随便用&#xff1f;可以每天玩玩游戏&#xff0c;不用忙工作&#xff0c;太爽了&#xff1f;有时朋友不理解…...

JVM垃圾回收调优知识点整理

目录 1、JVM内存模型 1.2、堆及垃圾回收 1.3、JVM参数设置经验: 1.4、对象逃逸分析:...

linux安装mysql-8.0.31

1)、下载mysql-8.0.31压缩包两种方式 a.本地下载后上传服务器解压&#xff0c;下载地址&#xff1a;https://downloads.mysql.com/archives/community/ b.服务器使用命令下载&#xff0c;注意&#xff1a;路径在那&#xff0c;就下载到那个位置。 wget https://dev.mysql.com/…...

2023 年会是网络安全的关键年吗?

过去 12 个月对网络安全领域和周围的每个人来说再次充满挑战。和往年不同&#xff0c;感觉很不一样&#xff0c;攻击源源不断。过去&#xff0c;大型漏洞每季度发生一次&#xff0c;但在过去一年中&#xff0c;在某些情况下&#xff0c;我们几乎每周都会处理严重漏洞。 已知利…...

【深度强化学习】(1) DQN 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位讲解一下深度强化学习中的基础模型 DQN&#xff0c;配合 OpenAI 的 gym 环境&#xff0c;训练模型完成一个小游戏&#xff0c;完整代码可以从我的 GitHub 中获得&#xff1a; https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Mod…...

Nginx服务优化与防盗链

目录 1.隐藏nginx版本号 1.查看版本号 2.隐藏版本信息 2.修改用户与组 3.缓存时间 4.日志分割 5.连接超时 6.更改进程数 7.网页压缩 8.配置防盗链 1.配置web源主机&#xff08;192.168.156.10 www.lhf.com&#xff09; 2.配置域名映射关系 3.配置盗链主机 &#xff0…...

npm与yarn常用命令

npm npm -v&#xff1a;查看 npm 版本npm init&#xff1a;初始化后会出现一个 Package.json 配置文件&#xff0c;可以在后面加上 -y&#xff0c;快速跳到问答界面npm install&#xff1a;会根据项目中的 package.json 文件自动给下载项目中所需的全部依赖npm insall 包含 --…...

【C++】C++11新特性——右值引用

文章目录一、左值引用、 右值引用1.1 左值与右值1.2 左值引用1.3 右值引用二、右值引用的意义三、移动语句3.1 移动构造3.2 移动赋值3.3 总结四、move问题五、完美转发5.1 万能引用与折叠5.2 完美转发std::forward一、左值引用、 右值引用 1.1 左值与右值 我们经常能听到左值…...

C#基础教程21 正则表达式

文章目录 简介正则表达式语法字符集元字符转义字符量词贪婪匹配和非贪婪匹配正则表达式类Regex类Match方法Matches方法简介 正则表达式是一种描述字符串模式的语言,它可以用来匹配、查找、替换字符串中的模式。在C#中,我们可以使用System.Text.RegularExpressions命名空间下的…...

聚观早报|谷歌发布最大视觉语言模型;王兴投资王慧文ChatGPT项目

今日要闻&#xff1a;谷歌发布全球最大视觉语言模型&#xff1b;马斯克预计Twitter下季度现金流转正&#xff1b;王兴投资王慧文ChatGPT项目&#xff1b;美国拟明年 11 月开展载人绕月飞行&#xff1b;慧与科技宣布收购Athonet谷歌发布全球最大视觉语言模型 近日&#xff0c;来…...

java Spring5 xml配置文件方式实现声明式事务

在java Spring5通过声明式事务(注解方式)完成一个简单的事务操作中 我们通过注解方式完成了一个事务操作 那么 下面 我还是讲一下 基于xml实现声明式事务的操作 其实在开发过程中 大家肯定都喜欢用注解 因为他方便 这篇文章中的xml方式 大家做个了解就好 还是 我们的这张表 记…...

常用存储芯片-笔记本上固态硬盘PTS11系列推荐

在存储领域中&#xff0c;除了存储颗粒之外&#xff0c;还有一种极其重要的芯片&#xff1a;存储控制芯片。存储控制芯片是CPU与存储器之间数据交换的中介&#xff0c;决定了存储器最大容量、存取速度等多个重要参数。特别是在AI、5G、自动驾驶时代&#xff0c;对于数据处理及存…...

【AI绘图学习笔记】奇异值分解(SVD)、主成分分析(PCA)

这节的内容需要一些线性代数基础知识&#xff0c;如果你没听懂本文在讲什么&#xff0c;强烈建议你学习【官方双语/合集】线性代数的本质 - 系列合集 文章目录奇异值分解线性变换特征值和特征向量的几何意义什么是奇异值分解&#xff1f;公式推导SVD推广到任意大小矩阵如何求SV…...

【设计模式】模板方法模式和门面模式

模板方法模式和门面模式模板方法模式代码示例门面模式代码示例门面模式的应用场景模板方法模式 模板方法模式非常简单&#xff0c;就是定义了一个固定的公共流程&#xff0c;整个流程有哪些步骤是事先定义好的&#xff0c;具体的步骤则交由子类去实现。属于行为型设计模式。 简…...

Kubernetes未来十年的四大发展趋势

作者&#xff1a;李翔 跟大家已经感受到的一样&#xff0c;Kubernetes已经成为了云计算领域最具统治力的平台&#xff0c;成为了云原生开发的绝对标准&#xff0c;而伴随Kubernetes诞生的CNCF (Cloud Native Computing Foundation) 也因此成为了业界影响力巨大的组织。在成为云…...

一、sql 基础知识、函数和子查询

MySQL 是一种流行的关系型数据库管理系统&#xff0c;使用 SQL 语言进行数据管理和操作。在 MySQL 中&#xff0c;常用的语句包括 SELECT 查询语句、WHERE 条件语句、算术表达式、函数、聚合函数、自定义函数、逻辑表达式、子查询和连接。这些语句可以帮助用户快速地进行数据查…...

产品射频认证笔记

文章目录1. 射频监管认证的目的&#xff1a;1.1 确保 RF 产品在其预期环境中按预期运行1.2 确保射频产品不会干扰其他电子或射频设备2. 射频认证地区规范3. FCC简介4. FCC认证需要准备的内容&#xff1a;5. 射频监管测量会话期间测量以下射频属性&#xff1a;6. 调整射频参数6.…...

做了个springboot接口参数解密的工具,我给它命名为万能钥匙(已上传maven中央仓库,附详细使用说明)

前言&#xff1a;之前工作中做过两个功能&#xff0c;就是之前写的这两篇博客&#xff0c;最近几天有个想法&#xff0c;给它做成一个springboot的start启动器&#xff0c;直接引入依赖&#xff0c;写好配置就能用了 springboot使用自定义注解实现接口参数解密&#xff0c;普通…...

【Flutter从入门到入坑】Flutter 知识体系

学习 Flutter 需要掌握哪些知识&#xff1f; 终端设备越来越碎片化&#xff0c;需要支持的操作系统越来越多&#xff0c;从研发效率和维护成本综合考虑&#xff0c;跨平台开发一定是未来大前端的趋势&#xff0c;我们应该拥抱变化。而 Flutter 提供了一套彻底的移动跨平台方案…...

顺序表的基本操作

目录 一.什么是顺序表 二.顺序表的基本操作 1.初始化 2.增容 3.尾插 4.头插 5.尾删 6.头删 7.指定位置插入 8.指定位置删除 9.打印 10.查找 11.销毁 一.什么是顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组…...

设计模式——创建型模型——单列模式(8种实现)

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;计算机基础专栏 &#x1f4e7;如果文章知识点有错误的地方&#…...

【软考中级】软件设计师笔记

计算机系统的性能一般包括两个方面&#xff1a;一方面是它的可用性&#xff0c;也就是计算机系统能正常工作的时间&#xff0c;其指标可以是能够持续工作的时间长度&#xff0c;也可以是在一段时间内&#xff0c;能正常工作的时间所占的百分比 另一方面是处理能力&#xff0c;又…...

包教包会的ES6

自学参考&#xff1a;http://es6.ruanyifeng.com/ 一、ECMAScript 6 简介 ECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在 2015 年 6 月正式发布了。它的目标&#xff0c;是使得 JavaScript 语言可以用来编写复杂的大…...

python学习——【第四弹】

前言 上一篇文章 python学习——【第三弹】 中学习了python中的流程控制语句&#xff0c;这篇文章我们接着学习python中的序列。先给大家介绍不可变序列 字符串和可变序列 列表&#xff0c;下一篇文章接着补充元组&#xff0c;集合和字典。 序列 指的是一块可以存放多个值的…...

Web3中文|无聊猿Otherside元宇宙启动第二次旅行

3月9日消息&#xff0c;无聊猿Bored Ape Yacht Club母公司Yuga Labs公布了其Otherside元宇宙游戏平台第二次测试的最新细节。Yuga Labs公司称&#xff0c;“第二次旅行”将于3月25日举行&#xff0c;由四位Otherside团队长带领完成近两小时的游戏故事。本次旅行对Otherdeed NFT…...

SpringCloud-7_OpenFeign服务调用

OpenFeign介绍OpenFeign是什么1.OpenFeign是个声明式WebService客户端&#xff0c;使用OpenFeign让编写Web Service客户端更简单2.它的使用方法是定义一个服务接口然后在上面添加注解3.OpenFeign也支持可拔插式的编码器和解码器4.Spring Cloud对OpenFeign进行了封装使其支持了S…...

解决docker容器之间网络互通

docker容器之间相互访问 1.查看当前的网络 Copy [roothost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 3dd4643bb158 bridge bridge local 748b765aca52 host host …...

测试微服务:快速入门指南

在过去几年中&#xff0c;应用程序已经发展到拥有数百万用户并产生大量数据。使用这些应用程序的人期望快速响应和 24/7 可用性。为了使应用程序快速可用&#xff0c;它们必须快速响应增加的负载。 一种方法是使用微服务架构&#xff0c;因为在单体应用程序中&#xff0c;主要…...