主页面
显示当前发表博客的完整内容,以及历史博客列表
Bootstrap Job
一个play job任务就是一个在没有任何http请求的情况下执行一些特定的方法
应用程序在启动时或间隔一定时间后自动执行某个方法
应用程序启动便执行基础数据的初始化操作:
- import models.User;
- import play.jobs.Job;
- import play.jobs.OnApplicationStart;
- import play.test.Fixtures;
- /**
- * 使用@OnApplicationStart注释Job,告诉Play在应用程序启动时便执行这个任务
- * DEV模式和PROD模式下,任务执行情况不同
- * DEV模式:等到第一个客户端请求才会执行
- * PROD模式:应用程序启动时就执行
- * @author lenovo
- *
- */
- @OnApplicationStart
- public class Bootstrap extends Job {
- public void doJob() {
- //检查用户是否为空
- if(User.count()==0) {
- Fixtures.loadModels("initial-data.yml");
- }
- }
- }
其中,在yabe\conf目录下新建initial-data.yml文件,用来初始化Blog系统的基础数据!
- # Test data
- User(bob):
- email: bob@gmail.com
- password: secret
- fullname: Bob
- isAdmin: true
- User(jeff):
- email: jeff@gmail.com
- password: secret
- fullname: Jeff
- User(paul):
- email: paul@gmail.com
- password: secret
- fullname: Paul
- Post(firstBobPost):
- title: About the model layer
- postedAt: 2009-06-14
- author: bob
- content: >
- The model has a central position in a Play! application. It is the domain-specific
- representation of the information on which the application operates.
- Martin fowler defines it as :
- Responsible for representing concepts of the business, information about the
- business situation, and business rules. State that reflects the business situation
- is controlled and used here, even though the technical details of storing it are
- delegated to the infrastructure. This layer is the heart of business software.
- Post(secondBobPost):
- title: Just a test of YABE
- postedAt: 2009-03-25
- author: bob
- content: >
- Well, it's just a test.
- Post(jeffPost):
- title: The MVC application
- postedAt: 2009-06-06
- author: jeff
- content: >
- A Play! application follows the MVC architectural pattern as applied to the
- architecture of the Web.
- This pattern splits the application into separate layers: the Presentation
- layer and the Model layer. The Presentation layer is further split into a
- View and a Controller layer.
- Comment(c1):
- author: Guest
- content: >
- You are right !
- postedAt: 2009-06-14
- post: firstBobPost
- Comment(c2):
- author: Mike
- content: >
- I knew that ...
- postedAt: 2009-06-15
- post: firstBobPost
- Comment(c3):
- author: Tom
- content: >
- This post is useless ?
- postedAt: 2009-04-05
- post: secondBobPost
打开yabe\app\controllers\Application.java,修改index()
- package controllers;
- import play.*;
- import play.mvc.*;
- import java.util.*;
- import models.*;
- public class Application extends Controller {
- public static void index() {
- //最新的博客
- Post frontPost = Post.find("order by postedAt desc").first();
- //过去的博客
- List<Post> olderPosts = Post.find("order by postedAt desc").from(1).fetch(10);
- render(frontPost,olderPosts);
- }
- }
修改yabe\app\views\Application\index.html
action通过render()传递对象,在模块中只需要使用${xxx}就能获取到相应的对象,进而展现数据。
- #{extends 'main.html' /}
- #{set title:'Home' /}
- #{if frontPost}
- <div class="post">
- <h2 class="post-title">
- <a href="#">${frontPost.title}</a>
- </h2>
- <div class="post-metadata">
- <span class="post-author">by ${frontPost.author.fullname}</span>
- <span class="post-date">${frontPost.postedAt.format('MMMdd')}</span>
- <span class="post-comments">
- |
- ${frontPost.comments.size() ?: 'no'}
- comment${frontPost.comments.size().pluralize()}
- #{if frontPost.comments}
- , latest by ${frontPost.comments[-1].author}
- #{/if}
- </span>
- </div>
- <div class="post-content">
- ${frontPost.content.nl2br()}
- </div>
- </div>
- #{if olderPosts}
- <div class="older-posts">
- <h3>
- Older posts <span class="from">from this blog</span>
- </h3>
- #{list items:olderPosts, as:'oldPost'}
- <div class="post">
- <h2 class="post-title">
- <a href="#">${oldPost.title}</a>
- </h2>
- <div class="post-metadata">
- <span class="post-author">by ${oldPost.author.fullname}</span>
- <span class="post-date">${oldPost.postedAt.format('dd MMM yy')}</span>
- <div class="post-comments">
- ${oldPost.comments.size() ?: 'no'}
- comment${oldPost.comments.size().pluralize()}
- #{if oldPost.comments}
- - latest by ${oldPost.comments[-1].author}
- #{/if}
- </div>
- </div>
- </div>
- #{/list}
- </div>
- #{/if}
- #{/if}
- #{else}
- <div class="empty">
- There is currently nothing to read here!
- </div>
- #{/else}
抽取相同部分出来,提高代码复用性
新增yabe\app\views\tags\display.html
display.html被index.html使用标签(另一个模板)方式进行操作
由于index.html中通过#{display post:frontPost, as:'home' /}来调用display.html模板
则display.html中就可以通过_post 和 _as 来获取对应的参数值
- #{extends 'main.html' /}
- #{set title:'Home' /}
- <div class="post ${_as == 'teaser' ? 'teaser' : ''}">
- <h2>
- <a href="#">${_post.title}</a>
- </h2>
- <div class="post-metadata">
- <span class="post-author">by ${_post.author.fullname}</span>
- <span class="post-date">${_post.postedAt.format('dd MMM yy')}</span>
- #{if _as!='full'}
- <span class="post-comments">
- |
- ${_post.comments.size() ?: 'no'}
- comment${_post.comments.size().pluralize()}
- #{if _post.comments}
- , latest by ${_post.comments[-1].author}
- #{/if}
- </span>
- #{/if}
- </div>
- #{if _as!='teaser'}
- <div class="post-content">
- <div class="about">Detail:</div>
- ${_post.content.nl2br()}
- </div>
- #{/if}
- </div>
- #{if _as=='full'}
- <div class="comments">
- <h3>
- ${_post.comments.size() ?: 'no'}
- comment${_post.comments.size().pluralize()}
- </h3>
- #{list items:_post.comments, as:'comment'}
- <div class="comment">
- <div class="comment-metadata">
- <span class="comment-author">by ${comment.author},</span>
- <span class="comment-data">${comment.postedAt.format('dd MMM yy')}</span>
- </div>
- <div class="comment-content">
- <div class="about">Detail: </div>
- ${comment.content.escape().nl2br()}
- </div>
- </div>
- #{/list}
- </div>
- #{/if}
修改index.html,直接通过display模板完成页面的显示
- #{extends 'main.html' /}
- #{set title:'Home' /}
- #{if frontPost}
- <!--调用display模板-->
- #{display post:frontPost, as:'home' /}
- #{if olderPosts.size()}
- <div class="older-posts">
- <h3>
- Older posts <span class="form">from this blog</span>
- </h3>
- #{list items:olderPosts ,as:'oldPost'}
- <!--调用display模板-->
- #{display post:oldPost, as:'teaser' /}
- #{/list}
- </div>
- #{/if}
- #{/if}
- #{else}
- <div class="empty">
- There is currently nothing to read here!
- </div>
- #{/else}
刷新页面
修改yabe\public\stylesheets\main.css,对页面进行美观修饰
附:main.css
- /** Main layout **/
- html, body {
- background: #364B66 !important;
- font-family: Helvetica, Arial, Sans !important;
- }
- body {
- width: 900px;
- padding: 0 30px;
- margin: auto;
- }
- /** Blog header **/
- #header {
- padding: 10px 0;
- position: relative;
- }
- #logo {
- display: block;
- height: 49px;
- margin-left: 20px;
- color: #fff;
- font-size: 48px;
- font-weight: bold;
- letter-spacing: -4px;
- text-shadow: 1px 2px 2px #000;
- }
- #logo span {
- color: #f00;
- font-size: 70%;
- }
- #tools {
- list-style: none;
- margin: 0;
- padding: 0;
- position: absolute;
- right: 0;
- top: 30px;
- right: 20px;
- }
- #tools a {
- color: #fff;
- text-decoration: none;
- }
- #title {
- background: #B8C569;
- padding: 20px 30px 30px 20px;
- margin: 20px 0;
- color: #3C4313;
- position: relative;
- -webkit-border-radius: 16px;
- -webkit-box-shadow: 0 2px 0 #93A045;
- -moz-border-radius: 16px;
- }
- /** A little hacky to create arrows without images **/
- .about {
- text-indent: -999em;
- display: block;
- width: 0;
- height: 0;
- border-left: 10px solid transparent;
- border-right: 10px solid transparent;
- border-bottom: 10px solid #BAC36E;
- border-top: 0;
- position: absolute;
- top: -10px;
- left: 60px;
- }
- #title h1 {
- font-size: 64px;
- margin: 0;
- }
- #title h1 a {
- text-decoration: none;
- color: inherit;
- }
- #title h2 {
- font-size: 26px;
- margin: 0;
- font-weight: normal;
- }
- /** Main content **/
- #main {
- background: #314660;
- background: -webkit-gradient(linear, left top, left 30%, from(#314660), to(#364B66));
- -webkit-border-radius: 16px;
- -moz-border-radius: 16px;
- padding: 20px;
- }
- /** Post **/
- .post .post-title {
- margin: 0;
- }
- .post .post-title a {
- font-size: 36px;
- color: #F5C2CC;
- text-decoration: none;
- }
- .post .post-metadata {
- color: #BAC36E;
- display: block;
- font-size: 70%;
- display: inline-block;
- }
- .post .post-author {
- font-size: 130%;
- font-weight: bold;
- }
- .post .post-metadata a {
- color: #9FA85D;
- }
- .post .post-content {
- position: relative;
- background: #fff;
- padding: 10px;
- margin: 10px 0 50px 0;
- -webkit-border-radius: 10px;
- -moz-border-radius: 10px;
- -webkit-box-shadow: 0 2px 0 #BBBBBB;
- }
- .post .about {
- text-indent: -999em;
- display: block;
- width: 0;
- height: 0;
- border-left: 10px solid transparent;
- border-right: 10px solid transparent;
- border-bottom: 10px solid #fff;
- border-top: 0;
- position: absolute;
- top: -6px;
- left: 24px;
- }
- /** Older posts **/
- .older-posts h3 {
- color: #869AB1;
- font-size: 28px;
- margin-bottom: 15px;
- }
- .older-posts h3 .from {
- font-weight: normal;
- font-size: 70%;
- }
- .older-posts .post {
- margin-bottom: 15px;
- border-left: 3px solid #869AB1;
- padding-left: 10px;
- }
- .older-posts .post-title a {
- padding: 0;
- color: #131921;
- font-size: 20px;
- }
- .older-posts .post-metadata {
- color: #869AB1;
- padding: 0;
- font-size: 12px;
- }
- .older-posts .post-metadata a {
- color: #869AB1;
- }
- /** Comments **/
- .comments {
- margin-bottom: 30px;
- }
- h3 {
- color: #869AB1;
- font-size: 18px;
- margin-bottom: 15px;
- }
- h3 span {
- font-size: 80%;
- font-weight: normal;
- }
- .comment {
- width: 70%;
- clear: both;
- }
- .comment .comment-metadata {
- color: #869AB1;
- display: block;
- font-size: 50%;
- display: block;
- float: left;
- width: 80px;
- text-align: right;
- }
- .comment .comment-author {
- font-size: 150%;
- font-weight: bold;
- display: block;
- }
- .comment .comment-content {
- position: relative;
- background: #E4EAFF;
- color: #242C58;
- font-size: 80%;
- margin-top: 10px;
- margin-bottom: 10px;
- margin-left: 100px;
- padding: 10px;
- -webkit-border-radius: 10px;
- -moz-border-radius: 10px;
- }
- .comment .about {
- text-indent: -999em;
- display: block;
- width: 0;
- height: 0;
- border-top: 10px solid transparent;
- border-bottom: 10px solid transparent;
- border-right: 10px solid #E4EAFF;
- border-left: 0;
- position: absolute;
- top: 4px;
- left: -4px;
- }
- /** Form **/
- form {
- padding: 10px;
- background: #253142;
- background: -webkit-gradient(linear, left top, left 60%, from(#253142), to(#364B66));
- -webkit-border-radius: 10px;
- -moz-border-radius: 10px;
- }
- form .error {
- background: #c00;
- color: #fff;
- font-size: 90%;
- padding: 3px 5px;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- -webkit-box-shadow: 0 2px 0 #800;
- }
- form .error:empty {
- display: none;
- }
- form p {
- margin: 5px 0 0 0;
- }
- form textarea {
- width: 70%;
- height: 150px;
- }
- form input, form textarea {
- font-size: 14px;
- }
- form label {
- display: block;
- font-weight: bold;
- font-size: 90%;
- color: #aaa;
- margin-bottom: 3px;
- }
- #captcha{
- display: block;
- height: 50px;
- }
- .success {
- background: #67AD10;
- color: #fff;
- padding: 10px;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- -webkit-box-shadow: 0 2px 0 #4E840B;
- }
- /** Pagination **/
- #pagination {
- list-style: none;
- padding: 0;
- position: relative;
- color: #869AB1;
- font-size: 90%;
- top: -20px;
- margin-bottom: 30px;
- }
- #pagination a {
- color: #869AB1;
- font-size: 90%;
- }
- #pagination #previous {
- position: absolute;
- top: 0;
- left: 0;
- }
- #pagination #previous:before {
- content: '<< ';
- }
- #pagination #next {
- position: absolute;
- top: 0;
- right: 0;
- }
- #pagination #next:after {
- content: ' >>';
- }
- /** Footer **/
- #footer {
- border-top: 1px solid #45597A;
- font-size: 70%;
- padding: 10px 30px;
- text-align: center;
- color: #869AB1;
- margin-top: 30px;
- }
- #footer a {
- color: #869AB1;
- font-weight: bold;
- }
- /** Admin **/
- .tags-list .tag {
- cursor: pointer;
- color: red;
- }
- #adminMenu {
- list-style: none;
- padding: 0;
- margin: 0 0 20px 0;
- }
- #adminMenu li {
- display: inline;
- }
- #adminMenu li a {
- color: #fff;
- text-decoration: none;
- font-size: 80%;
- background: #591C64;
- padding: 2px 10px;
- -webkit-border-radius: 9px;
- -moz-border-radius: 9px;
- }
- #adminMenu li.selected a {
- background: #82A346;
- }
- #crudContent {
- color: #8B98AD;
- }
- #crudContent h2 {
- color: #EDC3CD !important;
- }
- #crudContent thead tr {
- background: #512162 !important;
- }
- #crudContent table {
- border: none !important;
- }
- #crudContent table td {
- color: #444;
- }
- tr.odd {
- background: #BECCE7 !important;
- }
- #crud #crudContent, #crudContent form, #crudListSearch, #crudListPagination, .crudButtons {
- background: transparent;
- border: none;
- padding: 0;
- }
- #crudListTable {
- margin: 10px 0;
- }
- .crudField, .objectForm {
- border: none;
- padding-left: 0;
- }
- .crudField label {
- color: #B8FA5C;
- }
- .crudHelp {
- color: #fff !important;
- }
- .crudField .tag {
- color: #111;
- font-size: 80%;
- }
- .crudButtons input {
- font-size: 110%;
- }
- .crudButtons {
- margin-top: 20px;
- border-top: 1px dotted #8B98AD;
- padding-top: 10px;
- }
- .crudFlash {
- border: 0;
- -webkit-border-radius: 8px;
- font-size: 80%;
- padding: 2px 10px;
- }
- .crudField .tag.selected {
- -webkit-border-radius: 8px;
- -moz-border-radius: 8px;
- }
- .crudField .error {
- background: transparent;
- border: none;
- padding: 0;
- color: pink;
- -webkit-box-shadow: none;
- }
- /** Login **/
- #login form {
- background: #8B98AD !important;
- border: 0 !important;
- -webkit-border-radius: 16px;
- -moz-border-radius: 16px;
- }
- #login label, #password-field label, #username-field label {
- color: #161D28 !important;
- font-size: 110% !important;
- }
- #remember-field {
- display: none;
- }
- /** My posts **/
- #admin .post {
- background: #fff;
- padding: 4px;
- margin: 0;
- font-size: 90%;
- }
- #admin .post.odd {
- background: #C0CBE5;
- }
- #admin .post a {
- color: #444;
- }
- #newPost {
- border-top: 1px dotted #C0CBE5;
- padding-top: 15px;
- }
- #newPost a {
- background: #C88116;
- -webkit-border-radius: 12px;
- -moz-border-radius: 12px;
- padding: 5px 10px;
- font-size: 80%;
- text-decoration: none;
- color: #fff;
- font-weight: bold;
- -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,.3);
- }
- #newPost a span {
- background: #7D510E;
- -webkit-border-radius: 8px;
- -moz-border-radius: 8px;
- padding: 0 5px 2px 5px;
- position: relative;
- top: -1px;
- }
- #postContent {
- width: 100%;
- height: 300px;
- }
- .hasError {
- background: pink;
- }