示例所示的源代碼和本指南中未來的章節都可以在此找到Good Thymes Virtual Grocery GitHub repository.
一個購物網站
爲了更好地解釋Thymeleaf參與處理模板的概念,本教程將使用一個演示的應用程序,您可以從上面地址下載項目。
這個應用程序是一個虛構的虛擬商店網站,並將爲我們提供足夠的場景舉例說明不同Thymeleaf特性。
我們需要爲我們的應用程序設計一套非常簡單的實體模型: Products(商品) 通過創建orders(訂單)賣給Customers(客戶)。我們也管理這些產品的Comments(評論)。應用程序模型如下:
我們的小應用程序也將有一個非常簡單的服務層,服務對象包含方法如下:
public class ProductService {
...
public List<Product> findAll() {
return ProductRepository.getInstance().findAll();
}
public Product findById(Integer id) {
return ProductRepository.getInstance().findById(id);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
最後,在web層有一個過濾器,將根據請求URL委託執行Thymeleaf-enabled命令:
private boolean process(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
try {
/*
* Query controller/URL mapping and obtain the controller
* that will process the request. If no controller is available,
* return false and let other filters/servlets process the request.
*/
IGTVGController controller = GTVGApplication.resolveControllerForRequest(request);
if (controller == null) {
return false;
}
/*
* Obtain the TemplateEngine instance.
*/
TemplateEngine templateEngine = GTVGApplication.getTemplateEngine();
/*
* Write the response headers
*/
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
/*
* Execute the controller and process view template,
* writing the results to the response writer.
*/
controller.process(request, response, this.servletContext, templateEngine);
return true;
} catch (Exception e) {
throw new ServletException(e);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
這是我們的 IGTVGController 接口:
public interface IGTVGController {
public void process(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext, TemplateEngine templateEngine);
}
- 1
- 2
- 3
現在我們要做的就是創建IGTVGController接口的實現,從服務層獲取數據並使用TemplateEngine對象處理模板。最後,它會像這樣:
但首先讓我們看看模板引擎是如何初始化的。
建立和配置模板引擎
在我們的過濾器的process(…)方法包含這個句子:
TemplateEngine templateEngine = GTVGApplication.getTemplateEngine();
- 1
這意味着GTVGApplication類負責創建和配置程序中最重要的一個對象TemplateEngine實例。我們的org.thymeleaf.TemplateEngine對象初始化過程如下:
public class GTVGApplication {
...
private TemplateEngine templateEngine;
...
public GTVGApplication(final ServletContext servletContext) {
super();
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// HTML is the default mode, but we will set it anyway for better understanding of code
templateResolver.setTemplateMode(TemplateMode.HTML);
// This will convert "home" to "/WEB-INF/templates/home.html"
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
// Set template cache TTL to 1 hour. If not set, entries would live in cache until expelled by LRU
templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
// Cache is set to true by default. Set to false if you want templates to
// be automatically updated when modified.
templateResolver.setCacheable(true);
this.templateEngine = new TemplateEngine();
this.templateEngine.setTemplateResolver(templateResolver);
this.controllersByURL = new HashMap<String, IGTVGController>();
this.controllersByURL.put("/", new HomeController());
this.controllersByURL.put("/product/list", new ProductListController());
this.controllersByURL.put("/product/comments", new ProductCommentsController());
this.controllersByURL.put("/order/list", new OrderListController());
this.controllersByURL.put("/order/details", new OrderDetailsController());
this.controllersByURL.put("/subscribe", new SubscribeController());
this.controllersByURL.put("/userprofile", new UserProfileController());
}
...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
當然有很多方法配置TemplateEngine對象,但是現在這些幾行代碼將滿足我們所需。
模板解析器
讓我們先從模板解析器開始:
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
- 1
模板解析器是實現了Thymeleaf API中的org.thymeleaf.templateresolver.ITemplateResolver接口的對象。
public interface ITemplateResolver {
...
/*
* Templates are resolved by String name (templateProcessingParameters.getTemplateName())
* Will return null if template cannot be handled by this template resolver.
*/
public TemplateResolution resolveTemplate(
TemplateProcessingParameters templateProcessingParameters);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
模板解析器負責確定如何訪問我們的模板。並且我們能從servlet上下文環境中解析模板文件。
但上述並不是模板解析器的所有功能,因爲我們可以設置一些配置參數。首先, 設置模板模式,一個標準的例子如下:
templateResolver.setTemplateMode("XHTML");
- 1
XHTML是ServletContextTemplateResolver默認的模板模式。
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
- 1
- 2
這些前綴和後綴用來修飾模板引擎調用的模板路徑,比如模板的調用模板的路徑爲“product/list“相當於如下操作
servletContext.getResourceAsStream("/WEB-INF/templates/product/list.html")
- 1
可選地,在緩存中解析模板的有效時間是配置的,模板解析器通過cacheTTLMs屬性設置
templateResolver.setCacheTTLMs(3600000L);
- 1
當然,一個模板在到達最大緩存時間前是可以被去掉的,而到達最大緩存時間的時候,會去掉緩存中最老的。
緩存行爲和大小可以由用戶通過實現ICacheManager接口或簡單修改StandardCacheManager來改變默認緩存對象集。
模板引擎
模板引擎是類org.thymeleaf.TemplateEngine的對象。下面的例子創建了我們的模板引擎:
templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
- 1
- 2
非常簡單,不是嗎?我們所需要僅僅的是創建一個實例並設置模板解析器給它。
模板解析器是TemplateEngine唯一需要的參數,當然接下來還有很多其他參數需要設置(消息解析器、緩存大小等)。就目前而言,這就是我們所需要的。
我們的模板引擎現在準備好了,我們可以開始使用Thymeleaf創建我們的頁面了。