目录

Activiti 概述 与 下载

Activiti Hello World

安装流程设计器插件

绘制工作流程图

IDEA 编码实现工作流

Activiti 核心 API 预览


Activiti 概述 与 下载

1、工作流(Workflow):是对工作流程及其各个操作步骤之间业务规则的抽象、概况和描述。

2、工作流模型:将工作流程中的工作如何前后组织在一起的逻辑和规则,在计算机中以恰当的模型表达并对其实施计算。

3、工作流要解决的问题是实现某个业务目标、利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。

4、主流的工作流框架:Activiti、OSWorkflow、JBoss 的 JBPM、Apache 的 ofBiz 等。生活中有很多的流程管理,比如请假流程、报销流程、审批流程等等。

5、Activiti 历史:JBPM 4 的时候团队内部发生分歧,其中部分开发人员脱离了大部队(JBoss),出来独立写出了 Activiti5;JBoss 则继续 JBPM 的开发,后续又有了 JBPM 5 ...。

6、所以 Activiti 5 基本等同于 JBPM4,2016 年 11 月开源了 Activiti 5.22.0,2017 年 5 月开源了 Activiti 6.0.0,2018 年开始开源 Activiti 7.X。Activiti 7 分为了 Activiti Core 与 Activiti Cloud 两个方向,更倾向于云环境、微服务。

7、Activiti 易于与 Spring、Spring boot、Spring cloud 集成,BPM 全称 Business Process Management - 业务流程管理

8、Activiti 支持主流的数据库(官方文档):

Activiti database type Example JDBC URL Notes

h2

jdbc:h2:tcp://localhost/activiti

Default configured database

mysql

jdbc:mysql://localhost:3306/activiti?autoReconnect=true

Tested using mysql-connector-java database driver

oracle

jdbc:oracle:thin:@localhost:1521:xe

 

postgres

jdbc:postgresql://localhost:5432/activiti

 

db2

jdbc:db2://localhost:50000/activiti

 

mssql

jdbc:sqlserver://localhost:1433;databaseName=activiti (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) OR jdbc:jtds:sqlserver://localhost:1433/activiti (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)

Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver

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

Activiti Github 开源地址:https://github.com/Activiti/Activiti

Activiti v7.X 官方开发手册:https://activiti.gitbook.io/activiti-7-developers-guide/

Activiti v6.X 官方开发手册:https://www.activiti.org/userguide/

Activiti v5.X 官方开始手册:https://www.activiti.org/5.x/userguide/

9、maven 依赖:非 Spring Boot 项目,使用 activiti-engine 即可,否则推荐使用 activiti-spring-boot-starter-basic,activiti 与 spring boot 集成的启动器,里面包含了 activiti-engine 引擎,以及 activiti 与 spring 的集成,以及 jdbc 等。

        <!-- https://mvnrepository.com/artifact/org.activiti/activiti-engine --><dependency><groupId>org.activiti</groupId><artifactId>activiti-engine</artifactId><version>6.0.0</version></dependency>
        <!--activiti 官网地址:https://www.activiti.org/userguide/#_getting_started_2--><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter-basic</artifactId><version>6.0.0</version></dependency>

Activiti Hello World

1、千里之行,始于足下。学习一个新框架得先有一个 Hello World 压压惊,否则会很迷茫。

2、本文环境:Java JDK 1.8 + IDEA 2018 +Maven 3.1.6 + Activiti 6.0.0 + H2 Database + Spring Boot 2.1.4 进行开发。

1)使用 Maven 管理,不再去 Activiti 官网下载 jar 包,然后导入到项目中

2)暂时使用 H2 内存数据库,让 Activiti 的表和数据先直接在内存数据库中使用。

3、特别提醒:

1)Acticiti 工作流开发,第一步是需要绘制工作流程图(本文开头的那种图),第二步就是编码。

2)下载 Acticiti 6.0.0 开发包或者源码可以看到,里面提供了针对各种数据库的 sql 文件,然后实际中并不需要手动去执行这些 sql 脚本,因为在后台代码中构建流程引擎(ProcessEngine)的时候,它可以自动执行 sql 建表脚本创建好 28 张表

3)Activiti 6.0.0  有 28 张表,使用 Activiti API 操作工作流的时候,Activiti 会自动操作自己的数据库表。所以对于 activiti 的 28 张数据库表,前期并不需要关心,对我们来说是透明的,入门之后可以再去深入了解。

安装流程设计器插件

官网介绍地址:https://www.activiti.org/userguide/#eclipseDesignerInstallation

