Play Framework 框架 验证.docx
《Play Framework 框架 验证.docx》由会员分享,可在线阅读,更多相关《Play Framework 框架 验证.docx(11页珍藏版)》请在冰豆网上搜索。
PlayFramework框架验证
使用Play验证HTTP数据
ValidatingHTTPdatawithPlay
验证确保数据有确定的值,或者符合某种特殊的需求,你可以在模型被保存进数据库之前使用验证去核实你的模型,或者直接在HTTP参数中使用它们去验证一个简单的form表单。
Validationsensurethatthedatahascertainvaluesormeetsspecificrequirements.Youcanusevalidationtoverifythatyourmodelsarecorrectbeforesavingthemtothedatabase,orusethemdirectlyonHTTPparameterstovalidateasimpleform.
它们怎样工作?
Howdoesitwork?
每一次的请求使用它自己的验证去收集错误。
在控制器里,你可以直接使用Validation变量,你也可以直接访问play.data.validation.Validation类下的API中的静态方法。
Eachrequesthasitown**Validation**objectwhichcollectserrors.Fromacontroller,youaccessitdirectlyusingthe**validation**variable.YoucanstillaccessasubsetoftheAPIusingthe**play.data.validation.Validation**class’staticmethods.
验证对象包含一个集合play.data.validation.Error对象,每一个错误有2个属性。
Thevalidationobjectmaintainsacollectionof**play.data.validation.Error**objects.Eacherrorhastwoproperties:
key,它帮助你决定哪一个数据项引发的错误,key的值可以被定义但是当Play产生错误时,它使用默认的约定,遵循Java变量的名称。
*The**key**.Thishelpsyoutodeterminewhichdataelementcausedtheerror.ThekeyvaluecanbesetarbitrarilybutwhenPlaygenerateserrors,itusesdefaultconventionsthatfollowtheJavavariables’names.
message,它包含了错误的文字描述,message可以是文本信息,或者从错误集合里(典型的是为了国际化支持)参考一个key。
*The**message**.Thiscontainstheerror’stextualdescription.Themessagecanbeaplainmessageorrefertoakeyfromamessagebundle(typicallyforinternationalizationsupport).
下面我们看一下怎样去验证一个简单的HTTP参数。
Let’sseehowtovalidateasimpleHTTPparameter:
publicstaticvoidhello(Stringname){
validation.required(name);
...
}
这段代码检查name变量被正确的设置了,如果不是的话,相应的信息会被增加到当前的错误集合中去。
Thiscodechecksthatthenamevariableiscorrectlyset.Ifnot,thecorrespondingerrorisaddedtothecurrenterrorscollection.
你可以重复这个操作去验证每一个你需要的变量。
Youcanrepeatthisoperationforeachvalidationyouneed:
publicstaticvoidhello(Stringname,Integerage){
validation.required(name);
validation.required(age);
validation.min(age,0);
...
}
重新得到错误信息
Retrievingerrormessages
在每一个验证结束,你可以检查是否错误都被创建并显示出来了。
Attheendofthevalidationyoucancheckifanyerrorshavebeencreatedanddisplaythem:
publicstaticvoidhello(Stringname,Integerage){
validation.required(name);
validation.required(age);
validation.min(age,0);
if(validation.hasErrors()){
for(Errorerror:
validation.errors()){
System.out.println(error.message());
}
}
}
假设name和age是null,那么将会显示出:
Assumingthatnameandagearenull,thiswoulddisplay:
nameisrequired
ageisrequired
默认的消息是key和message集合中key一致的,所以在conf/messages文件中你可以看到:
Defaultmessagesarekeysthatrefertothemessagebundle.Sointhe**conf/messages**fileyouwillhave:
validation.required=%sisrequired
你可以改变这些默认的消息,然后再每一个项目中覆盖它,%s占位符会被错误的key所替代,你可以使用error.message(Stringfield)方法覆盖它。
Youcanchangethisdefaultmessageandoverrideitforeachapplicationlanguage.The**%s**placeholderwillbereplacedbytheerrorkey.Youcanoverrideusingthe**error.message(Stringfield)**method.
例如:
Forexample:
Errorerror=validation.required(name).error;
if(error!
=null){
System.out.println(error.message("Thename"));
}
你还可以为每一次检查明确指定不同的信息。
Youcanalsospecifyadifferentmessageforeachcheck:
Errorerror=validation.required(name).message("Fillthename!
").error;
if(error!
=null){
System.out.println(error.message());
}
再模板中显示错误信息
Displayingerrorsinthetemplate
再大多数情况下,你想让错误消息显示在视图模板中,你可以在模板中使用errors对象使用它们,一些tag帮助你显示这些错误。
Inmostcasesyouwanttodisplaytheerrormessagesintheviewtemplate.Youcanaccesstheminthetemplateusingthe**errors**object.Sometagshelpyoutodisplaytheerrors:
让我们看个例子。
Let’sseeasample:
publicstaticvoidhello(Stringname,Integerage){
validation.required(name);
validation.required(age);
validation.min(age,0);
render(name,age);
}
现在是模板。
andnowthetemplate:
#{ifErrors}
Oops...
#{errors}
${error} #{/errors}
#{/ifErrors}
#{else}
Hello${name},youare${age}.
#{/else}
但是在实际的应用中,你想显示原先的form表单。
所以你将有2个action,显示form表单,还要处理POST。
Butinarealapplicationyouwanttoredisplaytheoriginalform.Soyouwillhavetwoactions:
onetodisplaytheformandanotheronetohandlethePOST.
当然如果有错误发生的话你需要重新跳转到第一个action,但是验证会发生在第二个action中,这样你需要一些小技巧在跳转之前保持错误信息。
使用validate.keey()方法,它可以为下个action保存错误集合。
Ofcoursethevalidationwilloccurinthesecondactionandifsomeerroroccursyouwillhavetoredirecttothefirstaction.Inthiscaseyouneedaspecialtricktokeepyourerrorsduringtheredirect.Usethe**validation.keep()**method.Thiswillsavetheerrorscollectionforthenextaction.
让我们看一个真实的例子。
Let’sseearealsample:
publicclassApplicationextendsController{
publicstaticvoidindex(){
render();
}
publicstaticvoidhello(Stringname,Integerage){
validation.required(name);
validation.required(age);
validation.min(age,0);
if(validation.hasErrors()){
params.flash();//addhttpparameterstotheflashscope
validation.keep();//keeptheerrorsforthenextrequest
index();
}
render(name,age);
}
}
Andthe**view/Application/index.html**template:
#{ifErrors}
Oops...
#{errors}
${error} #{/errors}
#{/ifErrors}
#{form@Application.hello()}
#{/form}
Youcancreateabetteruserexperiencebydisplayingeacherrormessagenexttothefieldthatgeneratedtheerror:
#{ifErrors}
Oops...
#{/ifErrors}
#{form@Application.hello()}
#{/form}
使用注解
Usingannotations
你可以使用注解做相同的事。
Youcanuseannotationstodothesamething:
publicstaticvoidhello(@RequiredStringname,@Required@Min(0)Integerage){
if(validation.hasErrors()){
params.flash();//addhttpparameterstotheflashscope
validation.keep();//keeptheerrorsforthenextrequest
index();
}
render(name,age);
}
验证对象
Validatingobjects
使用注解你可以轻松的为你的model对象增加约束,让我们重写前一个例子,使用User类。
Usingannotationsyoucaneasilyaddconstraintstoyourmodelobjects.Let’srewritethepreviousexampleusingaUserclass.
Firstthe**User**class:
packagemodels;
publicclassUser{
@Required
publicStringname;
@Required
@Min(0)
publicIntegerage;
}
然后修改helloaction.
Thenthemodified**hello**action:
publicstaticvoidhello(@ValidUseruser){
if(validation.hasErrors()){
params.flash();//addhttpparameterstotheflashscope
validation.keep();//keeptheerrorsforthenextrequest
index();
}
render(name,age);
}
最后增加一个修改后的form表单
Andfinallythemodifiedform:
#{ifErrors}
Oops...
#{/ifErrors}
#{form@Application.hello()}
Name:
#{error'user.name'/}
#{/form}
自定义验证
Customvalidation
如果在play.data.validation没有发现你需要的验证,你可以自己写。
然后使用@CheckWith注解绑定到你自己的Check实现里去。
Can’tfindthevalidatoryouneedinthe**play.data.validation**package?
Writeyourown.Youcanusethegeneric**@CheckWith**annotationtobindyourown**Check**implementation.
例如
Forexample:
publicclassUser{
@Required
@CheckWith(MyPasswordCheck.class)
publicStringpassword;
staticclassMyPasswordCheckextendsCheck{
publicabstractbooleanisSatisfied(Objectuser,Objectpassword){
returnnotMatchPreviousPasswords(password);
}
}
}