Activiti工作流引擎进阶【收藏可做笔记系列】,那些被大厂优化的程序员们

  • 查询流程实例

    • 关联BusinessKey
  • 挂起、激活流程实例

    • 全部流程实例挂起
  • 单个流程实例挂起

  • 二、个人任务

    • 2.1、分配任务负责人
    • 2.1.1、固定分配
  • 2.1.2、表达式分配

    • 2.1.2.1、UEL 表达式
    • 1)UEL-value 定义
  • 2)UEL-method 方式

  • 3)UEL-method 与 UEL-value 结合

  • 4)其它

  • 2.1.2.2、编写代码配置负责人

    • 1)定义任务分配流程变量
  • 2)设置流程变量

  • 2.1.2.3、注意事项

  • 2.1.3、监听器分配

    • 2.1.3.1、注意事项
  • 2.2、查询任务

    • 查询任务负责人的待办任务
  • 关联 businessKey

  • 2.3、办理任务

  • 三、流程变量

    • 3.1、什么是流程变量
  • 3.2、流程变量类型

  • 3.3、流程变量作用域

    • 3.3.1、globa变量
  • 3.3.2、local变量

  • 3.4、流程变量的使用方法

    • 3.4.1、在属性上使用UEL表达式
  • 3.4.2、在连线上使用UEL表达式

  • 3.5、使用Global变量控制流程

    • 3.5.1、需求
  • 3.5.2、流程定义

  • 3.5.3、设置global流程变量

    • 3.5.3.1、创建POJO对象
  • 3.5.3.2、启动流程时设置变量

  • 3.5.3.2、任务办理时设置变量

  • 3.5.3.3、通过当前流程实例设置

  • 3.5.3.4、通过当前任务设置

  • 3.5.4、测试

  • 3.5.5、注意事项

  • 3.5.6、操作数据库表

  • 3.6、设置local流程变量

    • 3.6.1、任务办理时设置
  • 3.6.2、通过当前任务设置

  • 3.6.3、 Local变量测试1

  • 3.6.4、 Local变量测试2

  • 四、组任务

    • 4.1、需求
  • 4.2、设置任务候选人

  • 4.3、组任务

    • 4.3.1、组任务办理流程
    • a、查询组任务
  • b、拾取(claim)任务

  • c、查询个人任务

  • d、办理个人任务

  • 4.3.2、 查询组任务

  • 4.3.3 、 拾取组任务

  • 4.3.4、 查询个人待办任务

  • 4.3.5、 办理个人任务

  • 4.3.6、 归还组任务

  • 4.3.7、 任务交接

  • 4.3.8、 数据库表操作

  • 五、网关

    • 5.1 排他网关ExclusiveGateway
    • 5.1.1 什么是排他网关:
  • 5.1.2 流程定义

  • 5.1.3 测试

  • 5.2 并行网关ParallelGateway

    • 5.2.1 什么是并行网关
  • 5.2.2 流程定义

  • 5.2.3 测试

  • 5.3 包含网关InclusiveGateway

    • 5.3.1 什么是包含网关
  • 5.3.2 流程定义:

  • 5.3.3 测试

  • 5.4 事件网关EventGateway

    • 5.4.1流程定义

Activiti进阶

====================================================================

一、流程实例


什么是流程实例

流程实例(ProcessInstance)代表流程定义的执行实例。

一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。

例如:用户或程序按照流程定义内容发起一个流程,这就是一个流程实例。

流程定义和流程实例的图解:

请添加图片描述

启动流程实例 并添加Businesskey(业务标识)

流程定义部署在activiti后,就可以在系统中通过activiti去管理该流程的执行,执行流程表示流程的一次执行。

比如部署系统出差流程后,如果某用户要申请出差这时就需要执行这个流程,如果另外一个用户也要申请出差则也需要执行该流程,每个执行互不影响,每个执行是单独的流程实例。

启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey。

Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。

比如:出差流程启动一个流程实例,就可以将出差单的id作为业务标识存储到activiti中,将来查询activiti的流程实例信息就可以获取出差单的id从而关联查询业务系统数据库得到出差单信息。

/**

  • 启动流程实例,添加businessKey

*/

@Test

public void addBusinessKey(){

// 1、得到ProcessEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 2、得到RunTimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 3、启动流程实例,同时还要指定业务标识businessKey,也就是出差申请单id,这里是1001

ProcessInstance processInstance = runtimeService.

startProcessInstanceByKey(“myEvection”,“1001”);

// 4、输出processInstance相关属性

System.out.println(“业务id==”+processInstance.getBusinessKey());

}

