在“类 xxx”上设置“xxx”时捕获意外异常:用值 [“x”,] 设置表达式“xxx”时出错

2023-12-28

我将一些参数传递给一个执行操作的类ModelDriven<Transporter>通过查询字符串。

<s:form namespace="/admin_side" action="Test" id="dataForm" name="dataForm">
    <s:url id="editURL" action="EditTest" escapeAmp="false">
        <s:param name="transporterId" value="1"/>
        <s:param name="transporterName" value="'DHL'"/>
    </s:url>
    <s:a href="%{editURL}">Click</s:a>
</s:form>

动作类如下。

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "struts-default")
public final class TestAction extends ActionSupport 
                           implements Serializable, Preparable, ModelDriven<Transporter>
{
    private static final long serialVersionUID = 1L;
    private Transporter transporter = new Transporter();

    @Action(value = "Test",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "paramsPrepareParamsStack", 
                 params = {"params.acceptParamNames", "transporterId, transporterName"})})
    public String load() throws Exception {
        return ActionSupport.SUCCESS;
    }

    @Action(value = "EditTest",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "paramsPrepareParamsStack", 
                 params = {"params.acceptParamNames", "transporterId, transporterName"})})
    public String edit() {
        System.out.println(transporter.getTransporterId() 
                         + " : " + transporter.getTransporterName());
        return ActionSupport.SUCCESS;
    }

    @Override
    public Transporter getModel() {
        return transporter;
    }

    @Override
    public void prepare() throws Exception {}
}

服务器终端显示以下消息。

Jan 09, 2014 4:06:32 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor error
SEVERE: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'transporterId' on 'class actions.TestAction: Error setting expression 'transporterId' with value ['1', ]
Jan 09, 2014 4:06:32 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor error
SEVERE: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'transporterName' on 'class actions.TestAction: Error setting expression 'transporterName' with value ['DHL', ]

即使日志级别是SEVERE,这些参数的值在操作类中可用,如下所示

System.out.println(transporter.getTransporterId() 
                 + " : " + transporter.getTransporterName());

in the edit() method.

If paramsPrepareParamsStack被替换为defaultStack然后,这些消息就会消失。

表达如['DHL', ]表示一个数组。transporterId and transporterName在模型中,但是类型Long and String分别。

我究竟做错了什么?


这里不涉及数组问题(即使看起来是这样):这种异常意味着 Struts 无法为您的参数找到 Setter:

From 参数拦截器文档 http://struts.apache.org/core-developers/parameters-interceptor.html:

缺少参数时发出警告

当给定参数名称没有设置器时,会出现警告消息 如下所示将在 devMode 中登录:

SEVERE: Developer Notification (set struts.devMode to false to disable this 
message):
Unexpected Exception caught setting 'search' on 'class demo.ItemSearchAction: 
Error setting expression 'search' with value ['search', ]
Error setting expression 'search' with value ['search', ] - [unknown location] 
  at com.opensymphony.xwork2.ognl.OgnlValueStack.handleRuntimeException(OgnlValueStack.java:201)
  at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:178)
  at com.opensymphony.xwork2.ognl.OgnlValueStack.setParameter(OgnlValueStack.java:152)

因此,预期的行为是允许开发人员发现丢失的 setter 或参数名称或设置器中的拼写错误。

通过将 Action 中不存在的元素放入 JSP 中,您可以轻松地重现此错误。

由于您的属性(及其设置器)存在于模型中,并且您正在使用ModelDriven and paramsPrepareParamsStack,我认为发生的事情是:

  • ModelDriven Interceptor被委托处理 Model 对象;
  • 第一次打电话的时候Parameters Interceptor, ModelDriven Interceptor还没有运行;
  • 那么你的 Action 对 Model 对象一无所知,并尝试在 Action 中而不是在 Model 中找到你的参数的 Setter。
  • 第二个拦截器在 ModelDriven 拦截器之后运行,并且确切地知道在哪里设置参数。这就是您在 Action 方法中正确设置参数的原因。

但如果这是真的,那么你应该NOT能够检索这些参数prepare()方法(这就是你使用这个堆栈的原因......):
请尝试,并在此处发布结果。

要解决这个问题,我想到的第一件事就是将ModelDriven Interceptor在第一个之前Parameters Interceptor(通过复制它或移动它,我不确定在这两种情况下都会产生哪种副作用(如果有的话),您应该再次尝试并在此处报告)。

然后定义以下堆栈并使用它。

<interceptor-stack name="modelParamsPrepareParamsStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="multiselect"/>

    <!-- NEW ModelDriven Position -->
    <interceptor-ref name="modelDriven"/>

    <interceptor-ref name="params">
        <param name="excludeParams">^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
    </interceptor-ref>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="prepare"/>
    <interceptor-ref name="chain"/>

    <!-- OLD ModelDriven Position -->
    <!--interceptor-ref name="modelDriven"/-->

    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="params">
        <param name="excludeParams">^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
    </interceptor-ref>
    <interceptor-ref name="conversionError"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="workflow">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
</interceptor-stack>

希望有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在“类 xxx”上设置“xxx”时捕获意外异常:用值 [“x”,] 设置表达式“xxx”时出错 的相关文章

随机推荐