Активити это так просто

задняя часть база данных открытый источник Java EE

Введение в Активити

Что такое Активити?

Активити5 этоОпубликовано Alfresco Software 17 мая 2010 г.Структура управления бизнес-процессами (BPM), которая представляет собой гибкую и легко расширяемую среду исполняемого языка процессов с открытым исходным кодом, охватывающую управление бизнес-процессами, рабочие процессы, совместную работу служб и другие области. Activiti — это платформа BPM с открытым исходным кодом, основанная на лицензии Apache. Основатель Том Байенс является архитектором проекта JBoss jBPM. Он включает подключаемый модуль eclipse, и разработчики могут напрямую управлять бизнесом через подключаемый модуль. блок-схема. .

То, что мы собираемся узнать, являетсяСтруктура управления бизнес-процессами, Общие платформы механизма рабочих процессов с открытым исходным кодом: OSWorkFlow, jBPM (управление бизнес-процессами jboss),Рабочий процесс Activiti (это обновление до jBPM). Обычно мы называем это структурой рабочего процесса.

Зачем изучать Активити

Итак, почему мы должны изучать структуру управления бизнес-процессами? ? ? Изучить его для чего? ?? Рабочий процесс - это «автоматизация части или всего бизнес-процесса в среде компьютерных приложений».

Давайте придумаем общее требование, чтобы лучше понять:

В наши студенческие годы мы обязательно столкнемся с ситуацией, когда мы отпрашиваемся и пишем отпускную записку.Если школьная просьба об отпуске очень строгая, нам нужно пройти несколько уровней согласия, чтобы определить, можем ли мы просить об отпуске.

这里写图片描述

