【问题标题】:Struts2 INPUT result: how does it work? How are conversion / validation errors handled?Struts2 INPUT 结果:它是如何工作的?如何处理转换/验证错误?
【发布时间】:2014-06-20 08:19:09
【问题描述】:

主要问题

工作流程应该是这样的:如果输入的不是数字的String,首先要通过异常拦截器,通过param拦截器的时候,在转换成int类型的时候就不行了使用Integer.parseInt 会发生异常;不应该将该异常(即NumberFormatException)推入值堆栈吗?为什么不显示 NumberFormatException 并显示结果,即使不应该打印结果?

附带问题

每当我在表单中添加一个字母时,它都会变为零......?为什么会这样?

index.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>

divide.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;
    }


}

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>

【问题讨论】:

  • 这是什么意思:每当我添加一个字母时
  • 意思是说,在输入字段中,如果我写的是b或c,而不是数字,它应该抛出一个异常,但它会将其视为零
  • 定义输入结果,因为您遇到了验证错误。

标签: java validation struts2 casting type-conversion


【解决方案1】:

主要问题:

工作流程应该是这样的,如果一个字符串是 输入不是数字,首先它应该通过异常 拦截器,当通过参数拦截器时,而 转换为 int 类型,使用 Integer.parseInt 将无法做到 并且会发生异常,即数字格式的异常 异常应该被推入值堆栈?为什么它不显示 numberformatexception 并显示结果,即使结果应该 不打印?

概念

Struts 2 自动处理转换错误验证错误:它不会引发异常,因为它们不是阻塞错误,但是输入错误,因此最好的方法是通知用户提交的输入错误,要求他提供新的有效输入。为此,将返回 INPUT 结果,而忽略 Exception。

详细的工作流程

  1. Parameters Interceptor 尝试设置参数。如果捕获到RuntimeException(如NumberFormatException)并且devModetrue,则将错误消息添加到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);
                }
            }
        }
    }
    
  2. Conversion Errors Interceptor 检查是否发生了任何转换错误:每找到一个,就添加一个Field Error;它还保存原始值,以便对该值的任何后续请求都返回原始值而不是操作中的值。来自文档:

    此拦截器将在 ActionContext 的 conversionErrors 映射中发现的任何错误添加为字段错误(前提是该操作实现了 ValidationAware)。 此外,任何包含验证错误的字段都会保存其原始值,以便对该值的任何后续请求都返回原始值 价值而不是行动中的价值。这很重要,因为如果提交了值“abc”并且无法转换为 int,我们希望显示 再次返回原始字符串(“abc”)而不是 int 值(可能为 0,这对用户来说意义不大)。

  3. Validation Interceptor 执行所有请求的验证(在 XML、Annotations 中定义或通过 Action 的 validate()validateXXX() 方法),为每个验证添加一个或多个错误消息到 Field Errors字段未通过一个或多个验证条件。

  4. 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 -->

附加问题:

每当我在表单中添加一个字母时,它都会变为零......?为什么会这样?

最初的答案是:当将请求发布到服务器时,框架无法将String 设置为int 字段,并且在检索结果页面中的值时,它会调用该字段的 Getter多变的;由于您定义了int 而不是Integer,并且int 不能为空,它将返回int 的默认值:0

但我不记得 Conversion Interceptor 声称(请阅读第 2 点)保存原始值,以便在以后的请求中提供它们,以代替 Action 值(即为 null 或 0)。 Type Conversion Error Handling中也提到了这一点:

类型转换错误处理提供了一种区分输入验证问题和输入类型转换问题的简单方法。

在类型转换期间发生的任何错误可能会或可能不会被报告。 例如,报告输入“abc”无法转换为数字可能很重要。另一方面,报告空字符串“”无法转换为数字可能不重要很重要 - 尤其是在很难区分用户未输入值与输入空白值的 Web 环境中。

...

相反,我清楚地记得您问题中描述的行为。 所以这个案子已经被处理了......为什么它不起作用呢? 就我而言(也可能是你的),罪魁祸首是 value 属性:

这将在发布abc 时为您提供0

<s:textfield name = "myIntField" 
            value = "%{getText('format.number',{myIntField})}" />

因为发生了进一步的转换错误。

这两种情况的工作方式如上所述,在发布abc 时为您提供abc

<s:textfield name = "myIntField" />

<s:textfield name = "myIntField" 
            value = "%{myIntField}" />

结论

  • 确保拦截器堆栈配置正确,并且
  • 仔细检查您的代码(很可能不是此处发布的代码),看看您对value 属性做了什么。

出于测试目的,首先尝试完全删除 value 属性,以查看它是否以正确的方式工作,然后开始寻找错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 2011-07-14
    相关资源
    最近更新 更多