如何为play-framework编写自定义检查/验证 [英] Howto write custom checks/validation for the play-framework

查看:118
本文介绍了如何为play-framework编写自定义检查/验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试为游戏框架编写支票,并看到两种不同的可能性。我描述了两者,并想知道我的理解是否正确(所以它更像是一个教程而不是一个问题,特别是因为我没有得到任何我错过的回复)。
那么存在什么可能性。

I try to write checks for the play-framework and see two different possibilities. I described both and want to know if my understanding is correct (So it's more a tutorial than a question, specially because I didn't get any response that I missed something). So what possibilities exists.


  1. 简单方法:扩展类检查

    优点:更易于编写,更易于阅读

    缺点:您无法对检查进行参数化,只能定义消息。

  2. 高级方法:根据OVal编写支票 AbstractAnnotationCheck

    优点:您可以参数化检查并使用更简单的注释

    缺点:有点复杂。

  1. The simple way: Extending the class Check:
    Advantages: Easier to write, easier to read
    Disadvantages: You can't parametrized the check, you can only define the message.
  2. The advanced way: Writing an check based on OVal AbstractAnnotationCheck.
    Advantages: You can parametrized the check and have a simpler to use annotation
    Disadvantages: A little bit more complicated.

在我们查看实现之前,我想解释一下消息。您始终可以直接设置消息,也可以使用密钥在消息属性中引用消息。最后一个是更清洁和推荐的方式。每个验证都至少获得1个参数:属性的名称无效。因此,验证或检查特定参数始终用%i $ s 表示,其中i> 1。消息字符串的格式应遵循 Formatter <的规则/ a>但我不确定是否支持所有功能。据我所知只有%s,%d和%f支持定位。所以%[argument_index $] [flags]转换其中转换只能是s,d或f。

Before we have a look on the implementation I want to explain the messages. You can always set the message directly or use a key to refer the message in a message-properties. The last one is the cleaner and recommended way. Every validation get a least 1 parameter: The name of the property which isn't valid. So validation or check specific parameters are always referred with %i$s where i>1. The format of the message string should follows the rules of Formatter but I'm unsure if all features are supported. As far as I know only %s, %d and %f is supported togeter with positioning. So %[argument_index$][flags]conversion where conversion could only be s,d or f.

让我们看看两个例子:
我在模块中用于乐观锁定的简单方法:

Lets have a look on two examples: The simple way I used in my module for optimistic locking:

/**
 * Check with proof if the version of the current edited object is lesser
 * than the version in db.
 * Messagecode: optimisticLocking.modelHasChanged
 * Parameter: 1 the request URL.
 * Example-Message: The object was changed. <a href="%2$s">Reload</a> and do your changes again.
 *
 */
static class OptimisticLockingCheck extends Check {

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isSatisfied(Object model, Object optimisiticLockingViolatedValue) {
        //The comparision of version was made in the setter. Here
        //we only have to check the flag.
        if (((VersionedModel) model).optimisiticLockingViolated) {
            final Request request = Request.current();
            //The following doesn't work in 1.0 but in 1.1 see https://bugs.launchpad.net/play/+bug/634719
            //http://play.lighthouseapp.com/projects/57987-play-framework/tickets/116
            //setMessage(checkWithCheck.getMessage(), request != null ? request.url : "");
            setMessage("optimisticLocking.modelHasChanged", request != null ? request.url : ""); 

        }
        return !((VersionedModel) model).optimisiticLockingViolated;
    }
}

您使用此检查注释 @CheckWith(value = OptimisticLockingCheck.class,message =optimisticLocking.modelHasChanged)

所以让我们仔细看看它是如何工作的。我们唯一要做的就是扩展类play.data.validation.Check并覆盖isSatisfied方法。在那里,您可以获得模型和属性的值。你所要做的就是如果一切正常则返回true,否则返回false。在我们的例子中,我们想要将当前url设置为参数。这个
可以通过调用setMessage()轻松完成。我们给出消息属性和参数中定义的消息或消息密钥。请记住,我们只提供1个参数,但引用为%2 $ s,因为第一个参数始终是属性的名称。

