【真干货】Activiti7工作流如何使用?看这里

news2024/11/20 7:14:32

一. 前言

近日文哥有个毕业学员在公司开发时遇到了工作流的相关业务场景。在这里,文哥给大家精心准备了以Activiti为代表的工作流简单使用教程,希望能给有需要的小伙伴们一些帮助。下面我们就来开始介绍Activiti工作流的基本使用情况。

二. Activiti工作流的基本概述

2.1 什么是工作流

工作流就是用来做流程审批的,如:请假审批流程、报销审批流程、出差审批流程、合同审批流程等

工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目 标的实现”。

工作流引擎,主要是为了帮忙我们实现流程自动化控制,对应的Activiti引擎就可以实现自动化控制。

2.2 工作流的应用场景

工作流的应用场景主要有:

  • 业务类:合同审批流程、订单处理流程、出入库审批流程等。

  • 行政类:请假流程、出差流程、用车流程、办公用品申请流程等。

  • 财务类:报销流程、支付流程等。

  • 客户服务类:售后跟踪、客户投诉等。

2.3 什么是Activiti

Activiti项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准,包括支持对象管理组(OMG),面对新技术的机遇,诸如互操作性和云架构,提供技术实现。

创始人Tom Baeyens是JBoss jBPM的项目架构师,以及另一位架构师Joram Barrez,一起加入到创建Alfresco这项首次实现Apache开源许可的BPMN 2.0引擎开发中来。

Activiti是一个独立运作和经营的开源项目品牌,并将独立于Alfresco开源ECM系统运行。Activiti将是一种轻量级,可嵌入的BPM引擎,而且还设计适用于可扩展的云架构。Activiti将提供宽松的Apache许可2.0,以便这个项目可以广泛被使用,同时促进Activiti BPM引擎和BPMN 2.0的匹配,该项目现正由OMG通过标准审定。加入Alfresco Activiti项目的是VMware的SpringSource分支,Alfresco的计划把该项目提交给Apache基础架构,希望吸引更多方面的BPM专家和促进BPM的创新。

Activiti官网:https://www.activiti.org/

2.4 Activiti开发流程

  • 画流程定义模型;

  • 遵守BPMN的流程规范,使用BPMN的流程定义工具,通过 流程符号 把整个业务流程定义出来,可以将流程 定义文件字节流保存到模型数据表中(Model);

  • 部署流程定义;

  • 加载画好的流程定义文件,将它转换成流程定义数据(ProcessDefinition),保存到流程定义数据表中;

  • 启动流程(提交流程申请);

  • 生成流程实例数据(ProcessInstance),生成第1节点任务数据(Task);

  • 处理人审批流程节点任务;

  • 完成任务审批,生成审批结果,生成下一节点任务数据。

2.5 BPMN 2.0 规范是什么

业务流程模型注解(Business Process Modeling Notation - BPMN)是业务流程模型的一种标准图形注解。这个标准是由对象管理组(Object Management Group - OMG)维护的。

标准的早期版本(1.2版以及之前)仅仅限制在模型上,目标是在所有的利益相关者之间形成通用的理解,在文档,讨论和实现业务流程之上。BPMN标准证明了它自己,现在市场上许多建模工具都使用了BPMN标准中的元素和结构。

BPMN规范的2.0版本,当前已经处于最终阶段了,允许添加精确的技术细节在BPMN的图形和元素中,同时制定BPMN元素的执行语法。通过使用XML语言来指定业务流程的可执行语法, BPMN规范已经演变为业务流程的语言,可以执行在任何兼容BPMN2的流程引擎中,同时依然可以使用强大的图形注解。

目前BPMN2.0是最新的版本,它用于在BPM上下文中进行布局和可视化的沟通。BPMN 2.0是使用一些符号来明确业务流程设计流程图的一整套符号规范,它能增进业务建模时的沟通效率。

2.6 BPMN 2.0 基本流程符号

BPMN2.0对流程执行语义定义了三类基本要素,它们是日常业务流程的“三板斧”:

  • Activities(活动)——在工作流中所有具备生命周期状态的都可以称之为“活动”,如原子级的任务(Task)、流向(Sequence Flow),以及子流程(Sub-Process)等

  • Gateways(网关)——顾名思义,所谓“网关”就是用来决定流程流转指向的,可能会被用作条件分支或聚合,也可以被用作并行执行或基于事件的排它性条件判断

  • Events(事件)——在BPMN2.0执行语义中也是一个非常重要的概念,像启动、结束、边界条件以及每个活动的创建、开始、流转等都是流程事件,利用事件机制,可以通过事件控制器为系统增加辅助功能,如其它业务系统集成、活动预警等

