主要问题
工作流程应该是这样的:如果输入的是不是数字的String,首先要通过异常拦截器,通过param拦截器时,转换为int类型时,使用Integer.parseInt
and an会发生异常;不应该将该异常(即NumberFormatException
)推入 Value Stack 吗?NumberFormatException
即使不应打印结果,为什么它不显示和显示结果?
副题
每当我在表单中添加一个字母表时,它就会变成零...?为什么这样 ?
索引.jsp
<%@ taglib uri="/struts-tags" prefix="s"%>
<s:form action="divide">
<s:textfield name="number1" label="number1"/>
<s:textfield name="number2" label="number2"/>
<s:submit value="divide"/>
</s:form>
除法.java
package actions;
public class divide {
int number1,number2,result;
public String execute() throws Exception
{
result=number1/number2;
return "success";
}
public int getNumber1() {
return number1;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public int getNumber2() {
return number2;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
public int getResult() {
return result;
}
}
结果.jsp
<%@taglib uri="/struts-tags" prefix="s" %>
<b>
the result of division is
<s:property value="result"/>
</b>
<jsp:include page="index.jsp"></jsp:include>
处理程序jsp
<%@taglib uri="/struts-tags" prefix="s"%>
<b>
following exception occured during the processing
<s:property value="exception"/>
</b>
<jsp:include page="index.jsp"/>
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="yo" extends="struts-default">
<action name="divide" class="actions.divide">
<exception-mapping result="error" exception="Exception"/>
<result name="success">/result.jsp</result>
<result name="error">/handler.jsp</result>
</action>
</package>
</struts>
概念
Struts 2 自动处理转换错误和验证错误:它不会引发异常,因为它们不是阻塞错误,而是输入错误,因此最好的处理方式是通知用户提交的输入是错误的,询问他对于新的有效输入。为此,将返回 INPUT 结果,而忽略 Exception。
详细工作流程
在
Parameters Interceptor
试图设置的参数。如果一个RuntimeException
(likeNumberFormatException
) 被捕获并且devMode
是true
,则会向 中添加一条错误消息Action Errors
,否则将简单地吞下异常。从源代码:for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) { String name = entry.getKey(); Object value = entry.getValue(); try { newStack.setParameter(name, value); } catch (RuntimeException e) { if (devMode) { String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ "Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage() }); LOG.error(developerNotification); if (action instanceof ValidationAware) { ((ValidationAware) action).addActionMessage(developerNotification); } } } }
在
Conversion Errors Interceptor
为每一个找到,它增加了一个:如果任何转换误差发生的检查Field Error
; 它还保存原始值,以便对该值的任何后续请求都返回原始值而不是 action 中的值。从文档:在
Validation Interceptor
所有的验证请求的执行(在XML,注解或通过定义的validate()
或validateXXX()
行动的方法),将一个或多个错误消息到Field Errors
每个字段不通过一个或多个验证标准。该
Workflow Interceptor
检查是否存在Field Errors
(无论是从转换错误或验证错误来)。如果没有发现错误,它将继续链接到下一个拦截器。如果发现一个或多个错误,则返回 INPUT 结果。为确保此机制有效,您需要在自定义堆栈中以正确的顺序定义这四个拦截器,如果您不使用默认拦截器堆栈(否则您无需执行任何操作)。来自
struts-default.xml
:<!-- others interceptors here... --> <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> <!-- ... others interceptors here -->
最初的答案是:框架在向服务器发布请求时无法将 a 设置
String
为int
字段,并且在检索结果页面中的值时,它调用该变量的 Getter;由于您定义了 anint
而不是 anInteger
,并且 anint
不能为空,因此它将返回 an 的默认值int
:0。但我不记得转换拦截器声称(阅读第 2 点)保存原始值,在后续的未来请求中提供它们,代替 Action 值(即 null 或 0)。这也在类型转换错误处理中提到:
相反,我记得你的问题中描述的行为。所以这个案子已经处理了......为什么它不起作用呢?罪魁祸首,在我的情况下(也可能是你的),是
value
属性:这将
0
在发布时为您提供abc
:<s:textfield name = "myIntField" value = "%{getText('format.number',{myIntField})}" />
因为发生了进一步的转换错误。
这两种情况改为如上所述工作,
abc
在发布时为您提供abc
:<s:textfield name = "myIntField" /> <s:textfield name = "myIntField" value = "%{myIntField}" />
结论
value
属性做了什么。出于测试目的,首先尝试删除该
value
属性,看看它是否以正确的方式工作,然后开始寻找错误。