La arquitectura senior de Dachang lo llevará desde la entrada de actividades hasta el suelo, API combinada con ejemplos para explicar

Estaba pensando en no tener nada que hacer. Solo usé el marco de trabajo de Activiti en el proyecto para escribir un blog. Sin embargo, las cosas siempre están mezcladas y demoradas hasta ahora. Esta sección originalmente quería escribir sobre Activiti. APISin embargo, pensar demasiado en este blog, y parece demasiado rígido, difícil de entender, por lo que APIen la demostración real de explicar.

1. Establecer un diagrama de flujo

Antes de iniciar el flujo de trabajo, primero debemos reflejar el negocio específico en el diagrama de flujo de implementación del flujo de trabajo y pasar la prueba, que equivale a la mitad del éxito, y el desarrollo posterior del negocio específico es relativamente fácil.

Primero, echemos un vistazo a los controles que hay en la idea y los controles de uso común están marcados.

Hablemos del proceso específico de establecer un diagrama de flujo.

Primero, necesitamos ingresar a un nodo inicial del bpmnarchivo, que es una interfaz gráfica, simplemente puede extraer.

Luego, ingresamos a un control desde UserTaskel nodo de usuario al bpmnarchivo de tareas .

De esta manera, hay dos nodos de aprobación, si se necesitan otros requisitos comerciales, también podemos agregar algunas puertas de enlace , que no se agregarán aquí.

Finalmente, solo necesitamos un nodo final EndEventpara completar el flujo de trabajo del dibujo del diagrama de implementación.

Veamos finalmente el ejemplo completo.

Parece que se ha completado el dibujo de todo el diagrama de flujo, pero el problema es que actualmente no hemos configurado quién aprobará la aprobación del tutor y la aprobación del tutor , por lo que aún necesitamos ver cómo configurar los aprobadores .

Primero, debemos seleccionar un nodo de aprobación , por ejemplo, seleccionar el nodo de aprobación del supervisor.

En segundo lugar, podemos ver una idea obvia, llamada el lado izquierdo del editor del BPMN editorcuadro de propiedades, que incluye todos los atributos del nodo de tareas del usuario que se pueden configurar .

Nota: Usuario candidato, grupo candidato, oyente de tareas, estos tres atributos no se mencionan aquí por el momento y se agregarán más adelante.

Desde este paso, debemos configurar el aprobador, por lo que debemos Assigneeconfigurar nuestro aprobador esta propiedad.

Como se muestra en la figura anterior, aquí está el aprobador del tutor que aprueba este nodo sihai. Además de configurar el aprobador directamente, hay dos formas de configurarlo, que se agregarán más adelante.

También se puede configurar otro nodo de aprobación de esta manera para completar la configuración del aprobador.

Muy bien, esto básicamente completa la creación de un diagrama de flujo. A continuación, explicaremos la API de Activiti en detalle a través de ejemplos .

2. Ejemplos para explicar la API

En la creación del diagrama de flujo anterior, no hemos generado una imagen png, por lo que si no sabes cómo generarla, puedes consultar este artículo anterior: Flujo de trabajo de Activiti desde la entrada al suelo: integrando primavera .

Dado que se trata de la API, primero echemos un vistazo a las API principales, para que podamos tener una comprensión general.

Cómo usar estas API en detalle, vayamos una por una.

2.1 Definición de proceso

Dado que es una definición de proceso, debe ser cómo implementar la definición de proceso.

2.1.1 Método 1 de definición del proceso de implementación

 

 @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;

    /**
     * 部署流程定义(从classpath)
     */
    @Test
    public void deploymentProcessDefinition_classpath(){
        Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
                .createDeployment()//创建一个部署对象
                .name("流程定义")//添加部署的名称
                .addClasspathResource("bpmn/hello.bpmn")//从classpath的资源中加载,一次只能加载一个文件
                .addClasspathResource("bpmn/hello.png")//从classpath的资源中加载,一次只能加载一个文件
                .deploy();//完成部署
        System.out.println("部署ID:"+deployment.getId());
        System.out.println("部署名称:"+deployment.getName());
    }