事件 Event

  • 开始 - 表示一个流程的开始。

  • 中间 - 发生的开始和结束事件之间,影响处理的流程。

  • 结束 - 表示该过程结束。

活动Activity

活动是工作或任务的一个通用术语。一个活动可以是一个任务,还可以是一个当前流程的子处理流程;其次,你还可以为活动指定不同的类型。常见活动如下:

网关 Gateway

网关用来处理决策,有两种常用网关需要了解:

排他网关(x)

  • 只有一条路径会被选择。流程执行到该网关时,按照输出流的顺序逐个计算,当条件的计算结果为true时,继续执行当前网关的输出流;

  • 如果多条线路计算结果都是true,则会执行第一个值为 true 的线路。如果所有网关计算结果没有true,则引擎会抛出异常。

  • 排他网关需要和条件顺序流结合使用,default 属性指定默认顺序流,当所有的条件不满足时会执行默认顺序流。

并行网关(+)

  • 所有路径会被同时选择

      ○ 分支:并行执行所有输出顺序流,为每一条顺序流创建一个并行执行线路

     ○ 汇聚 :所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行。

包容网关(o)

  • 可以同时执行多条线路,也可以在网关上设置条件

     ○ 分支:计算每条线路上的表达式,当表达式计算结果为true时,创建一个并行线路并继续执行

     ○ 汇聚:所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行。

事件网关(o+)

  • 专门为中间捕获事件设置的,允许设置多个输出流指向多个不同的中间捕获事件。当流程执行到事件网关 后,流程处于等待状态,需要等待抛出事件才能将等待状态转换为活动状态。

定时器事件

  • 开始定时器事件: 

      ○ 可以设置时间,定时开始启动流程实例。

  • 中间定时器事件:

      ○ 设定延迟时间,当完成任务1后,到达延时时间,流程才会走向任务2。

  • 边界定时器事件: 

      ○ 用于向某节点上添加边界定时事件。在设定时间内没有完成,流程实例则自动走向下一节点。

三. Activiti 环境搭建和流程基础入门

3.1 创建一个maven项目

创建一个maven项目,取名activiti-demo1。文哥这里省略步骤。

3.2 添加相关依赖

<dependencies>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>7.1.0.M6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.23</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.26</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.26</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
</dependencies>

3.3 创建activiti核心配置文件

Activiti流程引擎通过名为的XML文件进行配置 activiti.cfg.xml,在resources目录下创建 activiti.cfg.xml文件。

注意:这里核心配置文件,参考官方文档:https://www.activiti.org/userguide/#demo.setup.one.minute.version

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:mysql://192.168.10.135:3306/activiti01?characterEncoding=utf8"/>
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="Admin123!" />
        <property name="databaseSchemaUpdate" value="true" />
    </bean>
</beans>

注意:防止插入中文数据乱码,要加上字符集 characterEncoding=utf8。

3.4 log4j.properties 配置日志

log4j.rootCategory=debug, CONSOLE, LOGFILE
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss.SSS} %p [%t] %C.%M(%L) | %m%n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:/java2103-workspace/spring-project/activiti-project/activiti.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

3.5 创建 ProcessEngine 流程引擎实例和数据表

加载类路径上的activiti.cfg.xml,并根据该文件中的配置构造一个流程引擎,和创建数据表。

public class ActivitiTest01 {
    /**
     * 创建ProcessEngine流程引擎,自动创建 activiti 数据表
     */
    @Test
    public void getProcessEngine(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(processEngine);
    }
}

注意:上面我们提到,在配置StandaloneInMemProcessEngineConfiguration这个bean的时候,bean的id必须是processEngineConfiguration,否则会获取不到流程实例,现在我们试验一下。然后进行测试,测试结果如下:

为什么会出现这样的情况?我们可以去跟踪一下源码。我们通过测试类作为入口,去跟踪一下获取流程实例的具体实现:

然后我们我们看看getDefaultProcessEngine方法的具体实现:

继续进入init方法,查看具体实现。init的方法,有描述初始化流程引擎的关键代码。

