Playframework(10)Scala Project and Database

Playframework(10)ScalaProjectandDatabase

UsingtheParserAPI

ThemosteasiestparseristoparseavaluetoScalaLong

valrowParser=scalar[Long]

valrsParser=scalar[Long].single

ThiskindofsimpleparserAPIisusefultoproducetheresultbyasimpleselectcountquery:

valcount:Long=SQL("selectcount(*)fromCountry").as(scalar[Long].single)

Acomplexonewithstr("name")~int("population")

valpopulations:List[String~Int]={

SQL("select*fromCountry").as(str("name")~int("population")*)

}

Alternatively,wecanwritelikethis:

valresult:List[String~Int]={

SQL("select*fromCountry").as(get[String]("name")~get[Int]("population")*)

}

…snip…

8.3Integratingwithotherdatabaseaccesslibraries

IntegratingwithScalaQuery

…snip..

ExposingthedatasourcethroughJNDI

…snip...

9.UsingtheCache

ItisbasedonEhcache.

AccessingtheCacheAPI

UsingthissimpleAPItostoredataincache:

Cache.set("item.key",connectedUser)

retrieveitlater:

valmaybeUser:Option[User]=Cache.getAs[User]("item.key")

CachingHTTPresponses

Playprovidesadefaultbuilt-inhelperforstandardcases:

defindex=Cached("homePage"){

Action{

Ok("Helloworld")

}

}

10.CallingWebServices

10.1ThePlayWSAPI

Anycallsmadebyplay.api.libs.ws.WSshouldreturnaPromise[play.api.libs.ws.Response]whichwecanlaterhandlewithPaly'sasynchronousmechanisms.

MakinganHTTPcall

Thesimplewayistousews.url().

valhomePage:Promise[ws.Response]=WS.url("http://mysite.com").get();

Or:

valresult:Promise[ws.Response]={

WS.url("http://localhost:9001/post").post("content")

}

Posturl-form-encodeddata

…snip…

10.2ConnectingtoOpenIDservices

TheOpenIDflowinanutshell

1.TheusergivesyouhisOpenID(aURL).

2.YourserverinspectsthecontentbehindtheURLtoproduceaURLwhereyouneedtoredirecttheuser.

3.TheuserconfirmstheauthorizationonhisOpenIDprovider,andgetredirectedbacktoyourserver.

4.Yourserverreceivesinformationfromthatredirect,andcheckswiththeproviderthattheinformationiscorrect.

OpenIDinPlay

TheopenIDAPIhas2importfunctions:

OpenID.redirectURL.ItreturnsaPromise[String]ratherthanaString.IftheOpenIDisinvalid,thereturnedPromisewillbeaThrown.

OpenID.verifiedId.ItwilldoacalltotheOpenIDservertochecktheauthenticityoftheinformation,thisiswhyitreturnsaPromise[UserInfo]ratherthanjustUserInfo.Iftheinformationisnotcorrectoriftheservercheckisfalse,thereturnedPromisewillbeaThrown.

Hereisanexampleofusage:

deflogin=Action{

Ok(views.html.login())

}

defloginPost=Action{implicitrequest=>

Form(single(

"openid"->nonEmptyText

)).bindFromRequest.fold(

error=>{

Logger.info("badrequest"+error.toString)

BadRequest(error.toString)

},

{

case(openid)=>AsyncResult(OpenID.redirectURL(openid,routes.Application.openIDCallback.absoluteURL()).extend(_.valuematch{

caseRedeemed(url)=>Redirect(url)

caseThrow(t)=>Redirect(routes.Application.login)

}))

}

)

}

defopenIDCallback=Action{implicitrequest=>

AsyncResult(

OpenID.verifiedId.extend(_.valuematch{

caseRedeemed(info)=>Ok(info.id+"\n"+info.attributes)

caseThrown(t)=>{

Redirect(routes.Application.login)

}

}

)

}

ExtendedAttributes

TheOpenIDofausergivesyouhisidentity.Theprotocolalsosupportsgettingextendedattributessuchasthee-mailaddress,thefirstname,orthelastname.

OpenID.redirectURL(

openid,

routes.Application.openIDCallback.absoluteURL(),

Seq("email"->"http://schema.openid.net/contact/email")

)

10.3AccessingresourcesprotectedbyOAuth

Thereare2verydifferentversionsofOAuth:OAuth1.0andOAuth2.0.Version2issimpleenoughtobeimplementedeasilywithoutlibraryorhelpers.PlayonlyprovidessupportforOAuth1.0.

…snip...

11.IntegratingwithAkka

…snip…

12.Internationlization

…snip...

13TheapplicationGlobalobject

13.1Applicationglobalsettings

TheGlobalobject

objectGlobalextendsGlobalSettings{

}

Hookingintoapplicationstartandstopevents

OverridetheonStartandonStopmethodstobenotifiedoftheeventsintheapplicationlife-cycle:

objectGlobalextendsGlobalSettings{

overridedefonStart(app:Application){

Logger.info("Applicationhasstarted")

}

overridedefonStop(app:Application){

Logger.info("Applicationshutdown...")

}

}

Providinganapplicationerrorpage

Whenanexceptionoccursinyourapplication,theonErroroperationwillbecalled.

objectGlobalextendsGlobalSettings{

overridedefonError(request:RequestHeader,ex:Throwable)={

InternalServerError(

views.html.errorPage(ex)

)

}

}

Handlingmissingactionsandbindingerrors

Iftheframeworkdoesn'tfindanActionforarequest,theonHandlerNotFoundoperationwillbecalled:

objectGlobalextendsGlobalSettings{

overridedefonHandlerNotFound(request:RequestHeader):Result={

NotFound(

views.html.notFoundPage(request.path)

)

}

}

onBadRequestisforthatifaroutewasfound,butitwasnotpossibletobindtherequestparameters.

13.2Interceptingrequests

OverridingonRouteRequest

objectGlobalextendsGlobalSettings{

defonRouteRequest(request:RequestHeader):Option[Handler]={

println("executedbeforeeveryrequest:"+request.toString)

super.onRouteRequest(request)

}

}

14Testingyourapplication

14.1Writingtests

Usingspecs2

Unitspecificationsextendtheorg.specs2.mutable.Specificationtraitandareusingtheshould/informat:

classHelloWorldSpecextendsSpecification{

"The'Helloworld'string"should{

"contain11characters"in{

"Helloworld"musthavesize(11)

}

"startwith'Hello'"in{

"Helloworld"muststartWith("Hello")

}

"endwith'world'"in{

"Helloworld"mustendWith("world")

}

}

}

Runninginafakeapplication

…snip...

References:

http://www.playframework.org/documentation/2.0.4/ScalaHome

http://www.playframework.org/documentation/2.0.4/ScalaAnorm

相关推荐