《Flowable流程引擎从零到壹》引入日志框架和部署流程定义

news2025/1/24 9:38:46

14天学习训练营导师课程:
邓澎波《Flowable流程引擎-基础篇【2022版】》
邓澎波《Flowable流程引擎-高级篇【2022版】》

学习笔记《Flowable流程引擎从零到壹》回城传送

❤️作者主页:小虚竹

❤️作者简介:大家好,我是小虚竹。Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作者🏆,阿里云专家博主🏆,51CTO专家博主🏆

❤️技术活,该赏

❤️点赞 👍 收藏 ⭐再看,养成习惯

PC端左侧加我微信,进社群,有送书等更多活动!

文章目录

  • 零:前言
  • 一、引入日志框架
  • 二、部署流程定义
    • 2.1、bpmn20.xml介绍
      • 2.1.1、流对象(Flow Objects):包括事件、活动、网关,是BPMN中的核心元素。
        • 2.1.1.1、事件
          • 分类
            • 开始事件:开始事件指示流程从何处开始。
            • 中间事件:
            • 结束事件:标志着流程的结束。
        • 2.1.1.2、任务(活动)
          • 分类
            • 人工任务(user task)
            • java服务任务(service task)
            • 脚本任务(script task)
            • web服务任务
            • 邮件任务(非BPMN2.0规范)
        • 2.1.1.3、网关(节点)
          • 分类:
            • 排他网关(exclusiveGateway)
            • 并行网关(parallelGateway)
            • 包含网关(inclusiveGateway)
      • 2.1.2、顺序流
        • 分类:
          • 条件顺序流
          • 默认顺序流
    • 2.2、部署流程定义
    • 2.3、查询流程定义
    • 2.4、删除流程定义
  • 总结
  • 参考

零:前言

  今天学习的内容是引入日志框架和部署流程定义,和虚竹哥一起学习吧。

一、引入日志框架

  上一篇文章初始化ProcessEngine流程引擎实例后,控制台没什么日志内容输出,只有提示日志没有正确配置。
在这里插入图片描述
  从提示内容可知Flowable使用SLF4J作为内部日志框架。
  本文使用log4j作为SLF4J的实现。因此在pom.xml文件中添加下列依赖:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>

在这里插入图片描述

  增加配置文件:log4j.properties文件

log4j.rootLogger=DEBUG, CA

log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

  重新运行应用,控制台就有日志出现了。
在这里插入图片描述
在这里插入图片描述

二、部署流程定义

  构建一个简单的请假流程,Flowable引擎需要流程定义为BPMN 2.0格式 ,这是一个业界广泛接受的XML标准。
  定义一个请假流程的流程步骤图,我们称为一个流程定义(process definition)。 一个流程定义可以启动多个流程实例(process instance)

以请假流程为例,流程定义定义了请假的各个步骤要做的事情;
一个流程实例是每个员工可以发起一个请假申请,直到这个请假申请的流程走完,这个流程实例才结束。

  BPMN 2.0存储为XML,并包含可视化的部分:使用标准方式定义了每个步骤类型(人工任务,自动服务调用,等等)如何呈现,以及如何互相连接。这样BPMN 2.0标准使技术人员与业务人员能用双方都能理解的方式交流业务流程。

本次请假流程的流程定义为:
在这里插入图片描述
说明:

  • 左侧的圆圈叫做启动事件(start event)。这是一个流程实例的起点。
  • 第一个矩形是一个用户任务(user task)。这是流程中用户操作的步骤。在这个例子中,经理需要批准或驳回申请
  • 取决于经理的决定,排他网关(exclusive gateway) (带叉的菱形)会将流程实例路由至批准或驳回路径
  • 如果批准,则需要将申请注册至某个外部系统,并跟着另一个用户任务,将经理的决定通知给申请人。当然也可以改为发送邮件。
  • 如果驳回,则为雇员发送一封邮件通知他。

  实际的业务场景,流程定义步骤图是用可视化建模工具的,如Flowable Designer(Eclipse)Flowable Web Modeler(Web应用)
  本文直接写XML,新手刚入门要熟悉下BPMN2.0及其概念。
  将下面的XML保存在src/main/resources文件夹下名为holiday-request.bpmn20.xml的文件中。

