L'architecture senior de Dachang vous mènera de l'entrée d'activité au sol, API combinée avec des exemples pour expliquer

Je pensais n'avoir rien à faire. J'ai juste utilisé le framework de workflow Activiti dans le projet pour écrire un blog. Cependant, les choses sont toujours mélangées et retardées jusqu'à présent. Cette section voulait à l'origine écrire sur Activiti. APICependant, trop de réflexion sur ce blog, et il semble trop rigide, difficile à comprendre, de sorte que APIdans la démo réelle à expliquer.

1. Établissez un organigramme

Avant de commencer le flux de travail, nous devons d'abord refléter l'activité spécifique dans l'organigramme de déploiement du flux de travail, et réussir le test, qui équivaut à la moitié du succès, et le développement ultérieur de l'entreprise spécifique est relativement facile.

Tout d'abord, examinons les contrôles dans l'idée et les contrôles couramment utilisés sont marqués.

Parlons du processus spécifique d'établissement d'un organigramme.

Tout d'abord, nous devons tirer dans un nœud de départ du bpmnfichier, qui est une interface graphique, vous pouvez simplement tirer.

Ensuite, nous avons intégré un contrôle du UserTasknœud utilisateur au bpmnfichier de tâches .

De cette façon, il y a deux nœuds d'approbation. Si d'autres exigences commerciales sont nécessaires, nous pouvons également ajouter des passerelles , qui ne seront pas ajoutées ici.

Enfin, nous n'avons besoin que d'un seul nœud d'extrémité EndEventpour terminer le flux de travail de dessin du diagramme de déploiement.

Regardons enfin l'exemple complet.

Il semble que le dessin de l'intégralité de l'organigramme soit terminé, mais le problème est que nous n'avons actuellement pas défini qui approuvera l'approbation du tuteur et l' approbation du tuteur , nous devons donc encore examiner comment configurer le personnel d'approbation .

Tout d'abord, nous devons sélectionner un nœud d'approbation , par exemple, sélectionnez le nœud d'approbation du superviseur.

Deuxièmement, nous pouvons voir une idée évidente, appelée le côté gauche de l'éditeur de la BPMN editorboîte de propriétés, qui comprend tous les attributs du nœud de tâche utilisateur peuvent être définis .

Remarque: Utilisateurs candidats, groupes candidats, écouteurs de tâches, ces trois attributs ne sont pas mentionnés ici pour le moment, et seront ajoutés ultérieurement.

Depuis cette étape, nous devons définir l'approbateur, nous devons donc Assigneedéfinir cette propriété à notre approbateur.

Comme le montre la figure ci-dessus, voici l'approbateur du tuteur approuvant ce nœud sihai. En plus de définir directement l'approbateur, il existe deux façons de le définir, qui seront ajoutées ultérieurement.

Un autre nœud d'approbation peut également être défini de cette manière pour terminer la configuration de l'approbateur.

Très bien, cela achève essentiellement la création d'un organigramme. Ensuite, nous expliquerons l' API Activiti en détail à travers des exemples .

2. Exemples pour expliquer l'API

Dans la création de l'organigramme ci-dessus, nous n'avons pas généré d'image png, donc si vous ne savez pas comment la générer, vous pouvez vous référer à cet article précédent: Flux de travail Activiti de l'entrée au sol: intégrer le ressort .

Puisqu'il s'agit de l'API, examinons d'abord les principales API, afin que nous puissions avoir une compréhension globale.

Comment utiliser ces API en détail, venons-en une par une.

2.1 Définition du processus

Puisqu'il s'agit d'une définition de processus, il doit s'agir de savoir comment déployer la définition de processus.

2.1.1 Méthode de définition du processus de déploiement 1

 

 @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());
    }

Remarque: L'environnement de test junit après l'intégration du ressort est utilisé ici. Pour savoir comment intégrer le ressort, veuillez consulter cet article: Flux de travail Activiti de l'entrée au sol: intégration du ressort .

Résultat de sortie:

