play框架入門知識(shí)分享_第1頁(yè)
play框架入門知識(shí)分享_第2頁(yè)
play框架入門知識(shí)分享_第3頁(yè)
play框架入門知識(shí)分享_第4頁(yè)
play框架入門知識(shí)分享_第5頁(yè)
已閱讀5頁(yè),還剩132頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Good is good, but better carries it.精益求精,善益求善。play框架入門Play框架入門play環(huán)境變量配置把play的路徑添加到系統(tǒng)環(huán)境變量的PATH路徑中進(jìn)入CMD環(huán)境,測(cè)試配置是否成功play創(chuàng)建一個(gè)簡(jiǎn)單項(xiàng)目,UserPostCommentTag這里我們用samples-and-tests下的yabe項(xiàng)目來(lái)做例子。在cmd中playnewyabe進(jìn)入創(chuàng)建的目錄運(yùn)行playrun命令.在瀏覽器中輸入HYPERLINKhttp:/localhost:9000http:/localhost:9000查看創(chuàng)建的項(xiàng)目是否成功。使用playeclipsify表示把

2、項(xiàng)目轉(zhuǎn)換成一個(gè)ECLIPSE項(xiàng)目。輸入playtest表示以測(cè)試模式啟動(dòng)。在瀏覽器中輸入HYPERLINKhttp:/localhost:9000/testshttp:/localhost:9000/tests表示進(jìn)入測(cè)試JUNIT頁(yè)面,并可進(jìn)行測(cè)試創(chuàng)建實(shí)體BEAN,play的實(shí)體BEAN使用的是JPA的實(shí)體把項(xiàng)目導(dǎo)入eclipse中,在models包中創(chuàng)建類,內(nèi)容如下:packagemodels;importjavax.persistence.Entity;importplay.db.jpa.Model;EntitypublicclassUserextendsModelpublicStrin

3、gemail;publicStringpassword;publicStringfullname;publicStringisAdmin;publicUser(Stringemail,Stringpassword,Stringfullname)this.email=email;this.password=password;this.fullname=fullname;關(guān)于實(shí)體中類的注解可以通過(guò)查看JPA2.0的相關(guān)文檔來(lái)進(jìn)行了解.注意一點(diǎn),我在創(chuàng)建的實(shí)體類中并沒有添加ID屬性,但是其實(shí)ID屬性是必須的屬性,如果我們?cè)趯?shí)體類中沒有顯示的指定ID屬性,PLAY會(huì)給我們創(chuàng)建一個(gè)默認(rèn)的id屬性,這個(gè)屬

