乐者为王

Do one thing, and do it well.

如何在WebWork的资源文件中获取验证字段的值

WebWork是一个非常不错的MVC框架,有着众多的优点,也有着细微的缺陷。在实现一个用户注册验证的例子时,发现在资源文件中不能获取验证字段的值,只能每个字段一个message。

1
2
3
class User {
    private String username;
    private String password;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<field name="username">
    <field-validator type="stringlength" short-circuit="true">
        <param name="minLength">5</param>
        <param name="maxLength">15</param>
        <message key="errors.username.range" />
    </field-validator>
</field>

<field name="password">
    <field-validator type="stringlength" short-circuit="true">
        <param name="minLength">5</param>
        <param name="maxLength">15</param>
        <message key="errors.password.range" />
    </field-validator>
</field>

资源文件中的消息内容:

1
2
errors.username.range=${username} is not in the range ${minLength} through ${maxLength}.
errors.password.range=${password} is not in the range ${minLength} through ${maxLength}.

到xwork的站点上去查找解决方法,在Issue Tracker里看到有人提交了一个Feature,采用的办法是给message传递参数,看了xwork的代码后,发现这样子的做法要修改的代码量非常大,所以只能另外想办法解决。

在资源文件中可以用${fieldName}来获取要验证的字段变量名,那是否可以用${fieldValue}来得到验证字段的值呢?查看代码后发现这种办法行不通。那么是否可以用${${fieldName}}来获得字段变量的值呢?查看代码发现验证失败后会调用Validator.getMessage()方法,追踪代码来到TextParseUtil.translateVariables()方法中,找到代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while (start != -1 && x < length && count != 0) {    // 该部分代码负责查找变量,即${}包围的字符串
    c = expression.charAt(x++);
    if (c == '{') {
        count++;
    } else if (c == '}') {
        count--;
    }
}
end = x - 1;

if ((start != -1) && (end != -1) && (count == 0)) {
    String var = expression.substring(start + 2, end);

    Object o = stack.findValue(var, asType);    // 此处就是获取变量值的地方

    String left = expression.substring(0, start);
    String right = expression.substring(end + 1);

由上面的代码可以看出WebWork只处理了最外围的${},所以要让它处理像${${}}这样的格式就需要在获取变量前再次处理变量。修改后的代码如下:

1
2
3
4
5
6
7
8
9
if ((start != -1) && (end != -1) && (count == 0)) {
    String nestedExpression = expression.substring(start + 2, end);
    String var = translateVariables(nestedExpression, stack);
    //String var = expression.substring(start + 2, end);

    Object o = stack.findValue(var, asType);

    String left = expression.substring(0, start);
    String right = expression.substring(end + 1);

现在就可以处理资源文件中的多重嵌套变量了。接着把修改验证文件和资源文件修改一下就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<field name="username">
    <field-validator type="stringlength" short-circuit="true">
        <param name="minLength">5</param>
        <param name="maxLength">15</param>
        <message key="errors.range" />
    </field-validator>
</field>

<field name="password">
    <field-validator type="stringlength" short-circuit="true">
        <param name="minLength">5</param>
        <param name="maxLength">15</param>
        <message key="errors.range" />
    </field-validator>
</field>
1
errors.range=${${fieldName}} is not in the range ${minLength} through ${maxLength}.

Comments