九。类型转换中的错误处理
实际上,表现层数据涉及的 2 个处理: 数据校验和类型转换 ; 只有当输入数据是有效数据时,系统才可以进行有效的类型转换。因此,可以进行有效的类型转换是基础,只有当数据完成了有效的类型转换后,下一步才去做数据校验。
1. 类型转换错误的处理流程
Struts 2 提供了一个名为 conversionError 的拦截器 ,这个拦截器被注册在默认的拦截器栈中。
struts-default.xml:
<interceptor-stack name="defaultStack">
<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>
在上面默认拦截器包含了 conversionError 的引用,如果 Struts 2 执行类型转换时出现错误,该拦截器将对应的错误封装成表单域错误 (fieldError), 并将这些错误信息放入 ActionContext 中。
注意: 为了让 Struts 2 框架处理类型转换的错误,以及使用后面的数据校验机制,系统的 Action 类都应该继承 ActionSupport 。 ActionSupport 类为完成类型转换错误处理,数据校验实现了许多基础工作。
2. 处理类型转换错误
下面将以最简单的局部类型转换器为示例 ,介绍如何处理类型转换错误
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport
{
//封装请求参数的两个属性
private User user;
private String tip;
//无参数的构造器
public LoginAction()
{
}
//user属性的setter和getter方法
public void setUser(User user)
{
this.user = user;
}
public User getUser()
{
return this.user;
}
//tip属性的setter和getter方法
public void setTip(String tip)
{
this.tip = tip;
}
public String getTip()
{
return this.tip;
}
public String execute() throws Exception
{
if (getUser().getName().equals("crazyit")
&& getUser().getPass().equals("leegang") )
{
setTip("转换成功");
return SUCCESS;
}
else
{
setTip("转换失败");
return ERROR;
}
}
}
conversionError拦截器会处理该异常,然后转入名为 input 的逻辑视图,因此要为Action 增加 input 的逻辑视图定义 。如下:
struts.xml
<?xml version="1.0" encoding="GBK"?> <!-- 指定Struts2配置文件的DTD信息 --> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <!-- 配置Struts 2的包空间 --> <package name="lee" extends="struts-default"> <!-- 定义处理用户请求的Action --> <action name="login" class="lee.LoginAction"> <!-- 配置名为input的逻辑视图,当校验失败后转入该逻辑视图 --> <result name="input">/input.jsp</result> <!-- 配置名为success的逻辑视图 --> <result name="success">/welcome.jsp</result> </action> <action name=""> <result>.</result> </action> </package> </struts>
以上改变后,如果用户的输入不能成功转换成用户实例,系统将转入 input.jsp
3. 输出类型转换错误
转换失败后,系统将进入 input 的视图。 conversionError 会负责将转换错误封装成 fieldError, 并将其放到 ActionContext 中。 因此页面要用 <s:fielderror/> 标签:
<body>
<s:fielderror/>
<form action="login.action" method="post">
<table align="center" width="360">
<caption><h3>类型转换的出错处理</h3></caption>
<tr align="center">
<td>用户信息的用户名和密码以英文逗号隔开</td>
</tr>
<tr>
<td>请输入用户信息:<input type="text" name="user"/></td>
</tr>
<tr align="center">
<td><input type="submit" value="转换"/>
<input type="reset" value="重填" /></td>
</tr>
</table>
</form>
</body>
为了显示国际化资源 ,需要配置 struts.xml
<?xml version="1.0" encoding="GBK"?> <!-- 指定Struts2配置文件的DTD信息 --> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <!-- 指定加载国际化资源文件 --> <constant name="struts.custom.i18n.resources" value="globalMessages"/> <constant name="struts.i18n.encoding" value="GBK"/> <!-- 配置Struts 2的包空间 --> <package name="lee" extends="struts-default"> <!-- 定义处理用户请求的Action --> <action name="login" class="lee.LoginAction"> <!-- 配置名为input的逻辑视图,当校验失败后转入该逻辑视图 --> <result name="input">/input.jsp</result> <!-- 配置名为success的逻辑视图 --> <result name="success">/welcome.jsp</result> </action> <action name=""> <result>.</result> </action> </package> </struts>
globalMessages_zh_CN.properties
xwork.default.invalid.fieldvalue={0}\u5b57\u6bb5\u7c7b\u578b\u8f6c\u6362\u5931\u8d25\uff01
globalMessages.properties
xwork.default.invalid.fieldvalue={0}字段类型转换失败!
如果需要特定的提示信息,可以用局部资源文件 ActionName.properties.
invalid.fieldvalue.属性名=提示信息
属性名是 Action 中的属性名,也就是请求参数名, value 是校验失败的提示信息
如:LoginAction.properties
#改变上面的Action中birth属性类型转换后的提示信息
invalid.fieldvalue.birth=生日信息必须满足yyyy-MM-dd格式
LoginAction_zh_CN.properties
invalid.fieldvalue.birth=\u751f\u65e5\u4fe1\u606f\u5fc5\u987b\u6ee1\u8db3yyyy-MM-dd\u683c\u5f0f
action:
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;
import java.util.List;
public class LoginAction extends ActionSupport
{
//下面提供了三个属性,分别用于封装name、age和birth三个请求参数
private String name;
private Integer age;
private Date birth;
//无参数的构造器
public LoginAction()
{
}
//初始化全部属性的构造器
public LoginAction(String name , Integer age , Date birth)
{
this.name = name;
this.age = age;
this.birth = birth;
}
//name属性的setter和getter方法
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
//age属性的setter和getter方法
public void setAge(Integer age)
{
this.age = age;
}
public Integer getAge()
{
return this.age;
}
//birth属性的setter和getter方法
public void setBirth(Date birth)
{
this.birth = birth;
}
public Date getBirth()
{
return this.birth;
}
}
4. 处理集合属性的转换错误
页面包含 3个 名字相同的 users 请求参数。 服务器会接受到一个字符串数组。
下面是处理的 Action
import com.opensymphony.xwork2.Action;
import java.util.Date;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport
{
//users属性
private List<User> users;
//无参数的构造器
public LoginAction()
{
}
//初始化全部属性的构造器
public LoginAction(List<User> users)
{
this.users = users;
}
//users属性的setter和getter方法
public void setUsers(List<User> users)
{
this.users = users;
}
public List<User> getUsers()
{
return this.users;
}
}
以上 Action 中已经用了泛型 ,所以 类型转换器会作用于 该 Action 的 users 属性,如果输入不正确,conversionError拦截器会起作用
如果将三个请求参数名字设为 user['0'],user['1'],user['2'], Struts 2 将可以区分每个请求参数,从而显示更加友好的转换错误提示。如:
<body>
<div style="color:red">
<s:fielderror />
</div>
<form action="login.action" method="post">
<table align="center" width="360">
<caption><h3>类型转换的错误处理</h3></caption>
<tr align="center">
<td>输入用户信息</td>
</tr>
<s:iterator value="new int[3]" status="stat">
<tr>
<td>用户<s:property value="%{#stat.index}"/> 的信息
<input name="users['<s:property value="%{#stat.index}"/>']" type="text"/></td>
</tr>
</s:iterator>
<tr align="center">
<td><input type="submit" value="转换"/>
<input type="reset" value="重设"/></td>
</tr>
</table>
<form>
</body>
上面代码使用了 迭代器标签指定三个表单域的 name, 三个表单域的 name 将分别是 user['0'],user['1'],user['2'],在这种情况下如果任一个表单域类型转换失败,将看到准确,详细的提示信息。