类型转换的流程
1、用户进行请求,根据请求名在struts.xml中寻找Action
2、在Action中,根据请求域中的名字去寻找对应的set方法。找到后在赋值之前会检查这个属性有没有自定义的类型转换。没有的话,按照默认进行转换;如果某个属性已经定义好了类型转换,则会去检查在Action同一目录下的 action文件名-conversion.properties 文件。
3、从文件中找到要转换的属性及其转换类。
4、然后进入转换类中,在此类中判断转换的方向。我们是先从用户请求开始的,所以这时先进入从字符串到类的转换。返回转换后的对象。流程返回Action。
5、将返回的对象赋值给Action中的属性,执行Action中的execute()
6、执行完execute()方法,根据struts.xml的配置转向页面
7、在jsp中显示内容时,根据页面中的属性名去调用相应的get方法,以便输出
8、在调用get方法之前,会检查有没有此属性的自定义类型转换。如果有,再次跳转到转换类当中。
9、在转换类中再次判断转换方向,进入由类到字符串的转换,完成转换后返回字符串。
10、将返回的值直接带出到要展示的页面当中去展示。
1.内建的类型转换
1. 原始类型
<input name=”user.username” />
<input name=”user.age” />
<input name=”user.birthday” />
类里 :
private String username;
private Double age;
private Date birthday
框架会自动帮我们转换 . 我们能成功获得到 .
2. 数组 ;
<input name=”ages” />
<input name=”ages” />
<input name=”ages” />
上面这些指向 ages 属性 :Double[] ages
<input name=”names[0]” />
<input name=”names[1]” />
<input name=”names[2]” />
上面指向 :String[] names
但要注意的是 : 当我们提交上面的整个表单时 ,HTTP 请求如下 :
ages=12,33,55
names[0]=jack
names[1]=green
names[2]=mary
可以看出差别了 .
当框架转移 ages 参数时 , 它先找到 ages 属性 , 并且知道 ages 参数是一个有 3 个字符串的数组 . 由于动作上的 ages 属性也是一个数组 , 这样 OGNL 创建一个新的数组 , 值是参数的值 , 并将它赋给动作 . 并且它知道动作的属性 ages 是 double 类型的 . 它会自动将参数的值转换成对应的类型 .
3. List
用法和数组一模一样 . 只不过 JAVA 中是 List 但注意 , 这里最好是用泛型来声明 . 不然它会自动将参数转换成String 类型并存入 List. 泛型用法 :
<input name=”names[0].username” />
<input name=”names[1].username” />
接收 :List<User> names
第一个 User 的 username 为第一个 input 提交的值 …
4. Map
和 list 不同 ,Map 需要一个键 , 一个值 . 如 :
<input name=”nameMap.mary” />
<input name=”nameMap.hellen” />
<input name=”nameMap[‘Sunyu’]” />
上面一种用点语法 , 一种用方括号 . 但两种意思一样 , 当我们提交上面表单后 , 后台获得的值如下 :
Map<String,String> nameMap; 值为 :
mary --- > 第一 input 提交的值 .
hello --- > 第二 input 提交的值 .
…..
(ActionName-conversion.properties文件{
Element_users = org.app.domain.User //List<User> users;
Key_users = java,lang.String
Element_user = java.lang.String //Map<String , String> users})
2.继承StrutsTypeConverter
StrutsTypeConverter是DefaultTypeConverter的子类,DefaultTypeConverter的类型转换器是在一个函数中进行双向转换,而继承StrutsTypeConverter的类型转换器则是将两个方向分别用两个函数实现:
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {}
@Override
public String convertToString(Map context, Object o) {}
客户输入错误信息是很正常的事,因此需要对此种行为进行处理,Struts2提供了很好的错误处理机制,是由conversionError拦截器自动完成,我们只需要配置输出什么错误信息即可;
当发生类型转换错误时,conversionError拦截器拦截此错误,并封装成fieldError,将此错误信息放入ActionContext中,并返回input逻辑视图;当然在<action>元素中必须配一个类似于<result name="input">/1.jsp</result>的子元素,以应对类型转换错误;
而为了显示错误信息,则在jsp页面中使用<s:fielderror/>即可显示错误信息;
注意:
类型转换的Action在struts.xml中配置所在包需要extends="struts-default",因此在此文件中包含conversionError拦截器;
必须让Action继承Struts2的ActionSupport类,因为Struts2的ActionSupport负责收集类型转换错误,输入校验错误,并将它们封装成FieldError对象,添加到ActionContext对象中
这时我们需要配置显示的错误信息,错误信息配置方式有两种:
1.配置默认提示信息
在国际化资源文件中配置形如:
xwork.default.invalid.fieldvalue={0},错误;
{0}代表类型转换错误的属性名称;
2.配置Action特定属性错误信息
在Action范围的国际化资源文件中配置形如:
invalid.fieldvalue.attributeName= 内容
attributeName是Action中的属性名称;
例如:invalid.fieldvalue.p=person类型转换错误
意思是对p属性配置了特定的错误提示信息,当p属性类型转换错误后就会显示此信息;