意外的exception在class xxx上设置了'xxx':设置值为'x'的错误'xxx'

我通过查询string将一些parameter passing给实现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 {} } 

服务器terminal显示以下消息。

 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 ,这些参数的值也可以在action类中使用

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

edit()方法中。

如果paramsPrepareParamsStackdefaultStackreplace,那么这些消息就会消失。

['DHL', ]这样的expression式表示一个数组。 模型中的transporterIdtransporterName分别是LongStringtypes。

我究竟做错了什么?

这里没有涉及数组问题(即使看起来像这样):这种exception意味着Struts无法为您的参数findSetter:

从ParametersInterceptor文档 :

警告缺less参数

当给定参数名称没有setter时,将在devMode中logging如下所示的警告消息:

 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或typo。

您可以通过在Action中不存在的JSP中添加一个元素来轻松地重现此错误。

由于你的属性存在(与他们的Setters)在模型中,并且你正在使用ModelDrivenparamsPrepareParamsStack ,我所想要的是:

  • ModelDriven Interceptor被委托来处理Model对象;
  • 您第一次调用Parameters InterceptorModelDriven Interceptor尚未运行;
  • 然后你的Action对Model对象一无所知,并且试着在Action中find你的参数的Setters,而不是在Model中。
  • 第二个拦截器在ModelDriven之后运行,并确切知道在哪里设置参数。 这就是为什么你在Action方法中正确设置了参数的原因。

但是,如果这是真的,那么你应该能够在prepare()方法中检索这些参数(这就是你使用这个堆栈的原因)。
请尝试,并在这里张贴结果。

我想到解决这个问题的第一件事就是将ModelDriven Interceptor放置在第一个Parameters Interceptor ModelDriven 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> 

希望有所帮助。