Nota: Aquí se utiliza el entorno de prueba junit después de integrar el resorte. Para saber cómo integrar el resorte, consulte este artículo: Flujo de trabajo de Activiti desde la entrada al suelo: integración del resorte .

Resultado de salida:

De esta manera, implementamos este proceso. Entonces, ¿cómo funciona? Echemos un vistazo a todo el proceso.

  • Obtener objeto de motor de proceso: está integrado con Spring.

  • Obtuvo un objeto RepositoryService (objeto de almacén) a través del motor de proceso

  • El objeto de servicio del almacén genera un objeto de configuración del objeto de implementación para encapsular la configuración relevante de la operación de implementación.

  • Esta es una programación en cadena. Establezca el nombre para mostrar en el objeto de configuración de implementación y cargue el archivo de reglas de definición de proceso

  • Almacene la información de la regla de la definición del proceso en la tabla de la base de datos.

De hecho, en este paso se utilizan tres tablas de la base de datos de Activiti, que son: act_re_deployment (tabla de objetos de implementación), act_re_procdef (tabla de definición de procesos), act_ge_bytearray (tabla de archivos de recursos).

Observamos los cambios en estas tres tablas:
1) act_re_deployment

 

Como puede ver, el ID de implementación y el nombre de implementación se almacenan en esta tabla.

2) act_re_procdef

En esta tabla, se almacena información como el ID del proceso de implementación Deployment_ID implementado, el nombre del archivo de recursos bpmn y el nombre de la imagen png.

3) act_ge_bytearray

Información de implementación relacionada con la definición del proceso de almacenamiento. Es decir, la ubicación de almacenamiento del documento de definición de proceso. Se agregarán dos registros para cada implementación, uno para el archivo de reglas bpmn y otro para la imagen (si solo se especifica un archivo para bpmn durante la implementación, activiti analizará el contenido del archivo bpmn durante la implementación y generará automáticamente un diagrama de flujo). Los dos archivos no son muy grandes y se almacenan en la base de datos en forma binaria.