So lets have a closer look how it works. The only thing we have to do is to extends the class play.data.validation.Check and overwrite the isSatisfied method. There you get your model and the value of the properties. All you have to do is to return true if everything is OK or false otherwise. In our case we want to set the current url as a parameter. This can be easily done by calling setMessage(). We give the message or the message key which is defined in the messages properties and the parameters. Remember we only give 1 parameter but referred as with %2$s, because the first parameter is always the name of the property.

现在基于范围的复杂方式-check of play:
首先我们需要定义一个注释

Now the complex way based on the Range-check of play: First we need to define an Annotation

/**
 * This field must be lower than and greater than.
 * Message key: validation.range
 * $1: field name
 * $2: min reference value
 * $3: max reference value
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Constraint(checkWith = RangeCheck.class)
public @interface Range {

    String message() default RangeCheck.mes;
    double min() default Double.MIN_VALUE;
    double max() default Double.MAX_VALUE;
}

然后检查

@SuppressWarnings("serial")
public class RangeCheck extends AbstractAnnotationCheck<Range> {

    final static String mes = "validation.range";

    double min;
    double max;

    @Override
    public void configure(Range range) {
        this.min = range.min();
        this.max = range.max();
        setMessage(range.message());
    }

    public boolean isSatisfied(Object validatedObject, Object value, OValContext context, Validator validator) {
        requireMessageVariablesRecreation();
        if (value == null) {
            return true;
        }
        if (value instanceof String) {
            try {
                double v = Double.parseDouble(value.toString());
                return v >= min && v <= max;
            } catch (Exception e) {
                return false;
            }
        }
        if (value instanceof Number) {
            try {
                return ((Number) value).doubleValue() >= min && ((Number) value).doubleValue() <= max;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    @Override
    public Map<String, String> createMessageVariables() {
        Map<String, String> messageVariables = new TreeMap<String, String>();
        messageVariables.put("2-min", Double.toString(min));
        messageVariables.put("3-max", Double.toString(max));
        return messageVariables;
    }

}

好的我认为注释不是'必须解释。让我们看看支票。在这种情况下,它扩展 net.sf.oval.configuration.annotation.AbstractAnnotationCheck 。我们必须编写一个configure-method来获取注释并可以复制参数。然后我们必须定义我们的支票。这类似于其他检查的实施。所以我们只写一个条件并返回true或false,除了一个特殊的行!如果我们使用参数化消息,我们必须在我们的方法中调用 requireMessageVariablesRecreation();
至少我们必须覆盖方法 createMessageVariables 。在这里,我们必须得到一个小小的play-knowlegde(所有其他的东西都在
这里中描述) 。您将消息放入带有键和值的映射中,但播放只接受值(请参阅框架代码中的 ValidCheck.java )。所以它将被位置引用。这就是我使用 TreeMap 而不是 HashMap改变 RangeCheck 的实现的原因。此外,我让密钥以他们可以引用的索引开始。

OK I think the annotation don't must be explained. Lets have look on the check. In this case it's extends net.sf.oval.configuration.annotation.AbstractAnnotationCheck. We have to write a configure-method where we get the annotation and can copy the parameters. Then we have to define our check. Which is analog to the implementation of the other check. So we only write our condition and return true or false, except one special line! If we used a parametrized message, we must call requireMessageVariablesRecreation(); in our method. At least we must override the method createMessageVariables. Here we have to get a littlebit play-knowlegde (all the other stuff is described here). You put your messages into an map with a key and value, but play only takes the values (see ValidCheck.java in framework code). So it will be referenced by position. This is the reason I changed the implementation of the RangeCheck using TreeMap instead of HashMap. Furthermore I let the keys start with the index which they can referred.

所以我希望这更清楚如何编写自定义验证/检查游戏。我希望描述是正确的。因此问题是我的理解正确吗?

So I hope this makes it more clear how to write custom validations/checks for play. I hope the description is correct. Therefor the question is my understanding correct?

推荐答案

至少你的第一个例子似乎在正确的路径上。您可以将它与下面提供的文档进行比较,但我会从您的示例的复杂性中假设您已经引用它。

At least your first example appears to be on the correct path. You can compare it to the documentation provided below, but I'd assume from the complexity of your example that you've already referred to it.

http://www.playframework.org/documentation/1.1/validation#custom

我不太了解播放框架对第二个例子的评论。

I don't know enough about the play framework to comment on the second example.

这篇关于如何为play-framework编写自定义检查/验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