2

我有一个模型 TestModel.java,其中包含一个声明如下的字段

@Required
@IntegerAnnotation
@Column (length = 4, nullable = false)
public Integer sort;

由于 Play 的默认验证注解不支持 Integer 检查,所以我创建了一个注解验证来检查输入值是否为 Integer。

IntegerAnnotation.java :

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Constraint(checkWith = IntegerCheck.class)
public @interface IntegerAnnotation {
    String message() default IntegerCheck.message;}
}

这个注解是指 IntegerCheck.java 的一个实现

public class IntegerCheck extends AbstractAnnotationCheck<IntegerAnnotation>{

final static String message = "validation.integer";

@Override
public boolean isSatisfied(Object validatedObject, Object value, OValContext context, Validator validator) throws OValException {
    // TODO Auto-generated method stub

    if(value == null) return false;
    return isInteger(value.toString());
}

private static boolean isInteger(String s) {
    return isInteger(s,10);
}

private static boolean isInteger(String s, int radix) {
    if(s.isEmpty()) return false;
    for(int i = 0; i < s.length(); i++) {
        if(i == 0 && s.charAt(i) == '-') {
            if(s.length() == 1) return false;
            else continue;
        }
        if(Character.digit(s.charAt(i), radix) < 0) return false;
    }
    return true;
}
}

并且控制器中有两个动作用于创建或更新TestModel,方法创建和方法更新。

public static void create(@Valid TestModel testModel){
    if(validation.hasErrors()) {
        params.flash();
        validation.keep();
        blank();
    }
}

public static void update(@Valid TestModel testModel) {

    if(validation.hasErrors()) {
        params.flash();
        validation.keep();
    }
    else{
        testModel.save();
        show(sys5000.id);
    }
}

我发现当字段排序没有输入整数值时,在create方法中该值将为null,这就是为什么我在IntegerCheck.class中放置了一个if null条件。

因此,如果字段排序的值输入错误,它会检测到 null 并返回 false。虽然这不是我期望的它会使用错误的类型值来验证,但它确实有效......有点。

问题出在更新方法上。因为在更新 TestModel 的实例时,它不会显示错误的类型值,而是显示从数据库中检索到的原始值。这确实是一个问题,因为如果从数据库中检索到的数据已经是整数,它将始终返回 true。然后验证将无法完成工作。

问题是:

  1. 对这个验证策略有什么建议吗?我想也许我没有正确的方法来验证整数值验证。

  2. 如何从操作中检索错误的类型值,或者这是不可能的,因为它已经不是该字段的有效数据类型。

4

1 回答 1

0

您在更新方法中看到的行为就是 Play 的工作方式!

这是文档中的相关部分

... 当 Play 找到 id 字段时,它会在编辑之前从数据库中加载匹配的实例。然后应用 HTTP 请求提供的其他参数。

因此,在您的情况下,当sort属性在更新期间为 null 时,将使用数据库中的值。

现在,如果我要尝试实现您想要做的事情,我可能会这样做:

在我的模型中

@Required
@CheckWith(IntegerCheck.class)
public int sort; // using primitive here to avoid null values.

static class IntegerCheck extends Check {

    public boolean isSatisfied(Object model, Object sort) {
        int fieldValue = (int) sort; // here you have the value as int

        // Here you would check whatever you want and return true or false.

        return ... 
    }

}
于 2013-07-18T21:28:26.070 回答