泛微E9 workflowService流程API开发实战指南
2026/9/10 2:14:14 网站建设 项目流程

简介:本资源是一份面向Java开发者与泛微E9流程定制实施人员的实战型开发Demo,聚焦workflowService流程引擎的RESTful集成与全流程CRUD操作实践。通过该Demo可系统掌握E9平台中流程模板的创建、部署、修改、删除及实例查询等核心能力,并深入理解如何基于HTTP接口(GET/POST/PUT/DELETE)与企业现有系统(如CRM、OA)实现审批流自动触发与状态同步。资源共41个文件,含11个Java源码、12个编译后Class、8个关键依赖Jar(如fastjson、httpclient、fel-all等)、5个配置XML及RSA密钥等安全组件,整体24.75MB,结构清晰,便于快速定位接口调用逻辑与流程建模代码。已有1955人学习下载,配套readme.md说明与E9对外API文档,开箱即用,适合需落地流程自动化、开展二次开发或备考泛微认证的技术人员。

1. 泛微 E9 workflowService 流程开发 demo 不是“玩具”,而是能直接跑通生产级流程 API 的最小可验证闭环

很多刚接触泛微 E9 的开发者,第一次看到workflow-restful-demo这个名字,下意识以为是教学用的静态页面或模拟请求工具。但实际解压后你会发现:它带完整 Maven 结构、含 RSA 加密依赖、封装了HttpURLConnection+httpclient-4.4.1双通道调用逻辑、所有接口都直连 E9 的/api/路径——这不是演示,是一套已通过泛微 E9 v9.8+ 环境实测的流程资源操作骨架。它解决的核心问题是:如何在不依赖泛微 ECOS 开发平台(即不走设计器导出 XML)的前提下,用标准 HTTP 协议完成流程模板的全生命周期管理。适合两类人:一是需要将 OA 审批能力嵌入自有业务系统(如 ERP、CRM)的后端工程师;二是正在做泛微二次开发交付、需快速验证流程 API 权限与参数组合的实施顾问。关键在于,它绕开了泛微传统「流程发布 → 导出 XML → 手动导入」的低效链路,把「增删改查」真正变成可编程、可测试、可 CI/CD 的原子操作。

2. RESTful 接口选型与泛微 E9 workflowService 协议层深度解析

2.1 为什么必须用 workflowService 而非 workflowEngine 或 processService?

泛微 E9 的流程服务存在多个命名相似的接口模块,但workflowService是唯一支持流程模板级 CRUD的 REST 接口集合。workflowEngine主要面向流程实例运行时控制(如启动、驳回、加签),processService则聚焦于流程定义的元数据查询(如获取节点列表)。而本 demo 中com.test.workflow.rest包下的核心类WorkflowRestClient明确指向/api/workflowService/前缀路径,其依据来自泛微官方《E9 流程对外 API(REST).zip》文档第 3.2 节:“workflowService提供流程模板的创建、更新、删除及版本管理能力,适用于第三方系统集成场景”。这意味着:若你尝试用processServicePOST /api/processService/create发送流程模板 JSON,服务器会返回405 Method Not Allowed—— 因为该接口仅接受 GET 查询。

提示:泛微 E9 的 REST 接口权限校验极为严格。workflowService相关接口默认仅开放给admin角色,普通用户即使拥有流程设计权限,也需在后台【系统管理】→【安全管理】→【API 权限配置】中显式勾选workflowService.*才能调用。未配置时,所有请求均返回{"code":403,"msg":"无权访问"},而非 401 认证失败。

2.2 请求头与认证机制:RSA 非对称加密 + Session Token 双重校验

demo 中keys/RSA-0.0.1-SNAPSHOT.jar并非泛微官方 SDK,而是项目组自行封装的 RSA 工具包,用于生成符合泛微要求的X-Auth-Token。其逻辑如下:

// com.test.util.RSAUtil.java 片段 public static String generateAuthToken(String username, String password) throws Exception { // 1. 使用公钥(从 E9 后台【系统管理】→【安全管理】→【密钥管理】导出)加密密码 String encryptedPassword = RSAUtil.encryptByPublicKey(password, "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu...-----END PUBLIC KEY-----"); // 2. 拼接 username:encryptedPassword 并 Base64 编码 String authStr = username + ":" + encryptedPassword; return Base64.getEncoder().encodeToString(authStr.getBytes(StandardCharsets.UTF_8)); }

X-Auth-Token需配合Cookie: JSESSIONID=xxx使用。JSESSIONID 不能硬编码,必须通过首次登录请求获取:

# 第一步:POST 登录获取 JSESSIONID 和 Set-Cookie curl -X POST "http://e9-server:8080/api/login" \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"encrypted_pwd"}' \ -i # 响应头中提取 Set-Cookie: JSESSIONID=ABC123DEF456; Path=/; HttpOnly

注意:httpclient-4.4.1.jar在 demo 中被用于自动管理 Cookie,但HttpURLConnection实现(见src/com/test/http/HttpUtil.java)需手动处理Cookie头。若忽略此步,所有后续请求将因401 Unauthorized失败——因为泛微 E9 的workflowService接口强制校验 Session 有效性,且 Session 与 Token 绑定。