Процесс классный руководитель->учитель->завуч->директор, прежде всего, давайте проясним:Будучи студентом, мы не можем пропустить учителя и пойти к директору, чтобы подать заявление на отпуск.[Вы случайно нашли директора? ? 】

поэтому мыПроцесс подачи заявления на отпуск поэтапный и не может быть перепрыгнут

Это,Когда классный руководитель не одобряет отпуск, даже если вы пойдете к классному руководителю, классный руководитель попросит вас вернуться к классному руководителю.Как классный руководитель, вы обращаете внимание только на то, утвердил ли классный руководитель ваш Уходи Аналогично, как директор, только обращай внимание на директора по обучению Ты утвердил свой отпуск?!

Идти дальше:Ваш запрос на отпуск не будет отображаться в компетенции директора, если суперинтендант не утвердил ваш отпуск.

Это на самом деле очень понятно.Это выполнять шаг за шагом.Когда идея обработки не будет реализована, не будет соответствующего запроса на обработку. Упорядоченное разделение труда

Анализ приведенного выше процесса ухода**, если бы мы не использовали фреймворк, а написали такой процесс ухода на свой сайт, что бы мы сделали**? ?

这里写图片描述

нам нужноСохраняйте переменную, чтобы продолжать переход к следующему обработчику...если все идет хорошо, спрос не меняется и условной обработки нет. Это то, что мы бы очень хотели увидеть... но,Если есть условное решение [обработка просьб об отпуске менее трех дней и просьб об отпуске более трех дней отличается], требование будет изменено [вам не требуется одобрение директора, после утверждения директор по обучению, вы можете отпроситься], тогда наш код изменится.

По этой причине нам нужно изучить структуру, которая поможет нам завершить рабочий процесс...

с системой управления рабочим процессомпреимущество

  • 1. Повысить гибкость системы и адаптироваться к изменениям бизнес-процессов
  • 2. Реализуйте лучший контроль бизнес-процессов и улучшите качество обслуживания клиентов.
  • 3. Сокращение затрат на разработку и обслуживание системы

1. Быстрый старт

Для начала разберем этапы разработки Activiti:

  1. Мы хотим использовать рабочий процесс, сначала определите этот рабочий процесс [что такое этапы рабочего процесса], Activiti поддерживает способ «карты» для определения рабочего процесса.
  2. После определения рабочего процесса необходимо его развернуть [Мы можем подумать о Tomcat, скачивать Tomcat бесполезно, мы должны его развернуть]
  3. Затем мы выполняем рабочий процесс, который следует шагам, которые мы определили!

1.1BPMN

Модель и нотация бизнес-процесса (BPMN), базовая нотация для описания процесса, включая то, как эти элементы объединяются в диаграмму бизнес-процесса (диаграмма бизнес-процесса).

BPMN — это то, что мы называемБлок-схема, определяющая рабочий процесс..

1.2 Связанные с базой данных

мы вПри выполнении шагов рабочего процесса задействовано много данных.[Кто тот человек, который выполняет процесс, какие параметры требуются, в том числе записи, которые хотят просмотреть предыдущее выполнение процесса и т. д.], поэтому нам нужно будет использовать таблицу базы данных для сохранения данных...

Поскольку мы используем фреймворк Activiti, этот фреймворк будетАвтоматически поможет нам создать соответствующую таблицу базы данных, там 23 таблицы, но часто используемых не так много, так что не паникуйте...

Ниже приведен список таблицы


Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

1.3 Создайте среду конфигурации

Здесь я использую идею Intellij для использования Activiti. Во-первых, нам нужно загрузить подключаемый модуль, чтобы использовать Activiti [потому что для определения блок-схем необходимы подключаемые модули].

Подробнее см. в этом сообщении в блоге:blog.sna.com.ca/is/blog_4 не 31…

Проблема китайского искажения плагина Activiti:

woo woo woo.cn blog on.com/my Melody/afraid/…

Соединение перед процессом подключается путем перетаскивания синих точек на рисунке...

Импортируйте соответствующий пакет jar

  • activation-1.1.jar
  • activiti-bpmn-converter-5.13.jar
  • activiti-bpmn-layout-5.13.jar
  • activiti-bpmn-model-5.13.jar
  • activiti-common-rest-5.13.jar
  • activiti-engine-5.13.jar
  • activiti-json-converter-5.13.jar
  • activiti-rest-5.13.jar
  • activiti-simple-workflow-5.13.jar
  • activiti-spring-5.13.jar
  • aopalliance-1.0.jar
  • commons-dbcp-1.4.jar
  • commons-email-1.2.jar
  • commons-fileupload-1.2.2.jar
  • commons-io-2.0.1.jar
  • commons-lang-2.4.jar
  • commons-pool-1.5.4.jar
  • h2-1.3.170.jar
  • hamcrest-core-1.3.jar
  • jackson-core-asl-1.9.9.jar
  • jackson-mapper-asl-1.9.9.jar
  • javaGeom-0.11.0.jar
  • jcl-over-slf4j-1.7.2.jar
  • jgraphx-1.10.4.2.jar
  • joda-time-2.1.jar
  • junit-4.11.jar
  • log4j-1.2.17.jar
  • mail-1.4.1.jar
  • mybatis-3.2.2.jar
  • mysql-connector-java.jar
  • org.restlet.ext.fileupload-2.0.15.jar
  • org.restlet.ext.jackson-2.0.15.jar
  • org.restlet.ext.servlet-2.0.15.jar
  • org.restlet-2.0.15.jar
  • slf4j-api-1.7.2.jar
  • slf4j-log4j12-1.7.2.jar
  • spring-aop-3.1.2.RELEASE.jar
  • spring-asm-3.1.2.RELEASE.jar
  • spring-beans-3.1.2.RELEASE.jar
  • spring-context-3.1.2.RELEASE.jar
  • spring-core-3.1.2.RELEASE.jar
  • spring-expression-3.1.2.RELEASE.jar
  • spring-jdbc-3.1.2.RELEASE.jar
  • spring-orm-3.1.2.RELEASE.jar
  • spring-tx-3.1.2.RELEASE.jar

1.4 Этапы разработки

Как упоминалось выше, если мы хотим использовать Activiti, нам нужна поддержка базы данных.Хотя Activiti автоматически создает для нас соответствующую таблицу базы данных, нам необходимо настроить информацию базы данных. Мы настраиваем информацию базы данных, а затем получаем самый важный API Activiti — движок Activiti.

这里写图片描述

1.4.1 Получите механизм рабочего процесса

Предоставлено АктивитиИспользуйте код для настройки информации базы данных:



    @Test
    public void createActivitiEngine(){

/*        *1.通过代码形式创建
         *  - 取得ProcessEngineConfiguration对象
         *  - 设置数据库连接属性
         *  - 设置创建表的策略 (当没有表时,自动创建表)
         *  - 通过ProcessEngineConfiguration对象创建 ProcessEngine 对象*/

         //取得ProcessEngineConfiguration对象
         ProcessEngineConfiguration engineConfiguration=ProcessEngineConfiguration.
         createStandaloneProcessEngineConfiguration();
         //设置数据库连接属性
         engineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
         engineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activitiDB?createDatabaseIfNotExist=true"
         + "&useUnicode=true&characterEncoding=utf8");
         engineConfiguration.setJdbcUsername("root");
         engineConfiguration.setJdbcPassword("root");


         // 设置创建表的策略 (当没有表时,自动创建表)
         //		  public static final java.lang.String DB_SCHEMA_UPDATE_FALSE = "false";//不会自动创建表,没有表,则抛异常
         //		  public static final java.lang.String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";//先删除,再创建表
         //		  public static final java.lang.String DB_SCHEMA_UPDATE_TRUE = "true";//假如没有表,则自动创建
         engineConfiguration.setDatabaseSchemaUpdate("true");
         //通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
        ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
         System.out.println("流程引擎创建成功!");
        
    }

