struts表单校验失败后的整数重显问题

通过王涛完成的项目练习,发现了struts中的表单校验失败后重显的一个问题:假设ActionForm Bean中有一个整数类型的属性,如果将其类型定义为int,这个属性的默认值是0;在表单页面中用一个文本框来输入这个属性的值,当文本框中没有填写任何内容时,发送到WEB服务器的参数值为一空字符串"";当ActionForm Bean中的其它属性校验失败时,回到表单页面重新显示,这时,与整数字段对应的文本框中显示的内容为0,而不是最初的那样(没有任何内容)。
为此,我们想到了在Spring MVC中所采用的办法:将整数类型的属性定义为Integer类型,这样,该属性的默认值为null,借助<html:property>可将null显示为空字符串,但是,实际运行发现,ActionForm Bean中的其它属性校验失败回到表单页面重新显示时,与Integer类型的属性对应的文本框中显示的内容仍然为0。这说明struts在将请求参数组装进ActionForm Bean对象中时、它也会将内容为空字符串""的请求参数(文本框中不填写任何内容时即会出现这种情况)装配到ActionForm Bean中,并且将空字符串""转变成0值的Integer数据。对于这种情况,我们想到了将原本属于整数的属性设计成String类型的妥协解决办法,但觉得不是很理想,想知道各位有经验的朋友对这种情况是如何处理的?特向各位朋友请教。

下面是问题的完整描述:
假设有一个注册课程的表单,其中包含有“课程名”、“学分”等字段信息,显然“课程名”是String类型,“学分”是整数类型,与这个表单对应的ActionForm可以设计成如下形式:
public class RegisterCourseForm extends ActionForm
{
private String name;

public String getName()
{ return name;
}

public void setName(String name) {
this.name = name;
}

private Integer score;

public Integer getScore()
{
return score;
}
public void setScore(Integer score)
{
this.score = score;
}

public ActionErrors validate(ActionMapping mapping,HttpServletRequest request)
{
if("".equals(name))
{
ActionErrors errors = new ActionErrors();
errors.add("name",new ActionMessage("required.name"));
return errors;
}
return null;
}

}
注册课程的表单页面的主要内容如下:
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>

<html:form action="/registerCourse">
name : <html:text property="name"/><html:errors property="name"/><br/>
score : <html:text property="score"/><html:errors property="score"/><br/>
<html:submit/>
</html:form>

为了让这个用例能够运行,同时又简化整个程序的代码,我们直接使用Struts提供的ForwardAction,大家也可以使用MyEclipse自动为我们创建的没有任何业务逻辑的Action。在struts-config.xml文件中的配置片段如下:
<form-bean name="registerCourseForm" type="cn.itcast.form.RegisterCourseForm" />
......
<action parameter="/WEB-INF/jsp/registerCourse.jsp"
path="/index" type="org.apache.struts.actions.ForwardAction"/>

<action
input="/WEB-INF/jsp/registerCourse.jsp"
name="registerCourseForm"
path="/registerCourse"
scope="request"
type="org.apache.struts.actions.ForwardAction"
parameter="/WEB-INF/jsp/registerCourse.jsp"
/>

(1)首先在浏览器地址栏中输入http://localhost:8080/CourseManager/index.do,请求交给第一个Action处理,浏览器中显示出registerCourse.jsp页面;
(2)在注册课程的表单页面不填写任何内容,直接提交表单,这时候表单校验失败(即RegisterCourseForm.validate方法返回ActionErrors对象),浏览器重新显示registerCourse.jsp页面。registerCourse.jsp页面除了显示出错误描述信息之外,还在表单中显示出上次输入的内容,现在遇到的问题是:我们上次提交表单时,并没有在学分(score)文本框中输入任何内容,但这次重显表单时,在学分(score)文本框中添入了一个0。
我猜想这是因为struts在将请求参数组装进RegisterCourseForm对象中时、将空字符串""的请求参数(文本框中不填写任何内容时即会出现这种情况)转变成了0值的Integer数据。查看struts的源代码,了解到请求参数组装到FormBean中的方法调用过程如下:
ActionServlet.doGet/doPost-->ActionServlet.process-->RequestProcessor.process-->
RequestProcessor.processActionForm,RequestProcessor.processPopulate-->RequestUtils.populate-->
BeanUtils.populate-->BeanUtilsBean.setProperty(Object bean, String name, Object value)

可见,将请求参数组装成FormBean的属性时,最终调用的是BeanUtilsBean.setProperty方法,可能的原因就是BeanUtilsBean.setProperty方法在为JavaBean的整数类型的属性进行赋值时,会将空字符串""转换成0。BeanUtilsBean类位于apache的commons-beanutils包中,大家从struts安装包的lib目录中能够找到commons-beanutils.jar包及相关的依赖包。我安排王涛写了一个程序,来验证这种效果:

package com.tony;
public class TestInteger {

public static void main(String[] args) {

Student student = new Student();
try {
BeanUtilsBean.getInstance().setProperty(student,"name","Tony");
BeanUtilsBean.getInstance().setProperty(student,"age","");
System.out.print(student);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

package com.tony;
public class Student {
private String name;
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString()
{
return this.name + ":" + this.age;
}
}
程序最后打印出来的结果为Tony:0,这说明BeanUtilsBean.setProperty方法确实将空字符串""转换成了整数类型的0。

你可能感兴趣的:(struts)