Play framework HTTP form表单数据校验

来源:互联网 发布:cntv for mac 编辑:程序博客网 时间:2024/06/11 08:54

使用Play校验HTTP数据

验证保证数据是一定的值或满足特定的需求,你可以在保存Model数据到数据库之前校验数据是否正确,或直接使用HTTP参数来验证一个简单的形式。


使用Play验证是如何发挥作用的

每个request对象有它自己的Validation 对象来收集错误,这里有三种方法来定义validations;

1.在控制器方法中,直接调用控制器方法来validation 字段,你也可以访问API的play.data.validation.validation类的静态方法的一个子集。

2.添加注释的方法验证控制器的参数声明。

3.添加@Valid注释到action方法的POJO参数,并且给POJO的属性添加校验注释。


验证对象保存一个play.data.validation.Error集合对象,每一个error有两个属性;

key,这个属性帮助你确定哪一个属性引发了错误,键值可以任意设置,但在使用Play时会产生错误。它使用默认的约定,遵循java变量的名字。

message,这包含错误文本的描述,消息可以是普通消息,也可以是消息包中的键(通常用于国际化支持)。


使用第一种方法,让我们看看如何验证一个简单的HTTP参数:

public static void hello(String name) {     validation.required(name);     …}
此代码检查名称变量是否正确设置。如果没有,则将相应的错误添加到当前错误集合中。


您可以为需要的每个验证重复此操作:

public static void hello(String name, Integer age) {     validation.required(name);     validation.required(age);     validation.min(age, 0);     …}

验证错误消息

在验证结束时,您可以检查是否已经创建了任何错误并显示它们:

public static void hello(String name, Integer age) {     validation.required(name);     validation.required(age);     validation.min(age, 0);          if(validation.hasErrors()) {         for(Error error : validation.errors()) {             System.out.println(error.message());         }     }}
假设名称和年龄为空,则显示:

RequiredRequired
这是因为默认消息,定义在$PLAY_HOME/resources/messages:

validation.required=Required
有定制的验证信息的三种方式。

1.通过在应用程序的消息文件中重新定义消息,覆盖默认消息。

2.将自定义消息作为附加的验证参数提供。

3.为一个本地化的消息提供一个消息键作为附加的验证参数。


局部验证消息

重写这些信息的最简单方法是使用相同的信息,关键的信息在您的应用程序的配置信息文件。例如:

validation.required = Please enter a value 
您也可以提供其他语言的本地化,如


验证消息参数

您可以使用消息中的占位符作为错误密钥:

validation.required=%s is required
这将输出更改为:

name is requiredage is required
限制:当多个参数是Play不能确定正确的参数名,必须的参数使用validation.required(age) 语法校验失败,在这种情况下,必须直接指定字段名。validation.required("age", age);


此错误键默认为参数名称,它本身就是用来查找消息的。例如,上面的hello action方法中的name参数可以本地化:

name = Customer name
这将导致输出:

Customer name is requiredage is required
你还可以使用 error.message(String key)方法,

Error error = validation.required(name).error;if(error != null) {    System.out.println(error.message("Customer name"));}
几个内置的验证定义额外的消息参数对应的验证参数,例如,“匹配”验证为指定的正则表达式定义了第二个字符串参数,它与上面的%s占位符不同,因为它指定参数索引“2”:

validation.match=Must match %2$s 
类似地,“范围”验证定义了两个附加的数字参数,索引2和3:

validation.range=Not in the range %2$d through %3$d 
查看文件 $PLAY_HOME/resources/messages ,查看其它的参数。



自定义局部验证消息

验证消息在 $PLAY_HOME/resources/messages文件中使用默认的消息key,你可以指定不同的key,例如:

validation.required.em = You must enter the %s! 
使用此消息的新消息键,在操作方法中进行手动验证:

validation.required(manualKey).message("validation.required.em");
或者,在注释的消息参数中使用该键:

public static void hello(@Required(message="validation.required.em") String name) {    …} 
可以使用与JavaBean属性上的验证注释相同的技术:


public static void hello(@Valid Person person) {    …}  public class Person extends Model {    @Required(message = "validation.required.emphasis")   public String name;    … } 
自定义文字(非本地化)验证消息

如果没有定义密钥的消息,则Play消息查找仅返回消息密钥,

也就是说,如果您愿意,也可以使用字面消息而不是消息键。使用上述示例,进行手动验证:

validation.required(manualKey).message("Give us a name!"); 
action方法参数的注释:

public static void save(@Required(message = "Give us a name!") String name) {    …} 
对于JavaBean注释是:

public static void save(@Valid Person person) {    …} public class Person extends Model {   @Required(message = "Give us a name!")   public String name;    … } 


在模板中验证错误