Activiti的act_ru_execution中存储业务标识:

请添加图片描述

操作数据库表

启动流程实例,操作如下数据库表:

SELECT * FROM act_ru_execution #流程实例执行表,记录当前流程实例的执行情况

请添加图片描述

说明:

流程实例执行,如果当前只有一个分支时,一个流程实例只有一条记录且执行表的主键id和流程实例id相同,如果当前有多个分支正在运行则该执行表中有多条记录,存在执行表的主键和流程实例id不相同的记录。不论当前有几个分支总会有一条记录的执行表的主键和流程实例id相同

一个流程实例运行完成,此表中与流程实例相关的记录删除。

SELECT * FROM act_ru_task #任务执行表,记录当前执行的任务

请添加图片描述

说明:启动流程实例,流程当前执行到第一个任务结点,此表会插入一条记录表示当前任务的执行情况,如果任务完成则记录删除。

SELECT * FROM act_ru_identitylink #任务参与者,记录当前参与任务的用户或组

请添加图片描述

SELECT * FROM act_hi_procinst #流程实例历史表

请添加图片描述

流程实例启动,会在此表插入一条记录,流程实例运行完成记录也不会删除。

SELECT * FROM act_hi_taskinst #任务历史表,记录所有任务

请添加图片描述

开始一个任务,不仅在act_ru_task表插入记录,也会在历史任务表插入一条记录,任务历史表的主键就是任务id,任务完成此表记录不删除。

SELECT * FROM act_hi_actinst #活动历史表,记录所有活动

请添加图片描述

活动包括任务,所以此表中不仅记录了任务,还记录了流程执行过程的其它活动,比如开始事件、结束事件。

查询流程实例

流程在运行过程中可以查询流程实例的状态,当前运行结点等信息。

@Test

public void queryProcessInstance() {

// 流程定义key

String processDefinitionKey = “evection”;

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取RunTimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

List list = runtimeService

.createProcessInstanceQuery()

.processDefinitionKey(processDefinitionKey)//

.list();

for (ProcessInstance processInstance : list) {

System.out.println(“----------------------------”);

System.out.println(“流程实例id:”

  • processInstance.getProcessInstanceId());

System.out.println(“所属流程定义id:”

  • processInstance.getProcessDefinitionId());

System.out.println(“是否执行完成:” + processInstance.isEnded());

System.out.println(“是否暂停:” + processInstance.isSuspended());

System.out.println(“当前活动标识:” + processInstance.getActivityId());

}

}

关联BusinessKey

需求:

在activiti实际应用时,查询流程实例列表时可能要显示出业务系统的一些相关信息,比如:查询当前运行的出差流程列表需要将出差单名称、出差天数等信息显示出来,出差天数等信息在业务系统中存在,而并没有在activiti数据库中存在,所以是无法通过activiti的api查询到出差天数等信息。

实现:

在查询流程实例时,通过businessKey(业务标识 )关联查询业务系统的出差单表,查询出出差天数等信息。

通过下面的代码就可以获取activiti中所对应实例保存的业务Key。而这个业务Key一般都会保存相关联的业务操作表的主键,再通过主键ID去查询业务信息,比如通过出差单的ID,去查询更多的请假信息(出差人,出差时间,出差天数,出差目的地等)

String businessKey = processInstance.getBusinessKey();

在activiti的act_ru_execution表,字段BUSINESS_KEY就是存放业务KEY的。

请添加图片描述

挂起、激活流程实例

某些情况可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行。

全部流程实例挂起

操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停:

流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行。

/**

  • 全部流程实例挂起与激活

*/

@Test

public void SuspendAllProcessInstance(){

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取repositoryService

RepositoryService repositoryService = processEngine.getRepositoryService();

// 查询流程定义的对象

ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().

processDefinitionKey(“myEvection”).

singleResult();

// 得到当前流程定义的实例是否都为暂停状态

boolean suspended = processDefinition.isSuspended();

// 流程定义id

String processDefinitionId = processDefinition.getId();

// 判断是否为暂停

if(suspended){

// 如果是暂停,可以执行激活操作 ,参数1 :流程定义id ,参数2:是否激活,参数3:激活时间

repositoryService.activateProcessDefinitionById(processDefinitionId,

true,

null

);

System.out.println(“流程定义:”+processDefinitionId+“,已激活”);

}else{

// 如果是激活状态,可以暂停,参数1 :流程定义id ,参数2:是否暂停,参数3:暂停时间

repositoryService.suspendProcessDefinitionById(processDefinitionId,

true,

null);

System.out.println(“流程定义:”+processDefinitionId+“,已挂起”);

}

}