继续进入initProcessEngineFromResource方法内部。

buildProceeEngine方法描述了通过资源加载流程引擎,我们继续进入这个方法查看:

继续进入这个方法:

由此可见,这个bean的名称必须是processEngineConfiguration,这是由底层源码定义的。

3.6 Activiti初始化的数据表分析

当我们执行获取流程实例的方法之后,我们发现,在对应的数据库里面生成了25张表。

Acitiviti数据库中表的命名都是以 ACT_ 开头的。第二部分是一个两个字符用例表的标识。此用例大体与服务API是 匹配的。ACT_GE_* :GE 表示 general 。通用数据,各种情况都使用的数据 ,如存放资源文件(图片,规则等)。

  • ACT_HI_xxx:HI 表示history。就是这些表包含着历史的相关数据,如结束的流程实例(变量,任务等)。

  • ACT_RE_xxx:RE 表示repository。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则 等)。Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。这样运行时表可以一直 很小速度很快。

  • ACT_RU_xxx:RU 表示 runtime。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的 数据。Activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的 表小且快。

  • ACT_EVT* :EVT表示EVENT,流程引擎的通用事件日志记录表,方便管理员跟踪处理。

下面对这些表的功能做了详细说明,大家先了解即可。

表名说明

act_ge_bytearray

二进制数据表(流程图)

act_ge_property

属性数据表,存储整个流程引擎级别的数据,初始化表结构时,会 插入版本号信息等

act_hi_actinst

历史节点表

act_hi_attachment

历史附件表

act_hi_comment

历史说明信息表

act_hi_detail

历史详情表,提供历史变量的查询

act_hi_identitylink

历史流程人员表,主要存储任务节点与参与者的相关信息

act_hi_procinst

历史流程人员表,主要存储任务节点与参与者的相关信息

act_hi_taskinst

历史任务实例表

act_hi_varinst

历史变量表

act_re_deployment

部署信息表

act_re_model

流程设计模型表

act_re_procdef

流程定义数据表

act_ru_deadletter_job

作业死亡信息表,如果作业失败超过重试次数,则写入到此表

act_ru_event_subscr

throwEvent、catchEvent时间监听信息表

act_ru_execution

运行时流程执行实例表

act_ru_identitylink

运行时流程人员表,主要存储任务节点与参与者的相关信息

act_ru_integration

运行时积分表

act_ru_job

定时异步任务数据表

act_ru_suspended_job

运行时作业暂停表, 比如流程中有一个定时任务,如果把这个任务停止工作了,这个任务写入到此表中

act_ru_task

运行时任务节点表

act_ru_timer_job

运行时定时器作业表

act_ru_variable

运行时流程变量数据表

act_procdef_info

流程定义的动态变更信息

act_evt_log

流程引擎的通用事件日志记录表

3.7 Activiti API 服务接口

Activiti 流程引擎包含了25张表,而且表之间的关系也比较复杂,比如包含各种外键约束。按照传统的方式,有了数据库表后,就应该为每张表创建pojo实体类,然后为其创建对应的DAO接口,然后再创建对应的Service来实现对表数据的增删改查。

但是按照传统方式的,就会有一个很严峻的问题,表的数量太多,并且关系复杂,还要兼顾流程引擎的处理方式,自己去搞一套,几乎不可能。

其实不需要我们去创建pojo、 DAO、Service、Controller,因为Activiti已经把这些东西给搞好了,只需要调用即可。

Process Engine API 和服务

引擎 API 是与 Activiti 交互的最常见方式。您可以从ProcessEngine中获取包含工作流/ BPM方法的各种服务。ProcessEngine和服务对象是线程安全的。因此,您可以为整个服务器保留对其中之一的引用。Service 是工作流引擎提供用于进行工作流部署、执行、管理的服务接口,我们使用对应Service接口可以操作对应的数据表。

Activiti7 的Servcie核心接口

  1.Service 管理接口说明

Service接口说明

RuntimeService

运行时Service,可以处理所有正在运行状态的流程实例和任务等。

RepositoryService

流程定义Service,主要用于管理流程定义信息,比如流程定义的控制管理(部署、删除、挂起、激活....)

DynamicBpmnService

RepositoryService可以用来部署流程定义(使用xml形式定义好的),一旦 部署到Activiti(解析后保存到DB),那么流程定义就不会再变了,除了修改 xml定义文件内容;而DynamicBpmnService就允许我们在程序运行过程中 去修改流程定义,例如:修改流程定义中的分配角色、优先级、流程流转的件...