Activiti также может настроить информацию базы данных через файл конфигурации, загрузить файл конфигурации, чтобы получить механизм рабочего процесса.


		/**2. 通过加载 activiti.cfg.xml 获取 流程引擎 和自动创建数据库及表
		 * 
		 
		ProcessEngineConfiguration engineConfiguration=
				ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
		    //从类加载路径中查找资源  activiti.cfg.xm文件名可以自定义
		ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
		System.out.println("使用配置文件Activiti.cfg.xml获取流程引擎");
		*/

activiti.cfg.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 <!-- 配置 ProcessEngineConfiguration  -->
 <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
   <!-- 配置数据库连接 -->
 <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activitiDB?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
 <property name="jdbcUsername" value="root"></property>
 <property name="jdbcPassword" value="root"></property>
 
  <!-- 配置创建表策略 :没有表时,自动创建 -->
  <property name="databaseSchemaUpdate" value="true"></property>
 
 </bean>

</beans>

这里写图片描述

В приведенном выше методе загрузки файлов конфигурации имя файла конфигурации можно настроить.Если имя нашего файла конфигурации по умолчанию равноactiviti.cfg.xmlЕсли он помещен в путь к классам, мы можем использовать метод по умолчанию для его загрузки!



    @Test
    public void createActivitiEngine(){
        /**
         * 3. 通过ProcessEngines 来获取默认的流程引擎
         */
        //  默认会加载类路径下的 activiti.cfg.xml
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println("通过ProcessEngines 来获取流程引擎");
    }

1.4.2 Определение рабочего процесса

Для определения рабочего процесса требуется подключаемый модуль, который мы только что загрузили.Мы определяем рабочий процесс графическим способом....

这里写图片描述

В каждом процессе мы можем указать, кто является соответствующим процессором и кто должен его обрабатывать.

1.4.3 Рабочий процесс развертывания

Мы определили выше рабочий процесс, механизм рабочего процесса, и у нас есть следующий шаг — развернуть рабочий процесс в механизме рабочего процесса.

    @Test
    public void deploy() {

        //获取仓库服务 :管理流程定义
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
                .addClasspathResource("LeaveActiviti.bpmn")//从类路径中添加资源,一次只能添加一个资源
                .name("请求单流程")//设置部署的名称
                .category("办公类别")//设置部署的类别
                .deploy();

        System.out.println("部署的id"+deploy.getId());
        System.out.println("部署的名称"+deploy.getName());
    }

Соответствующая таблица базы данных будет вставлять данные, а задействованная таблица базы данных будет подробно объяснена позже. Теперь нам просто нужно понять,Будут записи таблицы базы данных для нашего механизма рабочего процесса для выполнения операций.

这里写图片描述


1.4.4 Рабочий процесс выполнения

Указание указанного рабочего процесса — это когда мы определяемИдентификатор таблицы рабочего процесса

这里写图片描述



    @Test
    public void startProcess(){

        //指定执行我们刚才部署的工作流程
        String processDefiKey="leaveBill";
        //取运行时服务
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //取得流程实例
        ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefiKey);//通过流程定义的key 来执行流程
        System.out.println("流程实例id:"+pi.getId());//流程实例id
        System.out.println("流程定义id:"+pi.getProcessDefinitionId());//输出流程定义的id
    }

1.4.5 Запрос информации о текущей задаче в соответствии с агентом

Мы только что запустили рабочий процесс, а затем рабочий процесс должен перейти к процессу подачи заявления на отпуск.Обработчиком подачи заявления на отпуск является Чжун Фучэн, и мы можем запросить соответствующую информацию:

    //查询任务
    @Test
    public void queryTask(){
        //任务的办理人
        String assignee="钟福成";
        //取得任务服务
        TaskService taskService = processEngine.getTaskService();
        //创建一个任务查询对象
        TaskQuery taskQuery = taskService.createTaskQuery();
        //办理人的任务列表
        List<Task> list = taskQuery.taskAssignee(assignee)//指定办理人
                .list();
        //遍历任务列表
        if(list!=null&&list.size()>0){
            for(Task task:list){
                System.out.println("任务的办理人:"+task.getAssignee());
                System.out.println("任务的id:"+task.getId());
                System.out.println("任务的名称:"+task.getName());
            }
        }
    }

这里写图片描述

1.4.6 Обработка задач