单个流程实例挂起

操作流程实例对象,针对单个流程执行挂起操作,某个流程实例挂起则此流程不再继续执行,完成该流程实例的当前任务将报异常。

/**

  • 单个流程实例挂起与激活

*/

@Test

public void SuspendSingleProcessInstance(){

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// RuntimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 查询流程定义的对象

ProcessInstance processInstance = runtimeService.

createProcessInstanceQuery().

processInstanceId(“15001”).

singleResult();

// 得到当前流程定义的实例是否都为暂停状态

boolean suspended = processInstance.isSuspended();

// 流程定义id

String processDefinitionId = processInstance.getId();

// 判断是否为暂停

if(suspended){

// 如果是暂停,可以执行激活操作 ,参数:流程定义id

runtimeService.activateProcessInstanceById(processDefinitionId);

System.out.println(“流程定义:”+processDefinitionId+“,已激活”);

}else{

// 如果是激活状态,可以暂停,参数:流程定义id

runtimeService.suspendProcessInstanceById( processDefinitionId);

System.out.println(“流程定义:”+processDefinitionId+“,已挂起”);

}

}

/**

  • 测试完成个人任务

*/

@Test

public void completTask(){

// 获取引擎

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取操作任务的服务 TaskService

TaskService taskService = processEngine.getTaskService();

// 完成任务,参数:流程实例id,完成zhangsan的任务

Task task = taskService.createTaskQuery()

.processInstanceId(“15001”)

.taskAssignee(“rose”)

.singleResult();

System.out.println(“流程实例id=”+task.getProcessInstanceId());

System.out.println(“任务Id=”+task.getId());

System.out.println(“任务负责人=”+task.getAssignee());

System.out.println(“任务名称=”+task.getName());

taskService.complete(task.getId());

}

二、个人任务


2.1、分配任务负责人

2.1.1、固定分配

在进行业务流程建模时指定固定的任务负责人, 如图:

请添加图片描述

并在 properties 视图中,填写 Assignee 项为任务负责人。

2.1.2、表达式分配

由于固定分配方式,任务只管一步一步执行任务,执行到每一个任务将按照 bpmn 的配置去分配任

务负责人。

2.1.2.1、UEL 表达式

Activiti 使用 UEL 表达式, UEL 是 java EE6 规范的一部分, UEL(Unified Expression Language)即 统一表达式语言, activiti 支持两个 UEL 表达式: UEL-value 和 UEL-method。

1)UEL-value 定义

如图:

请添加图片描述

assignee 这个变量是 activiti 的一个流程变量,

或者使用这种方式定义:

如图:

请添加图片描述

user 也是 activiti 的一个流程变量, user.assignee 表示通过调用 user 的 getter 方法获取值。

2)UEL-method 方式

如图:

请添加图片描述

userBean 是 spring 容器中的一个 bean,表示调用该 bean 的 getUserId()方法。

3)UEL-method 与 UEL-value 结合

再比如:

${ldapService.findManagerForEmployee(emp)}

ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti

流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中。

4)其它

表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。

如下:

${order.price > 100 && order.price < 250}

2.1.2.2、编写代码配置负责人
1)定义任务分配流程变量

如图:

2)设置流程变量

在启动流程实例时设置流程变量,如下:

/**

  • 设置流程负责人

*/

@Test

public void assigneeUEL(){

// 获取流程引擎

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取 RuntimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 设置assignee的取值,用户可以在界面上设置流程的执行

Map<String,Object> assigneeMap = new HashMap<>();

assigneeMap.put(“assignee0”,“张三”);

assigneeMap.put(“assignee1”,“李经理”);

assigneeMap.put(“assignee2”,“王总经理”);

assigneeMap.put(“assignee3”,“赵财务”);

// 启动流程实例,同时还要设置流程定义的assignee的值

runtimeService.startProcessInstanceByKey(“myEvection1”,assigneeMap);

// 输出

System.out.println(processEngine.getName());

}

执行成功后,可以在act_ru_variable表中看到刚才map中的数据

请添加图片描述

2.1.2.3、注意事项

由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如:

某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在

流程变量中存在,否则 activiti 异常。

2.1.3、监听器分配

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

在本章我们使用监听器的方式来指定负责人,那么在流程设计时就不需要指定assignee。

