Struts2 INPUT结果:它是如何工作的?如何处理转换/验证错误? [英] Struts2 INPUT result: how does it work? How are conversion / validation errors handled?

查看:144
本文介绍了Struts2 INPUT结果:它是如何工作的?如何处理转换/验证错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

主要问题



工作流程应该是这样的:如果输入一个字符串而不是一个数字,一个异常拦截器,当通过param拦截器,而转换为int类型,它不能够使用 Integer.parseInt 做,并会发生异常;应该不是那个异常(即 NumberFormatException )被推入值栈?为什么不显示 NumberFormatException 并显示结果,即使不应打印结果?



侧问题



每当我在表单中添加字母表时,它会更改为零...?为什么这样?



index.jsp

 <%@ taglib uri =/ struts-tagsprefix =s%> 
< s:form action =divide>
< s:textfield name =number1label =number1/>
< s:textfield name =number2label =number2/>
< s:submit value =divide/>
< / s:form>

divide.java

 包操作; 

public class divide {
int number1,number2,result;
public String execute()throws Exception
{
result = number1 / number2;
returnsuccess;
}
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>
除法的结果是
< s:property value =result/>
< / b>
< jsp:include page =index.jsp>< / jsp:include>

handler jsp

 <%@ taglib uri =/ struts-tagsprefix =s%& 
< b>
在处理期间发生异常
< s:property value =exception/>
< / b>
< jsp:include page =index.jsp/>

struts.xml

 <?xml version =1.0encoding =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 =yoextends =struts-default>
< action name =divideclass =actions.divide>
< exception-mapping result =errorexception =Exception/>
< result name =success> /result.jsp< / result>
< result name =error> /handler.jsp< / result>
< / action>
< / package>
< / struts>


解决方案




主要问题:



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




Concept



Struts 2同时处理转换错误验证错误:不会引发异常,因为它们不是阻止错误,而是输入错误,因此最好的方法是通知用户提交的输入是错误的,要求他提供一个新的,有效的输入。要实现这一点,返回INPUT结果,而忽略异常。



详细worflow




  1. 参数拦截器 尝试设置参数。如果捕获到 RuntimeException (如 NumberFormatException )并且 devMode true ,则会向 Action Errors 中添加一条错误消息,否则该异常将被忽略。从源代码:

      for(Map.Entry< String,Object> entry:acceptableParameters。 entrySet()){
    String name = entry.getKey();
    对象值= entry.getValue();
    try {
    newStack.setParameter(name,value);
    } catch(RuntimeException e){
    if(devMode){
    String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class,devmode.notification,ActionContext.getContext()。getLocale ,开发人员通知:\ n {0},新对象[] {
    意外异常已捕获设置+名称+'上+ action.getClass()+:+ e。 getMessage()
    });
    LOG.error(developerNotification);
    if(action instanceof ValidationAware){
    ((ValidationAware)action).addActionMessage(developerNotification);
    }
    }
    }
    }


  2. p> 转换错误拦截器 检查是否发生任何转换错误:对于找到的每一个,它添加一个字段错误;它还保存原始值,以便对该值的任何后续请求都返回原始值,而不是操作中的值。从文档:


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



  3. 验证拦截器 执行所有请求的验证(在XML,注释中定义或通过 validate() validateXXX()的Action方法),添加一个或多个错误消息到字段错误

    org / release / 2.2.x / docs / workflow-interceptor.htmlrel =nofollow> 工作流拦截器 检查是否有字段错误(都来自转换错误或验证错误)。如果没有找到错误,它继续链到下一个拦截器。如果发现一个或多个错误,它会返回一个INPUT结果。


在自定义堆栈中按正确的顺序定义这四个拦截器,如果你不使用默认拦截器堆栈(你不需要做任何其他事情)。从 struts-default.xml

 <! - 其他拦截器。> 
< 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>输入,返回,取消,浏览< / param>
< / interceptor-ref>
< interceptor -ref name =workflow>
< param name =excludeMethods>输入,返回,取消,浏览< / param>
< / interceptor-ref>
<! - ...其他拦截器在这里 - >




副题:


$ b b

每当我在表单中添加字母表时,它会更改为零...?为什么这样?


原来的答案是:框架无法设置 String 插入到 int 字段中,并且当检索结果页面中的值时,它调用该变量的Getter;因为您定义了 int 而不是 Integer int 不能为null,它将返回 int 0 的默认值。



