如何在Spring Web Flow中自定义Execution Key适配路径式URL
解决Spring Web Flow隐藏execution参数到路径的密钥格式问题
你遇到的问题很典型——当把execution参数从查询字符串移到URL路径后,默认的DefaultFlowExecutionKeyFactory只认e{snapshotId}s{executionId}这种紧凑格式,自然无法识别你自定义的路径式密钥,所以才会报密钥格式错误。要搞定这个问题,你需要自定义FlowExecutionKeyFactory来适配新的密钥格式,同时在配置里替换掉默认的工厂类。
下面是具体的实现步骤:
1. 自定义FlowExecutionKeyFactory
这个工厂类要完成两个核心工作:一是把路径里的executionId和snapshotId解析成WebFlow能识别的FlowExecutionKey;二是把FlowExecutionKey转换回你需要的路径格式。
import org.springframework.webflow.execution.FlowExecution; import org.springframework.webflow.execution.FlowExecutionKey; import org.springframework.webflow.execution.repository.support.DefaultFlowExecutionKey; import org.springframework.webflow.execution.repository.support.DefaultFlowExecutionKeyFactory; public class PathBasedFlowExecutionKeyFactory extends DefaultFlowExecutionKeyFactory { @Override public FlowExecutionKey parseKey(String encodedKey) { // 解析路径中的"executionId/snapshotId"格式 String[] parts = encodedKey.split("/"); if (parts.length != 2) { throw new IllegalArgumentException("Invalid flow execution key format: " + encodedKey + ". Expected 'executionId/snapshotId'"); } Long executionId = Long.parseLong(parts[0]); Integer snapshotId = Integer.parseInt(parts[1]); return new DefaultFlowExecutionKey(executionId, snapshotId); } @Override public String encodeKey(FlowExecutionKey key) { // 把密钥转换成路径格式的字符串 DefaultFlowExecutionKey defaultKey = (DefaultFlowExecutionKey) key; return defaultKey.getExecutionId() + "/" + defaultKey.getSnapshotId(); } @Override public FlowExecutionKey createKey(FlowExecution flowExecution) { // 生成新密钥时沿用默认逻辑,只修改编码格式 return super.createKey(flowExecution); } }
2. 完善自定义FlowUrlHandler
确保你的PathBasedFlowUrlHandler能正确从路径中提取密钥,并且生成符合格式的URL:
import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.execution.FlowExecution; import org.springframework.webflow.execution.FlowExecutionKey; import org.springframework.webflow.mvc.servlet.DefaultFlowUrlHandler; import javax.servlet.http.HttpServletRequest; import java.util.Map; public class PathBasedFlowUrlHandler extends DefaultFlowUrlHandler { @Override public String getFlowExecutionKey(HttpServletRequest request) { // 从路径末尾提取executionId/snapshotId String pathInfo = request.getPathInfo(); if (pathInfo == null || pathInfo.length() <= 1) { return null; } String[] segments = pathInfo.substring(1).split("/"); if (segments.length >= 2) { return segments[segments.length - 2] + "/" + segments[segments.length - 1]; } return super.getFlowExecutionKey(request); } @Override public String createFlowExecutionUrl(String flowId, FlowExecutionKey flowExecutionKey, ExternalContext context) { // 生成带路径密钥的URL,比如/flowId/1/1 String encodedKey = flowExecutionKey.toString(); return "/" + flowId + "/" + encodedKey; } @Override public String createFlowDefinitionUrl(String flowId, Map<String, Object> input, ExternalContext context) { // 启动流程的基础URL,比如/flowId return "/" + flowId; } }
3. 在WebFlow配置中注入自定义组件
修改你的WebflowConfig,在flowExecutor的配置里替换默认的密钥工厂:
@Configuration public class WebflowConfig extends AbstractFlowConfiguration { // ... 保留你原有的其他Bean配置 ... @Bean public FlowExecutor flowExecutor() { return getFlowExecutorBuilder(this.flowRegistry()) // 注入自定义的FlowExecutionKeyFactory .setFlowExecutionKeyFactory(pathBasedFlowExecutionKeyFactory()) .build(); } @Bean public FlowExecutionKeyFactory pathBasedFlowExecutionKeyFactory() { return new PathBasedFlowExecutionKeyFactory(); } // ... 保留你原有的其他Bean配置 ... }
关键注意点
- 自定义密钥工厂和URL处理器的格式必须严格匹配,不然会出现解析失败的问题。
- 确保视图里的跳转链接用WebFlow的标签生成(比如
<a href="${flowExecutionUrl}">),这样才能自动生成正确的路径式URL。 - 测试时注意启动流程的URL(比如
/my-flow)和后续步骤的URL(比如/my-flow/1/1)是否符合预期。
内容的提问来源于stack exchange,提问作者Nadir
相关产品推荐
相关产品推荐

