Struts2的数据封装和类型转换
一、Struts2的Action对数据封装的两种方式
属性驱动
提供对应属性的set方法进行数据的封装
* 表单的哪些属性需要封装数据,那么在对应的Action类中提供该属性的set方法即可。
* 表单中的数据提交,最终找到Action类中的setXxx的方法,最后赋值给全局变量。
* 注意:Struts2的框架采用的拦截器完成数据的封装。
* 注意:这种方式不是特别好:因为属性特别多,提供特别多的set方法,而且还需要手动将数据存入到对象中.
* 注意:这种情况下,Action类就相当于一个JavaBean,就没有体现出MVC的思想,Action类又封装数据,又接收请求处理,耦合性较高。
在页面上,使用OGNL表达式进行数据封装
* 在页面中使用OGNL表达式进行数据的封装,就可以直接把属性封装到某一个JavaBean的对象中。
* 在页面中定义一个JavaBean,并且提供set方法:例如:private User user;
* 页面中的编写发生了变化,需要使用OGNL的方式,表单中的写法:<input type="text" name="user.username">
* 注意:只提供一个set方法还不够,如果没有user实例化,必须还需要提供user属性的get和set方法,先调用get方法,判断一下是否有user对象的实例对象,如果没有,调用set方法把拦截器创建的对象注入进来。
模型驱动
使用模型驱动的方式,也可以把表单中的数据直接封装到一个JavaBean的对象中,并且表单的写法和之前的写法没有区别!
编写的页面不需要任何变化,正常编写name属性的值。
模型驱动的编写步骤
* 手动实例化JavaBean,即:private User user = new User();
* 必须实现ModelDriven<T>接口,实现getModel()的方法,在getModel()方法中返回user即可!!
二、Struts2的Action对集合对象的封装的两种方式
封装复杂类型的参数(集合类型 Collection 、Map接口等)
需求:页面中有可能想批量添加一些数据,那么现在就可以使用上述的技术了。把数据封装到集合中。
把数据封装到Collection中
* 因为Collection接口都会有下标值,所有页面的写法会有一些区别,注意:
<input type="text" name="products[0].name" />
* 在Action中的写法,需要提供products的集合,并且提供get和set方法。
把数据封装到Map中
* Map集合是键值对的形式,页面的写
<input type="text" name="map['one'].name" />
* Action中提供map集合,并且提供get和set方法。
三、Struts2对数据的类型转换
Struts2中自带类型转换拦截器
Struts2内部提供了大量转换器,用来完成数据类型转换的问题,有如下
* boolean 和 Boolean
* char和 Character
* int 和 Integer
* long 和 Long
* float 和 Float
* double 和 Double
* Date 可以接收 yyyy-MM-dd 格式字符串
* 数组 可以将多个同名参数,转换到数组中
* 集合 支持将数据保存到 List 或者 Map 集合
当发生类型转换错误的时候,根据报错的信息提示,跳转input类型的结果视图。
* 说明如果程序出现异常,会跳转到input结果视图,那可以在<action>标签中配置input结果视图
在跳转的页面中可以通过一个固定的标签来显示错误的信息:
* 可以先需要先引入Struts2的标签库,然后使用标签显示错误!
<%@ taglib prefix="s" uri="/struts-tags" %>
* <s:fielderror/>,这是Struts2提供的标签,使用它显示错误的提示信息。
如果类型转换的拦截器中发生了错误,那么会把错误信息放在Struts2错误区域中(Struts2的错误区域分成两部分,一部分是字段错误,一部分是Actionc错误)
* 等执行到最后一个拦截器(workflow)时,workflow拦截器会去Struts2的错误区域中找是否存在错误。
* 如果存在错误,就跳转到input视图。
* 如果不存在错误,执行目标Action类中具体的方法。
自定义类型转换器
如果一些特殊的数据类型不能转换,那么需要自定义数据类型的转换器。
开发自定义类型转换的开发步骤
编写类型转换器
实现TypeConverter接口,实现一个方法
Object convertValue(Map<String,Object> context,Object target, Member member,String propertyName,Object value,Class toType);
继承DefaultTypeConverter类,重写一个方法
Object convertValue(Map<String,Object> context,Object value,Class toType)
继承StrutsTypeConverter类,重写两个方法
Object convertFromString(Map context,String[] values,Class toClass)
> 从字符串转换成具体类型
> values数组,存入的值就是用户输入的值
> toClass 要转换的数据的类型 Date.class
* String convertToString(Map context,Object o)
> 把具体的类型转换成字符串
> o 代表的要转换的数据
注意:类型转换本身就是一个双向的过程:
* JSP ---> Action String ---> 某个类型
* Action ---> JSP 某个类型 ---> String
* 类型转换的代码,以 1990/10/10 为例,自定义日期转换器,完成转换,下面这段代码是第二种方法,也就是继承了DefaultTypeConverter类。
public Object convertValue(Map<String, Object> context, Object value,
Class toType) {
// 根据toType判断 是请求封装 还是 数据回显
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
if (toType == Date.class) {
// 请求参数封装 (value是字符串)
String[] params = (String[]) value;
String strVal = params[0]; // 转换为 日期类型
try {
return dateFormat.parse(strVal);
} catch (ParseException e) {
e.printStackTrace();
}
} else {
// 回显(value是 Date)
Date date = (Date) value;
return dateFormat.format(date);
}
return null;
}
四、注册类型转换器
局部注册:
针对某个表单中的某个字段生效的!
* 属性驱动的方式:使用set方法接收数据
> 注意:在Action所在的包下创建一个文件,文件的格式是:Action类名-conversion.properties文件,该文件中配置要转换数据的字段和对应的转换器全路径
* 例如:birthday=cn.zlq.demo3.MyDateConverter
* 模型驱动的方式:实现ModelDriven接口的方式
> 注意:在实体类所在的包下创建一个文件,文件的格式是:实体类名-conversion.properties文件,该文件中配置要转换数据的字段和对应的转换器全路径
* 例如:birthday=cn.zlq.demo3.MyDateConverter
全局注册:
针对整个项目的所有的日期类型都会生效的!
* 在src的目录下,创建一个xwork-conversion.properties (名称是固定的)
> 例如:java.util.Date=cn.zlq.demo3.MyDateConverter
五、Struts2对数据的校验的两种方式
数据校验包含两种方式,第一种是手动编码完成数据校验方式,第二种是通过配置文件完成数据校验方式。
手动编码校验方式
开发的步骤
> 步骤一: 封装数据
> 步骤二: 实现校验Action ,必须继承ActionSupport 类
> 步骤三:覆盖validate方法,完成对Action的业务方法 数据校验 this.addFieldError (ActionSupport提供)
> 步骤四: 在jsp中 通过 <s:fieldError/> 显示错误信息
针对的是Action中所有的方法进行校验
让Action继承ActionSupport类,重写ActionSupport类中的validate()方法,在该方法中完成数据校验。
针对的是Action中某个方法完成校验
手动在Action中编写一个方法,方法名称是validate方法名称() 例如:public void validateAdd(){ }
* Action中有一个save的方法,只校验save方法。
* validateSave() -- 使用该方法去校验save的方法
通过XML配置文件的方式完成数据的校验
xml配置校验原理 : 将很多校验规则代码已经写好,只需要在xml中定义数据所使用校验规则就可以了
开发的步骤
> 步骤一 :编写jsp
> 步骤二 :编写Action 继承ActionSupport 或者 实现 Validateable 接口
> 步骤三 :封装请求参数
* 使用xml校验 必须提供get方法
> 步骤四 :编写校验规则xml文件
* 具体的配置文件相关标签和属性详解
<field name="password">
<!-- 校验器类型 -->
<field-validator type="requiredstring">
<message>密码不能为空</message>
</field-validator>
<!-- 规定密码的长度 -->
<field-validator type="stringlength">
<param name="minLength">3</param>
<param name="maxLength">8</param>
<message>密码在3-8位之间</message>
</field-validator>
</field>
针对的是Action中所有的方法进行校验
>在Action所在的包中创建一个XML文件,命名规则:Action类名-validation.xml。并且需要引入指定的DTD的约束:xwork-core-2.3.15.3.jar/xwork-validator-1.0.3.dtd
> 具体的值:
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
针对的是Action中的某个方法进行校验
在Action所在的包中创建一个XML文件,命名规则:Action类名-方法对应的访问路径-validation.xml。引入DTD文件等。
* 例如:Reg6Action-reg6-validation.xml
Struts2框架提供的XML校验规则
* required (必填校验器,要求被校验的属性值不能为null),空格没问题。
* requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
* stringlength (字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
* regex (正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
* int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
* double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
* fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
* email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)
* url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)
* date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)