【问题标题】:Recommended template engine to reduce redundancy of dynamic content (Spring Boot)推荐模板引擎以减少动态内容的冗余(Spring Boot)
【发布时间】:2018-04-17 17:00:45
【问题描述】:

我即将重写一个 web 平台,我正在使用 Spring Boot/Spring MVC。该平台的主要部分是网站。我正在努力决定使用哪个模板引擎。 Thymeleaf 似乎被推荐,而 JSP 不鼓励。我不确定我的要求是否不寻常,至少对我来说听起来不是这样:

  • 我不想在不同的模板中重复自己,它们都应该显示在“主模板/布局”中
  • 主模板/布局将具有导航和页脚,它们具有动态内容(例如,动态内容不仅是主要内容)

1) 据我所知,对于 Thymeleaf,使用 Layouts 将是推荐的(仅?)方法。但是,在我看来,所有动态内容仍然在每个模板中生成(使用layout:fragment 属性流入布局)。这听起来不太理想,因为这意味着我仍然必须在每个模板中生成布局的动态部分。有没有办法在 Thymeleaf 布局中包含动态内容,其中内容(菜单、页脚、twitter-feed 等)是与实际内容模板分开生成的?

2) JSP 似乎能够相当容易地解决这个问题,使用自定义标签进行布局,其中 <jsp:include> -tags 用于动态内容,<jsp:doBody> -tag 用于实际内容模板。然而,通过阅读 Spring Boot 文档,我以某种方式得到了鼓励使用与 JSP 不同的模板引擎的印象。然而,上述方法将让我定义一个动态生成内容的header.jspnavigation.jspfooter.jsptwitterFeed.jsp,而实际的内容模板纯粹关注在要显示的内容上。我在这里对 Thymeleaf 和 JSP 进行比较时是否遗漏了什么,为什么我不选择 JSP 作为我项目的模板引擎?

3) 使用 2) 中的方法,我是否仅限于将我的所有 Java 逻辑放入主布局中包含的模板(页眉、导航、页脚、twitter-feed)的 JSP 中,或者是否有使用类似控制器的类来支持这些存根的更好方法?

4) 是否有任何其他模板引擎可以与 Spring MVC / Spring Boot 很好地集成,这将是上述任何一个更好的选择?

【问题讨论】:

  • 不要使用 JSP。它不是模板引擎。这是更糟糕时期的可怕宿醉。 JSP 被编译成 Java 代码并被部署为一个单独的 servlet——请求然后被转发给它。老实说,我完全无法理解您的顾虑,或者无法理解您所说的“所有动态内容仍然在每个模板中生成”是什么意思。我不确定您是否将服务器端模板与 AJAX 之类的东西混淆了 - 但两者远非等价。
  • 我对 Thymeleaf 方法的担忧是,根据github.com/ultraq/thymeleaf-layout-dialect/blob/master/Docs/…,在我看来,我必须在每个子模板中定义父模板应该如何呈现菜单,twitter-提要、页脚等——不管子模板是 home.html、login.html、content.html、blogpost.html 等。我不是 JSP 的拥护者,我知道它的历史和缺点(甚至Spring Boot 有点不鼓励使用它)。我只需要确信 Thymeleaf(或任何其他)可以完成这项工作。

标签: java jsp spring-mvc spring-boot thymeleaf


【解决方案1】:

使用可以使用Thymeleaf Ultraq Layout 创建一个基本模板,它将充当您其他模板的装饰器,如下所示:

base-template.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>

  <title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">Sample</title>
  <meta name="description" content=""/>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <!-- all CSS links here -->
</head>


<body>
<div class="container">
  <div class="content">
    <div layout:fragment="page_content">
      <!-- Content from other pages which decorate using this template -->
    </div>
  </div>
</div>

<!-- /.container -->
<!-- All script tags here -->

<th:block layout:fragment="scripts">
  <!-- If you have any page specific scripts -->
</th:block>
</body>
</html>

那么其他页面就会使用上面的模板作为装饰器,如下图:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{base-template}">

<head>
  <title>This page title</title>
</head>

<div layout:fragment="page_content">
  <!-- content for this page -->
</div>

<th:block layout:fragment="scripts">
  <!-- add any scripts related to this page -->
</th:block>
</html>

语法 ~{base-template} 用于 Thymeleaf 3 及以后版本。

您可以继续使用上述方法,不要在其他页面上重复导航、页眉和页脚。

【讨论】:

  • 这是我自己一直在研究的例子,从那里我得出的结论是,使用这种方法,我还必须定义所有动态内容(我知道它在导航、标题、页脚等是静态的)在所有模板中(而 base-template.html 仅确定此内容站点在静态整体模板中的位置)。举个例子,每个模板都必须有一个
    ...
    并且每个控制器都必须将菜单设置为模型属性...或者它不是我的东西了解这里吗?
  • 不,您不需要每个模板中的菜单。菜单将在基本模板中。如果您的菜单在页面之间发生变化,那么您可以提取基本模板中的常用菜单项,然后在基本模板中提供一个占位符以添加特定于页面的菜单。你试试就知道了。因此,如果您有一些您认为设计不好的代码要分享,请随时在此处发布
猜你喜欢
  • 2014-11-26
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多