但我不记得转换拦截器声明(读取点n。2)保存原始值,以便在以后的请求中提供它们,而不是Action值(将为null或0 )。这也在 类型转换错误中提及处理 : :


类型转换错误处理提供了一种区分输入 / strong>问题和输入类型转换问题。



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



...


相反,我记得你的问题中描述的行为。
所以这个case已经处理了...为什么它不工作呢?
在我的情况下(可能是你的),罪魁祸首是 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 属性,看到它工作正确的方式,然后开始寻找错误。


Main Question

The work flow should be like this: if an String is entered other than a number, first it should pass through a exception interceptor, and when passing through param interceptor, while converting to int type, it wont be able to do it using Integer.parseInt and an exception would occur; shouldn't that exception (that is NumberFormatException) be pushed into Value Stack ? Why does it not show NumberFormatException and show the result even though result should not be printed instead ?

Side Question

Whenever I add an alphabet in the form, it changed to zero...? Why so ?

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>

handler 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>

解决方案

Main Question:

The work flow should be like this ,if an string is entered other than a number,first it should pass through a exception interceptor,and when passing through param interceptor,while converting to int type,it wont be able to do it using Integer.parseInt and an exception would occur,that exception that is number format exception should be pushed into value stack?so why does it not show numberformatexception and show the result even though result should not be printed instead?

Concept

Struts 2 handles both conversion errors and validation errors automatically: it does not raise an Exception, because they're not blocking errors, but input errors, hence the best way to proceed is to notify the user that the input submitted was wrong, asking him for a new, valid input. To achieve this, an INPUT result is returned, while the Exception is ignored.

Detailed worflow

  1. The Parameters Interceptor tries to set the parameters. If an RuntimeException (like NumberFormatException) is caught and devMode is true, an error message is added to the Action Errors, otherwise the exception is simply swallowed. From the source code:

    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. The Conversion Errors Interceptor checks if any conversion error happened: for each one found, it adds a Field Error; it also saves the original values such that any subsequent requests for that value return the original value rather than the value in the action. From the documentation:

    This interceptor adds any error found in the ActionContext's conversionErrors map as a field error (provided that the action implements ValidationAware). In addition, any field that contains a validation error has its original value saved such that any subsequent requests for that value return the original value rather than the value in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to the user).

  3. The Validation Interceptor performs all the validation requested (defined in XML, Annotations or through the validate() or validateXXX() methods of the Action), adding one or more error messages to the Field Errors for each field not passing one or more validation criteria.

  4. The Workflow Interceptor checks if there are Field Errors (both coming from conversion errors or validation errors). If no errors are found, it continues the chain to the next Interceptor. If one or more errors are found, it returns an INPUT result.

To ensure this mechanism works, you need to define this four Interceptors in the right order in your Custom Stack, if you are not using the Default Interceptors Stack (you don't need to do anything otherwise). From 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 -->

Side Question:

Whenever I add an alphabet in the form, it changed to zero...? Why so?

The original answer was: the framework has not been able to set a String into an int field when posting the request to the server, and when retrieving the value in the resulting page, it invokes the Getter of that variable; since you defined an int and not an Integer, and an int can't be null, it will return the default value for an int: 0.

But I wasn't remembering that Conversion Interceptor claims (read point n. 2) to save the original values, to provide them in subsequent future requests, in place of the Action values (that would be null, or 0). This is also mentioned in Type Conversion Error Handling:

Type conversion error handling provides a simple way to distinguish between an input validation problem and an input type conversion problem.

Any error that occurs during type conversion may or may not wish to be reported. For example, reporting that the input "abc" could not be converted to a number might be important. On the other hand, reporting that an empty string, "", cannot be converted to a number might not be important - especially in a web environment where it is hard to distinguish between a user not entering a value vs. entering a blank value.

...

Instead, I was remembering well the behavior described in your question. So this case has already been handled... why it is not working then ? The culprit, in my case (and probably your), was the value attribute:

This will give you 0 when posting abc:

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

because a further conversion error occours.

This two cases instead work as described above, giving you abc when posting abc:

<s:textfield name = "myIntField" />

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

Conclusions

  • Ensure the Interceptor Stack is correctly configured, and
  • check carefully your code (that is most likely not the one posted here) to see what are you doing with your value attribute.

For test purposes, try removing the value attribute at all at first, to see it working the right way, then start looking for the bug.

这篇关于Struts2 INPUT结果:它是如何工作的?如何处理转换/验证错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