2.1.2 Método de definición del proceso de implementación 2

 

 /**
     * 部署流程定义(从zip)
     */
    @Test
    public void deploymentProcessDefinition_zip(){
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("bpmn/hello.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
                .createDeployment()//创建一个部署对象
                .name("流程定义")//添加部署的名称
                .addZipInputStream(zipInputStream)//指定zip格式的文件完成部署
                .deploy();//完成部署
        System.out.println("部署ID:"+deployment.getId());//
        System.out.println("部署名称:"+deployment.getName());//
    }

La estructura del proyecto es la siguiente:

 

Resultado de salida:

 

De esta manera, no hay problema, la única diferencia es que está comprimido en un archivo zip, el flujo de entrada de zip se usa como la definición del proceso de implementación y otros usos no son diferentes.

Después de implementar la definición del proceso, deberíamos querer verificar alguna información sobre la definición del proceso.

2.1.3 Ver la definición del proceso

 

/**
     * 查询流程定义
     */
    @Test
    public void findProcessDefinition(){
        List<ProcessDefinition> list = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
                .createProcessDefinitionQuery()//创建一个流程定义的查询
                /**指定查询条件,where条件*/
//                      .deploymentId(deploymentId)//使用部署对象ID查询
//                      .processDefinitionId(processDefinitionId)//使用流程定义ID查询
//                      .processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
//                      .processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询

                /**排序*/
                .orderByProcessDefinitionVersion().asc()//按照版本的升序排列
//                      .orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列

                /**返回的结果集*/
                .list();//返回一个集合列表,封装流程定义
//                      .singleResult();//返回惟一结果集
//                      .count();//返回结果集数量
//                      .listPage(firstResult, maxResults);//分页查询
        if(list!=null && list.size()>0){
            for(ProcessDefinition pd:list){
                System.out.println("流程定义ID:"+pd.getId());//流程定义的key+版本+随机生成数
                System.out.println("流程定义的名称:"+pd.getName());//对应hello.bpmn文件中的name属性值
                System.out.println("流程定义的key:"+pd.getKey());//对应hello.bpmn文件中的id属性值
                System.out.println("流程定义的版本:"+pd.getVersion());//当流程定义的key值相同的相同下,版本升级,默认1
                System.out.println("资源名称bpmn文件:"+pd.getResourceName());
                System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
                System.out.println("部署对象ID:"+pd.getDeploymentId());
                System.out.println("*********************************************");
            }
        }
    }

Resultado de salida:

 

Resumen de la definición del proceso de consulta:

  • La definición del proceso y el servicio relacionado con el objeto de implementación son ambos RepositoryService, y encontrará ambos sobre la definición del proceso más adelante RepositoryService.

  • Con este createProcessDefinitionQuery()método de configuración, una serie de parámetros de consulta, condiciones tales como descendente ascendente like.

2.1.4 Eliminar definición de proceso

Eliminando la información con el ID de implementación 2501.

 

/**
     * 删除流程定义
     */
    @Test
    public void deleteProcessDefinition(){
        //使用部署ID,完成删除,指定部署对象id为2501删除
        String deploymentId = "2501";
        /**
         * 不带级联的删除
         *    只能删除没有启动的流程,如果流程启动,就会抛出异常
         */
//      processEngine.getRepositoryService()//
//                      .deleteDeployment(deploymentId);

        /**
         * 级联删除
         *    不管流程是否启动,都能可以删除
         */
        processEngine.getRepositoryService()//
                .deleteDeployment(deploymentId, true);
        System.out.println("删除成功!");
    }

Resultado de salida:

 

Para ver la base de datos y descubrí que los act_re_deploymentdatos ya no existen.

  • Aquí o mediante el getRepositoryService()método de adquisición para implementar un objeto personalizado y luego eliminar la información de identificación especificada.

2.1.5 Obtenga los recursos del documento de definición de proceso

La función aquí es principalmente para consultar imágenes, que se pueden utilizar para la visualización del proceso más tarde. Veamos cómo comprobarlo.

 

/**
     * 查看流程图
     *
     * @throws IOException
     */
    @Test
    public void viewPic() throws IOException {
        /**将生成图片放到文件夹下*/
        String deploymentId = "5001";
        //获取图片资源名称
        List<String> list = processEngine.getRepositoryService()//
                .getDeploymentResourceNames(deploymentId);
        //定义图片资源的名称
        String resourceName = "";
        if (list != null && list.size() > 0) {
            for (String name : list) {
                if (name.indexOf(".png") >= 0) {
                    resourceName = name;
                }
            }
        }

        //获取图片的输入流
        InputStream in = processEngine.getRepositoryService()//
                .getResourceAsStream(deploymentId, resourceName);

        //将图片生成到F盘的目录下
        File file = new File("F:/" + resourceName);

        //将输入流的图片写到磁盘
        FileUtils.copyInputStreamToFile(in, file);
    }

Puede encontrar imágenes debajo de la unidad F.

 

2.1.6 Consultar la última versión de la definición del proceso

 

 /**
     * 查询最新版本的流程定义
     */
    @Test
    public void findLastVersionProcessDefinition() {
        List<ProcessDefinition> list = processEngine.getRepositoryService()//
                .createProcessDefinitionQuery()//
                .orderByProcessDefinitionVersion().asc()//使用流程定义的版本升序排列
                .list();
        /**
         map集合的特点:当map集合key值相同的情况下,后一次的值将替换前一次的值
         */
        Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
        if (list != null && list.size() > 0) {
            for (ProcessDefinition pd : list) {
                map.put(pd.getKey(), pd);
            }
        }
        List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());
        if (pdList != null && pdList.size() > 0) {
            for (ProcessDefinition pd : pdList) {
                System.out.println("流程定义ID:" + pd.getId());//流程定义的key+版本+随机生成数
                System.out.println("流程定义的名称:" + pd.getName());//对应hello.bpmn文件中的name属性值
                System.out.println("流程定义的key:" + pd.getKey());//对应hello.bpmn文件中的id属性值
                System.out.println("流程定义的版本:" + pd.getVersion());//当流程定义的key值相同的相同下,版本升级,默认1
                System.out.println("资源名称bpmn文件:" + pd.getResourceName());
                System.out.println("资源名称png文件:" + pd.getDiagramResourceName());
                System.out.println("部署对象ID:" + pd.getDeploymentId());
                System.out.println("*********************************************************************************");
            }
        }
    }