1、eclipse、sts、idea 都有绘制 activiti 流程图的插件,但官方文档介绍的是 eclipse(sts本质也是eclipse),所以这里也采用 在 sts 上安装流程图插件。(注:在 sts 插件上绘制好流程图后,本人更喜欢 IDEA 编码,所以后续只需要将 sts 中创建好的 .bpmn 文件拷贝过去即可)

1、这里选择在线安装插件 activiti 插件,打开 help -> Install New Software 安装新的软件(插件),在 Install 面板中,点击 Add 按钮添加插件名称与地址:

Name: Activiti BPMN designer (名称可以随意取)
Location: http://activiti.org/designer/update/

2、点击 "Next" 下一步,然后会联网进行下载,之后在 "Install Detail" 面板直接 "Next",然后进入 "Review license" 查看许可证面板,点击第一项 "I accept ..." 同意,最后点击 "Finish" 完成安装。

3、安装过程中可能会弹框提示,选择安装所有即可,然后会提示重启,重启之后可以点击菜单 "Window -> Show View -> Other..." 看到 activiti 插件:

4、设置保存 bpmn 流程图时,同时保存一张同名的 .png 图片:

绘制工作流程图

1、安装好插件之后就可以开始绘制工作流程图了,随便在某个目录上右键,然后 "New -> Other...-> Activiti -> Activiti Diagram" 创建 Activiti 流程图:

2、基本工作流程图绘制并不难,从右侧的选项中拖到到中间即可,开始的黑色圆圈为开始事件,User Task 表示用户任务,带黑色叉的矩形为排它网关(用于条件判断),末尾的粗黑线圆圈为结束事件,箭头线表示顺序流。

3、排它网关用于条件判断,比如同意则继续往后走、不同意则重新返回,在网关上选择箭头按住拖到目标按钮上即可。

4、在空白处点击,为整个流程设置 id 与 name,在每个按钮上点击,为他们设置 id 与 name 值,这些值将来都是 .bpmn 文件中的属性值,代码中会操作它们,它们也会被自动处理到数据库中。

5、为3个用户任务设置 form 表单参数,即此任务执行需要的参数,因为操作比较长,无法全部做成动图,所以只演示添加1个属性。type 表示参数类型,required 表示参数是否必须要填。

6、用户任务设置的参数表示工作流中用户提供的参数,而这些参数需要在排它网关中进行判断,比如主管审批结果输入为 y 时才能继续往后走,否则输入 n 时,则应该重新回到 "填写审批信息"。当排它网关未作任何限制时,则主管和人事无论输入什么,都会继续往后走,显然这不满足我们的需求,则此时应该设置排它网关的条件,它类似 EL 表达式的写法 ${条件判断} ,|| 表示或,&& 表示与,条件判断的值是上一个用户任务中的 form 表单参数。

7、至此工作流程图绘制完毕,第一次可能比较难理解,但是多画几次,然后结合后面的代码,则容易理解。

注意:这个流程图(.bpmn文件)本质就是一个 .xml 文件,可以用记事本、或者浏览器等打开就可以看出来,后面会提供完整的文件,所以即使没画出来,也没关系,并不影响后面的代码运行。

IDEA 编码实现工作流

1、因为本人习惯使用 IDEA,所以在 IDEA 中新建一个 Maven 项目,Java SE 应用,直接在 main 方法中进行简单使用。

2、将 sts 中插件绘制好的流程文件 .bpmn 拷贝到 IDEA 项目的类路径下,当然直接使用 sts 、eclipse 开发也是一样的。

3、pom.xml 文件内容如下。

spring-boot-starter-parent 与 spring-boot-maven-plugin 是方便 maven 项目打包的,可选

slf4j-api 与 slf4j-log4j12 用于做日志框架,可选

activiti-spring-boot-starter-basic:activiti 与 spring boot 集成的启动器,里面包含了 activiti-engine 引擎,以及 activiti 与 spring 的集成,以及 jdbc 。必选,

h2 是内存数据库,必须使用一个数据库,当然可以换成其它数据库。

guava 方便做集合、字符串等操作,可选

junit 方便做单元测试,可选

<?xml version="1.0" encoding="UTF-8"?>
<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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>wmx.com</groupId><artifactId>activiti-first</artifactId><version>1.0-SNAPSHOT</version><dependencies><!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version></dependency><!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version></dependency><!-- https://mvnrepository.com/artifact/org.activiti/activiti-engine --><dependency><groupId>org.activiti</groupId><artifactId>activiti-engine</artifactId><version>6.0.0</version></dependency><!-- https://mvnrepository.com/artifact/com.h2database/h2 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><version>1.4.183</version></dependency><!-- https://mvnrepository.com/artifact/com.google.guava/guava --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>27.0-jre</version></dependency><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