De cette façon, nous avons déployé ce processus. Alors, comment ça marche? Jetons un coup d'œil à l'ensemble du processus.

  • Obtenir l'objet du moteur de processus: il est intégré au ressort.

  • Obtention d'un objet RepositoryService (objet d'entrepôt) via le moteur de processus

  • Un objet de configuration d'objet de déploiement est généré par l'objet de service de l'entrepôt pour encapsuler la configuration appropriée de l'opération de déploiement.

  • Il s'agit d'une programmation en chaîne. Définissez le nom d'affichage dans l'objet de configuration de déploiement et téléchargez le fichier de règles de définition de processus

  • Stockez les informations de règle de la définition de processus dans la table de base de données.

En fait, dans cette étape, trois tables de la base de données Activiti sont utilisées, à savoir: act_re_deployment (table des objets de déploiement), act_re_procdef (table de définition des processus), act_ge_bytearray (table des fichiers de ressources).

Nous regardons les changements dans ces trois tableaux:
1) act_re_deployment

 

Comme vous pouvez le voir, l'ID de déploiement et le nom du déploiement sont stockés dans ce tableau.

2) act_re_procdef

Dans ce tableau, des informations telles que l'ID du processus de déploiement Deployment_ID déployé, le nom du fichier de ressources bpmn et le nom de l'image png sont stockées.

3) act_ge_bytearray

Informations de déploiement liées à la définition du processus de stockage. C'est-à-dire l'emplacement de stockage du document de définition de processus. Deux enregistrements seront ajoutés pour chaque déploiement, un pour le fichier de règles bpmn et un pour l'image (si un seul fichier est spécifié pour bpmn lors du déploiement, activiti analysera le contenu du fichier bpmn pendant le déploiement et générera automatiquement un diagramme). Les deux fichiers ne sont pas très volumineux et sont stockés dans la base de données sous forme binaire.

2.1.2 Méthode de définition du processus de déploiement 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 structure du projet est la suivante:

 

Résultat de sortie:

 

De cette façon, il n'y a pas de problème. La seule différence est qu'il est compressé dans un fichier zip. Le flux d'entrée de zip est utilisé comme définition du processus de déploiement et les autres utilisations ne sont pas différentes.

Après avoir déployé la définition de processus, nous devrions vouloir vérifier certaines informations sur la définition de processus.

2.1.3 Afficher la définition du processus

 

/**
     * 查询流程定义
     */
    @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("*********************************************");
            }
        }
    }

Résultat de sortie:

 

Résumé de la définition du processus de requête:

  • La définition de processus et le service lié à l'objet de déploiement sont tous les deux RepositoryService, et vous trouverez les deux sur la définition de processus plus tard RepositoryService.

  • Avec cette createProcessDefinitionQuery()méthode de réglage un certain nombre de paramètres de requête, des conditions telles que par ordre décroissant croissant comme.

2.1.4 Supprimer la définition de processus

En supprimant les informations avec l'ID de déploiement 2501.

 

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

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

Résultat de sortie:

 

Pour afficher la base de données et a constaté que les act_re_deploymentdonnées n'existent plus.

  • Ici ou via une getRepositoryService()méthode d'acquisition pour déployer un objet personnalisé, puis supprimez les informations d'ID spécifiées.

2.1.5 Obtenir les ressources du document de définition de processus

La fonction ici est principalement d'interroger des vues, qui peuvent être utilisées ultérieurement pour l'affichage du processus. Voyons comment le vérifier.

 

/**
     * 查看流程图
     *
     * @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);
    }

Vous pouvez trouver des photos sous le lecteur F.

 

2.1.6 Interroger la dernière version de la définition de processus

 

 /**
     * 查询最新版本的流程定义
     */
    @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("*********************************************************************************");
            }
        }
    }

Résultat de sortie:

 

2.1.7 Résumé de la définition du processus

1. La définition du processus de déploiement utilise les tableaux suivants d'Activiti.

  • act_re_deployment: table des objets de déploiement
  • act_re_procdef: table de définition des processus
  • act_ge_bytearray: table des fichiers de ressources
  • act_ge_property: table de stratégie de génération de clé primaire

