領先一步
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://:8080
此應用程式完全用 Groovy 編寫,並且還使用了 GORM for Boot,但當然也可以只將 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 標記模板引擎提供了一個基於 builder 語法的創新模板系統。它提供各種關鍵功能
等等!您可以在文件中找到此模板引擎功能的完整列表。這些模板基本上是帶有特殊模板用例支援的 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>
因此,如果您習慣於使用 JSPs、GSPs 以及任何類似 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 的精彩!