Наш поток обработки теперь переходит к «Подача заявления на отпуск», а обработчиком является Чжун Фучэн...Далее идет Чжун Фучэн для обработки задачи, и процесс продолжает опускаться в соответствии с идентификатором задачи.

Идентификатор задачи был запрошен только что [выше].Если мы работаем с данными на веб-стороне, нам просто нужно передать его!



    //完成任务
    @Test
    public void compileTask(){
        String taskId="304";
        //taskId:任务id
        processEngine.getTaskService().complete(taskId);
        System.out.println("当前任务执行完毕");
    }

这里写图片描述

Когда мы закончим задание, пришло время утвердить задание [Учителя класса], давайте проверим, такой ли эффект, как мы себе представляли:

这里写图片描述

Мы спускаемся шаг за шагом в соответствии с установленной технологической схемой и, наконец, завершаем процесс.

这里写图片描述


Во-вторых, определение процесса в деталях

Определение процесса управления в основном включает следующие четыре таблицы:

-- 流程部署相关的表
SELECT * FROM act_ge_bytearray # 通用字节资源表

SELECT * FROM act_ge_property # 通用属性表,可以生成部署id

SELECT * FROM act_re_deployment  #部署表

SELECT * FROM act_re_procdef    # 流程定义表

2.1 PNG-ресурсы

В Eclipse плагин Activiti автоматически создаст изображение PNG, соответствующее BPMN, которое необходимо загрузить, загрузив изображение PNG.


    @Test
    public void deploy() {

        //获取仓库服务 :管理流程定义
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
                .addClasspathResource("LeaveActiviti.bpmn")//从类路径中添加资源,一次只能添加一个资源
                .name("请求单流程")//设置部署的名称
                .category("办公类别")//设置部署的类别
                .deploy();

        System.out.println("部署的id"+deploy.getId());
        System.out.println("部署的名称"+deploy.getName());
    }

Наш плагин Intellij idea не генерирует изображения PNG автоматически, но когда мы загружаем файл BPMN, кажется, что он автоматически вставляет изображения PNG, и в базе данных есть соответствующие записи [Мы не загружали ресурсы изображений PNG вручную]

这里写图片描述

давай проверим


    //查看bpmn 资源图片
    @Test
    public void viewImage() throws Exception{
        String deploymentId="201";
        String imageName=null;
        //取得某个部署的资源的名称  deploymentId
        List<String> resourceNames = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
        // buybill.bpmn  buybill.png
        if(resourceNames!=null&&resourceNames.size()>0){
            for(String temp :resourceNames){
                if(temp.indexOf(".png")>0){
                    imageName=temp;
                }
            }
        }

        /**
         * 读取资源
         * deploymentId:部署的id
         * resourceName:资源的文件名
         */
        InputStream resourceAsStream = processEngine.getRepositoryService()
                .getResourceAsStream(deploymentId, imageName);

        //把文件输入流写入到文件中
        File file=new File("d:/"+imageName);
        FileUtils.copyInputStreamToFile(resourceAsStream, file);
    }

К несчастью,Китайские данные просмотренных картинок будут искажены...

这里写图片描述

2.2 Просмотр определения процесса

В то время мы проверили определение процесса запроса, установив идентификатор блок-схемы... На самом деле, мы можем запрашивать другие атрибуты... и можем запрашивать более подробные данные.


	//查看流程定义
	@Test
	public void queryProcessDefination(){
		String processDefiKey="buyBill";//流程定义key
		//获取流程定义列表
		List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
		//查询 ,好比where
//		.processDefinitionId(proDefiId) //流程定义id
		 // 流程定义id  : buyBill:2:704   组成 : proDefikey(流程定义key)+version(版本)+自动生成id
		.processDefinitionKey(processDefiKey)//流程定义key 由bpmn 的 process 的  id属性决定
//		.processDefinitionName(name)//流程定义名称  由bpmn 的 process 的  name属性决定
//		.processDefinitionVersion(version)//流程定义的版本
		.latestVersion()//最新版本
		
		//排序
		.orderByProcessDefinitionVersion().desc()//按版本的降序排序
		
		//结果
//		.count()//统计结果
//		.listPage(arg0, arg1)//分页查询
		.list();
		
		
		//遍历结果
		if(list!=null&&list.size()>0){
			for(ProcessDefinition temp:list){
				System.out.print("流程定义的id: "+temp.getId());
				System.out.print("流程定义的key: "+temp.getKey());
				System.out.print("流程定义的版本: "+temp.getVersion());
				System.out.print("流程定义部署的id: "+temp.getDeploymentId());
				System.out.println("流程定义的名称: "+temp.getName());
			}
		}
	}

2.3 Ресурсы из ZIP