4、只建了一个 MainApp.java 文件操作工作流,编码分为 4 步:1)创建流程引擎 -> 2)部署流程定义文件 -> 3)启动运行流程、4)处理流程任务。内容如下:

import com.google.common.collect.Maps;
import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class MainApp {private static Logger LOGGER = LoggerFactory.getLogger(MainApp.class);public static void main(String[] args) throws ParseException {LOGGER.info(" App start...");//1、创建流程引擎ProcessEngine processEngine = getProcessEngine();//2、部署流程定义文件ProcessDefinition processDefinition = getProcessDefinition(processEngine);//3、启动运行流程ProcessInstance processInstance = getProcessInstance(processEngine, processDefinition.getId());//4、处理流程任务handlingTasks(processEngine, processInstance);LOGGER.info(" App quit...");}/*** 处理流程任务** @param processEngine* @param processInstance* @throws ParseException*/private static void handlingTasks(ProcessEngine processEngine, ProcessInstance processInstance) throws ParseException {Scanner scanner = new Scanner(System.in);//从控制台手动输入数据while (processInstance != null && !processInstance.isEnded()) {TaskService taskService = processEngine.getTaskService();//获取任务服务List<Task> taskList = taskService.createTaskQuery().list();for (Task task : taskList) {LOGGER.info("当前待处理任务id [{}],任务名称 [{}]", task.getId(), task.getName());Map<String, Object> dataMap = getStringObjectMap(processEngine, scanner, task);taskService.complete(task.getId(), dataMap);//提交任务/完成任务//重新获取流程实例processInstance = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();}}scanner.close();}/*** 设置当前任务的表单参数。从控制台输入** @param processEngine* @param scanner* @param task* @return* @throws ParseException*/private static Map<String, Object> getStringObjectMap(ProcessEngine processEngine, Scanner scanner, Task task) throws ParseException {FormService formService = processEngine.getFormService();//表单服务TaskFormData taskFormData = formService.getTaskFormData(task.getId());//根据任务id获取任务表单数据对象List<FormProperty> formPropertyList = taskFormData.getFormProperties();//获取表单属性Map<String, Object> dataMap = Maps.newHashMap();for (FormProperty formProperty : formPropertyList) {String line = null;if (StringFormType.class.isInstance(formProperty.getType())) {LOGGER.info("请输入 {}", formProperty.getName());line = scanner.nextLine();dataMap.put(formProperty.getId(), line);} else if (DateFormType.class.isInstance(formProperty.getType())) {LOGGER.info("请输入 {}", formProperty.getName());line = scanner.nextLine();dataMap.put(formProperty.getId(), DateUtils.parseDate(line, "yyyy-MM-dd HH:mm:ss"));} else {LOGGER.warn("暂时不支持此类型 [{}]", formProperty.getType());}LOGGER.info("您成功输入 [{}]", line);}return dataMap;}/*** 启动运行流程** @param processEngine* @param processDefinitionId*/private static ProcessInstance getProcessInstance(ProcessEngine processEngine, String processDefinitionId) {RuntimeService runtimeService = processEngine.getRuntimeService();ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId);String processDefinitionKey_ = processInstance.getProcessDefinitionKey();LOGGER.info("启动流程,流程key [{}] ", processDefinitionKey_);//输出:启动流程,流程key [approvalFor2Level]return processInstance;}/*** 部署流程定义文件** @param processEngine* @return*/private static ProcessDefinition getProcessDefinition(ProcessEngine processEngine) {RepositoryService repositoryService = processEngine.getRepositoryService();//获取存储服务DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();//创建部署构建器//通过类路径下的 .bpmn 文件进行构建。.bpmn 文件的本质其实就是一个定义好的 .xml 文件deploymentBuilder.addClasspathResource("approvalFor2Level.bpmn");//部署流程定义文件。此时 Activiti 会自动将 .bpmn 中的数据添加到数据库中,以备后续数据库操作Deployment deployment = deploymentBuilder.deploy();String deploymentId = deployment.getId();String deploymentKey = deployment.getKey();String deploymentName = deployment.getName();Date deploymentTime = deployment.getDeploymentTime();//输出:部署id [1],部署key [null],部署名称 [null],部署时间 [Wed Jul 24 09:40:00 CST 2019]LOGGER.info("部署id [{}],部署key [{}],部署名称 [{}],部署时间 [{}]", deploymentId, deploymentKey, deploymentName, deploymentTime);ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();String processDefinitionName = processDefinition.getName();String processDefinitionId = processDefinition.getId();String processDefinitionKey = processDefinition.getKey();//输出:流程定义文件名 [二级审批流程],流程id [approvalFor2Level:1:4],流程key [approvalFor2Level]LOGGER.info("流程定义文件名 [{}],流程id [{}],流程key [{}]", processDefinitionName, processDefinitionId, processDefinitionKey);return processDefinition;}/*** 创建流程引擎** @return*/private static ProcessEngine getProcessEngine() {//StandaloneInMemProcessEngineConfiguration:标准的基于内存数据库的流程引擎配置.ProcessEngineConfiguration pecfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();//buildProcessEngine:通过流程引擎配置构建流程引擎,此时会自动创建 activiti 的 28 张表ProcessEngine processEngine = pecfg.buildProcessEngine();String name = processEngine.getName();String version = ProcessEngine.VERSION;LOGGER.info("流程引擎名称 [{}],版本 [{}]", name, version);//输出:流程引擎名称 [default],版本 [6.0.0.4]return processEngine;}
}

5、整个项目源码:https://github.com/wangmaoxiong/activitiFirst,核心就是 pom.xml 文件、MainApp.java、approvalFor2Level.bpmn 流程文件、log4j.properties 日志文件。

1)上面的 hello World 要想成功运行,之前绘制好的 .bpmn 文件是必不可少的,因为内容较长,所以不再这里粘贴,从这里获取:https://github.com/wangmaoxiong/activitiFirst/tree/master/src/main/resources