4、性的值為自動(dòng)增加值。集成JUNIT單元測(cè)試在test包目錄下新建一個(gè)UserTest的測(cè)試類,繼承UnitTest類,如下:importmodels.User;importorg.junit.Test;importplay.test.UnitTest;publicclassUserTestextendsUnitTestTestpublicvoidcreateAndRetrieveUser()/添加Useruser=newUser(yh.sniaw,123456,小機(jī));assertNotNull(user.save();/查詢條件下的所有信息,并返回第一個(gè)Usersearch=user.fin

5、d(byEmailLike,%gmail%).first();assertNotNull(search);assertEquals(123456,search.password);運(yùn)行playtest在瀏覽器中輸入HYPERLINKhttp:/localhost:9000/testshttp:/localhost:9000/tests選擇UserTest點(diǎn)擊start按鈕測(cè)試。在User實(shí)體中編寫一個(gè)查詢的方法,并在測(cè)試類中添加一個(gè)測(cè)試方法,不需要重啟瀏覽器,直接進(jìn)行測(cè)試。查看效果。publicstaticUserconnect(Stringemail,Stringpassword)retur

6、nUser.find(byEmailLikeAndPassword,%+email+%,password).first();TestpublicvoidtestConnectMethod()/添加Useruser=newUser(yh.sniaw,123456,小機(jī));assertNotNull(user.save();/查詢assertNotNull(User.connect(gmail,123456);assertNull(User.connect(test,123456);assertNull(User.connect(yh.sniaw,aa);assertNotNull(User.co

7、nnect(yh.sniaw,123456);新建一個(gè)Post實(shí)體類,類的關(guān)系與User為多對(duì)一的關(guān)系。packagemodels;importjava.util.Date;importjavax.persistence.Entity;importjavax.persistence.Lob;importjavax.persistence.ManyToOne;importplay.db.jpa.Model;EntitypublicclassPostextendsModelpublicStringtitle;publicDatepostedAt;LobpublicStringcontent;Man

8、yToOnepublicUserauthor;publicPost(Userauthor,Stringtitle,Stringcontent)this.author=author;this.title=title;this.content=content;this.postedAt=newDate();創(chuàng)建一個(gè)測(cè)試方法:TestpublicvoidcreatePost()/添加Useruser=newUser(yh.sniaw,123456,小機(jī));assertNotNull(user.save();Postpost=newPost(user,title,content);assertNotN

9、ull(post.save();assertEquals(1,Post.count();Listlist=Post.find(byAuthor,user).fetch();assertEquals(1,list.size();PostfirstPost=list.get(0);assertNotNull(firstPost);assertEquals(title,firstPost.title);assertEquals(content,firstPost.content);assertNotNull(firstPost.postedAt);assertEquals(user,firstPos

10、t.author);查看測(cè)試結(jié)果。新建一個(gè)Comment實(shí)體類,實(shí)體類與Post為多對(duì)一的關(guān)系。packagemodels;importjava.util.Date;importjavax.persistence.Entity;importjavax.persistence.Lob;importjavax.persistence.ManyToOne;importplay.db.jpa.Model;EntitypublicclassCommentextendsModelpublicStringauthor;LobpublicStringcontent;publicDatepostedAt;Man

11、yToOnepublicPostpost;publicComment(Postpost,Stringauthor,Stringcontent)this.post=post;this.author=author;this.content=content;this.postedAt=newDate();新建一個(gè)測(cè)試Comment方法。TestpublicvoidcreateComments()Useruser=newUser(yh.sniaw,123456,小機(jī));assertNotNull(user.save();Postpost=newPost(user,title,content);asse

12、rtNotNull(post.save();newComment(post,author1,content1).save();newComment(post,author2,content2).save();Listlist=Comment.find(byPost,post).fetch();assertEquals(2,list.size();CommentfirstComment=list.get(0);assertEquals(author1,firstComment.author);assertNotNull(firstComment.postedAt);為Post添加一對(duì)多關(guān)系map

13、pedBy表示找到Comment類中的post對(duì)象進(jìn)行反轉(zhuǎn)OneToMany(mappedBy=post,cascade=CascadeType.ALL)Setcomments;publicPost(Userauthor,Stringtitle,Stringcontent)comments=newLinkedHashSet(0);this.author=author;this.title=title;this.content=content;this.postedAt=newDate();添加測(cè)試方法:TestpublicvoidpostAddComments()Useruser=newUse

14、r(yh.sniaw,123456,小機(jī));assertNotNull(user.save();Postpost=newPost(user,title,content);assertNotNull(post.save();ments.add(newComment(post,author1,content1);ments.add(newComment(post,author2,content2);post.save();PostfirstPost=Post.find(byTitle,title).first();assertEquals(2,firstPments.size();assertEq

15、uals(2,Comment.count();編寫視圖顯示添加在服務(wù)器啟動(dòng)時(shí)需要處理的事情。如加載一些基礎(chǔ)數(shù)據(jù):在models中添加一個(gè)Bootstarp類。此類繼承Job類。packagemodels;.Job;.OnApplicationStart;importplay.test.Fixtures;OnApplicationStartpublicclassBootstarpextendsJobpublicvoidloadUsers()if(User.count()表示換行User(bob):email:bobpassword:secretfullname:BobisAdmin:trueUs

16、er(jeff):email:jeffpassword:secretfullname:Jeff以上代碼為YAML代碼,代碼語(yǔ)法見YAML語(yǔ)法說(shuō)明:以上代碼表示添加一個(gè)User對(duì)象,對(duì)象名稱為bob,構(gòu)造方法中傳入了三個(gè)參數(shù)與值。創(chuàng)建一個(gè)測(cè)試方法進(jìn)行測(cè)試,看看USER對(duì)象是否已經(jīng)創(chuàng)建。代碼如下:TestpublicvoidshowUser()System.out.println(User.count();Useruser=User.find(byEmail,bob).first();assertNotNull(user);System.out.println(user);通過(guò)playtest方式

17、啟動(dòng)服務(wù)器,并進(jìn)行測(cè)試。以上的測(cè)試好像沒有用。加載完成后我是能查詢到。通過(guò)運(yùn)行環(huán)境不知道能不能行?,F(xiàn)在我們停止測(cè)試環(huán)境的運(yùn)行,啟動(dòng)運(yùn)行環(huán)境。Playrun現(xiàn)在我們修改下應(yīng)用的默認(rèn)首頁(yè)。打開controllers下的Application文件,修改index方法:publicstaticvoidindex()PostfirstPost=Post.find(orderbypostedAtdesc).first();ListpostList=Post.find(orderbypostedAtdesc).from(0).fetch(10);render(firstPost,postList);打開Ap

18、plication中index對(duì)應(yīng)的視圖文件,views/Application/index.html把代碼修改成如下內(nèi)容:#extendsmain.html/#settitle:Home/#iffirstPost$firstPost.titleBy$firstPost.author?.fullname$firstPost.postedAt.format(yyyy-MM-dd)|$firstPments.size()?:nocomment$firstPments.size().pluralize()#iffirstPmentslastby$firstPments.toArray()-1.aut

19、hor#/if$firstPost.content.nl2br()#ifpostList當(dāng)前頁(yè)數(shù)據(jù)#listitems:postList,as:oldPost$oldPost.titleBy$oldPost.author?.fullname$oldPost.postedAt.format(yyyy-MM-dd)|$oldPments.size()comment$oldPments.size().pluralize()#ifoldPments,lastby$oldPments.toArray()-1.author#/if#/list#/if#/if#elseThereiscurrentlynot

20、hingtoreadhere.#/else注意上面代碼中的紅色部分內(nèi)容,pluralize表示結(jié)果是否大于1,如果大于返回一個(gè)s,format可以對(duì)日期進(jìn)行格式化,XXXList.toArray()-1表示查詢List中最后一個(gè)值。nl2br()表示把n轉(zhuǎn)換成nl很容易看成是n1正確的是NL當(dāng)然上面這樣都是groovy的語(yǔ)法上面提示這些東西是因?yàn)楣俜降膖utoral中寫的方式不對(duì),找了下groovy的語(yǔ)法后添加正確。創(chuàng)建自定義標(biāo)簽自定義標(biāo)簽可以理解為頁(yè)面模板(可在自定義標(biāo)簽中寫HTML信息,并可以定義屬性,在引用標(biāo)簽時(shí)把屬性傳入進(jìn)來(lái))標(biāo)簽定義:在views/tags/目錄下創(chuàng)建html頁(yè)面就是

21、標(biāo)簽。如:display.html標(biāo)簽引用:在頁(yè)面中使用#display參數(shù):參數(shù)值/其中display為標(biāo)簽的HTML名稱標(biāo)簽中使用參數(shù):在標(biāo)簽中使用參數(shù)以“_”開始,后面是參數(shù)名稱。標(biāo)簽使用例子:定義標(biāo)簽:*這是一個(gè)注釋displaypostPostandasin(full,teaser,first)*$_post.titleBy$_post.author?.fullnameCreated$_post.postedAt.format(yyyy-MM-dd)#if_as!=full|$_ments.size()?:noComment$_ments.size().pluralize()#if_

22、ments,LastBy$_ments.toArray()-1.author#/if#/if#if_as!=teaserDetail:$_post.content.nl2br()#/if#if_as=full$_ments.size()?:noComment$_ments.size().pluralize()#if_ments#listitems:_ments,as:comment$comment?.authorCreated$comment.postedAt.format(yyyy-MM-dd)Detail:$comment.content.escape().nl2br()#/list#/i

23、f#/ifindex.html頁(yè)面引用標(biāo)簽:#extendsmain.html/#settitle:Home/#iffirstPost*引用自定義標(biāo)簽*#displaypost:firstPost,as:first/#ifpostList當(dāng)前頁(yè)數(shù)據(jù)#listitems:postList,as:oldPost*引用自定義標(biāo)簽*#displaypost:oldPost,as:teaser/#/list#/if#/if#elseThereiscurrentlynothingtoreadhere.#/else測(cè)試查看效果:修改布局現(xiàn)在我們打開views/main.html頁(yè)面,修改頁(yè)面的外觀。#get

24、title/#getmoreStyles/#getmoreScripts/yabe.LogintowritesomethingAboutthisblog$blogtitle$blogbaseline#doLayout/Yabeisa(notthat)powerfulblogenginebuiltwiththeitfutureasatutorialapplication.表示式語(yǔ)言符號(hào)注意:上面的代碼中我們使用了:可參見HYPERLINK/documentation/1.2.4/templates#syntax/documentation/1.2.4/templates#syntax#:表示引用

25、模板(標(biāo)簽)$:表示表達(dá)式:表示引用靜態(tài)資源%:使用一段腳本。&:表示引用一段消息注意,上面紅色部分引用了兩個(gè)變量值,這時(shí)候我們需要在ACTION中控制這兩個(gè)參數(shù)值。但是由于這是一個(gè)布局模塊文件,不需要在每一個(gè)控制器中重新賦值的情況下,我們可以在Application.java文件中定義一個(gè)方法,這個(gè)方法用Before來(lái)注解,表示方法在每一個(gè)動(dòng)作執(zhí)行前調(diào)用。BeforestaticvoidaddDefaults()renderArgs.put(blogtitle,Play.configuration.getProperty(blog.title);renderArgs.put(blogbase

26、line,Play.configuration.getProperty(blog.baseline);上面的代碼中我們?cè)趓enderArgs中存放了兩個(gè)值:bolgtitle,blogbaseline,那么這兩個(gè)值在頁(yè)面中就可以直接去使用。同時(shí),我在方法使用了Play.configuration.getProperty方法得到配置的兩個(gè)參數(shù)值。Play.configuration表示得到conf/application.conf中配置的參數(shù)值。現(xiàn)在我們打開application.conf文件,配置上面使用到的兩個(gè)參數(shù)值。blog.title=博客標(biāo)題blog.baseline=博客基線運(yùn)行pl

27、ayrun,測(cè)試下效果:從上圖我們可以看到。信息是出來(lái)了,但是還有亂碼的存在,現(xiàn)在我們處理下亂碼問題:其實(shí)這問題相對(duì)簡(jiǎn)單,把a(bǔ)pplication.conf文件修改為UTF-8編碼格式,同時(shí)打開application.conf文件時(shí)使用eclipse工具打開就不會(huì)出現(xiàn)問題。給模塊添加一些樣式,讓頁(yè)面看出來(lái)更加好看些。把HYPERLINKmain.cssmain.css文檔中的內(nèi)容復(fù)制到你的項(xiàng)目下面public/stylesheets目錄下的main.css文件中。通過(guò)上面的的郵件列表頁(yè)面我們學(xué)習(xí)了一定的知識(shí),現(xiàn)在我們繼續(xù)添加郵件的查看與更新功能。在Application.java中創(chuàng)建一個(gè)sh

28、ow的方法,方法中傳入一個(gè)Post的ID屬性,publicstaticvoidshow(Longid)Postpost=Post.findById(id);render(post);在views/Application/創(chuàng)建一個(gè)與方法同名的HTML文件show.html。#extendsmain.html/*引用一個(gè)模板*#settitle:showpost/*設(shè)置模板中的參數(shù)值*#displaypost:post,as:full/*調(diào)用一個(gè)自定義標(biāo)簽*修改views/tags/display.html的自定義標(biāo)簽,把$_post.title替換為:$_post.title修改views/ma

29、in.html模板頁(yè)面中$blogtitle替換為:$blogtitle運(yùn)行playrun查看效果。自定義URL路由規(guī)則:默認(rèn)(所有)的URL路由規(guī)則都需要在conf/routes文件中配置,#Catchall*/controller/actioncontroller.action上面代碼的意思:*表示GET/POST都可以,/controller/action表示客戶端訪問路徑。controller.action表示控制器類與方法具體說(shuō)明:HYPERLINK/documentation/1.2.4/routes#syntax/documentation/1.2.4/routes#syntax

30、那么通過(guò)上面的說(shuō)明我們就可以定義show.html的客戶端訪問路徑。GET/posts/idApplication.show*/controller/actioncontroller.action需要把自定義放到默認(rèn)的前面,否則找不到。BeforestaticvoidaddDefaults()renderArgs.put(blogtitle,Play.configuration.getProperty(blog.title);renderArgs.put(blogbaseline,Play.configuration.getProperty(blog.baseline);Mapmap=para

31、ms.data;/此處可以得到請(qǐng)求的參數(shù)值,并可對(duì)值進(jìn)行處理注意上面的紅色部分代碼?,F(xiàn)在標(biāo)記出來(lái),在實(shí)際的項(xiàng)目中我們可能會(huì)用到。添加一個(gè)分頁(yè)處理的方式:A.打開實(shí)體BEANPost類,添加如下兩個(gè)方法:publicPostprevious()Postprevious=Post.find(postedAt?orderbypostedAtdesc,postedAt).first();returnnext;修改show.html頁(yè)面。在頁(yè)面后邊添加如下信息:#ifpost.previous()$post.previous().title#/if#ifpost.next()$post.next().t

32、itle#/if運(yùn)行查看效果:給郵件添加回復(fù)功能:在Post實(shí)體中添加一個(gè)方法:publicvoidaddComment(Stringauthor,Stringcontent)Commentcomment=newComment(this,author,content);ments.add(comment);this.save();在Application.java中添加一個(gè)addComment方法:publicstaticvoidaddComment(Longpostid,Stringauthor,Stringcontent)Postpost=Post.findById(postid);pos

33、t.addComment(author,content);show(post.id);在show.html頁(yè)面中添加一個(gè)表單,讓用戶輸入Comment的相關(guān)信息,我們的表單定義通過(guò)play表達(dá)式來(lái)說(shuō)明:Postacomment#formApplication.addComment(post.id)Yourname:Message:#/form運(yùn)行,查看頁(yè)面效果,并添加一條回復(fù),查看是否可以添加成功。驗(yàn)證信息當(dāng)然,我們現(xiàn)在還需要給輸入添加一些驗(yàn)證信息,最少不能讓用戶直接提交,得先輸入值。添加play.data.validation.*下為所有的驗(yàn)證注解。HYPERLINK/documentati

34、on/1.2.4/validation/documentation/1.2.4/validation相關(guān)文檔在Application.java中修改addComment方法,publicstaticvoidaddComment(Longpostid,RequiredStringauthor,RequiredStringcontent)Postpost=Post.findById(postid);/判斷是否有錯(cuò)誤,如果有,直接轉(zhuǎn)向到提交頁(yè)面,并把錯(cuò)誤帶過(guò)去。if(validation.hasErrors()render(Application/show.html,post);post.addCo

35、mment(author,content);show(post.id);修改show.html頁(yè)面。#formApplication.addComment(post.id)#ifErrorsallfieldrequired#/ifErrorsYourname:Message:#/form紅色部分為為新添加的信息?,F(xiàn)在我們的錯(cuò)誤消息添加完成后,一般成功的消息我們也是需要提供給用戶查看的,所以我們現(xiàn)在添加回復(fù)后的成功消息提示。修改下Application.addComment方法,添加下面代碼中的紅色部分:publicstaticvoidaddComment(Longpostid,Required

36、Stringauthor,RequiredStringcontent)Postpost=Post.findById(postid);/判斷是否有錯(cuò)誤,如果有,直接轉(zhuǎn)向到提交頁(yè)面,并把錯(cuò)誤帶過(guò)去。if(validation.hasErrors()render(Application/show.html,post);post.addComment(author,content);flash.success(添加信息成功,謝謝你:%s!,author);show(post.id);修改show.html,在引用display標(biāo)簽前添加一個(gè)判斷是否有成功消息的地方,如果有,把消息顯示到頁(yè)面中。#iff

37、lash.success$flash.success#/if#displaypost:post,as:full/查看效果:當(dāng)然我們可以對(duì)添加comment方法添加自定義的URL路由,如:修改routes文件中,在最后一行前添加一行:POST/posts/postid/commentsApplication.addComment*/controller/actioncontroller.action為提交回復(fù)信息添加一個(gè)驗(yàn)證碼:通過(guò)play.libs.Images.captcha()方法來(lái)生成圖片驗(yàn)證碼,為了保證生成的驗(yàn)證證圖片與需要驗(yàn)證的頁(yè)面認(rèn)證一樣,我們需要在需要認(rèn)證的頁(yè)面上提交一個(gè)唯一的值

38、到生成驗(yàn)證碼圖片的方法中,通過(guò)此唯一的值把生成出來(lái)的驗(yàn)證碼存放到緩存中,在需要認(rèn)證的方法中通過(guò)此值得到緩存中存放的數(shù)據(jù),并判斷與輸入的值是否相同。如下,添加生成圖片驗(yàn)證碼的方法:publicstaticvoidimagecode(Stringid)Images.Captchacaptcha=Images.captcha();/生成圖片字體顏色,返回生成的驗(yàn)證碼Stringcode=captcha.getText(#E4EAFD);/把驗(yàn)證碼存放到緩存中,通過(guò)傳入的唯一UUID值,有效期為10分鐘Cache.set(id,code,10mn);/把圖片寫入到頁(yè)面流中renderBinary(ca

39、ptcha);在顯示的show方法中生成一個(gè)UUID,并存放到頁(yè)面對(duì)象中。publicstaticvoidshow(Longid)Postpost=Post.findById(id);Stringuuid=UUID.randomUUID().toString();render(post,uuid);修改show.html頁(yè)面中,添加comment部分代碼添加驗(yàn)證碼:#formApplication.addComment(post.id)#ifErrors#listitems:errors,as:error$error#/list#/ifErrorsYourname:Message:請(qǐng)輸入驗(yàn)證碼

40、:#/form修改添加回復(fù)方法addComment方法,添加必須的認(rèn)證與錯(cuò)誤消息,并添加驗(yàn)證碼認(rèn)證。publicstaticvoidaddComment(Longpostid,Required(message=用戶名稱必須輸入)Stringauthor,Required(message=回復(fù)內(nèi)容必須輸入)Stringcontent,Required(message=驗(yàn)證碼必須輸入)Stringcode,Stringuuid)Postpost=Post.findById(postid);/添加自定義驗(yàn)證Stringoldcode=(String)Cache.get(uuid);System.ou

41、t.println(oldcode);validation.equals(code,oldcode).message(驗(yàn)證碼輸入不正確);/判斷是否有錯(cuò)誤,如果有,直接轉(zhuǎn)向到提交頁(yè)面,并把錯(cuò)誤帶過(guò)去。if(validation.hasErrors()render(Application/show.html,post,uuid);post.addComment(author,content);flash.success(添加信息成功,謝謝你:%s!,author);show(post.id);運(yùn)行,查看效果?,F(xiàn)在我們添加Tag實(shí)體,從最上面的關(guān)系圖我們可以看出。Post實(shí)體與Tag實(shí)體為多對(duì)多的

42、關(guān)系,所以我們還要在Post中對(duì)Tag創(chuàng)建多對(duì)多關(guān)系。EntitypublicclassTagextendsModelimplementsComparableRequiredpublicStringname;privateTag(Stringname)=name;publicStringtoString()returnname;publicintcompareTo(TagotherTag)pareTo(otherT);在Post實(shí)體類中創(chuàng)建一個(gè)Tag關(guān)系:/PERSIST表示判斷實(shí)體存不存在,如果在實(shí)體活動(dòng)狀態(tài)同時(shí)數(shù)據(jù)庫(kù)存在OK,/如果實(shí)體非活動(dòng)狀態(tài)同時(shí)數(shù)據(jù)庫(kù)存在會(huì)報(bào)錯(cuò),都不存在,會(huì)添加到數(shù)據(jù)

43、庫(kù)ManyToMany(cascade=CascadeType.PERSIST)publicSettags;publicPost(Userauthor,Stringtitle,Stringcontent)comments=newLinkedHashSet(0);this.author=author;this.title=title;this.content=content;this.postedAt=newDate();this.tags=newTreeSet();/TreeSet會(huì)調(diào)用類的compareTo方法排序比較添加一個(gè)通過(guò)類別名稱把類別Tag添加到Post中的方法:在Tag中添加一個(gè)

44、通過(guò)名稱查詢的方法,如果查詢不到創(chuàng)建一個(gè)新的返回:publicstaticTagfindOrCreateByName(Stringname)Tagtag=Tag.find(byName,name).first();if(tag=null)tag=newTag(name);returntag;B.在Post中添加一個(gè)添加Tag的方法:publicPosttagItWith(Stringtag)TagtagObj=Tag.findOrCreateByName(tag);this.tags.add(tagObj);returnthis;在Post中添加一個(gè)通過(guò)Tag的name屬性查詢所有Post對(duì)象

45、集合的方法:publicListfindTaggedWith(Stringtag)Listlist=Post.find(selectdistinctpfromP=?,tag).fetch();returnlist;現(xiàn)在我們?cè)跍y(cè)試中創(chuàng)建一個(gè)PostTest的測(cè)試類,測(cè)試剛才的方法是否可行。importorg.junit.Test;importplay.test.UnitTest;publicclassPostTestextendsUnitTestTestpublicvoidtestpostAndTag()/CreateanewuserandsaveitUserbob=newUser(bob,se

46、cret,Bob).save();/CreateanewpostPostbobPost=newPost(bob,Myfirstpost,Helloworld).save();PostanotherBobPost=newPost(bob,Hop,Helloworld).save();/WellassertEquals(0,Post.findTaggedWith(Red).size();/TagitnowbobPost.tagItWith(Red).tagItWith(Blue).save();anotherBobPost.tagItWith(Red).tagItWith(Green).save(

47、);/CheckassertEquals(2,Post.findTaggedWith(Red).size();assertEquals(1,Post.findTaggedWith(Blue).size();assertEquals(1,Post.findTaggedWith(Green).size();以測(cè)試方式playtest方式運(yùn)行應(yīng)用,測(cè)試效果:現(xiàn)在我們還有一個(gè)新的需求,傳入多個(gè)Tag的名稱,通過(guò)Tag的name屬性in,同時(shí),通過(guò)傳入的tag.size()判斷Post引用tag的個(gè)數(shù):publicstaticListfindTaggedWith(String.tags)Listlist

48、=Post.find(selectdistinctpfromPostp+joinp.tagst+in(:tags)+groupbyp.id,p.author,p.title,p.content,p.postedAt+havingcount(t.id)=:size).bind(tags,tags).bind(size,tags.length).fetch();returnlist;添加測(cè)試方法:TestpublicvoidtestTags()/CreateanewuserandsaveitUserbob=newUser(bob,secret,Bob).save();/Createanewpost

49、PostbobPost=newPost(bob,Myfirstpost,Helloworld).save();PostanotherBobPost=newPost(bob,Hop,Helloworld).save();/WellassertEquals(0,Post.findTaggedWith(Red).size();/TagitnowbobPost.tagItWith(Red).tagItWith(Blue).save();anotherBobPost.tagItWith(Red).tagItWith(Green).save();/Check/返回1,Red有兩個(gè)Post引用assertE

50、quals(1,Post.findTaggedWith(Red,Blue).size();/返回1,Red有兩個(gè)Post引用assertEquals(1,Post.findTaggedWith(Red,Green).size();/返回0,Red只有兩個(gè)Post引用,并是我們傳入的為三個(gè)參數(shù)assertEquals(0,Post.findTaggedWith(Red,Green,Blue).size();/返回0,傳入的參數(shù)都只有一個(gè)Post引用,但是我們傳入?yún)?shù)為二。assertEquals(0,Post.findTaggedWith(Green,Blue).size();測(cè)試結(jié)果:在Tag

51、中添加一個(gè)統(tǒng)計(jì)Tag存在多個(gè)Post引用的統(tǒng)計(jì)查詢方法:publicstaticListfindTagPostCount()Listlist=Tag.find(selectnewmap(tag,count(p.id)size)fromPostp+).fetch();returnlist;添加測(cè)試方法:TestpublicvoidtestCount()Listlist=Tag.findTagPostCount();assertEquals(tag=Blue,size=1,tag=Green,size=1,tag=Red,size=2,list.toString();測(cè)試結(jié)果:此處測(cè)試不成功是因?yàn)?/p>

52、我數(shù)據(jù)庫(kù)中數(shù)據(jù)太多,現(xiàn)在我們可以在conf/init_user.yml文件中添加一些Tag的初始化數(shù)據(jù),Tag(play):name:PlayTag(architecture):name:ArchitectureTag(test):name:TestTag(mvc):name:MVCPost(jeffPost):title:TheMVCapplicationpostedAt:2009-06-06author:jefftags:-play-architecture-mvccontent:APlayOK,我們現(xiàn)在修改下display.html文件,把Post相關(guān)的tag顯示出來(lái)#if_as!=fu

53、ll|$_ments.size()?:noComment$_ments.size().pluralize()#if_ments,LastBy$_ments.toArray()-1.author#/if#/if#elseif_post.tags#listitems:_post.tags,as:tag$tag$tag_isLast?:,*從寫個(gè)Tag.toString()*#/list#/elseif紅色部分說(shuō)明可以通過(guò)每次迭代的對(duì)象_isLast來(lái)判斷是否是最后一個(gè)元素運(yùn)行,查詢效果。現(xiàn)在我們接著添加一個(gè)當(dāng)用戶點(diǎn)擊標(biāo)簽時(shí),顯示標(biāo)簽對(duì)應(yīng)的POST實(shí)體信息的頁(yè)面。與控制器,在Application.

54、java中添加方法listPostByTagpublicstaticvoidlistPostByTag(Stringtag)Listlist=Post.findTaggedWith(tag);render(tag,list);配置URL路由GET/posts/idApplication.showGET/posts/tagApplication.listPostByTag從上面的配置中我們可以看出,由于原來(lái)我們配置的顯示post信息的路由與現(xiàn)在配置的tag路由相同,從路由的角度上講,路由取的是最前的配置,所以現(xiàn)在的配置方式tag基本上可以說(shuō)是進(jìn)不去,所以我們還需要修改下/posts/id的配置,

55、我們知道show方法中傳入的Long類型的值,所以我們可以修改下id的表達(dá)方式:修改成如下所示:GET/posts/idApplication.showGET/posts/tagApplication.listPostByTag現(xiàn)在我們添加一個(gè)listPostByTag的頁(yè)面,并添加信息:#extendsmain.html/#settitle:showtagposts+tag/#iflist.size()1Thereare$list.size()posttaggedis$tag#/if#elseiflist.size()Thereisoneposttaggedis$tag#/elseif#el

56、seThereNoposttaggedis$tag#/else*Postslist*#listitems:list,as:post#displaypost:post,as:teaser/#/list修改display.html頁(yè)面中tag的超連接引用。*從寫了Tag.toString()*$tag$tag_isLast?:,運(yùn)行,查看效果。很好,連中文都已經(jīng)顯示出來(lái)了。使用play的CRUD操作:?jiǎn)⒂胏rud操作。打開conf/dependencies.yml把內(nèi)容修改為如下:B.require:-play-crudC.當(dāng)然,這樣還不夠,還需要把相應(yīng)的依賴模塊添加到項(xiàng)目中來(lái),運(yùn)行playdep

57、endencies添加依賴模塊,如果在Eclipse中開發(fā)項(xiàng)目,需要重新運(yùn)行下playeclipsify重新導(dǎo)入相關(guān)的依賴JAR,否則會(huì)提示找不到類。現(xiàn)在我們可以添加URL的路由功能,打開conf/routes文件,在所有控制器適配的上面添加一行,*/adminmodule:crud*/controller/actioncontroller.actionE.OK,現(xiàn)在我們就可以添加幾個(gè)控制器,現(xiàn)在我們的控制器不需要繼承Controller的類,而是去繼承CRUD類,如:我們創(chuàng)建以下幾個(gè)控制類,創(chuàng)建控制類時(shí),一般在實(shí)體類后添加一個(gè)s表示實(shí)體類的控制器,如:Post實(shí)體類,那么他的控制器默認(rèn)就應(yīng)該

58、是Posts.packagecontrollers;publicclassPostsextendsCRUDpackagecontrollers;publicclassCommentsextendsCRUDpackagecontrollers;publicclassTagsextendsCRUDpackagecontrollers;publicclassUsersextendsCRUD現(xiàn)在我們可以運(yùn)行應(yīng)用,在瀏覽器中輸入我們配置的地址(admin)來(lái)訪問,會(huì)看到如下的效果:當(dāng)前現(xiàn)在的顯示有點(diǎn)難看,因?yàn)楝F(xiàn)在的顯示默認(rèn)都是調(diào)用了對(duì)象的toString()方法,當(dāng)然,我們可以重寫toString()方

59、法來(lái)讓他們顯示更加友好。不過(guò),我們可以通過(guò)更加友好的樣式來(lái)控制這些信息,以后的教程中會(huì)提到相應(yīng)的信息。添加CRUD的驗(yàn)證信息EntitypublicclassUserextendsModelRequiredEmailpublicStringemail;RequiredpublicStringpassword;運(yùn)行Users的添加操作,查詢驗(yàn)證是否生效。同樣,現(xiàn)在我們可以添加Post的驗(yàn)證。EntitypublicclassPostextendsModelRequiredpublicStringtitle;RequiredpublicDatepostedAt;LobRequiredMaxSize

60、(10000)publicStringcontent;ManyToOneRequiredpublicUserauthor;測(cè)試,查看效果,同樣,我們?yōu)門ag與Comment添加驗(yàn)證。EntitypublicclassCommentextendsModelRequiredpublicStringauthor;LobMaxSize(10000)publicStringcontent;RequiredpublicDatepostedAt;ManyToOneRequiredpublicPostpost;RequiredpublicStringname;自定義CRUD模板頁(yè)面,CRUD中給我們定義了相當(dāng)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論