Resultado de salida:

 

2.1.7 Resumen de la definición del proceso

1. La definición del proceso de implementación utiliza las siguientes tablas de Activiti.

  • act_re_deployment: tabla de objetos de implementación
  • act_re_procdef: Tabla de definición de procesos
  • act_ge_bytearray: tabla de archivos de recursos
  • act_ge_property: tabla de estrategia de generación de claves primarias

2, encontramos que las definiciones del proceso de implementación operativa están en RepositoryServiceoperación bajo esta clase, solo necesitamos pasar getRepositoryService()todas las operaciones para obtener el objeto, puede definir el proceso de implementación por la regla de la cadena.

2.2 Uso de ejemplos completos de flujo de trabajo

En esta sección, usamos un ejemplo completo para resumir algunos de los conocimientos básicos mencionados anteriormente, de modo que podamos aprender mejor los puntos de conocimiento anteriores y posteriores Este también es un capítulo de transición.

Volviendo al diagrama de flujo de establecimiento en la primera sección , ya hemos establecido el diagrama básico de bpmn, pero necesitamos hacer un ejemplo completo, todavía necesitamos agregar algo de contenido, para poder completar dicho ejemplo. Tomemos primero la imagen bpmn de la primera sección.

En primer lugar, debemos ser claros: este diagrama hasta ahora, solo hemos dibujado el proceso, por ejemplo, cuando necesitamos revisar, debe ser revisado por una persona específica, por lo que necesitamos Configure personal específico para revisión en cada nodo.

Nota: El revisor que configura el nodo lo discutirá en detalle más adelante. Este es solo un ejemplo simple, por lo que solo necesita comprenderlo aquí y hacerlo bien.

Configurar los pasos del revisor

Primero, debemos seleccionar un nodo, por ejemplo, el nodo "aprobación del mentor" en la figura siguiente.

 

A continuación, en la barra de herramientas de la izquierda, veremos muchas opciones, una es Asignatario, necesitamos configurar el aprobador que nuestro nodo necesita configurar en esta opción.

Formato de configuración del asignatario: puede usar inglés o chino directamente, por ejemplo sihai, más adelante se discutirán configuraciones más complicadas.

La configuración del nodo a continuación es exactamente la misma que la anterior.

El examinador aprobado por el consejero es Ouyang Sihai.

 

Perfecto, para que se complete la tarea del diagrama de flujo, y luego podamos pasar a la fase de prueba de este ejemplo.

1) Definición del proceso de implementación La definición del proceso de
implementación, como se mencionó en el capítulo anterior, tiene dos formas de procesar, una es cargar el archivo bpmn y el archivo png, y la otra es comprimir estos dos archivos en un formato zip. Archivo, luego cargue. Aquí utilizamos el primer método de procesamiento.

 