Что мы также можем загрузить, так это данные ресурсов типа ZIP.


	//部署流程定义,资源来自zip格式
	@Test
	public void deployProcessDefiByZip(){
		InputStream in=getClass().getClassLoader().getResourceAsStream("BuyBill.zip");
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment()
				.name("采购流程")
				.addZipInputStream(new ZipInputStream(in))
				.deploy();
		
		System.out.println("部署名称:"+deploy.getName());
		System.out.println("部署id:"+deploy.getId());
	}

2.4 Удалить определение процесса

	//删除流程定义
	@Test
	public void deleteProcessDefi(){
		//通过部署id来删除流程定义
		String deploymentId="101";
		processEngine.getRepositoryService().deleteDeployment(deploymentId);
	}

При повторном запросе нет данных, определенных процессом 101.

这里写图片描述


В-третьих, примеры процессов и детали выполнения задач.

Общие таблицы для экземпляров процессов и выполнения задач следующие:


-- 流程实例与任务

SELECT * FROM act_ru_execution  # 流程执行对象信息
SELECT * FROM act_ru_task   # 正在运行的任务表

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


Вот краткое описание разницы между экземпляром процесса и объектом процесса:

  • (1)Если это одноэлементный процесс, идентификатор исполняемого объекта является идентификатором экземпляра процесса.
  • (2)Если у процесса есть ветви и агрегаты, идентификатор исполняемого объекта и идентификатор экземпляра процесса не совпадают.
  • (3)В процессе существует только один экземпляр процесса, а исполняемых объектов может быть несколько.

3.1 Запустите процесс##


    @Test
    public void startProcess(){
        String processDefiKey="leaveActiviti";//bpmn 的 process id属性
        ProcessInstance pi = processEngine.getRuntimeService()
                .startProcessInstanceByKey(processDefiKey);

        System.out.println("流程执行对象的id:"+pi.getId());//Execution 对象
        System.out.println("流程实例的id:"+pi.getProcessInstanceId());//ProcessInstance 对象
        System.out.println("流程定义的id:"+pi.getProcessDefinitionId());//默认执行的是最新版本的流程定义
    }

3.2 Просмотр запущенных задач


//查询正在运行任务 
	@Test
	public void queryTask(){
		//取得任务服务
		TaskService taskService = processEngine.getTaskService();
		//创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		//办理人的任务列表
		List<Task> list = taskQuery.list();
		//遍历任务列表
		if(list!=null&&list.size()>0){
			for(Task task:list){
				System.out.println("任务的办理人:"+task.getAssignee());
				System.out.println("任务的id:"+task.getId());
				System.out.println("任务的名称:"+task.getName());
				
			}
		}
		
	}

Запрос SELECT * FROM таблицы act_ru_task

这里写图片描述

这里写图片描述


3.3 Получить статус экземпляра процесса

Иногда нам нужно определить, находится ли он в процессе или процесс завершился. Мы можем судить, является ли полученный объект пустым или нет


    //获取流程实例的状态
    @Test
    public void getProcessInstanceState(){
        String processInstanceId="605";
        ProcessInstance pi = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();//返回的数据要么是单行,要么是空 ,其他情况报错
        //判断流程实例的状态
        if(pi!=null){
            System.out.println("该流程实例"+processInstanceId+"正在运行...  "+"当前活动的任务:"+pi.getActivityId());
        }else{
            System.out.println("当前的流程实例"+processInstanceId+" 已经结束!");
        }

    }

这里写图片描述


3.4 Просмотр информации об исторических экземплярах процесса


	//查看历史执行流程实例信息
	@Test
	public void queryHistoryProcInst(){
		List<HistoricProcessInstance> list = processEngine.getHistoryService()
		.createHistoricProcessInstanceQuery()
		.list();
		if(list!=null&&list.size()>0){
			for(HistoricProcessInstance temp:list){
				System.out.println("历史流程实例id:"+temp.getId());
				System.out.println("历史流程定义的id:"+temp.getProcessDefinitionId());
				System.out.println("历史流程实例开始时间--结束时间:"+temp.getStartTime()+"-->"+temp.getEndTime());
			}
		}
	}

Форма запроса:

这里写图片描述

这里写图片描述

3.5 Просмотр исторической информации о задаче выполнения экземпляра


    @Test
    public void queryHistoryTask(){
        String processInstanceId="605";
        List<HistoricTaskInstance> list = processEngine.getHistoryService()
                .createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        if(list!=null&&list.size()>0){
            for(HistoricTaskInstance temp:list){
                System.out.print("历史流程实例任务id:"+temp.getId());
                System.out.print("历史流程定义的id:"+temp.getProcessDefinitionId());
                System.out.print("历史流程实例任务名称:"+temp.getName());
                System.out.println("历史流程实例任务处理人:"+temp.getAssignee());
            }
        }
    }

