下载

1下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 Getting Started with Grails

Getting Started with Grails .pdf

Getting Started with Grails

laqxs
2011-01-31 0人阅读 举报 0 0 暂无简介

简介:本文档为《Getting Started with Grails pdf》,可适用于IT/计算机领域

DZone,Inc|wwwdzonecomByDaveKleinGettinGstartedwithGrailsGrailswwwdzonecomGetMoreRefcardz!Visitrefcardzcom#GettingStartedwithGrailsGrailsisafullstackwebapplicationframeworkbuiltontopofsuchtriedandtrueopensourceframeworksasSpring,Hibernate,Ant,JUnitandmoreByapplyingprinciplessuchasConventionoverConfigurationandDon’tRepeatYourself,andtakingadvantageofthedynamicGroovyprogramminglanguage,GrailsmakesitincrediblyeasytousethesepowerfultoolsGrailsdoesn’treinventthewheelGrailsmakesawheelthatinflatesitselfandrollswhereyouwantitto!IncaseyouarenewtoGrails,we’llstartwithabriefintroduction,whichshouldbeenoughtogetyouhookedandturnyouintoaGrailsdeveloperThat’swhenthisRefcardwillcomeinhandyitisacheatsheetforGrailsdevelopers,aquicksourceforthosethingsyoukeephavingtogobacktothedocstolookupControllers,ServicesandViewswithadetailedGSPtaglibreferenceInstallingGrailsDownloadtheGrailsarchivefromhttp:grailsorgdownloadandextractittoalocaldirectorySetaGRAILSHOMEenvironmentvariabletothatdirectoryandaddGRAILSHOMEbintoyourpath(YoualsoneedavalidJAVAHOMEenvironmentvariable)Nowyou’rereadytogo!AWebAppintheBlinkofanEyeTocreateanewGrailsapplication,type:$grailscreateappAutoMartNowchangetotheAutoMartdirectoryandcreateadomainclass:$grailscreatedomainclassCarOpenAutoMartgrailsappdomainCargroovyandeditit,likeso:classCar{StringmakeStringmodelIntegeryear}Savethisfile,andrun:$grailsgenerateallCarCreateappandcreatedomainclassareGrailsscriptsToseewhatotherscriptsareprovidedbyGrails,rungrailshelpfromthecommandlineYounowhaveacompleteworkingwebapplication,withpagesforcreating,displaying,editingandlistingCarinstancesYoucanlaunchitwith:$grailsrunappGrailsrunsonportbydefaultYoucaneasilyrunonadifferentportlikethis:$grailsDserverport=runappNavigatetohttp:localhost:AutoMartandlookaroundFigureandFigureshowacoupleoftheviewsGrailsgivesus“outofthebox”YoucanalsoleaveitrunningwhileyoucontinuetodevelopJustsaveyourchangesandrefreshyourbrowserThisrapidfeedbackisoneofthestrengthsofGrailsGrailsConventionsInourexampletheCargroovyfilethatGrailscreatedforuswasplacedinadirectorycalledgrailsappdomainThisisoneofthemanyconventionsinGrailsPlacingsourcefilesincertaindirectoriesandnamingthemincertainwayscanmakemagicalthingshappeninaGrailsapplicationDomainClassesPlacingaGroovyclassfileinthegrailsappdomaindirectorywillturnitintoapersistentdomainclassSeveralpropertiesandmethodswillbeaddedtotheclassdynamically,andGrailswillcreateatablebasedonthenameoftheclass,withfieldsforeachpropertyFigure:CarListFigure:CreateCarnAuthoritativecontentnDesignedfordevelopersnWrittenbytopexpertsnLatesttoolstechnologiesnHottipsexamplesnBonuscontentonlinenNewissueeveryweeksSubscribeNowforFREE!RefcardzcomGetMoreRefcardz(They’refree!)COntentsinClUde:nGettingStartedwithGrailsnTestingnDomainClassMosaicnTheThreeR’sofControllersnServicesnHotTipsandmoreDZone,Inc|wwwdzonecomGettingStartedwithGrailsControllersGrailscontrollersaresimpleGroovyclasseswithnamesendingin‘Controller’andresidinginthegrailsappcontrollersdirectoryControllersalsoreceiveseveralmethodsandpropertiesdynamicallyAnyclosuredefinedasapropertyinaControllerwillbecomeanactionreachablebyaURLinthefollowingform:applicationcontrolleractionViewsForeachcontrollerinyourapplicationtherewillbeadirectoryundergrailsappviewsnamedafterthecontrollerclass(iegrailsappviewscar)Thisdirectoryiswhereyourviews(gspfiles)goWhenacontrolleractioniscompleteditwillautomaticallyattempttorenderaviewwiththenameoftheactionSo,whenyoucallhttp:localhost:AutoMartcarlistthelistactionwillexecuteandrenderthelistgsppageYoucan,ofcourserenderspecificpagesbutconventioncanbeahugetimesaverServicesAGroovyclasswithanameendingin‘Service’andresidinginthegrailsappservicesdirectorybecomesaGrailsserviceandhasbuiltintransactionhandlingandmoreTagLibsCreatingcustomtagsinGrailsissoeasyitshouldbeillegalJustcreateaGroovyclassendingwith‘TagLib’andplaceitinthegrailsappTagLibdirectoryThendefineaclosurepropertyandwritetotheOutputStreamcalled‘out’thatisalreadygiventoyouYoucanalsousethetag’sattributesandbodybysimplydeclaringthemclassYourTagLib{defsaySomething={attrs,body>if(attrstone==‘loud’)out<<body()toUpperCase()elseif(attrstone==‘quiet’)out<<body()toLowerCase()elseout<<body()}Youcanusethistaginagsplikethis:<g:saySomethingtone=”loud”>I’mshoutingnow!<g:saySomething>Youcanusethistaginagsplikethis:<g:saySomethingtone=”loud”>I’mshoutingnow!<g:saySomething>I’MSHOUTINGNOW!Therearenoextraclassestocreate,nointerfacestoimplement,noTLDstocreateYoucouldprobablytakeupanewhobbywiththetimeyou’llsave!testinGUnitTestsGrailsencouragesunittestingbyautomaticallycreatingstubbedoutunittestswhencreatingartifacts(domainclasses,����������������������������������������������������������������������������������������������������������������������������������Figure:GrailsTestClassesmockDomain(class,list)MocksthedomainclassandstoresinstancesinthelistProvidesthedynamicGORMmethodstoclassmockFor(class,loose)–ReturnsamockoftheclassloosedetermineswhethermockhaslooseexpectationsorstrictmockForConstraintsTest(class,list)–SimilartomockDomainbutworksfordomainsorcommandobjectsandaddsavalidatemethodtotestconstraintsmockController(controllerClass)–Mocksacontroller,addingtheusualdynamicpropertiesandmethodsmockTagLib(tagLibClass)–MocksaTagLib,addingtheusualdynamicpropertiesandmethodsmockLogging(class,enableDebug)–AddsamockloggertotheclassHerearesomeofthemethodsthatareavailabletousintheGrailstestingframeworkdOmainClassmaGiCDynamicmethodsGrailsaddsseveralmethodstoourdomainclassesatruntimeHerearesomeofthemostcommonlyuseddomainclassmethods:MethodDescriptionget(id)RetrievesaninstancebyidgetAll(id,id,id)Retrievesmultipleinstancesbyidslist()RetrievesallinstanceslistOrderBy*()RetrieveslistofinstancessortedbyexpressionfindBy*()ReturnsfirstinstancematchingexpressionfindAllBy*()Returnsallinstancesmatchingexpressioncount()ReturnstotalnumberofinstancescountBy*()Returnscountofinstancesmatchingexpressionsave()Attemptstopersistinstancevalidate()Validatesaninstancebasedonconstraintsdelete()AttemptstopermanentlyremoveinstancewithTransactionExecutesaclosurewithinatransactionwithCriteriaExecutesahibernatecriteriausingtheCriteriaBuilderhasErrorsReturnstrueifinstancehasvalidationerrorsMethodssuchascountBy*()andfindBy*()aresynthesizedmethods,madeupoftherootmethodnameandacombinationofdomainclasspropertiesandthefollowingcomparators:NoteBecarefulaboutaddingmethodsbeginningwith‘get’toadomainclassGrailswillconsiderthatapropertyandtrytopersistitYoucanavoidthisbynotgivingthemethodareturntype(iedefgetSomething(){})controllers,services,andtaglibs),andbyincludingapowerfultestingframeworkbasedonJUnitInGrails(andearlierviaaplugin),thereareseveralclassesinheritingfromJUnit’sTestCaseclassFigureshowstheseclassesDZone,Inc|wwwdzonecomGettingStartedwithGrails•Equal(Implieddefaultcomparator)•NotEqual•LessThan•LessThanEquals•GreaterThan•GreaterThanEquals•Like•like(caseinsensitiveLike)•InList•Between•Is•IsNotUptotwopropertieswithoptionalcomparatorscanbecombinedwithalogicaloperatorforexample:CarcountByMakeAndAgeLessThan(‘Dodge’,)CarfindAllByMakeAndModelInList(‘Ford’,‘Mustang’,‘Explorer’)PaginationandSortingParametersThedomainmethodlist()takesfourparameterswhichareusedforsortingandpaginationThesesameparameterscanbepassedinaMapasthelastparametertothefindAllBy*methodsParameterDescriptionmaxThemaximumnumberofinstancestoreturnoffsetThepositiontobeginretrievingfromsortDomainpropertytosortbyorderWhethertosortascedingordecendingExample:Carlist(max:,sort:’year’,order:’desc’)ConstraintValidationEitherthesave()orvalidate()methodsshownabovewilltriggerGrails’powerfuldatavalidationGrailsprovidesbuiltinconstraintsplusthevalidationconstraintforcustomvalidationManyoftheseconstraintsalsoinfluencedatabaseschemagenerationthoseareinshowninboldblank(truefalse)allowanemptystringvalueable(truefalse)allowsmaxMaximumvalueofanytypethatimplementsjavalangComparableminMinimumvalueofanytypethatimplementsjavalangComparablesizeUsesarangetodeterminetheupperandlowerlimitsofacollectionoraStringmaxSizeThemaximumsizeofacollectionorStringminSizeTheminimumsizeofacollectionorStringrangeUsesarangetodeterminethelimitsofanumericvaluescaleRoundsvaluetospecifiednumberofdecimalplacesDoesnotgenerateanErrornotEqualNocommentinListValuemustbecontainedinsuppliedlistMatchesValuemustmatchsuppliedregularexpressionUnique(truefalse)Verifiesuniquenessindatabaseurl(truefalse)MustbevalidURLemail(truefalse)MustbevalidemailaddresscreditCard(truefalse)Mustbevalidcreditcardnumberpassword(truefalse)MustbevalidpasswordValidatorTakesaclosureforcustomvalidationFirstparameterisvalue,second(ifsupplied)istheinstancebeingvalidatedHere’sanexampleofhowconstraintsaredeclaredinadomainclass:���������Figure:OnetooneUnidirectionalonetooneisthesimplesttypeofrelationshipOneclasshasaReferencetoanotherThisisdeclaredbyapropertyofthetypeofanotherdomainclass:classCar{Engineengine}AbidirectionalonetooneisthesamethingbutwitheachclassintherelationshiphavingareferencetotheotherclassDriver{Carcar}classCar{Driverdriver}UsuallyinasituationlikethisyouwanttoshowownershipandhavecascadingupdatesbasedonthatownershipWithGrailsthatjusttakessinglelineofcode:classCar{DriverdriverstaticbelongsTo=Driver}NowaCarbelongstoaDriverandwhentheDriverissavedtheCarwillbesavedtooIftheDriverisdeletedthentheCargoeswithhimMakessensebelongsToalsoworkswithunidirectionalrelationshipsOnetomany���������������Figure:OnetomanyTodeclareaunidirectionalonetomanyrelationshipjustincludeastatichasManypropertyintheowningclassclassDriver{statichasMany=cars:Car}NowaDriverwillhaveaCollectionofCarinstancescalledcarsstaticconstraints={make()model()year()desription()}Ifvalidationfailsduringacalltosave(),noexceptionisthrownThefailureisquietlyrecordedandstoredintheinstanceserrorspropertyToseeifadomainclassinstancehasvalidationerrors,usethehasErrors()methodinconjuctionwiththeerrorsproperty,likeso:if(carInsancehasErrors()){carInstanceerrorsallErrorseach{printlnit}}RelationshipsGORMalsomakesrelationshipsbetweendifferentdomainclasseseasierHerewe’llshowhowtoimplementthebasicdomainrelationshipsOnetooneDZone,Inc|wwwdzonecomGettingStartedwithGrailsTomakethisbidirectionaladdabelongsTopropertytothemanyclassclassCar{DriverdriverstaticbelongsTo=Driver}Manytomany���������������������Figure:ManytomanyAmanytomanyrelationshipcanbedeclaredbyaddingahasManytobothclassesinvolvedandabelongsTopropertytooneofthemclassDriver{statichasMany=cars:Car}classCar{statichasMany=drivers:DriverstaticbelongsTo=Driver}serviCesGrailsserviceclassesarepowerfulandeasytouseHere’safewimportantthingstorememberwhenusingservicesTransactionsGrailsserviceclassesaretransactionalbydefaultIfyouimportorgcodehausgroovygrailscommonsApplicationHolderdefmyPogo=newMyPogo()defctx=ApplicationHolderapplicationmainContextctxautowireCapableBeanFactoryautowireBeanProperties(myPogo,AutowireCapableBeanFactoryAUTOWIREBYNAME,false)ThiswilltellSpringtoinjectanySpringbeansthataredeclaredintheMyPogoclassintothemyPogoinstanceSinceGrailsserviceclassesareSpringbeans,thecarServicewillbeinjectedServicesandScopeGrailsservicesaresingletonsbydefaultTochangethatyoujustneedtodeclareastaticscopevariablestaticscope=‘request’Herearethepossiblevaluesforscope:ScopeDescriptionrequestAnewinstanceiscreatedforeachrequestsessionOneinstanceiscreatedforanentiresessionflashAninstanceiscreatedthatwillexistforthisrequestandthenextrequestprototypeAnewinstanceiscreatedforeachobjecthatit’sinjectedintoflowinstanceexistsforthelifeofaflow(webflowonly)conversationInstanceexistsforthelifeofaflowandallsubflows(webflowonly)GsPAlongwiththeabilitytoeasilycreatecustomGSPtags,GrailsprovidesoverbuiltintagsSomanythatitcanbeeasytomissonethatcouldbejustwhatyouneedThefollowingtableshowssomeofthetagsyoudon’twanttomiss:LogicalTagsifConditionalyrenderGSPportionsAttributeDescriptiontest*Expressiontoevaluateenv*NameofaGrailsenvironmentthethreer’sOfCOntrOllersTherearethreepossibleconclusionstoacontrolleractioninGrailsYoucanreturnmapofdataornothingandGrailswillattempttodisplaythegspviewwiththesamenameastheactionYoucanalsoredirecttoanotherurloractionThethirdwayistorendersomethingThiscanbeaview,atemplate,JSON,XMLorjustaboutanythingthatcanbewrittentotheresponseRedirectMethodParameterscontrollerControllertoredirecttoIfactionisnotpresentthedefaultactionofthecontrollerwillbeusedactionActiontoredirecttoIfcontrollerisnotpresentcurrentcontrollerwillbeusedidIdtobepassed,asparamsid,totheredirecturlURLtoredirectto(‘http:grailsorg’)uriURItoredirectto(‘caredit’)paramsAmapofparameterstobepassedtotheredirectRenderMethodParameterstextTexttorenderedtotheresonseviewAGSPviewCanincludepathinfoortheviewfolderforthecurrentcontrollerwillbeassumedtemplateAtemplate(partialGSPview)OftenusedwithAJAXactionsmodelAmapcontainingdatatobeusedbytheviewortemplatebeanAsinglebeantousedasthemodelfortheviewortemplatecollectionAcollectionofobjectstobeusedasthemodelfortheviewortemplatebuilderBuilderobjecttobeusedtorendermarkupcontentTypeSetsthecontenttypeoftheresponseencodingSetstheencodingoftheresponsedon’twantthatbehavior,forexample,ifyouaregoingtohandletransactionswiththedynamicdomainclassmethodwithTransaction,youcanturnitoffwithasingleline:classCarService{statictransactional=false}ServiceInjectionServicescanbeinjectedintocontrollers,domainclasses,orotherservicessimplybydeclaringapropertywiththesamenameastheserviceclasstypebutwiththefirstletterlowercase:classCarController{defcarService}YoucanalsoinjectServicesintoplainoldgroovyobjects,butittakesacouplemorelinesofcodeFirstdeclaretheserviceinyourPOGOclassMyPogo{defcarService}ThenwhenyoucreateaninstanceofyourPOGOdothis:DZone,Inc|wwwdzonecomGettingStartedwithGrailsLoopingTagseachiterateovereachelementofthespecifiedobjectAttributeDescriptioninTheobjecttoiterateoverstatusVariabletostortheiterationindexinvarThenameoftheitem<g:eachvar=”car”in=”${cars}”><p>Make:${carmake}<p><p>Year:${caryear}<p><g:each>findAllcondtionallyiterateoverobjectsinacollectionAttributeDescriptioninThecollectiontoiterateoverexprAGpathexpression<h>Vehicles<h><ul><g:findAllin=”${cars}”expr=”ityear==‘’”><li>${itmake}${itmodel}<li><g:findAll><ul>FormTagsformHTMLFormwithanactionattributebasedoncontrolleractionidAttributeDescriptionaction*ActiontouseintheFormActioncontroller*ControllertouseintheFormActionid*IDtouseintheFormActionurl*Amapcontainingtheactioncontrollerid<g:formname=”myForm”action=”show”id=””><g:form><g:formname=”myOtherForm”url=”action:’list’,controller:’car’”><g:form>*ifnotspecified,thecurrentcontrolleractionwillbeuseddatePickerCreatesHTMLselectsfordaymonthyearhoursecondAttributeDescriptionnameNameofthedatepickerfieldsetvalueCurrentvalueofthedatepickerdefaultDefaultdateif“=none”,thedefaultisblankPrecisionDategranularity:year,month,day,hour,minutenoSelectionMapdetailingthekeyandvaluetouseforthe“noselectionmade”choiceintheselectedboxYearsListrangeofdisplayedyears,inspecificorder<g:datePickername=”myDate”value=”${newDate()}”noSelection=”‘’:’Choose’”><g:datePickername=”myDate”value=”${newDate()}”precision=”day”years=”${}”>checkBoxCreatesanHTMLcheckboxformfieldAttributeDescriptionnameNameofthecheckBoxvalueExpressionifevaluatestotrue,“checked=true”<g:checkBoxname=”Used”value=”${true}”>radioCreatesanHTMLradiobuttonAttributeDescriptionvaluevaluerepresentedbyradiobuttonDisplayedaslabelnameNameofradiobuttoncheckedBooleantruefalseforcheckedstatus<g:radioname=”myGroup”value=””>SelectCreatesanHTMLselectfromalistorrangetoselectfromvaluethecurrentvalueofthepropertyoptionKeypropertyofthebeantouseasthekeyoptionValuepropertyofthebeantouseasthevaluenoSelectionsingleentryMapwithadefaultkeytoreturnandadefaultvaluetodisplayvalueMessagePrefixWillbeprependedtotheoptionvaluewitha‘’tocreateakeytolookupthevalueintheinmessagebundle<g:selectname=”caryear”from=”${}”value=”${year}”noSelection=”‘’:’Choosecaryear’”>hiddenFieldCreatesanHTMLinputoftype‘hidden’namethenameoftheinputf

VIP免券下载文档

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/6

Getting Started with Grails

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利