/**
     * 部署流程定义(从classpath)
     */
    @Test
    public void deploymentProcessDefinition_classpath() {
        Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
                .createDeployment()//创建一个部署对象
                .name("hello")//添加部署的名称
                .addClasspathResource("bpmn/hello.bpmn")//从classpath的资源中加载,一次只能加载一个文件
                .addClasspathResource("bpmn/hello.png")//从classpath的资源中加载,一次只能加载一个文件
                .deploy();//完成部署
        log.info("部署ID:" + deployment.getId());
        log.info("部署名称:" + deployment.getName());
    }

Ahora que la definición del proceso está disponible, debemos iniciar esta instancia de proceso.

Respecto a lo realizado en este paso, lo puedes ver en el capítulo anterior.

2) Inicie la instancia del proceso

 

 /**
     * 启动流程实例
     */
    @Test
    public void startProcessInstance(){
        //1、流程定义的key,通过这个key来启动流程实例
        String processDefinitionKey = "hello";
        //2、与正在执行的流程实例和执行对象相关的Service
        // startProcessInstanceByKey方法还可以设置其他的参数,比如流程变量。
        ProcessInstance pi = processEngine.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
        log.info("流程实例ID:"+pi.getId());//流程实例ID
        log.info("流程定义ID:"+pi.getProcessDefinitionId());//流程定义ID
    }

 


Nota: processDefinitionKey es el nombre del archivo bpmn.

 

Paso
1 Obtenga la instancia de runtimeService.
2 Inicie la instancia del proceso mediante el nombre del archivo bpmn, que es processDefinitionKey.
3 Después de iniciar el proceso, la tarea del proceso pasa al nodo de aprobación del supervisor .

La siguiente es la consulta de tareas personales, podemos consultar las tareas del nodo de aprobación del supervisor.

3) Consultar tareas personales

 

/**
     * 查询当前人的个人任务
     */
    @Test
    public void findPersonalTask(){
        String assignee = "sihai";
        List<Task> list = processEngine.getTaskService()//与正在执行的任务管理相关的Service
                .createTaskQuery()//创建任务查询对象
                /**查询条件(where部分)*/
                .taskAssignee(assignee)//指定个人任务查询,指定办理人
//                      .taskCandidateUser(candidateUser)//组任务的办理人查询
//                      .processDefinitionId(processDefinitionId)//使用流程定义ID查询
//                      .processInstanceId(processInstanceId)//使用流程实例ID查询
//                      .executionId(executionId)//使用执行对象ID查询
                /**排序*/
                .orderByTaskCreateTime().asc()//使用创建时间的升序排列
                /**返回结果集*/
//                      .singleResult()//返回惟一结果集
//                      .count()//返回结果集的数量
//                      .listPage(firstResult, maxResults);//分页查询
                .list();//返回列表
        if(list!=null && list.size()>0){
            for(Task task:list){
                log.info("任务ID:"+task.getId());
                log.info("任务名称:"+task.getName());
                log.info("任务的创建时间:"+task.getCreateTime());
                log.info("任务的办理人:"+task.getAssignee());
                log.info("流程实例ID:"+task.getProcessInstanceId());
                log.info("执行对象ID:"+task.getExecutionId());
                log.info("流程定义ID:"+task.getProcessDefinitionId());
                log.info("********************************************");
            }
        }
    }

Por sihaieste revisor, la consulta a la siguiente información.

 

Paso de análisis
1 Primero, obtenga el objeto TaskService a través del método getTaskService.
2 Cree un objeto de consulta mediante el método createTaskQuery.
3 Configure el revisor mediante el método taskAssignee.
4 Para la devolución del resultado, podemos establecer otra información como ordenar a través de orderByTaskCreateTime (). Asc ().

Una cosa a tener en cuenta aquí es que una pieza importante de información consultada es: ID de tarea (taskId). A continuación, necesitamos usar esta identificación de tarea para completar la tarea.

4) Manejar tareas personales

 

