深色模式
2.1 示例:一家杂货店的网站
为了更好地解释使用 Thymeleaf 处理模板时涉及的概念,本教程将使用一个示例应用程序,你可以从项目网站下载它。 这个应用是一个虚构的虚拟杂货店网站,它将为我们提供许多场景,用来展示 Thymeleaf 的众多特性。 首先,我们需要为应用准备一组简单的模型实体: 通过创建订单(Orders)向顾客(Customers)销售产品(Products),并且管理这些产品的评论(Comments):
示例应用模型
我们的应用还会包含一个非常简单的服务层,由若干 Service 类构成,这些类中包含如下方法:
java
public class ProductService {
...
public List<Product> findAll() {
return ProductRepository.getInstance().findAll();
}
public Product findById(Integer id) {
return ProductRepository.getInstance().findById(id);
}
}在Web 层,我们的应用会有一个过滤器,它会根据请求 URL,将执行逻辑委托给支持 Thymeleaf 的处理逻辑:
java
/*
* 需先声明应用对象(实现 IWebApplication 接口)
* 本例中将使用基于 Jakarta 的版本。
*/
public void init(final FilterConfig filterConfig) throws ServletException {
this.application =
JakartaServletWebApplication.buildApplication(
filterConfig.getServletContext());
// 后续会介绍 TemplateEngine 对象的创建和配置方式
this.templateEngine = buildTemplateEngine(this.application);
}
/*
* 每个请求的处理流程:
* 1. 创建交换对象(封装请求、响应及处理所需的所有数据)
* 2. 调用对应的控制器处理请求
*/
private boolean process(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
try {
final IWebExchange webExchange =
this.application.buildExchange(request, response);
final IWebRequest webRequest = webExchange.getRequest();
// 过滤资源 URL,避免触发模板引擎执行(如 CSS/图片/网站图标)
if (request.getRequestURI().startsWith("/css") ||
request.getRequestURI().startsWith("/images") ||
request.getRequestURI().startsWith("/favicon")) {
return false;
}
/*
* 1. 查询控制器/URL 映射关系,获取处理当前请求的控制器
* 2. 若未找到对应控制器,返回 false,交由其他过滤器/Servlet 处理
*/
final IGTVGController controller =
ControllerMappings.resolveControllerForRequest(webRequest);
if (controller == null) {
return false;
}
/*
* 设置响应头信息
*/
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
/*
* 获取响应输出流的 Writer 对象
*/
final Writer writer = response.getWriter();
/*
* 执行控制器逻辑,处理视图模板,
* 并将结果写入响应的 Writer 中。
*/
controller.process(webExchange, this.templateEngine, writer);
return true;
} catch (Exception e) {
try {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final IOException ignored) {
// 忽略该异常
}
throw new ServletException(e);
}
}这是我们的 IGTVGController 接口定义:
java
public interface IGTVGController {
public void process(
final IWebExchange webExchange,
final ITemplateEngine templateEngine,
final Writer writer)
throws Exception;
}现在,我们只需实现 IGTVGController 接口即可——在实现类中从服务层获取数据,并通过 ITemplateEngine 对象处理模板。
最终的整体架构会是这样:
示例应用程序首页
但首先,我们先来看看这个模板引擎是如何初始化的。
