package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
|
|
import cn.hutool.core.util.StrUtil;
|
|
import java.net.URLDecoder;
|
import java.nio.charset.StandardCharsets;
|
|
/**
|
* Flowable 流程定义编号工具
|
*
|
* <p>流程定义编号形如 {@code qingjia:2:553a7ac9-...},包含冒号。
|
* 前端如果对该值做了 URL 编码后再作为查询参数传递(双重编码),
|
* Spring 只解码一层,最终拿到的仍是 {@code qingjia%3A2%3A...},
|
* Flowable 按该编号查不到流程定义,直接抛 FlowableObjectNotFoundException 导致 500。
|
*
|
* <p>这里在入口处做一次幂等的归一化:只在确实残留 % 转义时才解码,
|
* 合法的流程定义编号不可能包含 %,因此不会误伤。
|
*
|
* @author 超级管理员
|
*/
|
public class BpmProcessDefinitionIdUtils {
|
|
/** 最多解码层数,防止异常输入无限循环 */
|
private static final int MAX_DECODE_TIMES = 5;
|
|
private BpmProcessDefinitionIdUtils() {
|
}
|
|
/**
|
* 归一化流程定义编号:最多解码一层残留的 URL 转义
|
*
|
* @param id 流程定义编号
|
* @return 归一化后的编号;入参为空时原样返回
|
*/
|
public static String normalize(String id) {
|
if (StrUtil.isBlank(id) || id.indexOf('%') < 0) {
|
return id;
|
}
|
// 前端可能编码多次(1~3 层都见过),逐层解码直到不再含 % 转义
|
String current = id;
|
for (int i = 0; i < MAX_DECODE_TIMES && current.indexOf('%') >= 0; i++) {
|
String decoded;
|
try {
|
decoded = URLDecoder.decode(current, StandardCharsets.UTF_8);
|
} catch (Exception ignored) {
|
// 解码失败说明不是 URL 转义,保持原值
|
break;
|
}
|
if (decoded.equals(current)) {
|
break;
|
}
|
current = decoded;
|
}
|
return current;
|
}
|
|
}
|