任务监听器是发生对应的任务相关事件时执行自定义 java 逻辑 或表达式。

任务相当事件包括:

请添加图片描述

Event的选项包含:

Create:任务创建后触发

Assignment:任务分配后触发

Delete:任务完成后触发

All:所有事件发生都触发

定义任务监听类,且类必须实现 org.activiti.engine.delegate.TaskListener 接口

public class MyTaskListener implements TaskListener {

@Override

public void notify(DelegateTask delegateTask) {

if(delegateTask.getName().equals(“创建出差申请”)&&

delegateTask.getEventName().equals(“create”)){

//这里指定任务负责人

delegateTask.setAssignee(“张三”);

}

}

}

DelegateTask对象的内容如下:

请添加图片描述

2.1.3.1、注意事项

使用监听器分配方式,按照监听事件去执行监听类的 notify 方法,方法如果不能正常执行也会影响

任务的执行。

2.2、查询任务

查询任务负责人的待办任务

代码如下:

// 查询当前个人待执行的任务

@Test

public void findPersonalTaskList() {

// 流程定义key

String processDefinitionKey = “myEvection1”;

// 任务负责人

String assignee = “张三”;

// 获取TaskService

TaskService taskService = processEngine.getTaskService();

List taskList = taskService.createTaskQuery()

.processDefinitionKey(processDefinitionKey)

.includeProcessVariables()

.taskAssignee(assignee)

.list();

for (Task task : taskList) {

System.out.println(“----------------------------”);

System.out.println("流程实例id: " + task.getProcessInstanceId());

System.out.println("任务id: " + task.getId());

System.out.println("任务负责人: " + task.getAssignee());

System.out.println("任务名称: " + task.getName());

}

}

关联 businessKey

需求:

在 activiti 实际应用时,查询待办任务可能要显示出业务系统的一些相关信息。

比如:查询待审批出差任务列表需要将出差单的日期、 出差天数等信息显示出来。

出差天数等信息在业务系统中存在,而并没有在 activiti 数据库中存在,所以是无法通过 activiti 的 api 查询到出差天数等信息。

实现:

在查询待办任务时,通过 businessKey(业务标识 )关联查询业务系统的出差单表,查询出出差天数等信息。

@Test

public void findProcessInstance(){

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取TaskService

TaskService taskService = processEngine.getTaskService();

// 获取RuntimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 查询流程定义的对象

Task task = taskService.createTaskQuery()

.processDefinitionKey(“myEvection1”)

.taskAssignee(“张三”)

.singleResult();

// 使用task对象获取实例id

String processInstanceId = task.getProcessInstanceId();

// 使用实例id,获取流程实例对象

ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()

.processInstanceId(processInstanceId)

.singleResult();

// 使用processInstance,得到 businessKey

String businessKey = processInstance.getBusinessKey();

System.out.println(“businessKey==”+businessKey);

}

2.3、办理任务

注意:在实际应用中,完成任务前需要校验任务的负责人是否具有该任务的办理权限 。

/**

  • 完成任务,判断当前用户是否有权限

*/

@Test

public void completTask() {

//任务id

String taskId = “15005”;

// 任务负责人

String assingee = “张三”;

//获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 创建TaskService

TaskService taskService = processEngine.getTaskService();

// 完成任务前,需要校验该负责人可以完成当前任务

// 校验方法:

// 根据任务id和任务负责人查询当前任务,如果查到该用户有权限,就完成

Task task = taskService.createTaskQuery()

.taskId(taskId)

.taskAssignee(assingee)

.singleResult();

if(task != null){

taskService.complete(taskId);

System.out.println(“完成任务”);

}

}

三、流程变量


3.1、什么是流程变量

流程变量在 activiti 中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和 activiti

结合时少不了流程变量,流程变量就是 activiti 在管理工作流时根据管理需要而设置的变量。

比如:在出差申请流程流转时如果出差天数大于 3 天则由总经理审核,否则由人事直接审核, 出差天

数就可以设置为流程变量,在流程流转时使用。

注意:虽然流程变量中可以存储业务数据可以通过activiti的api查询流程变量从而实现 查询业务数据,但是不建议这样使用,因为业务数据查询由业务系统负责,activiti设置流程变量是为了流程执行需要而创建。

3.2、流程变量类型

如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无

法反序列化,需要生成 serialVersionUID。

请添加图片描述

3.3、流程变量作用域

流程变量的作用域可以是一个流程实例(processInstance),或一个任务(task),或一个执行实例