2)其中可以修改 log4j.properties 的日志输出级别为 DEBUG log4j.rootLogger=DEBUG ,console,logFile,就会发现应用启动到结束,它在不停的操作数据库,做 sql 操作。

6、因为使用的是 StandaloneInMemProcessEngineConfiguration 流程引擎配置,它的源码如下,显然它默认使用的是 h2 内存数据库,create-drop 表示应用启动时自动建表,应用关闭时自动删除,数据不会持久化到磁盘。

public class StandaloneInMemProcessEngineConfiguration extends StandaloneProcessEngineConfiguration {public StandaloneInMemProcessEngineConfiguration() {this.databaseSchemaUpdate = "create-drop";this.jdbcUrl = "jdbc:h2:mem:activiti";}
}

7、启动应用,测试如下:

上面只是测试了正常情况下,全部通过的情景,也可以放弃提交,主管或者人事输入 n 拒绝通过等否则情况都是没问题的

Activiti 核心 API 预览

1、ProcessEngine:流程引擎,这是最重要的 API,通过它可以获取其它的 API。

2、RepositoryService:流程存储服务,管理流程定义文件 xm 及静态资源的服务,对特定流程的暂停和激活,流程定义启动权限管理。

3、RuntimeService:流程运行服务,用于对流程运行过程的控制,如启动流程实例、暂停、挂起、继续等

4、TaskService:流程任务服务,用于对人工任务的管理(如增删改查),设置操作权限。

5、HistoryService:历史记录相关服务接口。

6、FormService:表单服务。

7、IdentityService:身份服务,提供对流程角色数据进行管理的 API,这些角色数据包括用户组、用户及它们之间的关系。

8、ManagementService:提供对流程引擎进行管理和维护的服务。

