playframework1.2.x 入门(四) 编写第一个页面

本篇引导重点在于使用playframework实现一个网页,使用groovy模板等技术。本系列代码已经上传至github,有需要的可以自行下载

上一篇我们已经建立了博客的数据模型data model,现在来实现一个博客中最常用的页面:最新文件展示页。

我们先脑补一下实现的效果:

启动时加载默认数据

此页面需要数据才能展示出效果,所以这里使用上一篇的yml的方式在应用启动时载入数据。

创建/app_1/app/Bootstrap.java作业,使用Fixtures加载默认数据集:


import models.User;
import play.Logger;
import play.jobs.Job;
import play.jobs.OnApplicationStart;
import play.test.Fixtures;

@OnApplicationStart
public class Bootstrap extends Job {
    @Override
    public void doJob() {
        if (User.count() == 0) {
            Fixtures.loadModels("inital-data.yml");
            Logger.info("init complated");
        }
    }
}

@OnApplicationStart注解告诉Play在应用启动时执行任务。

实际上任务会运行在DEV或者PROD模式下。在DEV模式下,Play会等待第一个请求去启动,所以Job会在收到请求时同步执行。用这种方式任务出错会在浏览器上显示错误信息;而在PROD模式下,任务会在应用启动时执行,与play run命令同步执行,如果任务发出错错误,将会阻止应用的启动。

这里用到的默认数据文件inital-data.yml放在app_/conf目录下,你可以把上一篇的data.yml复制过来使用。

博客的首页

现在,我们可以真正开始编码博客的首页

你还记得通过play new 生成的项目第一个页面是如何显示出来的吗?首先,指定路由的URL/会调用controllers.Application.index()方法,然后这个方法会调用render() 并且执行模板/app_1/app/views/Application/index.html

在本例中,我们继续使用他原有的代码,并在其基础上改一下。

打开/app_1/app/controllers/Application.java controller并且修改index()方法,如下:


package controllers;

import models.Post;
import play.mvc.Controller;

import java.util.List;

public class Application extends Controller {

    public static void index() {
        // 取出第一篇文章
        Post frontPost = Post.find("order by postedAt desc").first();
        // 取出第二篇到第11篇文章
        List<Post> olderPosts = Post.find("order by postedAt desc").from(1).fetch(10);

        render(frontPost, olderPosts);
    }

}

你能看到我们为render()方法传递了参数,它允许我们使用在模板通过相同的名字使用这些对象。也就是,frontPostolderPosts可以在模板中使用。

打开文件app_1/app/views/Application/index.html 按如下修改:


#{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('MMM dd')}</span>
            <span class="post-comments">
                &nbsp;|&nbsp;
            ${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}

你可以在模板章节 中看到Groovy是如何工作的。从根本上说,它允许你动态地访问Java对象。在Groovy模板引擎下,你能使用很多很好的结构(比如?:操作符),但你并不需要学习Groovy去写Play的模板,如果你对其他任何一门模板语言熟悉,比如JSP和JSTL,你将无师自通,得心应手。

添加样式文件

为了页面更美观,需要为页面添加样式,编样式文件/public/stylesheets/main.css,为了学便大家学习,可以在这里下载此css文件 。

刷新首页能看到如下效果:

一个简单的首页做完了,但你会发现页面模板中有很多重复的代码,比说文章内容和评论等,此时作为一名资深的程序员,如果在Java代码中,应该想要为相同的代码创建一个方法供模板调用,在Play中你可以使用Play tag标签来实现这个功能。

要创建一个标签,只需要在views/tags创建模板即可。本例中创建文件/app_1/app/views/tags/display.html,一个标签本质上就是一个模板,它像一个函数一样拥有参数,#{display /}标签有两个参数,Post model和显示模式hometeaserfull,代码如下


*{ 使用`full`, `home`, 'teaser`三种模式显示文章内容 }*
<div class="post ${_as == 'teaser' ? 'teaser' : ''}">
    <h2 class="post-title">
        <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">
                &nbsp;|&nbsp; ${_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-date">
                        ${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}

在模板中使用标签:


#{extends 'main.html'/}
#{set title :'Home' /}
#{if frontPost}
    #{display post:frontPost, as: 'home'/}

    #{if olderPosts.size()}
        <div class="older-posts">
            <h3>Older posts <span class="from">from this blog</span> </h3>

            #{list items:olderPosts, as :'oldPost'}
                #{display post:oldPost, as:'teaser'/}
            #{/list}
        </div>
    #{/if}
#{/if}

#{else}
<div class="empty">
    There is currently nothing to read here.
</div>
#{/else}




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值