【问题标题】:Is it possible to set multiple messages using oval AbstractAnnotationCheck?是否可以使用椭圆形 AbstractAnnotationCheck 设置多条消息?
【发布时间】:2011-11-30 16:02:51
【问题描述】:

我正在使用 Oval 验证框架来验证 HTML 字段不能包含恶意 javascript 代码的字段。对于恶意代码检测,我使用了一个外部框架,它返回一个错误列表,我想在现场用作错误消息。我遇到的问题是我只能在检查实现中设置消息,而我宁愿做类似 setMessages(List) 的事情。因此,虽然我目前只是用逗号加入错误,但我宁愿将它们作为列表传递回去。

注释

@Target({ ElementType.METHOD, ElementType.FIELD})
@Retention( RetentionPolicy.RUNTIME)
@Constraint(checkWith = HtmlFieldValidator.class)
public @interface HtmlField {
   String message() default "HTML could not be validated";
}

检查

public class HtmlFieldValidator  extends AbstractAnnotationCheck<HtmlDefaultValue> {
    public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
        if (o1 == null) {
            return true;
        } else {
            CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
            if (cleanResults.getErrorMessages().size() > 0) {
                String errors = StringUtils.join(cleanResults.getErrorMessages(), ", ");
                this.setMessage(errors);
                return false;
            } else {
                return true;
            }
        }
    }
}

模型类

class Foo {

    @HtmlField
    public String bar;

}

控制器代码

Validator validator = new Validator(); // use the OVal validator
Foo foo = new Foo();
foo.bar = "<script>hack()</script>";

List<ConstraintViolation> violations = validator.validate(bo);

if (violations.size() > 0) {
    // inform the user that I cannot accept the string because 
    // it contains invalid html, using error messages from OVal
}

【问题讨论】:

    标签: java annotations oval


    【解决方案1】:

    如果setMessage(String message) 是由超类创建的方法,您可以覆盖它,一旦它接收到数据,只需将字符串拆分为一个列表并调用您实际放置代码的第二个函数。附带说明一下,我还建议将分隔字符串更改为更独特的字符串,因为错误消息本身可能包含逗号。

    不过,您的问题并没有多大意义。如果您将它们“传递回”给在超类中实现的方法,那么这会使您的问题的整个要点无效,因为超类将处理数据。

    我将假设setError 方法是一个简单的设置器,它设置一个String 变量来存储您计划在检查数据后访问的错误消息。由于您希望拥有首选类型的数据,因此只需在您的类中创建一个新的字符串数组并忽略超类。如果您愿意,您甚至可以同时使用两者。

    public class HtmlFieldValidator  extends AbstractAnnotationCheck<HtmlDefaultValue> {
        public String[] errorMessages = null;
    
        public void setErrorMessages(String[] s) {
            this.errorMessages = s;
        }
    
        public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
            if (o1 == null) {
                return true;
            } else {
                CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
                if (cleanResults.getErrorMessages().size() > 0) {
                    //String errors = StringUtils.join(cleanResults.getErrorMessages(), ", ");
                    //this.setMessage(errors);
                    this.setErrorMessages(cleanResults.getErrorMessages());
                    return false;
                } else {
                    return true;
                }
            }
        }
    }
    

    其他地方:

    HtmlFieldValidator<DefaultValue> hfv = new HtmlFieldValidator<DefaultValue>();
    boolean satisfied = hfv.isSatisfied(params);
    if (!satisfied) {
        String[] errorMessages = hfv.errorMessages;
        //instead of using their error message
    
        satisfy(errorMessages);//or whatever you want to do
    }
    

    编辑:

    更新代码后,我明白你的意思了。虽然我认为这有点过头了,并且稍后将字符串转换为数组会容易得多,但您可以通过创建一个扩展 ValidatorsetMessage 方法的新类来做到这一点。在该方法中,您将调用super.setMethod 并将字符串拆分并存储为其类中的数组。

    class ValidatorWithArray extends Validator {
        public String[] errors;
        public final static String SPLIT_REGEX = ";&spLit;";// Something unique so you wont accidentally have it in the error
    
        public void setMessage(String error) {
            super.setMessage(error);
            this.errors = String.split(error, SPLIT_REGEX);
        }
    }
    

    HtmlFieldValidator:

    public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
                if (o1 == null) {
                    return true;
                } else {
                    CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
                    if (cleanResults.getErrorMessages().size() > 0) {
                        String errors = StringUtils.join(cleanResults.getErrorMessages(), ValidatorWithArray.SPLIT_REGEX);
                        this.setMessage(errors);
                        return false;
                    } else {
                        return true;
                    }
                }
            }
    

    现在只需使用ValidatorWithArray 而不是Validator

    【讨论】:

    • 虽然如果我控制了验证框架,您提供的代码会很好,但它没有与我正在使用的验证框架 (OVal) 集成。还有很多其他的验证正在进行中,我希望它可以无缝地使用。我还添加了一些额外的代码来尝试显示“将它们传递回去”的意思。
    【解决方案2】:

    我想要实现这一点的情况与你的不同,但是我发现在我的情况下最好的是为每个错误创建一个注释(而不是一个会返回多个错误的注释)。我想这取决于在我的情况下您可能会产生多少错误,它只有两个或三个。

    此方法还使您的代码非常易于重用,因为您可以在任何需要的地方添加注释并随意组合它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-12
      • 2014-03-11
      • 2020-01-01
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多