TaskService

任务 Service,用于管理和查询任务,例如:签收、办理等

HistoryService

历史 Service,可以查询所有历史数据,例如:流程实例信息、参与者信息、完成时间....

ManagementService

引擎管理Service,和具体业务无关,主要用于对Activiti流程引擎的管理和维护。

   2.核心Service 接口实例获取方式如下

@Test
public void getProcessEngine(){
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    System.out.println(processEngine);
    // 引擎管理类
    ManagementService managementService = processEngine.getManagementService();
    System.out.println("managementService:" + managementService);
    // 动态修改流程管理类
    DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
    System.out.println("dynamicBpmnService:" + dynamicBpmnService);
    // 流程运行管理类
    RuntimeService runtimeService = processEngine.getRuntimeService();
    System.out.println("runtimeService:" + runtimeService);
    // 流程定义管理类
    RepositoryService repositoryService = processEngine.getRepositoryService();
    System.out.println("repositoryService:" + repositoryService);
    // 任务管理类
    TaskService taskService = processEngine.getTaskService();
    System.out.println("taskService:" + taskService);
    // 历史管理类
    HistoryService historyService = processEngine.getHistoryService();
    System.out.println("historyService:" + historyService);
}

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

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

相关文章

利器 | Java 接口自动化测试首选方案:REST Assured 实践 (一)

在 REST Assured 的官方 GitHub 上有这样一句简短的描述&#xff1a; Java DSL for easy testing of REST services 简约的 REST 服务测试 Java DSL REST Assured 官方的 README 第一句话对进行了一个优点的概述&#xff0c;总的意思表达的就是简单好用。那么 REST Assured 有…

dolphinscheduler 调用shell脚本执行sql

1. 资源中心--创建文件 脚本&#xff1a; #!/bin/bash hive <<EOF alter table app.app_bi_test drop partition (dayid$1); insert overwrite table app.app_bi_test partition(dayid) select a.Ccode,a.inCcode ,a.Cname ,$1,COALESCE(b.num,0) ,COALESCE(c.c_num…

以前的任何一个行业只要与互联网技术产生联系,便焕发生机与活力

事实上&#xff0c;以往&#xff0c;我们所经历的那个互联网玩家频出的年代&#xff0c;其实就是一个以互联网技术为主导的年代。在那样一个年代里&#xff0c;互联网技术几乎是解决一切痛点和难题的万能解药&#xff0c;几乎是破解一切行业痛点和难题的杀手锏。任何一个行业&a…

XXE渗透与攻防(一)

目录 前言 XML基础知识 XML用途 XML内容 XML格式要求 XML格式校验 不同语言支持的协议 完整的XML内容 什么是XXE 案列演示 盲打-DNSLog XXE 防御 前言 现在许多不同的客户端技术都可以使用XMl向业务应用程序发送消息&#xff0c;为了使应用程序使用自定义的XML消…

高压放大器在介电泳分选的应用

实验名称&#xff1a;基于高压放大器的介电泳分选 研究方向&#xff1a;滴液分选 测试原理&#xff1a; 在非均匀电场中&#xff0c;介电体表面感生出的正负电荷处于不同场强的位置上在它受到的合力大于一定值时就会被拉向强电场方向。 测试设备&#xff1a;ATA-7030高压放大器…

类与对象(下)

类与对象构造函数构造函数体赋值初始化列表explicit关键字static成员概念特性友元友元函数友元类内部类匿名对象拷贝对象时的一些编译器优化构造函数 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值 clas…

勃仔诞生记:Hubbleverse哈勃元宇宙的起源故事

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;9分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 想象一个属于你的世界&#xff0c;一个资源丰富的世界&#xff0c;你可以在其中…

Android TV刷机Mstar篇——以乐视超4-X50Pro为例

家里这台乐视使用好几年了&#xff0c;最近闲来无事&#xff0c;就琢磨着刷一刷&#xff0c;打造一个纯净使用体验。 记录下刷机历程&#xff0c;方便后期再查看。 一、准备工作 1、下载刷机固件&#xff0c;这里使用了ZNDS大神出的包。 超4X43 Pro/超4X50 Pro通用流畅精简…

pytorch应用(入门1)