2, nous constatons que les définitions de processus de déploiement opérationnel sont en RepositoryServicecours dans cette classe, il nous suffit de passer getRepositoryService()toutes les opérations pour obtenir l'objet, vous pouvez définir le processus de déploiement par la règle de chaîne.

2.2 Utilisation d'exemples complets de workflow

Dans cette section, nous utilisons un exemple complet pour résumer certaines des connaissances de base mentionnées précédemment, afin que nous puissions mieux apprendre les points de connaissances précédents et suivants.Il s'agit également d'un chapitre de transition.

Pour revenir à l'organigramme d'établissement de la première section , nous avons déjà établi le diagramme bpmn de base, mais nous devons faire un exemple complet, nous devons encore ajouter du contenu, afin de pouvoir compléter un tel exemple. Prenons d'abord l'image bpmn de la première section.

Tout d'abord, nous devons être clairs: ce diagramme jusqu'à présent, nous n'avons simplement dessiné que le processus, par exemple, lorsque nous avons besoin de le revoir, il doit être examiné par une personne spécifique, nous avons donc besoin Mettre en place un personnel spécifique pour examen à chaque nœud.

Remarque: Le réviseur qui définit le nœud en discutera en détail plus tard. Il ne s'agit que d'un exemple simple, il vous suffit donc de le comprendre ici et de bien le faire.

Configurer les étapes du réviseur

Tout d'abord, nous devons sélectionner un nœud, par exemple, le nœud «approbation du mentor» dans la figure ci-dessous.

 

Ensuite, dans la barre d'outils à gauche, nous verrons beaucoup d'options, l'une est Assigné, nous devons définir l'approbateur que notre nœud doit définir dans cette option.

Format des paramètres du destinataire: vous pouvez utiliser directement l'anglais ou le chinois, par exemple sihai, des paramètres plus complexes seront abordés plus tard.

Les paramètres de nœud ci-dessous sont exactement les mêmes que ci-dessus.

L'examinateur approuvé par le conseiller est Ouyang Sihai.

 

Parfait, pour que la tâche de l'organigramme soit terminée, puis nous pouvons passer à la phase de test de cet exemple.

1) Définition du processus de
déploiement La définition du processus de déploiement, comme mentionné dans le chapitre précédent, comporte deux méthodes de traitement, l'une consiste à charger le fichier bpmn et le fichier png, et l'autre à compresser les deux fichiers au format zip. Fichier, puis chargez. Ici, nous utilisons la première méthode de traitement.

 

/**
     * 部署流程定义(从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());
    }

Maintenant que la définition de processus est disponible, nous devons démarrer cette instance de processus.

Concernant ce qui a été fait dans cette étape, vous pouvez le voir dans le chapitre précédent.

2) Démarrez l'instance de processus

 

 /**
     * 启动流程实例
     */
    @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
    }

 


Remarque: processDefinitionKey est le nom du fichier bpmn.

 

Étape
1 Obtenez l'instance runtimeService.
2 Démarrez l'instance de processus via le nom du fichier bpmn, qui est processDefinitionKey.
3 Une fois le processus lancé, la tâche du processus est transférée au nœud d' approbation du superviseur .

Ce qui suit est la requête des tâches personnelles, nous pouvons interroger les tâches du nœud d'approbation du superviseur.

3) Interroger des tâches personnelles

 

/**
     * 查询当前人的个人任务
     */
    @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("********************************************");
            }
        }
    }

Par sihaice réviseur, la requête aux informations suivantes.

 

Étape d'analyse
1 Tout d'abord, obtenez l'objet TaskService via la méthode getTaskService.
2 Créez un objet de requête via la méthode createTaskQuery.
3 Définissez le réviseur via la méthode taskAssignee.
4 Pour le retour du résultat, nous pouvons définir d'autres informations telles que le tri via orderByTaskCreateTime (). Asc ().

Une chose à noter ici est qu'une information importante demandée est: l'ID de tâche (taskId). Ensuite, nous devons utiliser cet ID de tâche pour terminer la tâche.

4) Gestion des tâches personnelles

 

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

