3、Flowable任务分配和流程变量

任务分配和流程变量

1.任务分配

1.1 固定分配

  固定分配就是我们前面介绍的,在绘制流程图或者直接在流程文件中通过Assignee来指定的方式
在这里插入图片描述
在这里插入图片描述

1.2 表达式分配

  Flowable使用UEL进行表达式解析。UEL代表Unified Expression Language,是EE6规范的一部分.Flowable支持两种UEL表达式: UEL-value 和UEL-method

1.2.1 值表达式

  值表达式 Value expression: 解析为一个值。默认情况下,所有流程变量都可以使用。(若使用Spring)所有的Spring bean也可以用在表达式里。例如

${myVar}
${myBean.myProperty}

案例讲解:

在这里插入图片描述
可以看到通过表达式处理的效果
在这里插入图片描述
先部署流程,然后在启动流程实例的时候绑定表达式对应的值

/*** 启动流程实例*/@Testpublic void testRunProcess(){// 获取流程引擎对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 启动流程实例通过 RuntimeService 对象RuntimeService runtimeService = processEngine.getRuntimeService();// 设置 assignee 的取值Map<String,Object> variables = new HashMap<>();variables.put("assignee0","张三") ;variables.put("assignee1","李四"); // 启动流程实例,第一个参数是流程定义的idProcessInstance processInstance = runtimeService.startProcessInstanceById("MyHolidayUI:1:4", variables);// 启动流程实例// 输出相关的流程实例信息System.out.println("流程定义的ID:" + processInstance.getProcessDefinitionId());System.out.println("流程实例的ID:" + processInstance.getId());System.out.println("当前活动的ID:" + processInstance.getActivityId());}

在这里插入图片描述

1.2.2 方法表达式

  方法表达式 Method expression: 调用一个方法,可以带或不带参数。**当调用不带参数的方法时,要确保在方法名后添加空括号(以避免与值表达式混淆)。**传递的参数可以是字面值(literal value),也可以是表达式,它们会被自动解析。例如:

${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.doSomething(myVar, execution)}

 myBean是Spring容器中的个Bean对象,表示调用的是bean的addNewOrder方法

1.3 监听器分配

可以使用监听器来完成很多Flowable的流程业务。

我们在此处使用监听器来完成负责人的指定,那么我们在流程设计的时候就不需要指定assignee

创建自定义监听器:

/*** 自定义的监听器*/
public class MyTaskListener implements TaskListener {@Overridepublic void notify(DelegateTask delegateTask) {System.out.println("监听器触发了:" + delegateTask.getName());if("提交请假流程".equals(delegateTask.getName()) &&"create".equals(delegateTask.getEventName())){// 指定任务的负责人delegateTask.setAssignee("小明");}else {delegateTask.setAssignee("小张");}}
}

然后在FlowableUI中关联对应的监听器
create:任务创建后触发
assignment:任务分配后触发
Delete:任务完成后触发
All:所有事件都触发

在这里插入图片描述
然后我们先部署流程,然后执行查看效果:
在这里插入图片描述
然后在Task表中我们可以看到对应的分配人为小明说明通过监听也完成了任务分配的工作了

在这里插入图片描述

2.流程变量

  流程实例按步骤执行时,需要使用一些数据。在Flowable中,这些数据称作变量(variable),并会存储在数据库中。变量可以用在表达式中(例如在排他网关中用于选择正确的出口路径),也可以在Java服务任务(service task)中用于调用外部服务(例如为服务调用提供输入或结果存储),等等。

  流程实例可以持有变量(称作流程变量 process variables);用户任务以及执行(executions)——流程当前活动节点的指针——也可以持有变量。流程实例可以持有任意数量的变量,每个变量存储为ACT_RU_VARIABLE数据库表的一行。

  所有的startProcessInstanceXXX方法都有一个可选参数,用于在流程实例创建及启动时设置变量。例如,在RuntimeService中:

ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);

在这里插入图片描述

2.1 全局变量

  流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例时,可以称为 global 变量

注意:如: Global变量:userId(变量名)、zhangsan(变量值)

  global 变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值。

2.2 局部变量

  任务和执行实例仅仅是针对一个任务和一个执行实例范围,范围没有流程实例大, 称为 local 变量。

  Local 变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。Local 变量名也可以和 global 变量名相同,没有影响。

2.3 案例讲解

需求:员工创建出差申请单,由部门经理审核,部门经理申请通过后3天以下由财务直接申批,3天以上先由总经理审批,总经理审批通过后再由财务审批。
在这里插入图片描述
连接先设置条件

在这里插入图片描述
在这里插入图片描述
部署流程

@Test
public void deploy(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deploy = repositoryService.createDeployment().addClasspathResource("出差申请单.bpmn20.xml").name("请假流程...").category("请假") // 分类.tenantId("dpb") // 租户id.deploy();System.out.println("deploy.getId() = " + deploy.getId());System.out.println("deploy.getName() = " + deploy.getName());System.out.println("deploy.getCategory() = " + deploy.getCategory());
}

启动流程实例:并且指定全局流程变量

/*** 在启动流程实例的时候设置流程变量*/@Testpublic void runProcess(){// 获取流程引擎对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 启动流程实例通过 RuntimeService 对象RuntimeService runtimeService = processEngine.getRuntimeService();// 设置流程变量Map<String,Object> variables = new HashMap<>();// 设置assignee的取值variables.put("assignee0","张三");variables.put("assignee1","李四");variables.put("assignee2","王五");variables.put("assignee3","赵财务");// 启动流程实例,第一个参数是流程定义的idProcessInstance processInstance = runtimeService.startProcessInstanceById("evection:1:4",variables);// 启动流程实例// 输出相关的流程实例信息System.out.println("流程定义的ID:" + processInstance.getProcessDefinitionId());System.out.println("流程实例的ID:" + processInstance.getId());System.out.println("当前活动的ID:" + processInstance.getActivityId());}

完成Task任务,同时也可以指定流程变量

/*** 完成任务时指定流程变量*/@Testpublic void completeTask(){// 获取流程引擎对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionId("evection:1:4").taskAssignee("李四").singleResult();// 添加流程变量Map<String, Object> map = task.getProcessVariables();map.put("num",4);// 完成任务taskService.complete(task.getId(),map);}

当然我们也可以在处理流程之外通过Task编号来修改流程变量

/*** 通过当前任务设置*/@Testpublic void currentTask(){//   当前待办任务id//  获取processEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionId("evection:1:4").taskAssignee("王五").singleResult();// 添加流程变量Map<String, Object> map = task.getProcessVariables();map.put("num",1);//  一次设置多个值 设置局部变量taskService.setVariables(task.getId(), map);}

二、候选人和候选人组

  在流程定义中在任务结点的 assignee 固定设置任务负责人,在流程定义时将参与者固定设置在.bpmn 文件中,如果临时任务负责人变更则需要修改流程定义,系统可扩展性差。针对这种情况可以给任务设置多个候选人或者候选人组,可以从候选人中选择参与者来完成任务。

1.候选人

1.1 定义流程图

  定义流程图,同时指定候选人,多个候选人会通过,连接

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

1.2 部署和启动流程实例

  部署流程,并且在启动流程实例的时候对UEL表达式赋值

  /*** 部署流程*/@Testpublic void deploy(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deploy = repositoryService.createDeployment().addClasspathResource("请假流程-候选人.bpmn20.xml").name("请求流程-候选人").deploy();System.out.println("deploy.getId() = " + deploy.getId());System.out.println(deploy.getName());}/*** 启动流程实例*/@Testpublic void runProcess(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RuntimeService runtimeService = processEngine.getRuntimeService();// 给流程定义中的UEL表达式赋值Map<String,Object> variables = new HashMap<>();variables.put("candidate1","张三");variables.put("candidate2","李四");variables.put("candidate3","王五");runtimeService.startProcessInstanceById("holiday-candidate:1:4",variables);}

  在对应的表结构中我们可以看到流程变量已经有了,但是对于的Task的Assignee还是为空。

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

1.3 任务的查询

  根据当前登录的用户,查询对应的候选任务

/*** 根据登录的用户查询对应的可以拾取的任务**/@Testpublic void queryTaskCandidate(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-candidate:1:4").taskCandidateUser("李四") # 注意.list();for (Task task : list) {System.out.println("task.getId() = " + task.getId());System.out.println("task.getName() = " + task.getName());}}

1.4 任务的拾取

  知道了我有可拾取的任务后,拾取任务。

/*** 拾取任务*    一个候选人拾取了这个任务之后其他的用户就没有办法拾取这个任务了*    所以如果一个用户拾取了任务之后又不想处理了,那么可以退还*/@Testpublic void claimTaskCandidate(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-candidate:1:4").taskCandidateUser("李四").singleResult();if(task != null){// 拾取对应的任务taskService.claim(task.getId(),"李四");System.out.println("任务拾取成功");}}

1.5 任务的归还

  拾取任务后不想操作那么就归还任务

 /*** 退还任务*    一个候选人拾取了这个任务之后其他的用户就没有办法拾取这个任务了*    所以如果一个用户拾取了任务之后又不想处理了,那么可以退还*/@Testpublic void unclaimTaskCandidate(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-candidate:1:4").taskAssignee("张三").singleResult();if(task != null){// 拾取对应的任务taskService.unclaim(task.getId());System.out.println("归还拾取成功");}}

在这里插入图片描述

1.6 任务的交接

  拾取任务后如果不想操作也不想归还可以直接交接给另外一个人来处理

 /*** 任务的交接*    如果我获取了任务,但是不想执行,那么我可以把这个任务交接给其他的用户*/@Testpublic void taskCandidate(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-candidate:1:4").taskAssignee("李四").singleResult();if(task != null){// 任务的交接taskService.setAssignee(task.getId(),"王五");System.out.println("任务交接给了王五");}}

1.7 任务的完成

  正常的任务处理

/*** 完成任务*/@Testpublic void completeTask(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-candidate:1:4").taskAssignee("王五").singleResult();if(task != null){// 完成任务taskService.complete(task.getId());System.out.println("完成Task");}}

2.候选人组

  当候选人很多的情况下,我们可以分组来处理。先创建组,然后把用户分配到这个组中。
在这里插入图片描述

2.1 管理用户和组

2.1.1 用户管理

  我们需要先单独维护用户信息。后台对应的表结构是ACT_ID_USER.

/*** 维护用户*/@Testpublic void createUser(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 通过 IdentityService 完成相关的用户和组的管理IdentityService identityService = processEngine.getIdentityService();User user = identityService.newUser("田佳");user.setFirstName("田");user.setLastName("jia");user.setEmail("tianjia@qq.com");identityService.saveUser(user);}
2.1.2 Group管理

  维护对应的Group信息,后台对应的表结构是ACT_ID_GROUP

   /*** 创建用户组*/@Testpublic void createGroup(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();IdentityService identityService = processEngine.getIdentityService();// 创建Group对象并指定相关的信息Group group = identityService.newGroup("group2");group.setName("开发部");group.setType("type1");// 创建Group对应的表结构数据identityService.saveGroup(group);}

在这里插入图片描述

2.1.3 用户分配组

  用户和组是一个多对多的关联关联,我们需要做相关的分配,后台对应的表结构是ACT_ID_MEMBERSHIP

 /*** 将用户分配给对应的Group*/@Testpublic void userGroup(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();IdentityService identityService = processEngine.getIdentityService();// 根据组的编号找到对应的Group对象Group group = identityService.createGroupQuery().groupId("group1").singleResult();List<User> list = identityService.createUserQuery().list();for (User user : list) {// 将用户分配给对应的组identityService.createMembership(user.getId(),group.getId());}}

在这里插入图片描述

2.2 候选人组应用

  搞清楚了用户和用户组的关系后我们就可以来使用候选人组的应用了

2.2.1 创建流程图

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

2.2.2 流程的部署运行

  然后我们把流程部署和运行,注意对UEL表达式赋值,关联上Group

/*** 部署流程*/@Testpublic void deploy(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deploy = repositoryService.createDeployment().addClasspathResource("请假流程-候选人组.bpmn20.xml").name("请求流程-候选人").deploy();System.out.println("deploy.getId() = " + deploy.getId());System.out.println(deploy.getName());}/*** 启动流程实例*/@Testpublic void runProcess(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();IdentityService identityService = processEngine.getIdentityService();Group group = identityService.createGroupQuery().groupId("group1").singleResult();RuntimeService runtimeService = processEngine.getRuntimeService();// 给流程定义中的UEL表达式赋值Map<String,Object> variables = new HashMap<>();// variables.put("g1","group1");variables.put("g1",group.getId()); // 给流程定义中的UEL表达式赋值runtimeService.startProcessInstanceById("holiday-group:1:17504",variables);}

对应表结构中就有对应的体现在这里插入图片描述

2.2.3 任务的拾取和完成

  然后完成任务的查询拾取和处理操作

/*** 根据登录的用户查询对应的可以拾取的任务**/@Testpublic void queryTaskCandidateGroup(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 根据当前登录的用户找到对应的组IdentityService identityService = processEngine.getIdentityService();// 当前用户所在的组Group group = identityService.createGroupQuery().groupMember("邓彪").singleResult();TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-group:1:17504").taskCandidateGroup(group.getId()).list();for (Task task : list) {System.out.println("task.getId() = " + task.getId());System.out.println("task.getName() = " + task.getName());}}/*** 拾取任务*    一个候选人拾取了这个任务之后其他的用户就没有办法拾取这个任务了*    所以如果一个用户拾取了任务之后又不想处理了,那么可以退还*/@Testpublic void claimTaskCandidate(){String userId = "田佳";ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 根据当前登录的用户找到对应的组IdentityService identityService = processEngine.getIdentityService();// 当前用户所在的组Group group = identityService.createGroupQuery().groupMember(userId).singleResult();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-group:1:17504").taskCandidateGroup(group.getId()).singleResult();if(task != null) {// 任务拾取taskService.claim(task.getId(),userId);System.out.println("任务拾取成功");}}  /*** 完成任务*/@Testpublic void completeTask(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-group:1:17504").taskAssignee("邓彪").singleResult();if(task != null){// 完成任务taskService.complete(task.getId());System.out.println("完成Task");}}

三、网关

网关用来控制流程的流向

1.排他网关

  排他网关(exclusive gateway)(也叫异或网关 XOR gateway,或者更专业的,基于数据的排他网关 exclusive data-based gateway),用于对流程中的决策建模。当执行到达这个网关时,会按照所有出口顺序流定义的顺序对它们进行计算。选择第一个条件计算为true的顺序流(当没有设置条件时,认为顺序流为true)继续流程。

  请注意这里出口顺序流的含义与BPMN 2.0中的一般情况不一样。一般情况下,会选择所有条件计算为true的顺序流,并行执行。而使用排他网关时,只会选择一条顺序流。当多条顺序流的条件都计算为true时,会且仅会选择在XML中最先定义的顺序流继续流程。如果没有可选的顺序流,会抛出异常。

图示

  排他网关用内部带有’X’图标的标准网关(菱形)表示,'X’图标代表异或的含义。请注意内部没有图标的网关默认为排他网关。BPMN 2.0规范不允许在同一个流程中混合使用有及没有X的菱形标志。
在这里插入图片描述
案例:
在这里插入图片描述

 /*** 部署流程*/@Testpublic void deploy(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deploy = repositoryService.createDeployment().addClasspathResource("请假流程-排他网关.bpmn20.xml").name("请求流程-排他网关").deploy();System.out.println("deploy.getId() = " + deploy.getId());System.out.println(deploy.getName());}/*** 启动流程实例*/@Testpublic void runProcess(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RuntimeService runtimeService = processEngine.getRuntimeService();// 给流程定义中的UEL表达式赋值Map<String,Object> variables = new HashMap<>();// variables.put("g1","group1");variables.put("num",3); // 给流程定义中的UEL表达式赋值runtimeService.startProcessInstanceById("holiday-exclusive:1:4",variables);}/*** 启动流程实例*/@Testpublic void setVariables(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RuntimeService runtimeService = processEngine.getRuntimeService();// 给流程定义中的UEL表达式赋值Map<String,Object> variables = new HashMap<>();// variables.put("g1","group1");variables.put("num",4); // 给流程定义中的UEL表达式赋值runtimeService.setVariables("12503",variables);}/*** 完成任务*/@Testpublic void completeTask(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery()//.processInstanceId("2501").processDefinitionId("holiday-exclusive:1:4").taskAssignee("zhangsan").singleResult();if(task != null){// 完成任务taskService.complete(task.getId());System.out.println("完成Task");}}

如果从网关出去的线所有条件都不满足的情况下会抛出系统异常,
在这里插入图片描述
但是要注意任务没有介绍,还是原来的任务,我们可以重置流程变量

   @Testpublic void setVariables(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RuntimeService runtimeService = processEngine.getRuntimeService();// 给流程定义中的UEL表达式赋值Map<String,Object> variables = new HashMap<>();// variables.put("g1","group1");variables.put("num",4); // 给流程定义中的UEL表达式赋值runtimeService.setVariables("12503",variables);}

2.并行网关

  并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进入和外出顺序流的:

  • fork分支:并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。

  • join汇聚: 所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。

  注意,如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。 这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。

与其他网关的主要区别是,并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略。

案例:

在这里插入图片描述
当我们执行了创建请假单后,到并行网关的位置的时候,在ACT_RU_TASK表中就有两条记录

然后同时在ACT_RU_EXECUTION中有三条记录,一个任务对应的有两个执行实例

3.包含网关

 包含网关可以看做是排他网关和并行网关的结合体。 和排他网关一样,你可以在外出顺序流上定义条件,包含网关会解析它们。 但是主要的区别是包含网关可以选择多于一条顺序流,这和并行网关一样。

包含网关的功能是基于进入和外出顺序流的:

  • 分支: 所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行方式继续执行, 会为每个顺序流创建一个分支。

  • 汇聚:所有并行分支到达包含网关,会进入等待状态, 直到每个包含流程token的进入顺序流的分支都到达。 这是与并行网关的最大不同。换句话说,包含网关只会等待被选中执行了的进入顺序流。 在汇聚之后,流程会穿过包含网关继续执行。

4.事件网关

  事件网关允许根据事件判断流向。网关的每个外出顺序流都要连接到一个中间捕获事件。 当流程到达一个基于事件网关,网关会进入等待状态:会暂停执行。与此同时,会为每个外出顺序流创建相对的事件订阅。

  事件网关的外出顺序流和普通顺序流不同,这些顺序流不会真的"执行", 相反它们让流程引擎去决定执行到事件网关的流程需要订阅哪些事件。 要考虑以下条件:

  1. 事件网关必须有两条或以上外出顺序流;
  2. 事件网关后,只能使用intermediateCatchEvent类型(activiti不支持基于事件网关后连接ReceiveTask)
  3. 连接到事件网关的中间捕获事件必须只有一个入口顺序流。

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

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

相关文章

无蓝光的护眼灯有哪些品牌?分享五款优秀的无蓝光护眼台灯

现在儿童近视率越来越高了&#xff0c;用眼过度疲劳是导致近视的主要因素&#xff0c;学习环境的光线是否合适&#xff0c;都会直接影响用眼的疲劳程度。所以给孩子营造一个良好的学习环境非常重要&#xff01;为大家推荐五大品牌的护眼台灯。 1.书客护眼台灯L1 推荐指数&…

jenkins pipeline使用

1、jenkins全局配置 1.1、maven配置 1.2、jdk配置 1.3、git配置 2、构建环境配置 2.1、安装时间插件 Date Parameter 2.2、Git Parameter 插件安装 3、pipeline如下 pipeline {agent anyenvironment {image_name "192.168.122.150/ken-test/price-service:${date}&…

【大数据】Kafka 入门简介

Kafka 入门简介 1.什么是 Kafka2.Kafka 的基本概念3.Kafka 分布式架构4.配置单机版 Kafka4.1 下载并解压包4.2 启动 Kafka4.3 创建 Topic4.4 向 Topic 中发送消息4.5 从 Topic 中消费消息 5.实验5.1 实验一&#xff1a;Python 实现生产者消费者5.2 实验二&#xff1a;消费组实现…

最新AI创作系统ChatGPT源码+搭建部署教程+支持GPT4.0+支持ai绘画(Midjourney)/支持Prompt

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统AI绘画系统&#xff0c;支持OpenAI GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署…

FPGA 图像缩放 1G/2.5G Ethernet PCS/PMA or SGMII实现 UDP 网络视频传输,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐UDP视频传输--无缩放FPGA图像缩放方案我这里已有的以太网方案 3、设计思路框架视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 UDP协议栈UDP视频数据组包U…

【Linux】文件IO基础知识——下篇

目录 一&#xff0c;stderr 2. errno全局变量 二&#xff0c;文件系统 1. 软链接 2. 硬链接 三&#xff0c;静态库 1. 制作静态库 2. 自动化生成静态库 & 自动发布库与头文件 3. 如何使用第三方库 法&#xff08;一&#xff09;&#xff1a;修改系统文件库 …

液压自动化成套设备比例阀放大器

液压电气成套设备的比例阀放大器是一种电子控制设备&#xff0c;用于控制液压动力系统中的液压比例阀1。 比例阀放大器通常采用电子信号进行控制&#xff0c;以控制比例阀的开度和流量&#xff0c;以实现液压系统的可靠控制。比例阀放大器主要由以下组成部分&#xff1a; 驱动…

网络安全是什么?一文认识网络安全

一、网络安全 1.概念 网络安全从其本质上讲就是网络上的信息安全&#xff0c;指网络系统的硬件、软件及数据受到保护。不遭受破坏、更改、泄露&#xff0c;系统可靠正常地运行&#xff0c;网络服务不中断。 &#xff08;1&#xff09;基本特征 网络安全根据其本质的界定&#…

Git构建分布式版本控制系统

一、版本控制 1、概念&#xff1a; 版本控制&#xff08;Version Control&#xff09;&#xff0c;也被称为版本管理、源代码管理或代码控制&#xff0c;是一种系统和工具&#xff0c;用于跟踪和管理文件、数据或源代码的不同版本和历史记录&#xff0c;在软件开发、文档管理…

jdbc设置StatementTimeout后还需要设置socket timeout参数吗

背景 我们设置JDBC参数时&#xff0c;不管有没有在Statement中配置超时时间StatementTimeout&#xff0c;我们都需要配置jdbc的socket timeout参数&#xff0c;那么为什么这个socket timeout参数如此必要&#xff0c;不设置又会怎么样&#xff1f; 问题真相 首先设置了State…

【Linux笔记】Linux基础权限

【Linux笔记】Linux基础权限 一、Linux权限的概念1.1、Linux中一切皆文件1.2、文件访问者的分类1.3、、Linux中的“用户白名单” 二、文件访问权限的修改2.1、权限的增加和减少的基础方法2.2、以八进制数修改权限 三、用户身份的修改3.1、修改文件的拥有者3.2、修改文件的所属组…

【VSCode】Windows环境下,VSCode 搭建 cmake 编译环境(通过配置文件配置)

除了之前的使用 VSCode 插件来编译工程外&#xff0c;我们也可以使用配置文件来编译cmake工程&#xff0c;主要依赖 launch.json 和 tasks.json 文件。 目录 一、下载编译器 1、下载 Windows GCC 2、选择编译器路径 二、配置 debug 环境 1、配置 lauch.json 文件 2、配置…

10.17课上(七段显示器,递归异或与电路)

异或的递归与数电实现 用二选一选择器实现异或函数 在异或当中&#xff0c;如果有一项为0&#xff0c;就可以把那一项消掉&#xff1b;如果有一项为1&#xff0c;就是把剩下的所有项运算完的结果取反 &#xff08;由此在算法当中可以采用递归解决&#xff09; 当w1为0时&…

百度文心一言 4.0 :如何申请百度文心一言 4.0

本心、输入输出、结果 文章目录 百度文心一言 4.0 &#xff1a;如何申请百度文心一言 4.0前言文心一言 4.0 ERNIE-Bot 4.0 &#xff1a;ERNIE-Bot 4.0 大模型深度测试体验报告如何申请千帆大模型试用百度文心一言 4.0 主要功能介绍配套发布的十余款AI原生应用插件、API 生态 百…

Python办公自动化完全指南(免费PDF)

Python办公自动化可以显著提速办公流程。通过自动执行那些重复繁琐又耗时的任务&#xff0c;大家可以把更多时间用在策略性和有创造性的工作上。 为了帮助大家更好地掌握如何将Python应用于办公自动化&#xff0c;我们整理了100个基本概念&#xff0c;让学习变得更轻松。 学习内…

C++项目实战——基于多设计模式下的同步异步日志系统-⑩-异步缓冲区类与异步工作器类设计

文章目录 专栏导读异步缓冲区设计思想异步缓冲区类设计异步工作器类设计异步日志器设计异步缓冲区类整理异步工作器类整理 专栏导读 &#x1f338;作者简介&#xff1a;花想云 &#xff0c;在读本科生一枚&#xff0c;C/C领域新星创作者&#xff0c;新星计划导师&#xff0c;阿…

[java进阶]——IO流,递归实现多级文件拷贝

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 一、认识IO流 二、了解编码与解码 二、IO流体系 三、字节输入输出流 四、字符输入输出流 五、多级文件拷贝 一、认识IO流 IO流也叫输入流(intput)、输出流(onput)&#xff0c;该流就像java程序同硬盘之间的…

第0章:怎么入手tensorflow

近年来人工智能的火爆吸引了很多人&#xff0c;网上相关的热门课程报名的人很多&#xff0c;但是坚持下去的人却少。那些晦涩的原理没有一定知识的积累很难能理解。 如果你对人工智能感兴趣&#xff0c;且想利用人工智能去实现某项功能&#xff0c;而不是对人工智能本身感兴趣&…

Linux性能优化--性能工具:磁盘I/O

6.0 概述 本章介绍的性能工具能帮助你评估磁盘I/O子系统的使用情况。这些工具可以展示哪些磁盘或分区已被使用&#xff0c;每个磁盘处理了多少I/O,发给这些磁盘的I/O请求要等多久才被处理。 阅读本章后&#xff0c;你将能够&#xff1a; 确定系统内磁盘I/O的总量和类型(读/写…

【网络安全 --- xss-labs通关】xss-labs靶场通关,让你巩固对xss漏洞的理解及绕过技巧和方法(提供资源)

一&#xff0c;资源下载准备 1-1 VMware 16.0 安装请参考以下博客&#xff0c;若已经安装请忽略&#xff1a; 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;…