Struts 7.0.0中<s:property>标签获取Bean属性值失败问题求助
Struts 7.0.0中
<s:property>无法获取Bean属性值的问题解决 问题现象
将项目从Struts 2.3.x迁移至Struts 7.0.0后,出现<s:property value="hola.valor"/>无输出,但<s:property value="hola"/>能正常显示HelloBean的toString()内容的问题,即使修改Struts Sitemesh官方示例也复现该问题。
相关代码片段
Struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" "https://struts.apache.org/dtds/struts-6.0.dtd"> <struts> <constant name="struts.devMode" value="true"/> <constant name="struts.ui.theme" value="simple"/> <constant name="struts.action.extension" value=""/> <constant name="struts.custom.i18n.resources" value="DefaultMessages"/> <package name="default" extends="struts-default"> <default-action-ref name="index"/> <action name="index"> <result>/WEB-INF/index.jsp</result> </action> <action name="hello" class="org.apache.struts.examples.sitemesh3.HelloAction"> <result name="success">/WEB-INF/hello1.jsp</result> <result name="other">/WEB-INF/hello2.jsp</result> <result name="error">/WEB-INF/error.jsp</result> </action> </package> </struts>
HelloBean.java
package org.apache.struts.examples.sitemesh3; public class HelloBean { private int numero; private String valor; public HelloBean(int numero, String valor) { this.numero = numero; this.valor = valor; } @Override public String toString() { return "HelloBean{" + "numero=" + numero + ", valor=" + valor + '}'; } public int getNumero() { return numero; } public void setNumero(int numero) { this.numero = numero; } public String getValor() { return valor; } public void setValor(String valor) { this.valor = valor; } }
HelloAction.java
package org.apache.struts.examples.sitemesh3; import org.apache.struts2.ActionSupport; import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Collections; import java.util.Map; import java.util.TreeMap; public class HelloAction extends ActionSupport { public HelloBean hola = new HelloBean(1, "Hola mundo"); private static final Map<String, String> DECORATORS = Collections.unmodifiableSortedMap(new TreeMap<>() {{ put("1", "Decorator 1"); put("2", "Decorator 2"); put("3", "Exclude from decorating"); }}); private String decorator; @Override public String execute() throws Exception { if ("1".equals(decorator)) { return SUCCESS; } else if ("2".equals(decorator)) { return "other"; } addActionError("Wrong decorator: " + decorator); return ERROR; } public String getDecorator() { return decorator; } @StrutsParameter public void setDecorator(String decorator) { this.decorator = decorator; } public Map<String, String> getDecorators() { return DECORATORS; } public HelloBean getHola() { return hola; } }
Hello2.jsp
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>SiteMesh example: Hello 2 with Decorator 2</title> </head> <body> <h2>SiteMesh example: Hello 2 with Decorator 2</h1> <h3>Decorators</h3> <div> <s:form action="hello" method="get"> <s:select name="decorator" list="decorators"/> <s:submit value="Decorate"/> </s:form> </div> <p>Selected decorator: <s:property value="decorator"/></p> <p><s:property value="hola.valor"/></p> <p><s:property value="hola"/> uno</p> </body> </html>
页面渲染结果
<html><head> <title>SiteMesh example: Hello 2 with Decorator 2</title> </head> <body> <h1>Decorator 2</h1> <h2>SiteMesh example: Hello 2 with Decorator 2</h2> <h3>Decorators</h3> <div> <form id="hello" name="hello" action="/sitemesh3/hello" method="get"> <select name="decorator" id="hello_decorator"> <option value="1">Decorator 1</option> <option value="2" selected="selected">Decorator 2</option> <option value="3">Exclude from decorating</option> </select> <input type="submit" value="Decorate" id="hello_0"> </form> </div> <p>Selected decorator: 2</p> <p></p> <p>HelloBean{numero=1, valor=Hola mundo} uno</p> </body></html>
问题原因
Struts 6.x及以上版本(含7.0.0)默认启用了严格的OGNL安全机制,同时要求JavaBean必须符合规范——即提供无参构造函数。你的HelloBean仅定义了带参构造函数,缺少无参构造,导致OGNL无法正常解析并访问其属性(虽然可以调用toString()方法,但属性路径解析失败)。而Struts 2.3.x对JavaBean规范的要求相对宽松,因此未出现该问题。
解决方案
给HelloBean添加无参构造函数,修改后的代码如下:
package org.apache.struts.examples.sitemesh3; public class HelloBean { private int numero; private String valor; // 添加无参构造函数 public HelloBean() { } public HelloBean(int numero, String valor) { this.numero = numero; this.valor = valor; } @Override public String toString() { return "HelloBean{" + "numero=" + numero + ", valor=" + valor + '}'; } public int getNumero() { return numero; } public void setNumero(int numero) { this.numero = numero; } public String getValor() { return valor; } public void setValor(String valor) { this.valor = valor; } }
添加后,<s:property value="hola.valor"/>即可正常输出Hola mundo。
补充说明
若因特殊场景无法添加无参构造,可尝试在struts.xml中调整OGNL相关配置(不推荐,可能带来安全风险):
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/> <constant name="struts.ognl.expression.evaluation" value="true"/>
但遵循JavaBean规范添加无参构造是更安全、合规的解决方案。
内容的提问来源于stack exchange,提问作者Ing. Margarita Velasco Perroni
相关产品推荐
相关产品推荐

