Skip to content

指令执行前与执行后扩展开发

指令执行前与执行后方法为默认触发,无需配置。

指令执行前方法配置为 指令:INIT ,例如 SendCommit:INIT

指令执行后方法配置为 指令:DESTROY ,例如 FlowSend:DESTROY

新建项目

pom.xml 中引入 co-service-macro-sdk-x.x.x.jar

xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.kanq</groupId>
  <artifactId>co-service-ext</artifactId>
  <version>1.0.1</version>
  <packaging>jar</packaging>

  <name>co_service_web_ext_demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>

    <dependency>
        <groupId>com.kanq</groupId>
        <artifactId>co-service-macro-sdk</artifactId>
        <version>1.x.x</version>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.kanq</groupId>
  <artifactId>co-service-ext</artifactId>
  <version>1.0.1</version>
  <packaging>jar</packaging>

  <name>co_service_web_ext_demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>

    <dependency>
        <groupId>com.kanq</groupId>
        <artifactId>co-service-macro-sdk</artifactId>
        <version>1.x.x</version>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

扩展接口实现

  • 创建 java 类 com.kanq.FlowDemo

  • 增加 private static byte[] sendCommitInit(byte[] macroHead, byte[][] argv); 流程发送前置处理方法

  • 增加指令注册注解 @Macro(name = "SendCommit:INIT", describe = "流程发送前置处理")

  • 增加 private static byte[] flowSendDestroy(byte[] macroHead, byte[][] argv); 流程发送查询接收人后置处理方法

  • 增加指令注册注解 @Macro(name = "FlowSend:DESTROY", describe = "流程发送查询接收人后置处理")

注意

  • 入参说明:
    • macroHead 请求头,参数不定,格式: form:2\r\nuser:1
    • argv 入参参数
  • 出参说明:
    • 字符串:json 格式
    • 文件: 字节流
  • 注解说明:
    • name 指令名称
    • describe 接口描述 :::

macroHead 参数说明

  • addr 当前用户 IP
  • client f: 函数,m:移动动
  • busi 当前业务编号
  • role 当前角色
  • user 当前用户编号
  • stat 当前流程状态
  • tach 当前流程环节
  • flow 当前打开流程
  • form 当前打开表单
  • prev 父级表单
  • tent 指定租户编号
  • trace 链路日志
  • ticket 票据
  • FormDemo.java
