JSP+Struts项目刷新页面重复执行Action,如何指定刷新时调用目标Action
问题根因
你遇到的是经典的表单重复提交问题,核心原因是POST请求提交后没有做跳转,直接返回了视图:
你提交plantillasAction_processUpdateNavigator请求后,后端直接返回updateCoordinates对应的JSP页面渲染,浏览器没有触发地址栏跳转,所以地址栏URL停留在了提交Action的路径,刷新页面就会重新发起该Action的请求。
可选解决方案
方案1:采用PRG(Post/Redirect/Get)模式(最推荐,符合规范)
这是解决表单重复提交的标准方案,改动逻辑如下:
- 调整Struts配置,给Action增加
redirectAction类型的返回结果,让processUpdateNavigator执行完成后重定向到viewUpdateTemplateAction,而非直接返回视图 - 把
processUpdateNavigator中需要保留的参数(比如当前页码currentPosition、模板ID等)通过URL参数或者Session传递给viewUpdateTemplate
配置示例:
<action name="plantillasAction_*" method="{1}" class="com.xxx.action.ActionPlantillas"> <!-- 原有其他result配置保持不变 --> <result name="redirectToView" type="redirectAction"> <param name="actionName">plantillasAction_viewUpdateTemplate</param> <!-- 按需传递需要的参数 --> <param name="currentPosition">${currentPosition}</param> <param name="templateId">${templateId}</param> </result> <!-- 原有拦截器、允许方法配置保持不变 --> </action>
然后修改processUpdateNavigator方法的返回值:
public String processUpdateNavigator() { // 原有业务逻辑不变 return "redirectToView"; }
配置完成后,提交表单后浏览器会自动跳转到viewUpdateTemplate的URL,刷新页面就会执行你期望的Action,不会重复提交。
方案2:前端替换地址栏URL(改动最小)
如果不想调整后端逻辑,可以直接在JSP页面增加JS代码,页面加载完成后用History API替换地址栏的URL,不会触发页面刷新:
window.addEventListener('load', function() { // 拼接正确的viewUpdateTemplate访问路径 const targetUrl = '${pageContext.request.contextPath}/plantillasAction_viewUpdateTemplate.action'; window.history.replaceState(null, document.title, targetUrl); });
该方案兼容IE10及以上所有现代浏览器,不需要修改后端逻辑,适配成本极低。
方案3:翻页逻辑改为Ajax实现
如果想要更好的交互体验,可以把翻页按钮的提交逻辑改为Ajax异步请求,提交后只更新页面的页码、PDF预览等局部内容,不需要刷新整个页面,自然不会出现URL变化的问题,也不会有重复提交的问题。
关于多表单设计的疑问
你当前的多表单设计是合理的,不同业务逻辑拆分到不同表单职责更清晰,不需要强制改为Ajax实现,根据你的业务需求选择方案即可。
内容的提问来源于stack exchange,提问作者Sebastian Ruiz
相关产品推荐
相关产品推荐