注意:*.bpmn20.xml 这个后缀是固定的

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:flowable="http://flowable.org/bpmn"
             typeLanguage="http://www.w3.org/2001/XMLSchema"
             expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">

    <process id="holidayRequest" name="请假流程" isExecutable="true">

        <startEvent id="startEvent"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

        <userTask id="approveTask" name="同意或拒绝请假"/>
        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>

        <exclusiveGateway id="decision"/>
        <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>
        <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${!approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>

        <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                     flowable:class="org.flowable.CallExternalSystemDelegate"/>
        <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>

        <userTask id="holidayApprovedTask" name="Holiday approved"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

        <serviceTask id="sendRejectionMail" name="Send out rejection email"
                     flowable:class="org.flowable.SendRejectionMail"/>
        <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>

        <endEvent id="approveEnd"/>

        <endEvent id="rejectEnd"/>
    </process>

</definitions>

现在我们已经有了流程BPMN 2.0 XML文件,现在需要将它部署到引擎中。

下面简单介绍下bpmn20.xml的几个重要的点

2.1、bpmn20.xml介绍

2.1.1、流对象(Flow Objects):包括事件、活动、网关,是BPMN中的核心元素。

2.1.1.1、事件

作用:用于对流程生命周期中发生的事件进行建模。

分类
开始事件:开始事件指示流程从何处开始。

定义:
没有启动事件,需要调用startProcessInstanceByXXX方法执行该空开始事件。

图形表示:
在这里插入图片描述
XML表示:

<startEvent id="startEvent"/>
中间事件:

正常是任务和网关的混合体

结束事件:标志着流程的结束。

定义:
没有结束事件,当流程引擎检测到执行到该空结束事件时会自动执行,已结束整个流程。
图形表示:
在这里插入图片描述
xml表示:

<endEvent id="approveEnd"/>

2.1.1.2、任务(活动)

定义:
任务表示流程中具体要做的事情,通常一个任务表示工作需要被外部实体完成,比如人工任务和自动服务。
图形表示:
任务通常有圆角矩形表示,内部文字为任务名称或描述,左上角的图标表示任务类型。

分类
人工任务(user task)

定义:
最典型的任务。需要由人工来完成的任务,比如请假审批、财务审核等。
图形表示:
在这里插入图片描述
xml表示:
id是必须的,name是可选的,通过documentation元素对任务进行描述。任何bpmn2.0元素都可用documentation元素进行描述。

<userTask id="theTask" name="Schedule meeting" > <documentation> Schedule an engineering meeting for next week with the new hire. </documentation> </userTask>

到期日:
可通过dueDate字段设置任务的到期时间。

用户分配:
人工任务可分配给三种人:assignee(办理人、受让人),candidate(候选人),candidateGroup(候选人组)

  • assignee是任务的实际办理人,任务只能同时有一个办理人。

  • 任务可以有多个候选人,每个候选人都能看到该任务,候选人需要claim(拾取)任务成为assignee后,才能进行任务的办理,任务被拾取后其他候选人就看不到该任务了。候选人在拾取任务后可以unclaim,将任务归还,此时其他候选人可以看到并claim任务。

  • 不想单独指定多个候选人,可以指定一个候选人组,一般为角色ID。

分配方式有三种:

  • 画图时写死。

  • 通过UEL表达式动态设置。

  • 通过TaskListener监听器指定。

java服务任务(service task)

定义:
用于调用外部Java代码。

图形表示:
在这里插入图片描述
xml表示:

<serviceTask id="javaService" name="My Java Service Task" activiti:class="org.activiti.MyJavaDelegate" />
脚本任务(script task)

定义:

用于执行脚本文件(如javascript)

图形表示:
在这里插入图片描述
xml表示:

<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy"> 
    <script> 
        sum = 0 
        for ( i in inputArray ) { 
            sum += i 
        } 
    </script> 
</scriptTask>
web服务任务

用于调用外部web接口服务。

邮件任务(非BPMN2.0规范)

用于发送邮件。

还有手工任务、java接收任务、shell任务等。

2.1.1.3、网关(节点)

作用:
用来控制流程的流向。

图形表示:
网关通常以菱形图形表示,内部带有一个图标。该图标显示网关的类型。

分类:
排他网关(exclusiveGateway)

定义:
也叫XOR网关,对所有的传出分支进行条件判断,仅选择一个条件为true的分支执行,当有多个分支条件满足时,默认执行xml中定义的第一个。若多个分支条件都不满足时,就走默认顺序流。如果没有默认顺序流,将抛出异常。

图形表示:
在这里插入图片描述
xml表示:

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" />
并行网关(parallelGateway)

定义:

并行网关模拟多个同时并行执行的流程这种情况。两个特点:

  • 具有fork-join行为(发散和汇聚,想起了java中的fork-join线程框架),即从并行网关传出的流程会并行执行,传入并行网关的流程会进入里面等待,知道并行的流程都进入到并行网关后,再一起发散出去。
  • 并行网关忽略分支的条件判断。
    图形表示:
    在这里插入图片描述
    xml表示:
<parallelGateway id="myParallelGateway" />
包含网关(inclusiveGateway)

定义:
看作是排他网关和并行网关的组合,包含网关既能进行条件判断,又能并行执行多个分支。

图形:
在这里插入图片描述
xml表示:

<inclusiveGateway id="myInclusiveGateway" />

还是事件网关等。

2.1.2、顺序流

定义:
顺序流就是事件,活动和网关之间的连线,显示为一条实线 带有箭头,在BPMN图形中每个顺序流都有一个源头和一个 目标引用,包含了 活动,事件或网关的id。

<sequenceFlow id="myFlow" name="MyFlow" sourceRef="sourceId" targetRef="targetId" />

分类:

条件顺序流

定义:
给顺序流添加表达式条件,当条件判断为true时,该顺序流将会被执行。这意味着如果多个顺序流的条件都为true时,会有多个顺序流并行执行。

图形表示:
在这里插入图片描述
XML表示:
条件序列流在XML中表现为常规序列流,其中包含conditionExpression子元素。当前conditionalExpression仅可与UEL一起使用。

<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask"> 
    <conditionExpression xsi:type="tFormalExpression"> 
        <![CDATA[${order.price > 100 && order.price < 250}]]> 
    </conditionExpression>
</sequenceFlow>
默认顺序流

定义:
所有BPMN 2.0任务和网关都可以具有默认序列流。当且仅当其他条件顺序流都为false时,才选择执行默认顺序流。默认序列流的条件总是被忽略。

图形表示:
默认序列流是开始处带有斜杠标记的常规顺序流。
在这里插入图片描述
xml表示:
通过default属性执行默认顺序流。flow2为排他网关的默认顺序流。

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow2" />         
      <sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1">     
          <conditionExpression xsi:type="tFormalExpression">
            ${conditionA}    
          </conditionExpression> 
       </sequenceFlow> 
      <sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/> 
      <sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3"> 
         <conditionExpression xsi:type="tFormalExpression">
            ${conditionB}
         </conditionExpression> 
      </sequenceFlow>
</exclusiveGateway>

2.2、部署流程定义

先了解下ProcessEngine下提供了哪些主要的服务:
在这里插入图片描述

  • RepositoryService:资源管理的一些服务
  • RuntimeService:流程运行时的服务
  • TaskService:任务处理的服务
  • HistoryService:历史信息,历史流转的服务

实现部署:

  • 获取流程引擎对象
  • 将流程定义部署至Flowable引擎
  • 需要使用RepositoryService,其可以从ProcessEngine对象获取
  • 使用RepositoryService,可以通过XML文件的路径创建一个新的部署(Deployment)
  • 并调用*deploy()*方法实际执行
  • 输出deployment对象的id和名称。
package com.xiaoxuzhu.flowable.test;

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.junit.Test;

public class Test03 {

    /**
     * 部署流程
     */
    @Test
    public void testDeploy() {
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
        //数据库配置
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
        //自动创建表结构-表不存在时
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 部署流程 获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()// 创建Deployment对象
                .addClasspathResource("holiday-request.bpmn20.xml") // 添加流程部署文件
                .name("流程名称:请假流程") // 设置部署流程的名称
                .deploy(); // 执行部署操作
        System.out.println("deployment.getId() = " + deployment.getId());
        System.out.println("deployment.getName() = " + deployment.getName());

    }
}

执行日志成功的截图:
在这里插入图片描述

成功后会在表结构插入数据:
act_re_deployment: 流程定义部署表,每部署一次就增加一条记录
在这里插入图片描述

act_re_procdef :流程定义表,部署每个新的流程定义都会在这张表中增加一条记录
在这里插入图片描述
在这里插入图片描述
act_ge_bytearray :流程资源表,流程部署的 bpmn xml文件会保存在该表中
在这里插入图片描述

2.3、查询流程定义

    @Test
    public void testDeployQuery() {
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
        //数据库配置
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
        //自动创建表结构-表不存在时
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 部署流程 获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 获取流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId("1")
                .singleResult();
        System.out.println("processDefinition.getId() = " + processDefinition.getId());
        System.out.println("processDefinition.getName() = " + processDefinition.getName());
        System.out.println("processDefinition.getDeploymentId() = " + processDefinition.getDeploymentId());
        System.out.println("processDefinition.getDescription() = " + processDefinition.getDescription());

    }

在这里插入图片描述

2.4、删除流程定义

通过idea下载源码
在这里插入图片描述

    @Test
    public void testDeployDelete() {
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
        //数据库配置
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
        //自动创建表结构-表不存在时
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 部署流程 获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //从注释可知 通过部署ID,删除流程部署定义 id值不为空。 如果部署的流程启动了,就会抛出RuntimeException 异常。不执行删除
        repositoryService.deleteDeployment("1");
    }

如图删除成功
在这里插入图片描述
数据库的值也没了
在这里插入图片描述

//级联删除 如果流程启动了,此方法也能删除相关任务。
 repositoryService.deleteDeployment("1",true);

从注释可知
在这里插入图片描述

总结

今天学会了如何引入log4j日志框架,在控制台顺利输出日志。同时也掌握了部署一个流程定义,查询流程定义和删除流程定义。
一定要懂得bpmn20.xml的结构,虽然后面可以用可视化配置生成,但只有先懂得结构是什么意思,后面心里才有底,整个脉络了然于胸。

参考

java Log4j日志配置详解大全
bpmn20.xml结构介绍
activiti7(一):思想指导实践——BPMN2.0规范

我是虚竹哥,我们下文见~

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

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

相关文章

目标检测算法——YOLOv5/YOLOv7改进之结合​PP-LCNet(轻量级CPU网络)

>>>深度学习Tricks&#xff0c;第一时间送达<<< 目录 ​PP-LCNet——轻量级且超强悍的CPU级骨干网络&#xff01;&#xff01; &#xff08;一&#xff09;前沿介绍 1.PP-LCNet主要模块 2.相关实验结果 &#xff08;二&#xff09;YOLOv5/YOLOv7改进之结…

GreenPlum6.x之ETL工具

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、ETL是什么&#xff1f;二、数据加载工具GPLoad1.GPLoad安装部署2.编写控制文件test.yml总结前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#…

[Flask]Flask零基础项目---登录demo

借助Flask框架实现模拟用户登录操作&#xff1b; 一步一步的来实现这个登录接口 login.py from flask import Flask, render_template,requestapp Flask(__name__, template_folderlogin)app.route(/) def hello_flask():data request.get_data()print(data)return render_…

黑白图片和黑白图片上色系统毕业设计,AI黑背图像上色系统设计与实现,AI黑白照片上色系统论文毕设作品参考

功能清单 【后台管理员功能】 系统设置&#xff1a;设置网站简介、关于我们、联系我们、加入我们、法律声明 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支持删除 会员列表&#xff1a;查看所有注册会员信息&a…

电子商务交易系统的设计与实现(javaee+mysql)

目录 1 概论 1 1.1电子商务交易发展 1 1.1.1电子商务交易 1 1.1.2发展前景&#xff1a; 1 2 系统可行性及需求分析 3 2.1 系统调研 3 2.2 系统可行性分析 3 2.2.1技术可行性分析 3 2.2.2 操作可行性分析 3 2.2.3 社会可行性分析 4 2.2.4可行性分析小结 4 2.3 系统需求分析 4 2.…

Windows10添加群晖磁盘映射,总是提示用户名密码不正确解决办法

在使用群晖NAS时&#xff0c;我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过winr键&#xff0c;输入\\NAS的IP地址&#xff0c;登录设备时总是提示”用户名或密码不正确”。但是实际密码是正确的。 原因描述&#xff1a;Windows 10&#xff08;或更早版本&a…

Android如何自定义服务器DynamicMockServer的使用

在平时开发时经常需要与服务器进行联调&#xff0c;但是服务器开发往往比前端的要滞后。这时候需要我们自己去mock数据来调通流程。 今天给大家介绍一款Android上的MockServer----DynamicMockServer&#xff0c;支持接口调用&#xff0c;静态文件。 DynamicMockServer&#x…

Web 安全:PKI 扫盲

个人博客 在互联网世界&#xff0c;我们广泛采用 TLS 来保护通信安全&#xff0c;这里的安全主要包含两部分内容&#xff1a;身份鉴别、通信加密。身份鉴别是一切的基础&#xff0c;特别当发送消息比较敏感需要加密时&#xff0c;对接收方必然有一个身份“假设”&#xff0c;“…

MacBook Pro M1 Docker 环境安装 Nacos 2.x 版本

MacBook Pro M1 Docker 环境安装 Nacos 2.x 版本 前言 由于 rocksdb 暂不支持 M1 平台&#xff0c;所以使用 Zulu JDK 的小伙伴们运行 Nacos 2.x 版本会报错&#xff0c;网上通用的解决方案是使用 Oracle JDK 来运行 Nacos 2.x 版本&#xff0c;但对于强迫症的我来说&#xf…

图书管理系(统附源码PPT)

图书管理系统1 绪 论1.1 研究背景1.2 研究意义1.3 相关研究现状1.3.1 高校图书管理面临的问题1.3.2 信息化为图书管理带来新变化2 相关技术2.1 JSP 概述2.2 MySQL 数据库技术2.3 Spring2.4 SpringMVC2.5 Dbcp2.6 Maven3 系统分析3.1 需求分析3.1.1 系统的功能需求分析3.1.2 系统…

【Git】一文带你入门Git分布式版本控制系统(必要配置、工作原理、创建/克隆项目)

Git 系列文章目录 Git 专栏参考链接Git&#xff08;一&#xff09;【Git】一文带你入门Git分布式版本控制系统&#xff08;简介&#xff0c;安装&#xff0c;Linux命令&#xff09;文章目录Git 系列文章目录一、Git 的必要配置二、Git 的工作原理三、Git 项目创建1、创建本地项…

【kafka】十四、kafka生产者API

kafka Producer API 1.消息发送流程 kafka的producer发送消息采用的是异步发送的方式。在消息的发送过程中&#xff0c;涉及到了两个线程–main线程和sender线程&#xff0c;以及一个线程共享变量–RecordAccumulator。main线程将消息发送给RecordAccumulator&#xff0c;send…

单向环形链表介绍以及约瑟夫问题分析

❤️一名热爱Java的大一学生&#xff0c;希望与各位大佬共同学习进步❤️ &#x1f9d1;个人主页&#xff1a;周小末天天开心 各位大佬的点赞&#x1f44d; 收藏⭐ 关注✅&#xff0c;是本人学习的最大动力 感谢&#xff01; &#x1f4d5;该篇文章收录专栏—数据结构 目录 单…

不敲代码就能搭建个人博客?快解析内网穿透来助力

记得很多年前看到一句话&#xff0c;“博客是一个人的狂欢”。无论是享受搭建的过程&#xff0c;还是享受创作的乐趣&#xff0c;更多时候博客是在取悦自己。那么&#xff0c;在2022年的今天&#xff0c;搭建个人博客还有意义吗&#xff1f;答案是肯定的&#xff0c;当我们在搜…

Day4: 应用篇-1

应用篇-1 环境安装 应用开发交叉编译环境&#xff0c; 【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.7.pdf 章节4.3.1 在 Ubuntu 中创建目录&#xff1a;/usr/local/arm&#xff0c;命令如下&#xff1a; sudo mkdir /usr/local/arm令将交叉编译器复制到/usr/local/arm 中…

Arduino开发实例-DIY分贝测量仪

DIY分贝测量仪 1、应用介绍 分贝计,它通常用于测量声音的强度和水平。 声音响度是用分贝来衡量的。 从飞机到人类耳语的不同发声介质都有一定的声音响度,以分贝表示。 声波是具有来回运动的纵波,给出高音或低音,如图所示: 声音的响度取决于频率或波长或传播所需的时间。…

APK构建过程-命令行编译

官方对APK构建过程的介绍 官方 - 构建流程介绍 典型 Android 应用模块的构建流程&#xff0c;按照以下常规步骤执行&#xff1a; 编译器将您的源代码转换成 DEX 文件&#xff08;Dalvik 可执行文件&#xff0c;其中包括在 Android 设备上运行的字节码&#xff09;&#xff0c;…

【强化学习论文合集】专栏介绍(订阅前必读)

导读&#xff1a;什么是强化学习&#xff1f; 强化学习&#xff08;Reinforcement Learning, RL&#xff09;&#xff0c;又称再励学习、评价学习或增强学习&#xff0c;是机器学习的范式和方法论之一&#xff0c;用于描述和解决智能体&#xff08;agent&#xff09;在与环境的…

AtCoder Beginner Contest 263 G.Erasing Prime Pairs(二分图最大匹配-网络流)

题目 黑板上有n(n<100)个不同的数&#xff0c;第i个数ai(1<ai<1e7)出现了bi(1<1e9)次&#xff0c; 你每次可以选择当前黑板上存在的两个数x、y&#xff0c;满足xy是质数&#xff0c;擦掉这两个数&#xff0c; 求可以擦掉的最大次数 思路来源 AtCoder Beginner…

[LeetCode周赛复盘] 第 321 场周赛20221127

[LeetCode周赛复盘] 第 321 场周赛20221127 一、本周周赛总结二、 [Easy] 6245. 找出中枢整数1. 题目描述2. 思路分析3. 代码实现三、[Medium]6246. 追加字符以获得子序列1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6247. 从链表中移除节点1. 题目描述2. 思路分析3. 代码实…