表单验证
传统的应用中,表单中的数据是放在Java代码中进行检验的。这种方法在编写java代码的时候很无聊,而且后期的修改也不方便。 而webx框架将表单验证的逻辑独立放在配置文件中。这种方式更加方便。
webx中,表单的验证有三个步骤:
- 定义验证规则
- 在Java代码中调用该规则
- 在页面中显示验证结果。
定义验证规则。下面是验证规则的一个例子。
必须填写 ${displayName}${displayName} 必须由字母、数字、下划线构成${displayName} 最少必须由 ${minLength} 个字组成,最多不能超过 ${maxLength} 个字
上面这个例子中,最外层是form
,表示表单验证服务。一个验证服务中可以包含多个group
,表示验证组。 一个验证组中可以包含多个field
,表示验证字段。每个验证字段中可以包含多个validator
,表示验证规则。 每个验证规则只能包含一个错误消息。
编写Java代码。下面是Java代码的一个例子。
}
上面这个例子中使用了@FormGroup
注解,它的意思是通过register
规则校验表单, 如果校验失败会让用户重新填写表单,如果校验成功,就会执行方法中的代码。 AddUserAction
、doAdd
这些符号需要告诉框架,在后面会详细讲解。
编写表单。首先要定义表单工具,这样才能在页面中通过$form
进行访问。
...
表单内容。
<!-- 获取一个名为register的Group验证规则。由于每个group可以有多个实例,这里只使用默认的实例。-->#set ($group = $form.register.defaultInstance)<!-- 用户名字段。 --><!-- 用户名验证错误消息 -->#if(!$group.username.valid)$group.username.message#end<!--其他字段也是类似,这里就不赘述了。--><!--提交表单时交给AddUserAction进行处理。--><!--提交表单时调用doAdd方法--><!-- 表单默认值。配置方法如下。 -->
修改老数据。有时候项目的需求比如是修改账户资料。那么在打开修改页面的时候,表单中就已经有数据了, 那么这种需求该怎么做呢?只要在Java代码中将数据填入到Context
中,再将数据填充给group
即可。
Java代码:将数据放在context中。
public void throws Exception {User user = ...;context.;}
页面中:将user
变量中的数据填充到group
中:
#set ($group = $form.userAccount.defaultInstance)$group.mapTo($user)
如果$user
没有定义,那么mapTo
会忽略。
postonly
属性。这个属性的作用是让表单只支持post
方式提交,这样会略微提高CSRF的攻击难度。它的配置方法如下:
trimming
参数。目的是去除字段值两端的空格。下面是配置的例子:
displayName
参数。目的是让错误消息中重复使用字段的显示名称。下面是配置方法:
必须填写 ${displayName}
类型转换。表单中的值只能用字符串表示,如果想要转换成Java中的类型,就需要声明类型转换器。
验证消息国际化。目的是让验证消息支持多语言。下面这段配置告诉框架,消息文本需要从form_msgs***
中加载。
form_msgs
下面这段验证规则,消息内容会对应到ResourceBundle
中的form.register.userId.required
中:
表单拆分。有时候表单的数量非常多,放在一个文件中不方便维护,这时就需要将form
标签进行拆分,分配到多个文件中。 配置方法如下。例子中的primary
属性表示框架会从这个form
开始加载验证规则,而不是从其他文件中进行加载。
...
其他文件中的form
配置如下:
......
Group
继承。有时候两个Group
之间有很多相似的地方。这时就可以用继承来消除重复。
......
默认值:
验证错误消息。它可以包含变量,下面是一个例子。
${displayName} 最少必须由 ${minLength} 个字组成,最多不能超过 ${maxLength} 个字
验证器。有以下几种:
名称 | 作用 |
---|---|
required-validator | 必选验证器。 |
regex-validator | 正则验证器 |
string-length-validator | 字串长度验证器 |
string-byte-length-validator | 字节长度验证器 |
string-compare-validator | 字符串比较验证器。属性有equalTo 、notEqualTo 、ignoreCase 。 |
mail-address-validator | 邮箱验证器 |
number-validator | 数字验证器 |
number-compare-validator | 数字比较验证器 |
date-validator | 日期验证器 |
uploaded-file-validator | 文件上传验证器 |
csrf-validator | 验证csrf字段 |
custom-error | 自定义验证 |
multi-values-count-validator | 多值验证 |
number-validator
数字验证器。属性有以下几个:
- numberType 数字的类型。可用的类型为:
int
、long
、float
、double
、bigDecimal
。 如不设置,默认值为int
。 - equalTo 可选数字范围:要求数字等于指定值。
- notEqualTo 可选数字范围:要求数字不等于指定值。
- lessThan 可选数字范围:要求数字小于指定值。
- lessThanOrEqualTo 可选数字范围:要求数字小于或等于指定值。
- greaterThan 可选数字范围:要求数字大于指定值。
- greaterThanOrEqualTo
number-compare-validator
数字比较验证器。有以下几个属性:
- numberType 数字的类型。可用的类型为:int、long、float、double、bigDecimal。如不设置, 默认值为int。
- equalTo
- notEqualTo 可选数字范围:要求数字不等于指定字段的值。
- lessThan 可选数字范围:要求数字小于指定字段的值。
- lessThanOrEqualTo 可选数字范围:要求数字小于或等于指定字段的值。
- greaterThan 可选数字范围:要求数字大于指定字段的值。
- greaterThanOrEqualTo
date-validator
日期验证器。可以指定的属性有:
- format 日期的格式,如不指定,默认为yyyy-MM-dd。
- minDate 可选的日期范围:最早的日期。该日期格式也是用format参数来表示的。
- maxDate
uploaded-file-validator
文件上传验证器。可以验证以下属性。
- minSize 最小文件尺寸。可使用K/M等单位,例如:10K、1M等。
- maxSize 最大文件尺寸。可使用K/M等单位,例如:10K、1M等。
- extension 允许的文件名后缀,多个后缀以逗号分隔。例如:gif、jpg、png。注意,文件名是由浏览器传递给服务器的,因此验证器并不能保证文件的扩展名和内容一致。例如,xxx.jpg有可能是一个exe可执行文件。
- contentType
custom-error
自定义验证。将验证逻辑放在action中,其余特性与普通的验证器一样。首先要增加CustomErrors参数,错误通过setError进行设置。
public void throws Exception {try {...} catch (DuplicatedUserException e) {Map<String, Object> params = ;params.;err.;}}
验证器还可以增加条件验证,有if、choose、all-of、none-of、any-of。
必须填写 ${displayName}
多值验证。可以验证值的数量范围。
至少选择 ${minCount} 项,最多选择 ${maxCount} 项
还可以对各个值进行验证。
<all-of-values><validator /><validator /></all-of-values><any-of-values><mess age> 至少有一个 ${displayName} 要符合要求 </message><validator /><validator /></any-of-values><none-of-values><validator /><validator /></none-of-values>
form-tool对象。首先要声明pull服务。
...
这样在页面中就可以直接引用$form
对象了。 它的接口如下:
$form.valid#set ($group = $form.group1.defaultInstance) 取得group1的默认实例,如果不存在,则创建之。#set ($group = $form.group1.getInstance("id")) 取得group1的指定id的实例,如果不存在,则创建之。#set ($group = $form.group1.getInstance("id", false)) 取得group1的指定id的实例,如果不存在,则返回null。#foreach ($group in $form.groups) ... #end 遍历当前form中所有group实例。#foreach ($group in $form.getGroups("group1")) ... #end
$group
对象有以下接口:
#if ($group.valid) ... #end 判断当前group是否验证为合法,或者未经过验证(即初始表单)#if ($group.validated) ... #end 判断当前group是否经过验证(初始表单为未经过验证的表单)$group.field1 取得field1#foreach ($field in $group.fields) ... #end 遍历当前group中所有的fields$group.mapTo($bean)
$field
对象提供的接口:字段的名称、字段值、多值、是否验证通过、错误消息。
#if (!$field.valid)$field.message#end#foreach ($value in $field.values) ... #end$field.getAbsentHiddenField($value)
在字段中附上一个Java对象。
$field.setAttachment($obj)$field.attachmentHiddenField