2.3 流程模板 JSON 结构:字段含义与必填约束

workflow-restful-demo/src/main/resources/template.json定义了标准流程模板结构。关键字段解析如下:

字段名类型是否必填说明示例值
namestring流程名称(唯一性校验)"采购审批流程_v2"
codestring流程编码(英文+数字,全局唯一)"proc_pur_2024"
versioninteger版本号,新增时为 1,更新时递增1
nodesarray节点数组,至少包含 start/end[{"id":"start1","type":"start","name":"开始"},{"id":"end1","type":"end","name":"结束"}]
transitionsarray流转关系,定义节点间连接[{"from":"start1","to":"end1","condition":"true"}]
variablesobject流程变量定义,用于表单绑定{"amount":{"type":"double","required":true}}

特别注意:nodes中的type必须为泛微预定义类型(start/end/userTask/serviceTask/parallelGateway),自定义类型会导致400 Bad RequestuserTask节点需指定assigneeTypeuser/role/dept)和assigneeId(对应 ID),否则保存失败。

3. 流程增删改查四步实战:从模板创建到实例追踪

3.1 创建新流程模板:POST /api/workflowService/create

WorkflowRestClient.createWorkflow()方法封装了完整创建逻辑。核心步骤如下:

// com.test.workflow.rest.WorkflowRestClient.java public String createWorkflow(String templateJson) throws IOException { URL url = new URL("http://e9-server:8080/api/workflowService/create"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); conn.setRequestProperty("X-Auth-Token", generateAuthToken("admin", "pwd")); conn.setRequestProperty("Cookie", "JSESSIONID=" + sessionId); // 写入 JSON 数据 try (OutputStream os = conn.getOutputStream()) { os.write(templateJson.getBytes(StandardCharsets.UTF_8)); } // 解析响应 int responseCode = conn.getResponseCode(); if (responseCode == 200) { return readResponse(conn.getInputStream()); // 返回 {"code":0,"data":{"id":"12345","name":"采购审批流程_v2"}} } else { throw new RuntimeException("Create failed: " + responseCode + ", " + readResponse(conn.getErrorStream())); } }

参数说明:

  • templateJson:必须是合法 JSON 字符串,nodestransitions数组不能为空;
  • X-Auth-Token:由RSAUtil.generateAuthToken()生成,密码必须经公钥加密;
  • Cookie:必须携带有效的JSESSIONID,否则返回401
  • 成功响应data.id即为流程模板 ID,后续操作均需此 ID。

3.2 查询流程模板:GET /api/workflowService/{id}

WorkflowRestClient.getWorkflowById()支持按 ID 精确查询。需注意两点:

  1. URL 编码问题:若流程 ID 含特殊字符(如/),必须URLEncoder.encode(id, "UTF-8")
  2. 版本控制:泛微 E9 默认返回最新版本,若需指定版本,需在 URL 后加?version=2
# 正确请求(ID 为纯数字) curl -X GET "http://e9-server:8080/api/workflowService/12345" \ -H "X-Auth-Token: YWRtaW46YWJjMTIz..." \ -H "Cookie: JSESSIONID=ABC123DEF456" # 响应包含完整 nodes/transitions 结构,可用于前端渲染流程图

3.3 更新流程模板:PUT /api/workflowService/update

更新操作不是 PATCH,而是全量替换。updateWorkflow()方法要求传入完整模板 JSON(含id字段),且version必须比当前版本高 1:

// templateJson 必须包含 "id":"12345" 和 "version":2 String updatedJson = templateJson.replace("\"version\":1", "\"version\":2"); String result = client.updateWorkflow(updatedJson); // 调用 PUT 接口

version不匹配,返回{"code":500,"msg":"版本号错误,应为2"}。这是泛微防止并发修改的强一致性设计。

3.4 删除流程模板:DELETE /api/workflowService/{id}

删除前需确认该流程无运行中实例,否则返回{"code":500,"msg":"该流程存在运行中的实例,无法删除"}deleteWorkflow()方法实现:

public void deleteWorkflow(String id) throws IOException { URL url = new URL("http://e9-server:8080/api/workflowService/" + id); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("DELETE"); // 注意:不是 POST conn.setRequestProperty("X-Auth-Token", token); conn.setRequestProperty("Cookie", "JSESSIONID=" + sessionId); int code = conn.getResponseCode(); if (code != 200) { throw new RuntimeException("Delete failed: " + code); } }

提示:泛微 E9 的 DELETE 接口不接受请求体(body),所有参数必须通过 URL 路径传递。若误加-d '{}',将导致400 Bad Request

4. 流程实例操作与监控权限绕过技巧

4.1 启动流程实例:POST /api/workflowEngine/start

workflowService管理模板,workflowEngine管理实例。启动实例需提供模板 ID 和表单数据:

{ "workflowId": "12345", "formData": { "amount": 5000.0, "reason": "服务器采购" }, "starter": "zhangsan" }

关键点:starter必须是 E9 系统中存在的用户名,且该用户需有流程启动权限(在流程模板的【启动权限】设置中配置)。若未配置,返回{"code":403,"msg":"用户 zhangsan 无权启动此流程"}

4.2 查询流程实例状态:GET /api/workflowEngine/instances

支持多条件过滤。常用参数:

参数类型说明示例
workflowIdstring模板 ID12345
statusstring实例状态(running/completed/abortedrunning
startTimestring开始时间(ISO8601)2024-06-01T00:00:00
pageSizeinteger分页大小10
curl -X GET "http://e9-server:8080/api/workflowEngine/instances?workflowId=12345&status=running&pageSize=5" \ -H "X-Auth-Token: ..." \ -H "Cookie: ..."

4.3 “没有监控权限也能点开”的真实解法:利用流程实例 ID 直接跳转

网络热词“怎么配置没有监控权限也能点开”本质是规避泛微后台【流程监控】菜单的权限限制。正确做法不是修改权限,而是构造前端 URL:

http://e9-server:8080/wui/Resource/Process/ProcessInstanceDetail.jsp?instanceId=67890

其中instanceId为流程实例 ID(启动成功后返回的data.id)。该页面仅校验用户是否为流程参与者(发起人、审批人、抄送人),不校验【流程监控】菜单权限。因此,在自有系统中,只需将instanceId嵌入<a href="...">查看详情</a>即可实现免权限跳转。

注意:此 URL 依赖 E9 前端资源路径,若 E9 升级至 v10.x,路径可能变为/wui/portal/ProcessInstanceDetail.jsp,需根据实际环境调整。

4.4 获取流程 ID 的三种可靠方式

针对热词“泛微获取流程id”,明确以下优先级:

  1. 创建时返回POST /api/workflowService/create成功响应中的data.id(最准确);
  2. 按名称查询GET /api/workflowService/list?name=采购审批流程_v2,遍历结果匹配name字段;
  3. 按编码查询GET /api/workflowService/list?code=proc_pur_2024,泛微保证code全局唯一,推荐此方式。

避免使用GET /api/workflowService/list不带参数全量拉取——当流程数超 1000 时,响应体积过大易超时。

5. 生产环境避坑指南:SSL 证书、超时设置与日志定位

5.1 HTTPS 调用必须处理泛微自签名证书

若 E9 部署 HTTPS 且使用自签名证书(常见于内网环境),httpclient-4.4.1默认拒绝连接。需在HttpClient初始化时添加信任策略:

// com.test.http.HttpClientFactory.java public static CloseableHttpClient createTrustAllClient() { SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(null, (chain, authType) -> true) // 信任所有证书 .build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext, NoopHostnameVerifier.INSTANCE); return HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); }

提示:生产环境严禁使用trustAll策略。正确做法是将 E9 的 CA 证书导入 JVM truststore:keytool -import -alias e9-ca -file e9.crt -keystore $JAVA_HOME/jre/lib/security/cacerts

5.2 连接超时与读取超时的合理设置

泛微 E9 流程保存涉及数据库事务,耗时较长。HttpURLConnection默认超时为无穷,需显式设置:

conn.setConnectTimeout(5000); // 连接建立超时 5 秒 conn.setReadTimeout(30000); // 响应读取超时 30 秒

httpclient-4.4.1对应配置:

RequestConfig config = RequestConfig.custom() .setConnectTimeout(5000) .setSocketTimeout(30000) .setConnectionRequestTimeout(5000) .build(); CloseableHttpClient client = HttpClients.custom() .setDefaultRequestConfig(config) .build();

若超时设置过短(如readTimeout=5000),流程模板较大时(含 20+ 节点)易触发SocketTimeoutException

5.3 日志定位:从 HTTP 状态码快速判断故障根因

状态码常见原因定位方法
400 Bad RequestJSON 格式错误、必填字段缺失、version不合法检查template.json是否有语法错误;用在线 JSON 校验工具验证
401 UnauthorizedX-Auth-Token过期或格式错误、JSESSIONID无效抓包确认请求头是否含X-Auth-TokenCookie;重新登录获取新 Session
403 Forbidden用户无workflowServiceAPI 权限、流程启动权限不足登录 E9 后台,检查【API 权限配置】和流程模板的【启动权限】设置
404 Not FoundURL 路径错误(如误用/processService/)、流程 ID 不存在核对泛微官方文档路径;确认GET /api/workflowService/{id}中 ID 是否真实存在
500 Internal Error流程模板逻辑冲突(如循环流转)、数据库唯一索引冲突查看 E9 服务器logs/catalina.out,搜索Caused by:关键字

实际排错时,建议在WorkflowRestClientexecuteRequest()方法中增加日志:

log.info("Request URL: {}, Method: {}, Headers: {}", url, method, headers); log.debug("Request Body: {}", body); log.info("Response Code: {}, Response Body: {}", responseCode, responseBody);

这样可在不开启泛微 DEBUG 日志的情况下,快速复现请求上下文。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询