主页面
显示当前发表博客的完整内容,以及历史博客列表
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; }
相关推荐
矢部 另一个博客引擎-Curso Play 1.3.1 看到
矢部 另一个博客引擎(Play Framework 1.3.x)
yabe:另一个后端库
学习BACnet/IP协议所使用的Yabe和VTS工具
用C#编写的图形化资源管理器程序,用于浏览BACnet设备(在Windows和Linux上运行)。 当前同时支持BACnet IPv4,IPv6 + BACnet MSTP + BACnet PTP + BACnet以太网。 用于读取,写入,读取多个,写入多个,iam,whois...
BACNET测试工具、可以扫描所有的BACnet设备,点位读取。
这是一个小组摸索了近一个月的成果,资料太少了,走了太多弯路,希望BACNet尽快普及起来
yabe_sql 剧本1.3.x教程紧随其后
Currently supports both BACnet IPv4, IPv6 + BACnet MSTP + BACnet PTP + BACnet Ethernet. Basic functions for read, write, read multiple, write multiple, iam, whois, subscribeCOV, notify, WriteFile, ...
语言:English 更好的书签popup 功能: 1.左键单击在新选项卡中打开书签。 2.中间单击或“Ctrl”单击单击“在”新建后台“选项卡中打开书签。 3.... 4.... 5.... v1.2.1 - 节点删除后还原滚动位置。 v1.2.0....
矢部网上商城
迅饶BACnet客户端免费调试助手—BACnetScanzip,BACnetSCAN用于扫描BACnet IP 和BACnet MSTP设备,导出数据到XLS和.csv文档进行编辑,导入到X2OPC,X2Modbus 非常方便
BACnetScan是由上海迅饶自动化科技有限公司自主研发的BACnet客户端扫描软件 ,该软件同时具备BACnetIP和BACnetMS/TP扫描功能,并且具有读属性、写当前值属性、和导出EXCEL等功能。在PC上安装此软件,通过IP协议和...
BACnet开发资料与调试工具-附件资源
一些常用的BACnet点位扫描工具包括Yabe,BACnetscan 等。 BACnet主站模拟工具:主站模拟工具用于模拟BACnet主站的功能,以便测试和验证设备的响应和行为。它们允许开发人员发送和接收BACnet命令和数据,并模拟不同的...
在Hiroshi Yabe等提出的新拟牛顿方程基础上,给出一类新拟牛顿算法(称为MBFGS算法),同时在一定的假设条件下,结合Wolfe搜索准则,证明了MBFGS算法具有全局收敛性,并进行了数值试验,结果表明,对于一般的无约束...