Activiti 6.0 概述与 Hello World 快速入门 与 核心 API 概述相关推荐

  1. Lua快速入门篇(基础概述)(Yanlz+toLua+xLua)

    <Lua热更新> ##<Lua热更新>发布说明: ++++"Lua热更新"开始了,立钻哥哥终于开始此部分的探索了. ++++作为游戏发布迭代的重要技术:Lu ...

  2. SSM_Mybatis_Day01(快速入门、映射文件概述、核心配置文件概述、相应API、代理开发方式、映射文件深入、数据类型的映射、列名和属性名不一致的时候的处理)

    SSM_Mybatis_Day01(快速入门.映射文件概述.核心配置文件概述.相应API.代理开发方式.映射文件深入.数据类型的映射.列名和属性名不一致的时候的处理) 1. Mybatis mybat ...

  3. mybatis select count(*) 一直返回0 mysql_Mybatis教程1:MyBatis快速入门

    点击上方"Java技术前线",选择"置顶或者星标" 与你一起成长 一.Mybatis介绍 MyBatis是一个支持普通*SQL*查询,存储过程和高级映射的优秀持 ...

  4. 【vue2.0进阶】vue-router10分钟快速入门

    又一周过去了,时间过得很快,更新不能落下,继续我们的vue2.0进阶教程.今天前端君来跟大家一起快速入门vue-router. 学一个新东西之前,我们一定先要学会问:它有什么作用,为什么要学它? 对于 ...

  5. java day53【 Mybatis框架概述 、 Mybatis 框架快速入门、自定义 Mybatis 框架 】

    第1章 框架概述 1.1 什么是框架 1.1.1 什么是框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种 定义认为,框架是可被应用开发者定 ...

  6. 【VMware vSAN 7.0】6.6 使用快速入门功能配置延伸集群或双节点集群—我们有软硬件解决方案

    目录 1. vSAN简介 1.1 vSAN 概念 1.1.1 vSAN 的特性 1.2 vSAN术语和定义 1.3 vSAN 和传统存储 1.4 构建 vSAN 群集 1.5 vSAN 部署选项 1. ...

  7. JDBC第一回——JDBC简介、JDBC原理图、JDBC快速入门、JDBC API(DriverManager、Connection、Statement)详解

    文章目录 JDBC JDBC简介 JDBC原理图 JDBC快速入门 JDBC API详解 DriverManager Connection Statement JDBC JDBC简介 JDBC概念 J ...

  8. Apache Superset 1.2.0教程 (二)——快速入门(可视化王者英雄数据)

    上一篇我们已经成功的安装了superset,那么该如何可视化我们的数据呢?本文将可视化王者英雄的数据,快速的入门Superset. 一.连接数据源 亦寒小说网 https://www.duxi.inf ...

  9. 第 1 章 MybatisPlus 快速入门

    第 1 章 MybatisPlus 快速入门 1.MybatisPlus 概述 MybatisPlus:一款 Mybatis 的增强工具包 MybatisPlus 官网:https://mybatis ...

  10. JSON数据结构(A、快速入门篇)(Yanlz+Data+JsonArray+JsonObject+JsonValue+JsonMapper.ToJson+JsonMapper.ToObject+)

    <JSON数据结构> 版本 作者 参与者 完成日期 备注 Data_JSON_V01_1.0 严立钻 2018.08.24 ++++一个好用的JSON在线编辑:http://www.kjs ...

最新文章

  1. 警惕,MyBatis的size()方法竟然有坑!
  2. mysql备份slave_MySQL主(Master)从(Slave)备份;
  3. 从源码分析DEARGUI之add_slider_float-4和add_slider_int-4
  4. QString和string互相转换乱码处理
  5. xmlspy php,XMLSpy使用流程 - tnlzz31985的个人空间 - OSCHINA - 中文开源技术交流社区
  6. 2007标注没有文字_Hi,siri,你的商标注册了吗
  7. 对象可以在栈上分配空间吗?_Java面试题之:Java中所有的对象都分配在堆中吗?...
  8. Python可视化 | Seaborn(01)
  9. 相机标定(三)—— 正交投影和透视投影变换
  10. 【Linux 操作系统】vim编辑器配置及常用命令
  11. 下列不是python内置函数的是_Python 内置函数
  12. html涂鸦画板插件,sketchpad-简单的HTML5 Canvas涂鸦画板插件 -HTML5功能
  13. STM32L476+STM32cubeMx+Freemodbus移植记录
  14. 快速解决win7系统Aero主题无法使用
  15. STM32F103_study64_The punctual atoms(Simulator and downloader)
  16. 转:无视苹果 Adobe欲将Flash推广到iPhone
  17. php移除excel密码,excel2007密码怎么取消
  18. [计算机数值分析]埃特金算法加速迭代法求根过程
  19. 算法设计-递归法解最长公共子序列问题 C代码
  20. TypeScript中的泛型

热门文章

  1. jquery mysql jsp搜索功能_jquery实现的一个提前搜索功能
  2. mysql 没有三级模式两级映像_数据库三级模式/两级映像
  3. 【大数据部落】R语言实现:混合正态分布EM最大期望估计法
  4. nginx基础配置,转发所有
  5. SLIC算法分割超像素原理及Python、C++
  6. yolobile 道路损坏检测实战
  7. Python 手写数字识别实战分享
  8. 2021-06-29操作DOM元素
  9. linux上设置jar包加载顺序,SpringBoot配置加载顺序
  10. python图层合并_Python 2种方法实现叠加矩形框图层