Вы можете запросить, какая задача выполняется, указав соответствующий идентификатор экземпляра...

这里写图片描述

这里写图片描述

3.6 Выполнение задач

По id задачи можно выполнить задачу.

    @Test
    public void compileTask(){
        String taskId="608";
        //taskId:任务id
        processEngine.getTaskService().complete(taskId);
        System.out.println("当前任务执行完毕");
    }

В-четвертых, переменные процесса в деталях

Таблицы базы данных, задействованные в переменных процесса:


act_ru_variable:正在执行的流程变量表
act_hi_varinst:流程变量历史表


Переменные процесса играют очень важную роль в рабочем процессе. Например: в процессе отпуска некоторые параметры, такие как количество дней, чтобы попросить отпуск и причина запроса на отпуск, все находятся в области переменных процесса**. Область действия переменной процесса соответствует только одному экземпляру процесса**. Другими словами, переменные процесса каждого экземпляра процесса не влияют друг на друга. После завершения экземпляра процесса переменные процесса также сохраняются в базе данных (хранятся в таблице истории переменных процесса).

这里写图片描述

4.1 Установка переменных процесса

У нас есть две службы, которые могут устанавливать переменные процесса: TaskService [служба задач] и RuntimeService [служба времени выполнения].

Сцены

  • Установите переменную процесса в начале процесса
  • Установите переменные процесса, когда задача завершена
  • Настройка службы с помощью TaskService
  • Настройка сервисов с помощью RuntimeService

эффект:

  • Передать бизнес-параметры
  • Динамически указать агента [пример нашего быстрого старта зафиксирован на схеме определения процесса и написан агент]
  • Укажите соединение [решите, в каком направлении пойдет процесс]

4.2 Типы поддержки переменных процесса

Если мы используем JavaBean как переменную процесса, то нам нужно реализовать интерфейс Serializable для JavaBean.

Настройка типа Javabean для получения переменных процесса, в дополнение к требованию, чтобы javabean реализовывал интерфейс Serializable, также требует, чтобы свойства объекта переменной процесса не могли быть изменены, иначе будет выдано исключение. Решение, фиксированный идентификатор сериализации

这里写图片描述

4.3 Разница между setVariable и setVariableLocal

这里写图片描述

4.4 Примеры


