Java 在“class xxx”上设置“xxx”时捕获到意外异常:将表达式“xxx”设置为值 ['x', ] 时出错
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21018018/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unexpected Exception caught setting 'xxx' on 'class xxx: Error setting expression 'xxx' with value ['x', ]
提问by Tiny
I'm passing some parameters to an action class implementing ModelDriven<Transporter>
through a query-string.
我将一些参数传递给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>
The action class is as follows.
动作类如下。
@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 {}
}
The server terminal displays the following messages.
服务器终端显示以下消息。
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', ]
Even though the log level is SEVERE
, the values of these parameters are available in the action class as
即使日志级别是SEVERE
,这些参数的值在操作类中也可用
System.out.println(transporter.getTransporterId()
+ " : " + transporter.getTransporterName());
in the edit()
method.
在edit()
方法。
If paramsPrepareParamsStack
is replaced by defaultStack
then, these messages disappear.
如果paramsPrepareParamsStack
被defaultStack
then替换,这些消息就会消失。
Expressions like ['DHL', ]
indicate an array. transporterId
and transporterName
in the model are, however of type Long
and String
respectively.
像这样的表达式['DHL', ]
表示一个数组。transporterId
和transporterName
在模型中,然而分别是类型Long
和String
。
What am I doing wrong?
我究竟做错了什么?
采纳答案by Andrea Ligios
No array problem is involved here (even if it seems like that): this kind of exception means that Struts can't find a Setter for your parameter:
这里不涉及数组问题(即使看起来是这样):这种异常意味着 Struts 无法为您的参数找到 Setter:
From ParametersInterceptor documentation:
Warning on missing parameters
When there is no setter for given parameter name, a warning message like below will be logged in 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)
Thus is expected behaviour to allow developer to spot missing setter or typo in either parameter name or setter.
缺少参数的警告
当给定参数名称没有设置器时,将在 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 中发现缺失的 setter 或错字是预期的行为。
You can easily reproduce this error by putting an element in JSP that does not exist in the Action.
您可以通过在 JSP 中放置一个在 Action 中不存在的元素来轻松重现此错误。
Since your properties exist (with their Setters) in the Model, and you are using ModelDriven
and paramsPrepareParamsStack
, what I think is going on is:
由于您的属性存在于模型中(及其设置器),并且您正在使用ModelDriven
and paramsPrepareParamsStack
,我认为正在发生的是:
ModelDriven Interceptor
is delegated to handle the Model object;- The first time you call
Parameters Interceptor
,ModelDriven Interceptor
has not run yet; - Then your Action knows nothing about the Model object, and try to find the Setters for your parameters in the Action, NOT in the Model.
- The second interceptor instead runs after the ModelDriven one, and knows exactly where to set the parameters. This is why you have the parameters correctly set in the Action method.
ModelDriven Interceptor
被委托处理模型对象;- 第一次调用
Parameters Interceptor
,ModelDriven Interceptor
还没跑; - 然后您的操作对模型对象一无所知,并尝试在操作中而不是在模型中找到您的参数的设置器。
- 第二个拦截器在 ModelDriven 之后运行,并且确切地知道在哪里设置参数。这就是您在 Action 方法中正确设置参数的原因。
But if this is true, then you should NOTbe able to retrieve those parameters in the prepare()
method (that is the reason you are using this stack...):
please try, and post here the result.
但是,如果这是真的,那么你应该不能够检索在这些参数prepare()
的方法(即您使用该堆栈...的原因):
请尝试,并张贴在这里的结果。
The first thing that comes to my mind to resolve this issue, is to place the ModelDriven Interceptor
before the first Parameters Interceptor
(by either copying it, or by moving it, I'm not sure which kind of side effect, if any, it could produce in both cases, you should again try and reporting it here).
我想到解决这个问题的第一件事是将第一个放在第一个ModelDriven Interceptor
之前Parameters Interceptor
(通过复制它或移动它,我不确定哪种副作用,如果有的话,它会在两者中产生)情况,您应该再次尝试并在此处报告)。
Then define the following stack, and use it.
然后定义如下堆栈,并使用它。
<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>
Hope that helps.
希望有帮助。
回答by ghshan
In the code that you have given, I can't find the declaration of the Transporter Class.
在您提供的代码中,我找不到 Transporter 类的声明。
So I guess that maybe it is because your Transpoter class has more parameters than 2, not just id and name.
所以我想这可能是因为您的 Transpoter 类的参数多于 2 个,而不仅仅是 id 和 name。
In fact, this error message always occurred on the situation I mentioned.
事实上,这个错误信息总是出现在我提到的情况下。
To solve this problem, you can define a data transport object(DTO) which only has 2 attributes,id and name. Use this DTO to accept parameters from the jsp, and then pass the attributes value to the Transporter object.
为了解决这个问题,你可以定义一个数据传输对象(DTO),它只有 2 个属性,id 和 name。使用这个 DTO 从 jsp 接受参数,然后将属性值传递给 Transporter 对象。
I see this problems in 2019, and offer a solution, hoping that it can be of use by others in the future.
2019年看到这个问题,提出解决方案,希望以后能帮到大家。