Terminez la tâche avec l'ID de tâche de l'étape précédente: 7504.

Étape
1 Commencez par obtenir l'objet TaskService via la méthode getTaskService.
2 Appelez la méthode complète et terminez la tâche avec un ID de tâche spécifique.

5) Statut du processus de requête (juger à quel nœud
le processus va ) cette interface est toujours très nécessaire. Lorsque nous sommes dans une entreprise spécifique, nous devons déterminer quel est l'état de notre processus, ou lequel notre processus a atteint En ce qui concerne les nœuds, cette interface nous permet de sauver beaucoup de choses dans notre entreprise.

 

/**
     * 查询流程状态(判断流程走到哪一个节点)
     */
    @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());
        }
    }

Étapes:
1 Obtenez l'objet ProcessInstance de l'instance de processus.
2 Obtenez l'ID d'instance (id de nœud) via la méthode getActivityId.

Alors, 节点 Idquel est l'effet de l' obtenir ?
En fait, après avoir eu cet identifiant, nous pouvons juger où se trouve le processus. Par exemple, l'ID de nœud de la sortie ci-dessus est _4, et ce _4 est le correspondant 辅导员审批节点的 id, nous pouvons donc juger que le processus a réellement atteint ce nœud, et il jouera un rôle lorsque l'état du processus sera affiché sur la page plus tard.

6) Interrogez les informations historiques de l'exécution du processus
En visualisant l'interface API officielle d'activiti 5, il s'avère que l'interface de requête suivante est disponible pour visualiser les informations historiques.

Ci-dessous, nous utilisons les exemples ci-dessus pour tester les méthodes suivantes une par une.

Interface de requête d'instance d'activité historique

 

/**
     * 历史活动查询接口
     */
    @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("************************************");
        }
    }

Grâce à cette interface, non seulement ces informations peuvent être trouvées, mais il existe d'autres méthodes pour obtenir plus d' autres informations sur les activités historiques .

Interface de requête d'instance de processus historique

 

/**
     * 查询历史流程实例
     */
    @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());
    }

Cette interface peut interroger toutes les informations sur les instances de processus historiques .

Interface de requête d'instance de tâche historique

 

 /**
     * 查询历史任务
     */
    @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());
            }
        }
    }

Cette interface de requête peut interroger les informations de tâches historiques .

Interface de requête de variable de processus historique

 

/**
     * 查询历史流程变量
     */
    @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());
            }
        }
    }

Dans cet exemple, aucune variable de processus n'est définie, donc aucune information historique ne peut être interrogée ici.

Cette interface contient principalement des informations sur le paramétrage des variables de processus historiques .

Interface de requête d'interface locale historique

 

/**
     * 通过执行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());
    }

Cette interface est fournie via une sql 语句requête directe d'informations historiques, il suffit d' sql()écrire la méthode native de l'instruction SQL pour effectuer des requêtes de données.

À ce stade, je pense que l'API du workflow Activiti devrait être présentée à travers un exemple aussi complet, et je dirai au revoir à cette section. Revenons à l'interface de l'API au début de l'article. Ceci est également un résumé de cette section.

 

 

Enfin:

Grâce à l'étude ci-dessus, j'ai trouvé qu'il y avait pas mal de gens qui interviewaient cette année. Pour beaucoup de gens qui interviewent récemment, j'ai également compilé beaucoup de matériel spécial d'entretien (spring, mybatis, jvm, Zookeeper, distribué, etc.). Vous pouvez cliquer ci-dessous Link) et les vraies questions de la dernière interview d'Ali en 2020.

Les réponses aux questions d'entrevue ci-dessus sont organisées en notes documentaires. J'ai également trié certains documents d'entrevue et les dernières questions d'entrevue collectées par certaines grandes entreprises en 2020 (toutes organisées en documents, une petite partie des captures d'écran), si nécessaire, vous pouvez  cliquer pour entrer pour afficher les informations .

J'espère que ce sera utile à tout le monde. Si c'est utile, veuillez me soutenir!

Je suppose que tu aimes

Origine blog.csdn.net/SQY0809/article/details/108827620
conseillé
Classement