//模拟流程变量设置
	@Test
	public void  getAndSetProcessVariable(){
		//有两种服务可以设置流程变量
//		TaskService taskService = processEngine.getTaskService();
//		RuntimeService runtimeService = processEngine.getRuntimeService();
		
		/**1.通过 runtimeService 来设置流程变量
		 * executionId: 执行对象
		 * variableName:变量名
		 * values:变量值
		 */
//		runtimeService.setVariable(executionId, variableName, values);
//		runtimeService.setVariableLocal(executionId, variableName, values);
		//设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
//		runtimeService.setVariables(executionId, variables); 
		  //可以设置多个变量  放在 Map<key,value>  Map<String,Object>
		
		/**2. 通过TaskService来设置流程变量
		 * taskId:任务id
		 */
//		taskService.setVariable(taskId, variableName, values);
//		taskService.setVariableLocal(taskId, variableName, values);
////		设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
//		taskService.setVariables(taskId, variables); //设置的是Map<key,values>
		
		/**3. 当流程开始执行的时候,设置变量参数
		 * processDefiKey: 流程定义的key
		 * variables: 设置多个变量  Map<key,values>
		 */
//		processEngine.getRuntimeService()
//		.startProcessInstanceByKey(processDefiKey, variables)
		
		/**4. 当任务完成时候,可以设置流程变量
		 * taskId:任务id
		 * variables: 设置多个变量  Map<key,values>
		 */
//		processEngine.getTaskService().complete(taskId, variables);
		
		
		/** 5. 通过RuntimeService取变量值
		 * exxcutionId: 执行对象
		 * 
		 */
//		runtimeService.getVariable(executionId, variableName);//取变量
//		runtimeService.getVariableLocal(executionId, variableName);//取本执行对象的某个变量
//		runtimeService.getVariables(variablesName);//取当前执行对象的所有变量
		/** 6. 通过TaskService取变量值
		 * TaskId: 执行对象
		 * 
		 */
//		taskService.getVariable(taskId, variableName);//取变量
//		taskService.getVariableLocal(taskId, variableName);//取本执行对象的某个变量
//		taskService.getVariables(taskId);//取当前执行对象的所有变量
	}

	//设置流程变量值
	@Test
	public void setVariable(){
		String taskId="1804";//任务id
		//采用TaskService来设置流程变量
		
		//1. 第一次设置流程变量
//		TaskService taskService = processEngine.getTaskService();
//		taskService.setVariable(taskId, "cost", 1000);//设置单一的变量,作用域在整个流程实例
//		taskService.setVariable(taskId, "申请时间", new Date());
//		taskService.setVariableLocal(taskId, "申请人", "何某某");//该变量只有在本任务中是有效的
		
		
		//2. 在不同的任务中设置变量
//		TaskService taskService = processEngine.getTaskService();
//		taskService.setVariable(taskId, "cost", 5000);//设置单一的变量,作用域在整个流程实例
//		taskService.setVariable(taskId, "申请时间", new Date());
//		taskService.setVariableLocal(taskId, "申请人", "李某某");//该变量只有在本任务中是有效的
		
		/**
		 * 3. 变量支持的类型
		 * - 简单的类型 :String 、boolean、Integer、double、date 
		 * - 自定义对象bean  
		 */
		TaskService taskService = processEngine.getTaskService();
		//传递的一个自定义bean对象
		AppayBillBean appayBillBean=new AppayBillBean();
		appayBillBean.setId(1);
		appayBillBean.setCost(300);
		appayBillBean.setDate(new Date());
		appayBillBean.setAppayPerson("何某某");
		taskService.setVariable(taskId, "appayBillBean", appayBillBean);
		
		
		System.out.println("设置成功!");

	}

	
	//查询流程变量
	@Test
	public void getVariable(){
		String taskId="1804";//任务id
//		TaskService taskService = processEngine.getTaskService();
//		Integer cost=(Integer) taskService.getVariable(taskId, "cost");//取变量
//		Date date=(Date) taskService.getVariable(taskId, "申请时间");//取本任务中的变量
////		Date date=(Date) taskService.getVariableLocal(taskId, "申请时间");//取本任务中的变量
//		String appayPerson=(String) taskService.getVariableLocal(taskId, "申请人");//取本任务中的变量
////		String appayPerson=(String) taskService.getVariable(taskId, "申请人");//取本任务中的变量
//		
//		System.out.println("金额:"+cost);
//		System.out.println("申请时间:"+date);
//		System.out.println("申请人:"+appayPerson);
		
		
		//读取实现序列化的对象变量数据
		TaskService taskService = processEngine.getTaskService();
		AppayBillBean appayBillBean=(AppayBillBean) taskService.getVariable(taskId, "appayBillBean");
		System.out.println(appayBillBean.getCost());
		System.out.println(appayBillBean.getAppayPerson());
		
	}


public class AppayBillBean  implements Serializable{
	private Integer id;
	private Integer cost;//金额
	private String appayPerson;//申请人
	private Date date;//申请日期
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Integer getCost() {
		return cost;
	}
	public void setCost(Integer cost) {
		this.cost = cost;
	}
	public String getAppayPerson() {
		return appayPerson;
	}
	public void setAppayPerson(String appayPerson) {
		this.appayPerson = appayPerson;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
	

}

5. Подключение

Мы уже узнали о переменных процесса выше, мы можем установить переменные процесса в [служба задач, служба времени выполнения, запуск процесса, завершение задачи], и нашиСоединения — это фактическое применение переменных процесса.....

5.1 Определение блок-схемы

Не все наши процессы идут по одному пути, и иногда мы идем разными путями в зависимости от условий. Конечно, в конце концов, процесс будет завершен шаг за шагом...

пример:

Важная информация обрабатывается начальником, а неважная информация обрабатывается менеджером.

这里写图片描述

Результат выражения должен быть логическим

  • #{variable=='value'}
  • ${variable==value}

5.2 Тестирование

Я устанавливаю переменную процесса в неважную, когда задача завершена, тогда менеджер будет обрабатывать ее при переходе к следующему процессу.

这里写图片描述

Когда я ставлю это важным, тогда босс должен справиться с этим.

这里写图片描述

6. Эксклюзивный шлюз

Когда мы использовали соединение выше, мы использовали два условия: либо условие «важно», либо условие «неважно»... Что, если есть другая ситуация? ? ? То есть пользователь ввел неправильное условие и написал его как «не знаю, важно это или нет», тогда как нам быть в этом процессе? ? ? Разве это не сбой? ? ?

Следовательно, у нас должен быть путь по умолчанию, простозаключается в том, что когда переменная не соответствует ни одному из условий, у нас также есть путь по умолчанию

这里写图片描述

Стоит отметить, что:Если это блок-схема BPMN с использованием подключаемого модуля в Eclipse, если используется эксклюзивный шлюз, ее нельзя проанализировать в разделе Idea....

решать:

Нам просто нужно переопределить эксклюзивный шлюз блок-схемы BPMN. Плагин Activiti в идее не должен формулировать процесс по умолчанию. Пока мы не устанавливаем условия, это линия подключения по умолчанию.

6.1 Тестирование


public class ExclusiveGetWay {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();

	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("排他网关流程")
				.addClasspathResource("ExclusiveGateway.bpmn")
				.deploy();

		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "bankBill";// bpmn 的 process id属性
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey);

		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
																	// 对象
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}

	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "2404";
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("visitor", 6);
		// taskId:任务id
		processEngine.getTaskService().complete(taskId, params);
