【问题标题】:JSR-303 Bean Validation annotate multiple fieldsJSR-303 Bean Validation 注解多个字段
【发布时间】:2012-04-05 22:27:34
【问题描述】:

我刚刚开始测试 JSR-303 Bean 验证,想知道是否可行。我们的应用程序中有一个用于所有字符串字段的默认正则表达式。如果我想使用 bean 验证来应用它,我想我需要注释我的表单对象中的每个字段。

@Pattern(regexp = REG_EXP)
private String aString;

@Pattern(regexp = REG_EXP)
private String anotherString;

是否可以一次将@Pattern 应用于所有字符串(或某些字段)?我们在 Weblogic 10.3.4 上使用 Hibernate 实现,JSF2.0 作为前端。验证应该独立于视图,因为我可能来自网络服务。

【问题讨论】:

    标签: java bean-validation


    【解决方案1】:

    我没有使用,但 java 在服务器端使用 grovvy 支持脚本,javascript..。您可以检查 @ScriptAssert(lang = "javascript", script =_this.startDate.before(_this.endDate) 脚本注释,它是休眠注释。

    【讨论】:

    • 谢谢,但我刚刚编辑了我的问题,因为无论访问方法如何,即通过 Web 服务或浏览器,都需要运行验证。
    【解决方案2】:

    要一次验证多个字段,请在类型级别上使用注释并编写自定义验证器,使用您的 REGEXP 检查所有字符串字段。

    编辑:提供示例。这很丑陋,因为它使用了反射并且违反了安全性,但也许它给了你一个大概的想法。如果您不使用“对象”而是使用具体的类或接口,那么您可能会使用常规 getter 获得成功。

    被测类(和 Runner)

       import javax.validation.Validation;
    import javax.validation.Validator;
    
    import validation.AllStringsRegex;
    
    @AllStringsRegex(value="l")
    public class UnderValidation {
        String a;
        String b;
    
       public static void main(String... args) {
           UnderValidation object = new UnderValidation();
           object.a = "hello";
           object.b = "world";
    
           Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
           System.out.println(validator.validate(object));
       }
    }
    

    我的注释:

    @Target( { TYPE, ANNOTATION_TYPE })
    @Retention(RUNTIME)
    @Constraint(validatedBy = AllStringsRegexValidator.class)
    @Documented
    public @interface AllStringsRegex {
        String message() default "String not regex";
        String value() default "";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    我的验证者

    public class AllStringsRegexValidator implements ConstraintValidator<AllStringsRegex, Object> {
        private Pattern pattern = null;
    
        @Override
        public void initialize(AllStringsRegex annotation) {
            pattern = Pattern.compile(annotation.value());
        }
    
        @Override
        public boolean isValid(Object object, ConstraintValidatorContext ctx) {
            for (Field f : object.getClass().getDeclaredFields()) {
                if (f.getType().equals(String.class)) {
                    try {
                        f.setAccessible(true);
                        String value = (String)f.get(object);
                        if (!pattern.matcher(value).find()) {
                            return false;
                        }
                    }
                    catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            return true;
        }
    }
    

    【讨论】:

    • 谢谢,但 JSF 未验证 @type。但是自定义验证器如何检查所有字符串字段?
    • 在上面的例子中,没有抛出错误,因为“l”同时匹配“hello”和“world”。更改为“ll”以获得 ConstraintViolation。
    • 感谢 Jan,非常好的例子,我从中学到了一些新东西。
    • 一月,还有一个问题。你能解释一下你对反射和安全的负面评价吗?谢谢。
    • 安全性:我使用“setAccessible”直接访问字段值。这违反了封装契约(私有属性、公共 getter/setter)。任何生产系统都会阻止这一点,因此这仅用于测试和 poc。反射:反射会变慢,它违反了面向对象的方法。正如我所提到的:尝试为具体类(客户而不是对象)编写验证器,然后删除反射部分,但通过具体的 getter 访问值(getName()、get() ...)
    猜你喜欢
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 2011-12-28
    • 2016-06-19
    相关资源
    最近更新 更多