使用Spring Boot进行服务器端渲染 (SSR)
理解项目设置中的共同步骤是至关重要的,在深入了解每种客户端增强技术的细节之前。我这边的要求(来自上一篇帖子)非常简单明了:
我将以后端开发者的视角来看这个问题。
无需使用TypeScript等前端构建工具,如压缩代码。
- 所有依赖项都通过后端应用程序(比如Maven)管理。
重要的是要指出,我将详细介绍的技术,除了Vaadin之外的其他技术都采用了相似的途径。Vaadin因为其独特的方法,在这些技术中脱颖而出。
WebJars,即WebjarWebJars,这项技术由詹姆斯·沃德在2012年设计,旨在处理这些具体需求。
WebJars是将客户端Web库(如jQuery和Bootstrap)打包成JAR(Java Archive)文件的格式。
明确且轻松地管理基于JVM的Web应用程序中的客户端依赖
使用基于JVM的构建工具(如Maven、Gradle、sbt等)下载客户端依赖
了解您正在使用的客户端依赖
传递依赖项会自动解析并可通过RequireJS加载
公共CDN由JSDelivr提供
WebJar 是一个普通的 JAR 文件,里面包含了 web 资源。将 WebJar 添加到项目的依赖中并不特别奇怪。
<dependencies>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>alpinejs</artifactId>
<version>3.14.1</version>
</dependency>
</dependencies>
这是一个配置示例,展示了如何将Alpine.js作为一个依赖项添加到项目中。
框架的责任是让资源可以通过一个URL访问。例如,Spring Boot 在 WebMvcAutoConfiguration
类中完成这个功能。
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("// 默认资源处理已关闭");
return;
}
addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(),
"classpath:/META-INF/resources/webjars/");
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
registration.addResourceLocations(resource);
}
});
}
- 默认是
"/webjars/**"
在 JAR 文件内,你可以通过各自的路径和文件名访问资源。约定的存储结构为 resources/webjars/<库名>/<版本号>
。以下是 alpinejs-3.14.1.jar
的内部结构:
META-INF 文件夹
|- 包含一个 MANIFEST.MF 文件
|- maven.org.webjars.npm.alpinejs 目录
|- resources.webjars.alpinejs.3.14.1 目录,该目录下包含
|- builds 文件夹
|- dist 文件夹,该文件夹中包含
|- cdn.js 文件
|- cdn.min.js 文件
|- src 文件夹
|- package.json 文件
在 Spring Boot 中,你可以通过这个路径访问未压缩的原版:/webjars/alpinejs/3.14.1/dist/cdn.js
。
开发人员经常发布客户端库,这些库。当你在POM中更改依赖版本时,你可能需要在多个地方修改前端路径。这既枯燥又毫无意义,还可能遗漏某个更改。
WebJars 定位器项目旨在通过提供一个不包含版本号的路径来解决这些问题,例如 webjars/alpinejs/dist/cdn.js
。你可以通过在你的项目中添加 webjars-locator
JAR 来实现。
<dependencies>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>alpinejs</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.52</version>
</dependency>
</dependencies>
我将对每一种前端技术框架或工具都采用这种方法。我还将引入Bootstrap CSS库,以提升用户界面的美观度。
ThymeLeaf 模板引擎Thymeleaf 是一种服务器端的模板引擎。
Thymeleaf 是一个现代的服务器端Java模板引擎,适用于Web和独立的应用程序环境。
Thymeleaf的主要目标是将自然风格的HTML模板带入您的开发工作流程——可以在浏览器中正确显示的HTML,也可以作为静态原型使用,从而加强开发团队间的协作。
通过Spring框架的模块、与您喜爱工具的各种集成以及轻松集成您自定义的功能,Thymeleaf非常适合现代HTML5 JVM Web开发——虽然它还有许多其他用途。
当我第一次听说Thymeleaf时,我仍然是个顾问。那时,JSP已经接近尾声。JSF正试图取代它们,但在我看来,它们没能成功。
我觉得Thymeleaf是一个很酷的方案:它让你可以在设计时看到静态结果,开发时看到服务器上的结果。更酷的是,你可以在同一个文件里轻松切换这两种环境。我还从来没见这种功能被用过。
然而,Spring Boot 完全支持 Thymeleaf。真是好上加好:后者可以通过页面上的一个 HTML 命名空间获得。如果你对 JSF 不感冒(提示:我对它也不感冒),Thymeleaf 是今天最常用的 SSR(服务端渲染)模板语言。
这里有一个网站上的演示样本。
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">名称:</th>
<th th:text="#{msgs.headers.price}">价格:</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">橙</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
如果你需要熟悉Thymeleaf,这里有一份Thymeleaf入门教程。
- 当你打开 HTML 文件时,浏览器会显示标签中的默认值,即
Name
和Price
。当你在服务器端运行时,Thymeleaf 会介入并渲染从th:text
、#{msgs.headers.name}
和#{msgs.headers.price}
计算后的值。 - `# 使用Spring Boot进行服务器端渲染 (SSR)
理解项目设置中的共同步骤是至关重要的,在深入了解每种客户端增强技术的细节之前。我这边的要求(来自上一篇帖子)非常简单明了:
我将以后端开发者的视角来看这个问题。
无需使用TypeScript等前端构建工具,如压缩代码。
- 所有依赖项都通过后端应用程序(比如Maven)管理。
重要的是要指出,我将详细介绍的技术,除了Vaadin之外的其他技术都采用了相似的途径。Vaadin因为其独特的方法,在这些技术中脱颖而出。
WebJars,即WebjarWebJars,这项技术由詹姆斯·沃德在2012年设计,旨在处理这些具体需求。
WebJars是将客户端Web库(如jQuery和Bootstrap)打包成JAR(Java Archive)文件的格式。
明确且轻松地管理基于JVM的Web应用程序中的客户端依赖
使用基于JVM的构建工具(如Maven、Gradle、sbt等)下载客户端依赖
了解您正在使用的客户端依赖
传递依赖项会自动解析并可通过RequireJS加载
公共CDN由JSDelivr提供
WebJar 是一个普通的 JAR 文件,里面包含了 web 资源。将 WebJar 添加到项目的依赖中并不特别奇怪。
<dependencies>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>alpinejs</artifactId>
<version>3.14.1</version>
</dependency>
</dependencies>
这是一个配置示例,展示了如何将Alpine.js作为一个依赖项添加到项目中。
框架的责任是让资源可以通过一个URL访问。例如,Spring Boot 在 WebMvcAutoConfiguration
类中完成这个功能。
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("// 默认资源处理已关闭");
return;
}
addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(),
"classpath:/META-INF/resources/webjars/");
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
registration.addResourceLocations(resource);
}
});
}
- 默认是
"/webjars/**"
在 JAR 文件内,你可以通过各自的路径和文件名访问资源。约定的存储结构为 resources/webjars/<库名>/<版本号>
。以下是 alpinejs-3.14.1.jar
的内部结构:
META-INF 文件夹
|- 包含一个 MANIFEST.MF 文件
|- maven.org.webjars.npm.alpinejs 目录
|- resources.webjars.alpinejs.3.14.1 目录,该目录下包含
|- builds 文件夹
|- dist 文件夹,该文件夹中包含
|- cdn.js 文件
|- cdn.min.js 文件
|- src 文件夹
|- package.json 文件
在 Spring Boot 中,你可以通过这个路径访问未压缩的原版:/webjars/alpinejs/3.14.1/dist/cdn.js
。
开发人员经常发布客户端库,这些库。当你在POM中更改依赖版本时,你可能需要在多个地方修改前端路径。这既枯燥又毫无意义,还可能遗漏某个更改。
WebJars 定位器项目旨在通过提供一个不包含版本号的路径来解决这些问题,例如 webjars/alpinejs/dist/cdn.js
。你可以通过在你的项目中添加 webjars-locator
JAR 来实现。
<dependencies>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>alpinejs</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.52</version>
</dependency>
</dependencies>
我将对每一种前端技术框架或工具都采用这种方法。我还将引入Bootstrap CSS库,以提升用户界面的美观度。
ThymeLeaf 模板引擎Thymeleaf 是一种服务器端的模板引擎。
Thymeleaf 是一个现代的服务器端Java模板引擎,适用于Web和独立的应用程序环境。
Thymeleaf的主要目标是将自然风格的HTML模板带入您的开发工作流程——可以在浏览器中正确显示的HTML,也可以作为静态原型使用,从而加强开发团队间的协作。
通过Spring框架的模块、与您喜爱工具的各种集成以及轻松集成您自定义的功能,Thymeleaf非常适合现代HTML5 JVM Web开发——虽然它还有许多其他用途。
当我第一次听说Thymeleaf时,我仍然是个顾问。那时,JSP已经接近尾声。JSF正试图取代它们,但在我看来,它们没能成功。
我觉得Thymeleaf是一个很酷的方案:它让你可以在设计时看到静态结果,开发时看到服务器上的结果。更酷的是,你可以在同一个文件里轻松切换这两种环境。我还从来没见这种功能被用过。
然而,Spring Boot 完全支持 Thymeleaf。真是好上加好:后者可以通过页面上的一个 HTML 命名空间获得。如果你对 JSF 不感冒(提示:我对它也不感冒),Thymeleaf 是今天最常用的 SSR(服务端渲染)模板语言。
这里有一个网站上的演示样本。
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">名称:</th>
<th th:text="#{msgs.headers.price}">价格:</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">橙</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
如果你需要熟悉Thymeleaf,这里有一份Thymeleaf入门教程。
操作符用于查询模型中的 Spring bean。${prod.name}
等同于 model.getBean("prod").getName()
。
#
调用一个函数或方法。th:each
可用于循环
将Thymeleaf与前端框架集成
大多数前端框架通常使用的是客户端模型。我们需要在服务器端和客户端模型之间建立连接。
下面是我的服务器端代码:
data class Todo(val id: Int, var label: String, var completed: Boolean = false) //1 数据类
fun 配置() = beans {
bean {
mutableListOf( // 可变列表
Todo(1, "买杂货", false),
Todo(2, "遛遛狗", false),
Todo(3, "扔垃圾", false)
)
}
bean {
router {
GET("/") {
ok().render( // 渲染
"index", // 渲染模板
mapOf("title" to "标题", "todos" to ref<List<Todo>>()) // 引用待办事项列表
)
}
}
}
}
- 定义
Todo
类 - 向 bean 工厂添加一个内存列表。在常规应用中,你会使用一个
Repository
来从数据库读取数据 - 渲染一个 HTML 模板
- 模板位于
src/main/resources/templates/index.html
,使用了 Thymeleaf 属性 - 将模型放入页面上下文中
Thymeleaf 在 <script>
标签上提供了 th:inline="javascript"
属性。它将服务器端的数据渲染成 JavaScript 变量。文档对此的解释比我所能做的要详细得多:
我们可以用内联脚本做的第一件事就是将表达式的值写入脚本中,例如:
<script th:inline="javascript">
/<![CDATA[/
…var username = /[[${session.user.name}]]/ 'Sebastian';
…
/]]>/
</script>这里的
_/*[[...]]*/_
语法让Thymeleaf去计算包含的表达式。但这里还有其他含义:
由于是 JavaScript 注释
(/*...*/)
,当页面在浏览器中静态显示时,该表达式会被忽略。内联表达式后面的代码 (
'Sebastian'
) 会在页面静态显示时执行。- Thymeleaf 会执行表达式并插入结果,同时,它还会移除内联表达式之后的代码(这部分会在页面静态显示时执行)。
如果我们把上述做法应用于我们的代码,Spring传递给我们的模型的属性将如下所示:
<script th:inline="javascript">
/*<![CDATA[*/
window.title = /*[[${title}]]*/ '标题'
window.todos = /*[[${todos}]]*/ [{ 'id': 1, 'label': '倒一趟垃圾', 'completed': false }]
/*]]>*/
</script>
这样在服务器端渲染时产生的结果是:
<script>
/*<![CDATA[*/
window.title = "我的标题";
window.todos = [{"id":1,"label":"去超市","completed":false},{"id":2,"label":"遛狗","completed":false},{"id":3,"label":"倒垃圾","completed":false}]
/*]]>*/
</script>
概述.
在这篇文章里,我将介绍两个模块,它们将在后续文章中使用。
- WebJars 可以帮助您在 Maven POM 中管理客户端依赖项
- Thymeleaf 是一个与 Spring Boot 配套使用的优质模板引擎
该帖子的完整源代码可以在GitHub上找到。
更进一步!
- WebJars
- Spring Boot 使用 WebJars 指南
-
原发表于 A Java Geek ,2024年9月15日星期X(A Java Geek)
共同学习,写下你的评论
评论加载中...
作者其他优质文章