You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:20:00