(execution)

3.3.1、globa变量

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

注意:

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

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

3.3.2、local变量

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

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

3.4、流程变量的使用方法

3.4.1、在属性上使用UEL表达式

可以在 assignee 处设置 UEL 表达式,表达式的值为任务的负责人,比如: ${assignee}, assignee 就是一个流程变量名称。

Activiti获取UEL表达式的值,即流程变量assignee的值 ,将assignee的值作为任务的负责人进行任务分配

3.4.2、在连线上使用UEL表达式

可以在连线上设置UEL表达式,决定流程走向。

比如:${price<10000} 。price就是一个流程变量名称,uel表达式结果类型为布尔类型。

如果UEL表达式是true,要决定 流程执行走向。

3.5、使用Global变量控制流程

3.5.1、需求

员工创建出差申请单,由部门经理审核,部门经理审核通过后出差3天及以下由人财务直接审批,3天以上先由总经理审核,总经理审核通过再由财务审批。

请添加图片描述

3.5.2、流程定义

1)、出差天数大于等于3连线条件

请添加图片描述请添加图片描述

也可以使用对象参数命名,如evection.num:

请添加图片描述

请添加图片描述

2)、出差天数小于3连线条件

请添加图片描述

请添加图片描述

也可以使用对象参数命名,如:

请添加图片描述

请添加图片描述

3.5.3、设置global流程变量

在部门经理审核前设置流程变量,变量值为出差单信息(包括出差天数),部门经理审核后可以根据流程变量的值决定流程走向。

在设置流程变量时,可以在启动流程时设置,也可以在任务办理时设置

3.5.3.1、创建POJO对象

创建出差申请pojo对象

package com.itheima.demo.pojo;

import java.io.Serializable;

import java.util.Date;

/**

  • 出差申请 pojo

*/

public class Evection implements Serializable {

/**

  • 主键id

*/

private Long id;

/**

  • 出差申请单名称

*/

private String evectionName;

/**

  • 出差天数

*/

private Double num;

/**

  • 预计开始时间

*/

private Date beginDate;

/**

  • 预计结束时间

*/

private Date endDate;

/**

  • 目的地

*/

private String destination;

/**

  • 出差事由

*/

private String reson;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getEvectionName() {

return evectionName;

}

public void setEvectionName(String evectionName) {

this.evectionName = evectionName;

}

public Date getBeginDate() {

return beginDate;

}

public void setBeginDate(Date beginDate) {

this.beginDate = beginDate;

}

public Date getEndDate() {

return endDate;

}

public void setEndDate(Date endDate) {

this.endDate = endDate;

}

public String getDestination() {

return destination;

}

public void setDestination(String destination) {

this.destination = destination;

}

public String getReson() {

return reson;

}

public void setReson(String reson) {

this.reson = reson;

}

public Double getNum() {

return num;

}

public void setNum(Double num) {

this.num = num;

}

}

3.5.3.2、启动流程时设置变量

在启动流程时设置流程变量,变量的作用域是整个流程实例。

通过Map<key,value>设置流程变量,map中可以设置多个变量,这个key就是流程变量的名字。

/**

  • 启动流程实例,设置流程变量的值

*/

@Test

public void startProcess(){

// 获取流程引擎

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取RunTimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 流程定义key

String key = “myEvection2”;

// 创建变量集合

Map<String, Object> map = new HashMap<>();

// 创建出差pojo对象

Evection evection = new Evection();

// 设置出差天数

evection.setNum(2d);

// 定义流程变量,把出差pojo对象放入map

map.put(“evection”,evection);

// 设置assignee的取值,用户可以在界面上设置流程的执行

map.put(“assignee0”,“张三”);

map.put(“assignee1”,“李经理”);

map.put(“assignee2”,“王总经理”);

map.put(“assignee3”,“赵财务”);

// 启动流程实例,并设置流程变量的值(把map传入)

ProcessInstance processInstance = runtimeService

.startProcessInstanceByKey(key, map);

// 输出

System.out.println(“流程实例名称=”+processInstance.getName());

System.out.println(“流程定义id==”+processInstance.getProcessDefinitionId());

}