//		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
	
}

Указываем значение не VIP и не background, тогда оно автоматически перейдет в обычное окно для обработки

这里写图片描述


7. Расширенное чтение

Параллельный шлюз:

这里写图片描述

Ожидание активности:

这里写图片描述

Задачи пользователя:

  • Используйте переменные процесса для указания обработчиков:

В нашем примере быстрого запускаОпределите жестко назначенный обработчик на блок-схеме, на самом деле это недостаточно гибко.После того, как мы узнаем переменные процесса, мы можем гибко назначать обработчик....

这里写图片描述


	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("用户任务指定流程")
				.addClasspathResource("AppayBill.bpmn")
				.deploy();

		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "appayBill";// bpmn 的 process id属性
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("userID", "王某某");
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey, params);

		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
		// 对象
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		String assignee="王某某";//指定任务处理人
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery
				.taskAssignee(assignee)
				.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}

	}

这里写图片描述

Используйте спецификацию класса:

这里写图片描述

Групповые задания:

  • Непосредственно назначить менеджера

这里写图片描述

  • Используйте переменные процесса

这里写图片描述

  • использовать класс

这里写图片描述

Суммировать

  • Если бизнес должен обрабатываться несколькими ролями, то нам лучше использовать структуру рабочего процесса.Потому что, если требования одной из ссылок меняются, мы не используем рабочий процесс. Это потребовало бы большой модификации кода. Очень хлопотно.
  • Краткое руководство по платформе рабочего процесса Activiti:
    • Определите рабочий процесс и используйте плагин, чтобы нарисовать нашу блок-схему. Эта блок-схема является нашим определенным рабочим процессом.
    • Механизм рабочего процесса — это ядро ​​рабочего процесса, которое позволяет развертывать рабочий процесс, который мы определяем.
    • Поскольку при использовании рабочего процесса генерируется много данных, Activiti сохраняет данные в таблице базы данных. Эти таблицы базы данных создаются Actitviti и поддерживаются Activiti.
    • Развернутый рабочий процесс необходимо выполнить вручную.
    • В зависимости от того, кто обрабатывает текущую задачу, мы можем запросить информацию о конкретной задаче.
    • По id задачи мы можем выполнить задачу.
  • Определение процесса включает четыре таблицы базы данных.
    • Мы можем прочитать нашу диаграмму определения процесса через API
    • Вы можете запросить последнюю версию определения процесса в соответствии с
    • удалить определение процесса
    • Определение процесса развертывания также может быть ZIP-файлом.
  • Процесс запущен, в нем задействованы два объекта и четыре таблицы базы данных:
    • Экземпляр процесса
    • Задачи процесса
    • Может быть несколько экземпляров процесса и только один объект процесса.
      • Если процесс не разветвляется, то экземпляр процесса равен объекту процесса.
    • На основе этих двух объектов мы можем делать много вещей
      • Получить историческую информацию об экземплярах процессов и задачах
      • Определите, пуст ли экземпляр процесса, чтобы определить, завершен ли процесс
      • Просмотр сведений о запущенных службах
      • Запуск процесса с экземпляром процесса
  • Переменные процесса: включает две таблицы.Переменные процесса на самом деле являются нашими условиями.
    • Область действия переменных процесса находится только внутри экземпляра процесса.
    • Мы можем установить переменные процесса, когда процесс запускается и когда задача завершается.
    • И службы времени выполнения, и задачи процесса могут задавать переменные процесса.
  • Через подключение мы можем задавать в нем условия, и брать разные ветки по разным условиям.
  • Если условия по умолчанию не установлены, когда условия не совпадают, процесс не может продолжаться, поэтому для установки пути по умолчанию требуется эксклюзивный шлюз.

Если в статье есть какие-либо ошибки, пожалуйста, поправьте меня, и мы сможем общаться друг с другом. Учащиеся, привыкшие читать технические статьи в WeChat и желающие получить больше ресурсов по Java, могутОбратите внимание на публичный аккаунт WeChat: Java3y