/**
     * 完成我的任务
     */
    @Test
    public void completePersonalTask() {
        //任务ID,上一步查询得到的。
        String taskId = "7504";
        processEngine.getTaskService()//与正在执行的任务管理相关的Service
                .complete(taskId);
        log.info("完成任务:任务ID:" + taskId);
    }

Complete la tarea con el ID de tarea del paso anterior: 7504.

Paso
1 Primero, obtenga el objeto TaskService a través del método getTaskService.
2 Llame al método completo y complete la tarea con una identificación de tarea específica.

5) Consulta del estado del proceso (juzga a qué nodo
va el proceso ) esta interfaz todavía es muy necesaria. Cuando estamos en un negocio específico, necesitamos determinar cuál es el estado de nuestro proceso, o cuál ha alcanzado nuestro proceso. Cuando se trata de nodos, esta interfaz nos permite ahorrar muchas cosas en nuestro negocio.

 

/**
     * 查询流程状态(判断流程走到哪一个节点)
     */
    @Test
    public void isProcessActive() {
        String processInstanceId = "7501";
        ProcessInstance pi = processEngine.getRuntimeService()//表示正在执行的流程实例和执行对象
                .createProcessInstanceQuery()//创建流程实例查询
                .processInstanceId(processInstanceId)//使用流程实例ID查询
                .singleResult();
        if (pi == null) {
            log.info("流程已经结束");
        } else {
            log.info("流程没有结束");
            //获取任务状态
            log.info("节点id:" + pi.getActivityId());
        }
    }

Pasos:
1 Obtenga el objeto ProcessInstance de la instancia de proceso.
2 Obtenga el Id. De instancia (Id. De nodo) a través del método getActivityId.

Entonces, ¿ 节点 Idcuál es el efecto de conseguirlo ?
De hecho, después de tener esta identificación, podemos juzgar dónde está el proceso. Por ejemplo, el ID de nodo de la salida anterior es _4, este _4 es el correspondiente 辅导员审批节点的 id, por lo que podemos juzgar que el proceso realmente ha llegado a este nodo, y jugará un papel cuando el estado del proceso se muestre en la página más adelante.

6) Consultar la información histórica de la ejecución del proceso
Al verificar la interfaz API oficial de la actividad 5, se encuentra que la siguiente interfaz de consulta está disponible para ver información histórica.

A continuación, utilizamos los ejemplos anteriores para probar los siguientes métodos uno por uno.

Interfaz de consulta de instancia de actividad histórica

 

/**
     * 历史活动查询接口
     */
    @Test
    public void findHistoryActivity() {
        String processInstanceId = "7501";
        List<HistoricActivityInstance> hais = processEngine.getHistoryService()//
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        for (HistoricActivityInstance hai : hais) {
            log.info("活动id:" + hai.getActivityId()
                    + "   审批人:" + hai.getAssignee()
                    + "   任务id:" + hai.getTaskId());
            log.info("************************************");
        }
    }

A través de esta interfaz, no solo se puede encontrar esta información, sino que existen otros métodos para obtener más información sobre actividades históricas .

Interfaz de consulta de instancia de proceso histórico

 

/**
     * 查询历史流程实例
     */
    @Test
    public void findHistoryProcessInstance() {
        String processInstanceId = "7501";
        HistoricProcessInstance hpi = processEngine.getHistoryService()// 与历史数据(历史表)相关的Service
                .createHistoricProcessInstanceQuery()// 创建历史流程实例查询
                .processInstanceId(processInstanceId)// 使用流程实例ID查询
                .orderByProcessInstanceStartTime().asc().singleResult();
        log.info(hpi.getId() + "    " + hpi.getProcessDefinitionId() + "    " + hpi.getStartTime() + "    "
                + hpi.getEndTime() + "     " + hpi.getDurationInMillis());
    }

Esta interfaz puede consultar toda la información sobre instancias de procesos históricos .