在大多数情况下,您希望在视图模板中显示错误消息。你可以在模板中使用errors对象接收他们,一些标签帮助你去显示错误信息。

让我们看一个例子:

public static void hello(String name, Integer age) {   validation.required(name);   validation.required(age);   validation.min(age, 0);   render(name, age);}
现在模板:

#{ifErrors}    <h1>Oops…</h1>    #{errors}       <li>${error}</li>   #{/errors} #{/ifErrors}#{else}    Hello ${name}, you are ${age}. #{/else}

但是在实际的应用中,你想显示原始形式,因此,您将有两个动作:一个显示窗体,另一个操作句柄。


当然,验证将发生在第二个操作中,如果出现一些错误,您将不得不重定向到第一个操作。在这种情况下,您需要一个特殊的技巧来在重定向期间保持错误。使用validation.keep()方法,将会给下一个action请求保存错误集合。


让我们看看真正的样例:

public class Application extends Controller {    public static void index() {      render();   }    public static void hello(String name, Integer age) {      validation.required(name);      validation.required(age);      validation.min(age, 0);      if(validation.hasErrors()) {          params.flash(); // add http parameters to the flash scope          validation.keep(); // keep the errors for the next request          index();      }      render(name, age);   } }
与视图view/Application/index.html一起使用。

#{ifErrors}   <h1>Oops…</h1>    #{errors}       <li>${error}</li>   #{/errors}#{/ifErrors} #{form @Application.hello()}   <div>      Name: <input type="text" name="name" value="${flash.name}" />   </div>   <div>      Age: <input type="text" name="age" value="${flash.age}" />    </div>   <div>      <input type="submit" value="Say hello" />    </div>#{/form}
通过在生成错误的字段旁边显示每个错误消息,可以创建更好的用户体验:

#{ifErrors}   <h1>Oops…</h1>#{/ifErrors} #{form @Application.hello()}   <div>      Name: <input type="text" name="name" value="${flash.name}" />      <span class="error">#{error 'name' /}</span>   </div>   <div>      Age: <input type="text" name="age" value="${flash.age}" />       <span class="error">#{error 'age' /}</span>   </div>   <div>      <input type="submit" value="Say hello" />    </div>#{/form}

验证注释

play.data.validation包 中的注释提供了一种更简单的方法来验证错误,使用对应于每个对象方法的Validation注释,去使用validation 注释,只需注释控制器的参数:

public static void hello(@Required String name, @Required @Min(0) Integer age) {   if(validation.hasErrors()) {       params.flash(); // add http parameters to the flash scope       validation.keep(); // keep the errors for the next request       index();   }   render(name, age);}

您还可以使用验证注释轻松地为模型对象的属性添加约束。然后在控制器中指定所有属性必须是有效的。让我们使用用户类重写前面的示例。


首先关于User类,关于属性的验证注释:

package models; public class User {        @Required    public String name;     @Required    @Min(0)    public Integer age;}

然后是被修改的hello action,他是用@Valid注释指定所有用户对象的属性必须是有效的:

public static void hello(@Valid User user) {   if(validation.hasErrors()) {       params.flash(); // add http parameters to the flash scope       validation.keep(); // keep the errors for the next request       index();   }   render(name, age);}
最后是修改后的表单:

#{ifErrors}   <h1>Oops…</h1>#{/ifErrors} #{form @Application.hello()}   <div>      Name: <input type="text" name="user.name" value="${flash['user.name']}" />      <span class="error">#{error 'user.name' /}</span>   </div>   <div>      Age: <input type="text" name="user.age" value="${flash['user.age']}" />       <span class="error">#{error 'user.age' /}</span>   </div>   <div>      <input type="submit" value="Say hello" />    </div>#{/form}

内置的验证

play.data.validation包包含多个内置验证,可以在验证对象上使用,也可以在注释中使用。


自定义校验使用@CheckWith注释

在包play.data.validation中不能找到需要校验?编写你自己的校验使用@CheckWith注释绑定你自己的校验实现。

public class User {        @Required    @CheckWith(MyPasswordCheck.class)    public String password;        static class MyPasswordCheck extends Check {                public boolean isSatisfied(Object user, Object password) {            return notMatchPreviousPasswords(password);        }    }}
默认的校验错误信息key是validation.invalid,使用不同的键,调用Check.setMessage使用一个消息key和消息参数。

static class MyPasswordCheck extends Check {     public boolean isSatisfied(Object user, Object password) {        final Date lastUsed = dateLastUsed(password);        setMessage("validation.used", JavaExtensions.format(lastUsed));        return lastUsed == null;    }}
消息查找总是以字段名作为第一个参数,和你的消息参数作为后续参数,因此,对于上面的例子,您可以定义如下消息:


validation.used = &{%1$s} already used on date %2$suser.password = Password

原创粉丝点击