目录学习用具张量的定义和运算Variable&#xff08;变量&#xff09;Dataset数据集之前一直是拿一个个项目来学pytorch&#xff0c;感觉不是很系统&#xff0c;借着假期的机会系统学一下。预计先把入门的知识一周学完吧。 学习用具 《深度学习入门之Pytorch》廖星宇 在Z-lib…

数字孪生流域建设及其应用

2021年底水利部召开推进数字孪生流域建设工作会议&#xff0c;会议按照“需求至上、应用至上、数字赋能、提升能力”要求&#xff0c;以数字化、网络化、智能化为主线&#xff0c;以数字化场景、智慧化模拟、精准化决策为路径&#xff0c;以算据、算法、算力建设为支撑&#xf…

美国服务器安全吗?如何进行安全检测和使用?

对服务器安全检测是保证稳定运行的一种方式&#xff0c;尤其面向海外的一些用户&#xff0c;因为使用的服务器无法时刻检查&#xff0c;对安全系数要求又很高。因此&#xff0c;在租用前和使用时进行安全检测是十分有必要的。那么&#xff0c;美国服务器怎么进行安全检测呢? 一…

为深度学习选择最好的GPU

在进行机器学习项目时&#xff0c;特别是在处理深度学习和神经网络时&#xff0c;最好使用GPU而不是CPU来处理&#xff0c;因为在神经网络方面&#xff0c;即使是一个非常基本的GPU也会胜过CPU。 但是你应该买哪种GPU呢?本文将总结需要考虑的相关因素&#xff0c;以便可以根据…

直播倒计时1天!“基于AIOps的全面可观测性网络研讨会”与你不见不散

当企业云化不断加速&#xff0c;应对重复冗杂的运维活动&#xff0c;引入智能算法的AIOps已成发展趋势&#xff1a; 高效定位故障来源&#xff0c;保证数字业务稳定可靠运行&#xff0c;深挖数据价值促进企业创新……AIOps能做的还有很多。 想了解更多关于AIOps的相关内容&am…

Spring注册Bean系列--方法4:@Import+ImportSelector接口

原文网址&#xff1a;Spring注册Bean系列--方法4&#xff1a;ImportImportSelector接口_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring注册Bean的方法&#xff1a;ImportImportSelector接口。 注册Bean的方法我写了一个系列&#xff0c;见&#xff1a;Spring注册Bean(提供Be…

php宝塔搭建部署实战SDCMS蓝色系列包装行业网站源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的SDCMS蓝色系列包装行业网站源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&…

房产管理系统平台架构求分析

数图互通房屋管理系统遵循高校房产“分级授权、分类管理、网络化、图形化、精细化、流程化”的管理理念&#xff0c;在资产管理部门统一管理全校房产的前提下&#xff0c;注重二级单位在房产管理中的参与&#xff0c;注重针对不同类型类别房产的分类管理提高学校房产的使用效率…

加强舆情监控有哪些方法,互联网舆情监控平台有哪些?

加强舆情监控是指企业通过提升监控能力&#xff0c;更好地了解公众对其产品、服务、品牌形象等的看法&#xff0c;并及时采取应对措施。接下来TOOM舆情监测小编带您简单了解加强舆情监控有哪些方法&#xff0c;互联网舆情监控平台有哪些&#xff1f; 企业可以通过以下方式加强舆…

C# 并行编程

一 并行任务库TPL 1 并行任务库&#xff08;TPL&#xff0c;Task Parallel Library&#xff09; 2 最重要的是Task类&#xff0c;还有Parallel类 3 Task类&#xff0c;是利用线程池来进行任务的执行 比如直接用ThreadPool更优化&#xff0c;而且编程更方便 4 Paallel类&…

右值引用与移动语义

目录 一、左、右值引用 1.1 什么是左值 1.2 什么是右值 1.3 右值引用特性 1.4 move语义 二、左、右值引用的比较 三、右值引用的使用场景 3.1 左值引用的短板 3.2 解决方案 四、移动构造与移动赋值 注意情况 五、万能引用与完美转发 5.1 万能引用 5.2 完美转发 …

【SpringMVC】SpringMVC中异常处理

1.异常处理的思路 系统中异常包括两类&#xff1a;预期异常和运行时异常 RuntimeException&#xff0c;前者通过捕获异常从而获取异常信息&#xff0c;后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的 dao、service、controller 都通过 throws Excepti…