/**

  • 完成任务,判断当前用户是否有权限

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

文末

技术是没有终点的,也是学不完的,最重要的是活着、不秃。

零基础入门的时候看书还是看视频,我觉得成年人,何必做选择题呢,两个都要。喜欢看书就看书,喜欢看视频就看视频。

最重要的是在自学的过程中,一定不要眼高手低,要实战,把学到的技术投入到项目当中,解决问题,之后进一步锤炼自己的技术。

自学最怕的就是缺乏自驱力,一定要自律,杜绝“三天打鱼两天晒网”,到最后白忙活一场。

高度自律的同时,要保持耐心,不抛弃不放弃,切勿自怨自艾,每天给自己一点点鼓励,学习的劲头就会很足,不容易犯困。

技术学到手后,找工作的时候一定要好好准备一份简历,不要无头苍蝇一样去海投简历,容易“竹篮打水一场空”。好好的准备一下简历,毕竟是找工作的敲门砖。

拿到面试邀请后,在面试的过程中一定要大大方方,尽力把自己学到的知识舒适地表达出来,不要因为是自学就不够自信,给面试官一个好的印象,面试成功的几率就会大很多,加油吧,骚年!

ap.put(“evection”,evection);

// 设置assignee的取值,用户可以在界面上设置流程的执行

map.put(“assignee0”,“张三”);

map.put(“assignee1”,“李经理”);

map.put(“assignee2”,“王总经理”);

map.put(“assignee3”,“赵财务”);

// 启动流程实例,并设置流程变量的值(把map传入)

ProcessInstance processInstance = runtimeService

.startProcessInstanceByKey(key, map);

// 输出

System.out.println(“流程实例名称=”+processInstance.getName());

System.out.println(“流程定义id==”+processInstance.getProcessDefinitionId());

}

/**

  • 完成任务,判断当前用户是否有权限

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-zjNKM3m2-1711729043131)]
[外链图片转存中…(img-LOXzZWoz-1711729043132)]
[外链图片转存中…(img-RxtgBeuo-1711729043132)]
[外链图片转存中…(img-HETthZ0Q-1711729043133)]
[外链图片转存中…(img-K9yb3yCs-1711729043133)]
[外链图片转存中…(img-qKqHpHgE-1711729043133)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-meHC1fvx-1711729043134)]

文末

技术是没有终点的,也是学不完的,最重要的是活着、不秃。

零基础入门的时候看书还是看视频,我觉得成年人,何必做选择题呢,两个都要。喜欢看书就看书,喜欢看视频就看视频。

最重要的是在自学的过程中,一定不要眼高手低,要实战,把学到的技术投入到项目当中,解决问题,之后进一步锤炼自己的技术。

自学最怕的就是缺乏自驱力,一定要自律,杜绝“三天打鱼两天晒网”,到最后白忙活一场。

高度自律的同时,要保持耐心,不抛弃不放弃,切勿自怨自艾,每天给自己一点点鼓励,学习的劲头就会很足,不容易犯困。

技术学到手后,找工作的时候一定要好好准备一份简历,不要无头苍蝇一样去海投简历,容易“竹篮打水一场空”。好好的准备一下简历,毕竟是找工作的敲门砖。

拿到面试邀请后,在面试的过程中一定要大大方方,尽力把自己学到的知识舒适地表达出来,不要因为是自学就不够自信,给面试官一个好的印象,面试成功的几率就会大很多,加油吧,骚年!

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Activiti 是一个轻量级、灵活的开源工作流引擎,用于在应用程序中实现业务流程的自动化。它是一个基于Java的工作流和业务流程管理(BPM)平台,可以帮助开发人员设计、执行和管理各种业务流程。 Activiti 提供了许多功能,包括: 1. 流程定义:您可以使用 Activiti 的图形化设计器来定义和建模业务流程。这些流程可以由各种任务、条件和网关组成,以满足您的业务需求。 2. 流程执行:一旦定义了流程,您可以使用 Activiti 引擎来执行和管理流程实例。引擎会按照定义的流程规则自动处理任务、路由流程和记录执行历史。 3. 任务管理:Activiti 允许您分配和管理任务,以便团队成员可以完成特定的工作。您可以指定任务的优先级、截止日期和参与者,以确保任务按时完成。 4. 事件监听:Activiti 支持监听各种事件,例如流程启动、任务分配、任务完成等。这使得您可以根据不同的事件触发自定义逻辑来处理业务需求。 5. 历史数据记录:Activiti 可以记录所有流程实例和任务的历史数据,包括执行时间、参与者、结果等。这些数据有助于您分析和优化业务流程。 总的来说,Activiti 提供了一个强大且可扩展的平台,使您能够轻松地管理和优化业务流程。无论是简单的审批流程还是复杂的工作流,Activiti 都可以满足您的需求,并帮助您提高工作效率和业务质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值