摘要:所以任务会在第一个请求时同步执行。修改来展示这些对象你可以阅读模板是怎么工作的。标签只有两个参数用于展示的文章对象以及展示的模式可以是全文,全文附评论,预告中的一种现在我们可以将冗余代码替换成标签,重写主页重载页面,检查是否一切安好。
建立第一个页面
既然我们完成了数据模型的初步定义,是时候开始创建应用的页面了。这个页面将仅仅展示最近的博文,以及一个旧文章的列表。
下面是我们想要实现的目标的草图:
用默认数据启动事实上,在开始编写第一个页面之前,我们还有一件事要做。编写一个缺乏数据的Web应用是乏味的。你甚至不能测试正在做的事情。但因为我们还没完成编辑页面,所以不能发布新的文章作为测试。
有一个注入默认数据到博客中的方法是在应用加载时加载一个fixture文件。要想这么做,我们得创建一个启动(Bootstrap)任务。一个Play任务可以在任意HTTP请求之外执行,比如在应用启动时或者通过CRON,或在特定时间点执行。
让我们来创建/yabe/app/Bootstrap.java任务,通过Fixtures加载一堆数据:
import play.*; import play.jobs.*; import play.test.*; import models.*; @OnApplicationStart public class Bootstrap extends Job { public void doJob() { // Check if the database is empty if(User.count() == 0) { Fixtures.loadModels("initial-data.yml"); } } }
我们用@OnApplicationStart注解这个任务,告诉Play我们希望在应用启动时,同步执行该任务。
事实上该任务的启动时机取决于是在开发模式还是在生产模式。在开发模式,Play会等待第一个请求才开始。所以任务会在第一个请求时同步执行。这样,当任务失败,你将在浏览器中看到错误信息。在生产模式,任务会在应用启动时执行(就在运行play run的时候),如果出错,应用将无法启动。
你可以在yabe/conf/文件夹下创建一个initial-data.yml。你当然可以重用我们之前用过的data.yml文件。
现在用play run运行应用,并在浏览器打开http://localhost:9000/
主页面终于,是时候编写主页了。
你还记得第一个页面是如何输出的么?首先路由文件指定/URL将调用controllers.Application.index()action方法。然后这个方法调用render()并执行/yabe/app/views/Application/index.html模板。
我们将保持这些组件,不过给它们添加新的代码来加载文章列表并展示。
打开/yabe/app/views/Application/index.html控制器,修改index()action来加载文章列表,就像这样:
package controllers; import java.util.*; import play.*; import play.mvc.*; import models.*; public class Application extends Controller { public static void index() { Post frontPost = Post.find("order by postedAt desc").first(); ListolderPosts = Post.find( "order by postedAt desc" ).from(1).fetch(10); render(frontPost, olderPosts); } }
你可以看懂我们是怎样向render方法传递对象的吗?这将允许我们用同样的名字在模板中访问它们。在这个例子,变量frontPage和olderPosts将在模板中可用。
修改/yabe/app/views/Application/index.html来展示这些对象:
#{extends "main.html" /} #{set title:"Home" /} #{if frontPost}#{if olderPosts}${frontPost.title}
${frontPost.content.nl2br()}#{/if} #{/if} #{else}Older posts from this blog
#{list items:olderPosts, as:"oldPost"} #{/list}There is currently nothing to read here.#{/else}
你可以阅读模板是怎么工作的。简单地说,它允许你动态访问Java对象。在幕后我们使用Groovy的语法。大多数你看到的优雅的结构(比如?:运算符)就来自Groovy。但你并不需要为了写Play模板而学习Groovy。如果已经熟悉其他像JSP with JSTL的模板语言,你不会感到惘然无所适。
Ok,现在刷新博客的首页。
不是很美观,但是至少有内容了!
但是因为需要通过多种方式展示文章(全文,全文附评论,预告),现在我们不得不写了过于冗余的代码。我们应该创建一些类似函数的东西,这样就可以在不同的模板中调用它们了。这实际就是Play标签所做的事情!
要想创建一个标签,仅需创建新的/yabe/app/views/tags/display.html文件。一个标签只是另一个模板。它就像函数一样可以接受参数。#{display /}标签只有两个参数:用于展示的文章对象以及展示的模式(可以是全文,全文附评论,预告中的一种)
*{ Display a post in one of these modes: "full", "home" or "teaser" }*#{if _as == "full"}${_post.title}
#{if _as != "teaser"}#{/if}Detail:${_post.content.nl2br()}
现在我们可以将冗余代码替换成标签,重写主页:
#{extends "main.html" /} #{set title:"Home" /} #{if frontPost} #{display post:frontPost, as:"home" /} #{if olderPosts.size()}#{/if} #{/if} #{else}Older posts from this blog
#{list items:olderPosts, as:"oldPost"} #{display post:oldPost, as:"teaser" /} #{/list}There is currently nothing to read here.#{/else}
重载页面,检查是否一切安好。
改进布局如你所见,index.html继承自main.html。因为我们需要给所有的博客页面提供通用的布局,包括博客标题和验证链接,我们需要修改这个文件。
编辑/yabe/app/views/main.html:
#{get "title" /} #{doLayout /}
刷新并检查结果。大体上能工作,除了blogTitle和blogBaseLine变量未能显示。这是因为我们还没把它们传递给render(...)调用。当然我们可以在index action的render()调用中加入它们。但因为main.html将被作为整个应用的主模板,我们不想每次都添加它们。
要让一个控制器(或者其子类)的每个action都执行同样的代码,有一个方式是定义@Before拦截器。
让我们给Application控制器添加addDefaults()方法:
@Before static void addDefaults() { renderArgs.put("blogTitle", Play.configuration.getProperty("blog.title")); renderArgs.put("blogBaseline", Play.configuration.getProperty("blog.baseline")); }
你需要在Application.java中导入play.Play。
所有添加进renderArgs作用域的变量将可被模板访问。并且你可以看到这个方法从Play.configuration对象中读取变量的值。Play.configuration对象包括/yabe/conf/application.conf的所有配置键。
在配置文件中添加这两个键:
# Blog engine configuration # ~~~~~ blog.title=Yet another blog blog.baseline=We will write about nothing
刷新主页,检查现在能否正常展示。
加入样式现在博客的主页已经基本完成,但不是很美观。我们需要添加一些样式来装扮它。如你所见,主模板main.html文件引入了/public/stylesheets/main.css。我们将往它里面添加更多样式。
从这里下载一份样式表,然后复制到/public/stylesheets/main.css。(译者注:最困难的部分就这样一笔带过了,这让我想到了如何画一匹马)
刷新页面,你应该看到最终的完成稿了。
提交你的成果博客主页已经完成。又到了提交修改的时候了:
$ bzr st $ bzr add $ bzr commit -m "Home page"
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64102.html
摘要:确保你的文本编辑器已经做了相应的配置。第一个,会自动监测源代码的改变并在运行时自动重载。检查下面的一行是否出现在应用日志中使用版本控制系统来追踪变化当你开发一个项目时,最好使用版本控制系统来存储你的源代码。 Play是一个Java Web敏捷开发的框架http://www.playframework.com/documentation/1.2.7/home 之所以要翻译这个教程,是因...
摘要:设置验证码任何人都可以在我们的博客下发布评论,所以我们需要避免非人类用户来扰乱秩序。一个简单的防范方法是设置验证码。然后我们修改表单来显示验证码,并把写入隐藏的域里面。检查验证码功能是否完成了。 设置验证码 任何人都可以在我们的博客下发布评论,所以我们需要避免非人类用户来扰乱秩序。一个简单的防范方法是设置验证码。 生成验证码 如何利用Play框架来生成验证码?简单来说,我们需要增...
摘要:浏览和提交评论博客主页现在已经完成,接下来要完成博客正文页面。整个页面将展示当前文章的所有评论,还包括一个用于提交新的评论的表单。刷新浏览器,检查这次是否使用了正确的。给模板添加表单在后面试下提交新的评论。 浏览和提交评论 博客主页现在已经完成,接下来要完成博客正文页面。整个页面将展示当前文章的所有评论,还包括一个用于提交新的评论的表单。 创建show action 要显示文章内...
摘要:完成应用测试我们已经完成了我们想要创建的博客引擎。当然我们已经完成了测试所有模型层的功能。评估代码覆盖率当然我们还没有完成应用所需的所有测试用例。如你所见,我们远远没有完成对应用的全面测试。 完成应用测试 我们已经完成了我们想要创建的博客引擎。不过这个项目尚未完全结束。为了保证代码的质量,我们需要添加更多的测试。 当然我们已经完成了测试所有模型层的功能。所以博客引擎的核心功能已经被...
摘要:自定义编辑区域在前一章,我们给创建了一个关于面板,并准备了我的文章的部分。从文章列表开始我们仅需要查询用户相关的文章并显示出来。如果发生错误,它会刷新表单,显示错误信息。它表示使用的默认模板。这意味着,如果提交了参数,将选择这条路由。 自定义编辑区域 在前一章,我们给yabe创建了一个关于面板,并准备了我的文章的部分。每个作者可以在这个部分看到他们发布过的文章,以及进行编辑或者创建新...
阅读 1974·2023-04-26 00:38
阅读 1913·2021-09-07 10:17
阅读 874·2021-09-02 15:41
阅读 626·2021-08-30 09:45
阅读 527·2019-08-29 17:25
阅读 3186·2019-08-29 15:07
阅读 2147·2019-08-29 12:52
阅读 3718·2019-08-26 13:35
${_post.comments.size() ?: "no"} comment${_post.comments.size().pluralize()}
#{list items:_post.comments, as:"comment"}