意外的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()
方法中。
如果paramsPrepareParamsStack
被defaultStack
replace,那么这些消息就会消失。
像['DHL', ]
这样的expression式表示一个数组。 模型中的transporterId
和transporterName
分别是Long
和String
types。
我究竟做错了什么?
这里没有涉及数组问题(即使看起来像这样):这种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)在模型中,并且你正在使用ModelDriven
和paramsPrepareParamsStack
,我所想要的是:
-
ModelDriven Interceptor
被委托来处理Model对象; - 您第一次调用
Parameters Interceptor
,ModelDriven 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>
希望有所帮助。