Struts2升级至6.3.0.2后chain结果类型丢失actionMessages问题咨询
问题场景
我通过以下代码添加ActionMessages:
this.addActionMessage("alert:" + getText("message.display.Sucess"));
Struts配置如下:
<action name="resetpass" method="resetpass" class="com.UserAction"> <result type="chain">usersAdmin</result> </action> <action name="usersAdmin" method="usersAdmin" class="com.UserAction"> <result name="List">/jsp/templates/admin/user/UserAdmin.jsp </result>
使用Struts2 2.5.33时,点击重置按钮后alert可正常显示;但升级至6.3.0.2后,调用新action时actionMessages值为null,无法保留。我了解到chain结果类型会重建请求和action上下文,但为何旧版本无此问题?
已尝试的临时方案:显式添加store拦截器(STORE/RETRIVE)可保留值,使用request.setAttribute("message",this.getActionMessages())也有效,但这类操作在多处使用不太合适。
变更原因
Struts2 6.x系列对Chain结果类型的上下文传递机制做了严格规范。在2.5.x版本中,Chain结果会默认将原Action的ActionMessages、ActionErrors等消息对象,通过ActionContext的内部映射直接传递给后续Action;但6.x版本为了遵循Servlet规范的请求隔离原则,修复了Chain结果中跨Action上下文数据泄露的潜在问题,默认不再自动传递这些消息对象,而是要求开发者显式声明数据传递规则。
合适的修复方案
方案1:全局配置Store拦截器(推荐)
在struts.xml中配置全局拦截器栈,将store拦截器加入,统一处理消息传递:
<interceptors> <interceptor-stack name="defaultStack"> <interceptor-ref name="store"> <param name="operationMode">AUTOMATIC</param> </interceptor-ref> <!-- 保留原有的默认拦截器 --> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors>
AUTOMATIC模式会自动在Chain结果的前后完成消息的存储与恢复,无需在每个Action单独配置。
方案2:针对单个Action配置Store拦截器
如果不需要全局生效,可在涉及Chain跳转的Action中单独配置:
<action name="resetpass" method="resetpass" class="com.UserAction"> <interceptor-ref name="store"> <param name="operation">STORE</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> <result type="chain">usersAdmin</result> </action> <action name="usersAdmin" method="usersAdmin" class="com.UserAction"> <interceptor-ref name="store"> <param name="operation">RETRIEVE</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> <result name="List">/jsp/templates/admin/user/UserAdmin.jsp</result> </action>
方案3:使用Struts2的MessageStore接口(代码层面优化)
如果不想依赖拦截器,可在Action中通过MessageStore工具类显式处理消息传递,避免直接操作request:
// 在resetpass方法中存储消息 MessageStore messageStore = ActionContext.getContext().get(MessageStore.class); if (messageStore != null) { messageStore.store(ActionContext.getContext()); } // 在usersAdmin方法中恢复消息 MessageStore messageStore = ActionContext.getContext().get(MessageStore.class); if (messageStore != null) { messageStore.retrieve(ActionContext.getContext()); }
内容的提问来源于stack exchange,提问作者priya Jain