java
package com.kanq;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.kanq.sdk.config.Macro;
import com.kanq.sdk.impl.ParmImpl;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FlowDemo {

    /**
     * 流程发送查询接收人后置处理
     * @param macroHead
     * @param argv
     * @return
     * @throws JsonProcessingException
     */
    @Macro(name = "FlowSend:DESTROY", describe = "流程发送查询接收人后置处理")
    private static byte[] flowSendDestroy(byte[] macroHead, byte[][] argv) throws JsonProcessingException {

        //获取parm
        byte[] parm_byte = argv[1];
        String parm = new String(parm_byte,StandardCharsets.UTF_8);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = null;
        try {
            // 读取 JSON 文件
            rootNode = objectMapper.readTree(parm);
            // 确保根节点是一个对象
            if (rootNode.isObject()) {
                // 获取 "tach" 字段,确保它是一个数组
                JsonNode tachNode = rootNode.path("tach");
                if (tachNode.isArray()) {
                    ArrayNode tachArray = (ArrayNode) tachNode;
                    // 遍历数组中的每个对象
                    for (JsonNode item : tachArray) {
                        // 检查是否是目标对象
                        if (item.isObject()) {
                            // 获取 "children" 字段,确保它是一个数组
                            JsonNode childrenNode = item.path("children");
                            if (childrenNode.isArray()) {
                                ArrayNode childrenArray = (ArrayNode) childrenNode;
                                // 遍历 children 数组中的每个对象
                                for (JsonNode child : childrenArray) {
                                    // 检查是否是目标对象
                                    if (child.isObject()) {
                                        // 获取 "children" 字段,确保它是一个数组
                                        JsonNode innerChildrenNode = child.path("children");
                                        if (innerChildrenNode.isArray()) {
                                            ArrayNode innerChildrenArray = (ArrayNode) innerChildrenNode;
                                            // 遍历 innerChildren 数组中的每个对象
                                            for (JsonNode innerChild : innerChildrenArray) {
                                                // 替换指定 text 值
                                                if (innerChild.isObject()
                                                        && innerChild.has("text")
                                                        && innerChild.get("text").asText().equals("Admin")) {
                                                    ((ObjectNode) innerChild).put("text", "张晓明");
                                                    break; // 替换完成后退出循环
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objectMapper.writeValueAsBytes(rootNode);
    }

    /**
     * 流程发送前置处理
     * @param macroHead
     * @param argv
     * @return
     * @throws JsonProcessingException
     */
    @Macro(name = "SendCommit:INIT", describe = "流程发送前置处理")
    private static byte[] sendCommitInit(byte[] macroHead, byte[][] argv) throws JsonProcessingException, DocumentException {
        ObjectMapper mapper = new ObjectMapper();

        // 获取参数
        byte[] parm_byte = argv[0];
        String parm = new String(parm_byte,StandardCharsets.UTF_8);
        // 解析XML
        Document document = org.dom4j.DocumentHelper.parseText(parm);
        // 获取根节点
        Element root = document.getRootElement();
        // 设置审批意见
        root.addAttribute("msg", "扩展:同意");
        // 转换为XML
        parm = document.getRootElement().asXML();
        // 组装格式
        ArrayNode arrayNode = mapper.createArrayNode();
        arrayNode.add(parm);
        // 返回赋值
        ParmImpl parmImpl = new ParmImpl();
        parmImpl.setParameter(arrayNode);

        return mapper.writeValueAsString(parmImpl).getBytes(StandardCharsets.UTF_8);
    }
}


package com.kanq;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.kanq.sdk.config.Macro;
import com.kanq.sdk.impl.ParmImpl;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FlowDemo {

    /**
     * 流程发送查询接收人后置处理
     * @param macroHead
     * @param argv
     * @return
     * @throws JsonProcessingException
     */
    @Macro(name = "FlowSend:DESTROY", describe = "流程发送查询接收人后置处理")
    private static byte[] flowSendDestroy(byte[] macroHead, byte[][] argv) throws JsonProcessingException {

        //获取parm
        byte[] parm_byte = argv[1];
        String parm = new String(parm_byte,StandardCharsets.UTF_8);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = null;
        try {
            // 读取 JSON 文件
            rootNode = objectMapper.readTree(parm);
            // 确保根节点是一个对象
            if (rootNode.isObject()) {
                // 获取 "tach" 字段,确保它是一个数组
                JsonNode tachNode = rootNode.path("tach");
                if (tachNode.isArray()) {
                    ArrayNode tachArray = (ArrayNode) tachNode;
                    // 遍历数组中的每个对象
                    for (JsonNode item : tachArray) {
                        // 检查是否是目标对象
                        if (item.isObject()) {
                            // 获取 "children" 字段,确保它是一个数组
                            JsonNode childrenNode = item.path("children");
                            if (childrenNode.isArray()) {
                                ArrayNode childrenArray = (ArrayNode) childrenNode;
                                // 遍历 children 数组中的每个对象
                                for (JsonNode child : childrenArray) {
                                    // 检查是否是目标对象
                                    if (child.isObject()) {
                                        // 获取 "children" 字段,确保它是一个数组
                                        JsonNode innerChildrenNode = child.path("children");
                                        if (innerChildrenNode.isArray()) {
                                            ArrayNode innerChildrenArray = (ArrayNode) innerChildrenNode;
                                            // 遍历 innerChildren 数组中的每个对象
                                            for (JsonNode innerChild : innerChildrenArray) {
                                                // 替换指定 text 值
                                                if (innerChild.isObject()
                                                        && innerChild.has("text")
                                                        && innerChild.get("text").asText().equals("Admin")) {
                                                    ((ObjectNode) innerChild).put("text", "张晓明");
                                                    break; // 替换完成后退出循环
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objectMapper.writeValueAsBytes(rootNode);
    }

    /**
     * 流程发送前置处理
     * @param macroHead
     * @param argv
     * @return
     * @throws JsonProcessingException
     */
    @Macro(name = "SendCommit:INIT", describe = "流程发送前置处理")
    private static byte[] sendCommitInit(byte[] macroHead, byte[][] argv) throws JsonProcessingException, DocumentException {
        ObjectMapper mapper = new ObjectMapper();

        // 获取参数
        byte[] parm_byte = argv[0];
        String parm = new String(parm_byte,StandardCharsets.UTF_8);
        // 解析XML
        Document document = org.dom4j.DocumentHelper.parseText(parm);
        // 获取根节点
        Element root = document.getRootElement();
        // 设置审批意见
        root.addAttribute("msg", "扩展:同意");
        // 转换为XML
        parm = document.getRootElement().asXML();
        // 组装格式
        ArrayNode arrayNode = mapper.createArrayNode();
        arrayNode.add(parm);
        // 返回赋值
        ParmImpl parmImpl = new ParmImpl();
        parmImpl.setParameter(arrayNode);

        return mapper.writeValueAsString(parmImpl).getBytes(StandardCharsets.UTF_8);
    }
}


打包

将程序和依赖 jar 分离打包

  • 程序保存 ./jar/co/ 目录下
  • 依赖保存 ./jar/lib/ 目录下
xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.kanq</groupId>
  <artifactId>co-service-ext</artifactId>
  <version>1.0.1</version>
  <packaging>jar</packaging>

  <name>co_service_web_ext_demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <!-- 打包不含依赖jar -->
  <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

  <!-- 依赖包导出lib文件夹下 -->
  <build>
        <finalName>Ext</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.2.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!--<fork>true</fork>-->
                    <layout>ZIP</layout>
                    <includes>
                        <include>
                            <!-- 排除所有Jar -->
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- ${project.build.directory}是maven变量,内置的,表示target目录,如果不写,将在跟目录下创建/lib -->
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <!-- excludeTransitive:是否不包含间接依赖包,比如我们依赖A,但是A又依赖了B,我们是否也要把B打进去 默认不打-->
                            <excludeTransitive>false</excludeTransitive>
                            <!-- 复制的jar文件去掉版本信息 true去掉 false 不去-->
                            <stripVersion>false</stripVersion>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.kanq</groupId>
  <artifactId>co-service-ext</artifactId>
  <version>1.0.1</version>
  <packaging>jar</packaging>

  <name>co_service_web_ext_demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <!-- 打包不含依赖jar -->
  <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

  <!-- 依赖包导出lib文件夹下 -->
  <build>
        <finalName>Ext</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.2.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!--<fork>true</fork>-->
                    <layout>ZIP</layout>
                    <includes>
                        <include>
                            <!-- 排除所有Jar -->
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- ${project.build.directory}是maven变量,内置的,表示target目录,如果不写,将在跟目录下创建/lib -->
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <!-- excludeTransitive:是否不包含间接依赖包,比如我们依赖A,但是A又依赖了B,我们是否也要把B打进去 默认不打-->
                            <excludeTransitive>false</excludeTransitive>
                            <!-- 复制的jar文件去掉版本信息 true去掉 false 不去-->
                            <stripVersion>false</stripVersion>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

注意

  • 新接口需重启 co-service 后才能生效

启动服务

扩展开发注册成功如下:

20250226145623

注意

  • co-service 日志级别为 调试

测试初始化 init 处理方法

流程发送前置处理扩展方法前: 20250226145112

流程发送前置处理扩展方法后: 20250226150427

测试后置 destroy 处理方法

流程发送查询接收人后置处理扩展方法前: 20250226144320

流程发送查询接收人后置处理扩展方法后: 20250226145908

DEMO 代码下载

本示例代码在 com.kanq.FlowDemo 类中的 flowSendDestroysendCommitInit 方法

Powerd by Vitepress.