领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多随着Spring Boot 1.1.0.M2 的发布,新的模板引擎也得到了支持,该引擎由Groovy 2.3提供。在这篇文章中,我们将描述使用这种引擎的好处,当然还有如何在 Boot 中使用它。
本文中的所有源代码都可以在 GitHub 上找到,因此请随时克隆存储库并试一试
git clone https://github.com/melix/springboot-groovytemplates.git
cd springboot-groovytemplates
./gradlew run
然后在浏览器中打开https://127.0.0.1:8080
此应用程序完全使用Groovy编写,并且还使用了用于 Boot 的 GORM,但当然也可以仅将 Groovy 用于模板部分,并使用 Java 编写应用程序的其余部分。从现在开始,我们将只关注该项目的模板方面。
在 Spring Boot 中集成 Groovy 2.3 模板非常简单。您只需在构建文件中添加对 groovy-templates
模块的依赖项即可。例如,如果您使用 Gradle,只需使用以下代码
dependencies {
compile "org.codehaus.groovy:groovy:${groovyVersion}"
compile "org.codehaus.groovy:groovy-templates:${groovyVersion}"
compile "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
compile "org.grails:gorm-hibernate4-spring-boot:1.0.0.RELEASE"
runtime "com.h2database:h2:1.3.173"
}
Groovy 标记模板引擎提供了一个基于构建器语法的创新模板系统。它提供了各种关键功能
等等!您可以在文档中找到此模板引擎功能的完整列表。模板基本上是 Groovy 代码,并针对模板用例提供了特殊支持。
让我们从一个非常简单的示例开始,我们希望显示一个索引,其中包含一条简单消息,其中包含当前使用的 Spring Boot 和 Groovy 的版本号
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title('Spring Boot - Groovy templates example')
link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
}
body {
div(class: 'container') {
div(class: 'navbar') {
div(class: 'navbar-inner') {
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
a(class: 'brand',
href: 'hhttp://projects.spring.io/spring-boot/') {
yield 'Spring Boot docs'
}
}
}
div("This is an application using Boot $bootVersion and Groovy templates $groovyVersion")
}
}
}
在第一行,您可以阅读 yieldUnescaped
指令。它指示渲染器按原样渲染参数。此指令可用于渲染任何类型的基于文本的内容。在这里,它用于渲染 HTML 文件的文档类型声明,但您确实可以使用它来渲染任何内容。模板引擎提供了许多辅助函数,如 yield
,这些函数在文档中进行了描述。
模板的其余部分由与 HTML 输出匹配的分层结构组成,这使得渲染 HTML 内容变得非常自然。例如,代码:link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
将被渲染为
<link rel='stylesheet' href='/css/bootstrap.min.css'/>
类似地,这
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
将被渲染为
<a class='brand' href='http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html'>Groovy - Template Engine docs</a>
请注意模板中的属性如何映射到渲染的 HTML 中的标签属性。最后一个参数对应于标签的主体。或者,可以使用 yield
指令来渲染标签的主体
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html') {
yield 'Groovy - Template Engine docs'
}
选择通常取决于您是否有嵌套内容要渲染。但到目前为止,我们的模板生成的所有内容都是静态的。模板的最后一部分更有趣
div("This is an application using Boot $bootVersion and Groovy templates $groovyVersion")
正如您所料,这将被渲染为
<div>This is an application using Boot 1.1.0.M2 and Groovy templates 2.3.2</div>
模板在这里使用了两个变量,这些变量位于模型中
这些由我们的应用程序作为模板中的变量公开,所以让我们看看我们如何做到这一点。
我们唯一需要做的是创建一个将渲染我们的视图的控制器,并且像往常一样使用 Spring Boot,这只需要几行代码
package sample
import org.springframework.boot.Banner
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.servlet.ModelAndView
@Controller
class SampleController {
@RequestMapping("/")
def home() {
new ModelAndView(
"views/home",
[bootVersion: Banner.package.implementationVersion,
groovyVersion: GroovySystem.version])
}
}
我们的 home
方法返回一个 ModelAndView
实例,并且模型仅包含两个元素,即 Spring Boot 版本以及 Groovy 版本。视图会根据其引用 views/home
自动找到。Spring Boot 预计可以在 src/main/resources/templates/views
中找到视图。还能更简单吗?
在现实生活中,模板不太可能那么简单。您将拥有实体、数据库、CRUD 操作等... 因此,下一步是向您展示如何使用新的模板引擎来渲染更复杂的模型。为此,我们使用了 GORM,因此我们将从定义一个名为 Person
的实体开始
package sample
import grails.persistence.*
@Entity
class Person {
String firstName
String lastName
}
我们想要做的是,例如
因此我们需要两个模板:一个用于列出人员,另一个用于创建人员(或编辑)。列表示例很有趣,因为它将让我们向您展示如何在模板中迭代列表。所以在那之前,让我们创建一个带有列表操作的控制器
@Controller
@RequestMapping("/person")
class PersonController {
@RequestMapping("list")
def list() {
new ModelAndView('views/person/list', [persons: Person.list()])
}
}
您可以看到,与我们在简单示例中所做的一样,我们返回了一个 ModelAndView
示例,但这次,模型包含人员列表。所以让我们看看模板是什么样的
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title('Spring Boot - Groovy templates example')
link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
}
body {
div(class: 'container') {
div(class: 'navbar') {
div(class: 'navbar-inner') {
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
a(class: 'brand',
href: 'hhttp://projects.spring.io/spring-boot/') {
yield 'Spring Boot docs'
}
}
}
ul {
persons.each { person ->
li {
a(href:"/person/$person.id", "$person.lastName $person.firstName")
}
}
}
div {
a(href:'/person/add', 'Add new person')
}
}
}
}
模板的大部分实际上对应于页面的装饰,并从原始模板复制而来。此时,您可能想知道您可以做些什么来改进它,但我们稍后会再讨论,并专注于此模板最有趣的部分,即迭代
ul {
persons.each { person ->
li {
a(href: "/person/$person.id", "$person.lastName $person.firstName")
}
}
}
通过 Groovy 开发人员习惯使用的传统 each
方法,可以遍历 persons
变量。这很正常,因为模板实际上是 Groovy 代码!因此,我们可以迭代人员,为迭代中的当前人员指定一个名称(person
),然后在 a
标签内使用它。
如果数据库中有几个人,则生成的 HTML 将类似于以下内容
<ul>
<li><a href='/person/1'>John Doe</a></li>
<li><a href='/person/2'>Bob Dylan</a></li>
<li><a href='/person/3'>Guillaume Laforge</a></li>
<li><a href='/person/4'>Graeme Rocher</a></li>
<li><a href='/person/5'>Dave Syer</a></li>
</ul>
因此,如果您习惯于 JSP、GSP 和任何类型的类似 HTML 的模板系统,您就可以立即看到此模板引擎将使您免受处理打开/关闭标签的臭名昭著的问题。这仅仅是一个开始... 为了说明如何简化事物,我们将向您介绍布局机制。
如果您还记得,我们实际上有两个模板共享一个公共结构。它们都使用 Twitter Bootstrap,它们都共享相同的菜单,最终,唯一变化的是页面标题和主体。如果我们可以从我们的模板中提取出来并共享它怎么办?
布局就是为此而设计的。因此,让我们将模板的公共部分提取到一个名为 main.tpl 的文件中,我们将将其保存到 src/main/resources/templates/layouts 中
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title(pageTitle)
link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
}
body {
div(class: 'container') {
div(class: 'navbar') {
div(class: 'navbar-inner') {
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
a(class: 'brand',
href: 'hhttp://projects.spring.io/spring-boot/') {
yield 'Spring Boot docs'
}
}
}
mainBody()
}
}
}
这看起来非常类似于标准模板,但您实际上可以找到两个特殊的东西
title(pageTitle)
,其中 pageTitle
预计是我们想要提供的页面标题mainBody()
,这将导致渲染使用该布局的页面的主体。请注意括号很重要。现在让我们更新主页模板以使用此布局
layout 'layouts/main.tpl',
pageTitle: 'Spring Boot - Groovy templates example with layout',
mainBody: contents {
div("This is an application using Boot $bootVersion and Groovy templates $groovyVersion")
}
您可以看到我们调用了layout
方法并为其提供了几个参数。
layouts/main.tpl
)pageTitle
,一个简单的字符串mainBody
,使用contents
块使用contents
块将在找到mainBody()
指令时触发在布局内渲染mainBody
的内容。因此,使用此布局文件,我们肯定是在多个模板之间共享一个通用的结构模式。作为示例,让我们看看list.tpl
模板现在是什么样子。
layout 'layouts/main.tpl',
pageTitle: 'List persons',
mainBody: contents {
ul {
persons.each { person ->
li {
a(href:"/person/$person.id", "$person.lastName $person.firstName")
}
}
}
div {
a(href:'/person/add', 'Add new person')
}
}
当然,布局本身是可以组合的,因此您可以在布局内使用布局……
在这篇文章中,我们向您展示了 Spring Boot 如何使使用 Groovy 在 Groovy 2.3 中引入的新模板引擎变得非常容易。这个模板引擎提供了一个非常自然且强大的语法来生成任何类型的基于文本的内容。模板引擎功能的完整描述可以在Groovy 文档中找到,并且可以在Spring Boot 示例中找到使用相同技术的替代应用程序。
最后但并非最不重要的一点是,对这个模板引擎的原生支持即将进入 Spring 4.1!所以期待未来有更多的 Groovy 爱!