Interfaz de consulta de instancia de tarea histórica

 

 /**
     * 查询历史任务
     */
    @Test
    public void findHistoryTask() {
        String processInstanceId = "7501";
        List<HistoricTaskInstance> list = processEngine.getHistoryService()// 与历史数据(历史表)相关的Service
                .createHistoricTaskInstanceQuery()// 创建历史任务实例查询
                .processInstanceId(processInstanceId)//
                .orderByHistoricTaskInstanceStartTime().asc().list();
        if (list != null && list.size() > 0) {
            for (HistoricTaskInstance hti : list) {
                log.info("\n 任务Id:" + hti.getId() + "    任务名称:" + hti.getName() + "    流程实例Id:" + hti.getProcessInstanceId() + "\n 开始时间:"
                        + hti.getStartTime() + "   结束时间:" + hti.getEndTime() + "   持续时间:" + hti.getDurationInMillis());
            }
        }
    }

Esta interfaz de consulta puede consultar información histórica de tareas .

Interfaz de consulta de variables de proceso históricas

 

/**
     * 查询历史流程变量
     */
    @Test
    public void findHistoryProcessVariables() {
        String processInstanceId = "7501";
        List<HistoricVariableInstance> list = processEngine.getHistoryService()//
                .createHistoricVariableInstanceQuery()// 创建一个历史的流程变量查询对象
                .processInstanceId(processInstanceId)//
                .list();
        if (list != null && list.size() > 0) {
            for (HistoricVariableInstance hvi : list) {
                log.info("\n" + hvi.getId() + "   " + hvi.getProcessInstanceId() + "\n" + hvi.getVariableName()
                        + "   " + hvi.getVariableTypeName() + "    " + hvi.getValue());
            }
        }
    }

En este ejemplo, no se configuran variables de proceso, por lo que no se puede consultar aquí información histórica.

Esta interfaz trata principalmente de información sobre la configuración de variables históricas del proceso .

Interfaz de consulta de interfaz local histórica

 

/**
     * 通过执行sql来查询历史数据,由于activiti底层就是数据库表。
     */
    @Test
    public void findHistoryByNative() {
        HistoricProcessInstance hpi = processEngine.getHistoryService()
                .createNativeHistoricProcessInstanceQuery()
                .sql("查询底层数据库表的sql语句")
                .singleResult();
        log.info("\n" + hpi.getId() + "    " + hpi.getProcessDefinitionId() + "    " + hpi.getStartTime()
                + "\n" + hpi.getEndTime() + "     " + hpi.getDurationInMillis());
    }

Esta interfaz se proporciona a través de una sql 语句consulta directa de información histórica, solo necesitamos sql()escribir la declaración SQL, el método nativo puede realizar consultas de datos.

En este punto, creo que deberíamos presentar la API de flujo de trabajo de Activiti a través de un ejemplo tan completo, y me despediré de esta sección. Repasemos la interfaz API al principio del artículo, que también es un resumen de esta sección.

 

 

Al final:

A través del estudio anterior, descubrí que hay bastantes entrevistados este año. Para muchas personas que han estado entrevistando recientemente, también he recopilado bastantes temas de entrevistas (primavera, mybatis, jvm, Zookeeper, distribuido, etc.). Puede hacer clic a continuación Link) y las preguntas reales de la última entrevista de Ali de 2020.

Las respuestas a las preguntas de la entrevista anteriores están organizadas en notas de documentos. También clasifiqué algunos materiales de la entrevista y las últimas preguntas de la entrevista recopiladas por algunas grandes empresas en 2020 (todo organizado en documentos, una pequeña parte de las capturas de pantalla), si es necesario, puede  hacer clic para ingresar para ver los materiales .

Espero que sea de ayuda para todos. Si es útil, ¡por favor bríndeme apoyo!

Supongo que te gusta

Origin blog.csdn.net/SQY0809/article/details/108827620
Recomendado
Clasificación