【模板引擎】Thymeleaf 介绍及使用

本文阅读 15 分钟
首页 代码,Java 正文

这里介绍两种常用的服务器生成动态页面的方式:服务器渲染和客户端渲染

渲染就是把数据和页面结合起来

1.1 客户端渲染(前后端分离)

客户端渲染流程:

img

客户端渲染是在请求回数据后就开始渲染了,只是有些数据还没有拿到,故暂时没法渲染。但是大部分页面的内容是可以获取到的,因此客户端渲染可以完成页面的部分刷新。

客户端渲染示例: 淘宝某商品的评论,我们点击该商品评论区的其它页面,只是刷新了评论区域,整个商品页面并没有刷新,浏览器的网址也没有变。当我们点击评论区的下一页时,客户端就会向服务器发送 Ajax 请求,之后就会拿到该页评论信息,并对这个局部区域进行渲染

img

客户端渲染的特点:

  • 客户端通过 Ajax 的方式和服务器进行交互
  • 服务器返回的不是完整的 html,通常只是纯粹的数据,这些数据常见的以 json 的方式来组织

客户端渲染的优点:

  • 能够让前后端进行充分的解耦,前后端的开发互不干扰,也能各自进行测试
  • 可以向用户快速展示页面的内容,增加用户体验
  • 通过爬虫爬取响应的内容会增加一定的难度

客户端渲染的缺点:

  • 前后端交互的次数比较多
  • 一个页面可能需要多组 Ajax 来获取完整的数据,效率稍微低一些
  • 不利于 SEO 搜索引擎优化,即搜索引擎搜索不到客户端渲染的数据

1.2 服务器渲染(使用模板引擎)

服务器渲染流程:

img

服务器渲染是在请求后,服务器对于请求的网页文件直接渲染好,然后返回给客户端。

服务器渲染示例: 淘宝上搜索某商品,当我们通过销量、价格、信用等分类查询该商品时,整个页面都会被刷新,浏览器的网址也会改变img

服务器渲染的特点:

  • 服务器返回一整个 html 页面
  • html 页面上的一些动态数据,往往是通过“模板引擎”的方式来进行动态替换的

服务器渲染的优点:

  • 前后端交互次数比较少,一次 HTTP 请求/响应,就能够拿到一个完整的页面,比较高效
  • 利于 SEO 搜索引擎优化,即能被搜索引擎搜索到,能向用户展示你网页的内容

服务器渲染的缺点:

  • 前后端代码不能充分解耦合,前后端开发很难进行明确分工,不能够独立测试
  • 如果数据量过大,服务器渲染的时间就会过长,造成浏览器的暂时性空白
  • 页面上的数据容易被爬虫获取

2.1 模板引擎介绍

  • 模板引擎(template engine): 是为了使用户界面与业务数据分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的 HTML 文档。当服务器将模板中动态变化的部分计算好之后,将模板中的占位符给替换成计算的结果,然后将这个组装好的 HTML 格式的字符串返回给浏览器。
  • 模板(template): 就是一个 HTML,只不过这个 HTML 是把一些动态变化的数据给挖空,用特殊符号代替。

2.2 模板引擎的作用

  • 模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这就大大提升了开发效率,并且良好的设计也使得代码重用变得更加容易。
  • 模板引擎不只是可以让你实现代码分离(业务逻辑代码和用户界面代码),也可以实现数据分离(动态数据与静态数据),还可以实现代码单元共享(代码重用),甚至是多语言、动态页面与静态页面自动均衡(SDE)等等与用户界面可能没有关系的功能。

2.3 常见的模板引擎

  • Thymeleaf
<p>Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为 .html,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 Thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时 Thymeleaf 会动态地替换掉静态内容,使页面动态显示。</p>
  • FreeMaker
<p>在所有采用网页静态化手段的网站中,FreeMarker 使用的比例大大的超过了其他的一些技术。HTML 静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以使用 FreeMarker 将 HTML 静态化。比如一些网站的公用设置信息,这些信息基本都是可以通过后台来管理并存储在数据库中,这些信息其实会大量的被前台程序调用,每一次调用都会去查询一次数据库,但是这些信息的更新频率又会很小,因此也可以考虑将这部分内容进行后台更新的时候进行静态化,这样就避免了大量的数据库访问请求,提高了网站的性能。</p>
  • Enjoy
<p>Enjoy 是基于 Java 语言的极轻量极模板引擎且不依赖任何第三方。极简设计仅由 if、for、switch、set、define、include、render 七个核心指令,让学习成本低到极致。独创 DKFF(Dynamic Key Feature Forward)词法分析算法与 DLRD(Double Layer Recursive Descent)语法分析算法,避免使用 javacc、antlr、jflex 生成器,令代码量少到极致。</p>
  • Velocity
<p>Velocity 是一个基于 Java 的模板引擎。它允许任何人使用简单但功能强大的模板语言来引用 Java 代码中定义的对象。</p>
  • JSP
<p>JSP 虽然是一款功能比较强大的模板引擎,并被广大开发者熟悉,但它前后端耦合比较高。比如说前端的 HTML 页面还要手动修改成 JSP 页面,大大加重了工作量,而且动态和静态资源也是耦合性太高。其次是 JSP 页面的效率没有 HTML 高,因为 JSP 是同步加载。而且 JSP 需要tomcat,但又不支持 nginx 等,已经跟不上时代的潮流。</p>

3.1 Thymeleaf 介绍

Thymeleaf 基本介绍:

Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为 .html,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 Thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时 Thymeleaf 会动态地替换掉静态内容,使页面动态显示。

Thymeleaf 的特点:

  • 动静结合:Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
  • 开箱即用:Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
  • 多方言支持:它提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式;必要时,开发人员也可以扩展和创建自定义的方言。
  • 与 SpringBoot 完美整合:SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合。

3.2 Thymeleaf 语法规则

Thymeleaf 作为一种模板引擎,它拥有自己的语法规则。Thymeleaf 的语法分为两类:标准表达式语法和 th 属性

3.2.1 标准表达式语法

Thymeleaf 模板引擎支持多种表达式,以下重点介绍变量表达式

变量表达式:${表达式}

获取对象的属性和方法

选择表达式:*{表达式}

选择变量表达式与变量表达式功能基本一致,只是在变量表达式的基础上增加了与 th:object 的配合使用。当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式获取该对象中的属性,其中 * 即代表该对象。

链接表达式:@{表达式}

不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式

消息表达式:#{表达式}

消息表达式一般用于国际化的场景

片段表达式:~{表达式}

片段引用表达式用于在模板页面中引用其他的模板片段

3.2.2 th 属性

Thymeleaf 提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用,其中常用 th 属性及其示例如下表。

3.3 Thymeleaf 使用流程

接下来通过写一个猜数字的程序来演示 Thymeleaf 模板引擎的使用流程

  1. 创建一个 Maven 项目,引入 Thymeleaf 依赖(在 maven 中央仓库搜索 Thymeleaf,选择合适版本) <!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
    <dependency>

    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.15.RELEASE</version>

    </dependency>

  2. 编写 HTML 模板文件(在 webapp/WEB-INF 目录下再创建一个 template 目录用于存放 HTML 模板文件) <!DOCTYPE html>
    <html lang="en">

<head>

<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>猜数字游戏</title>

</head>
<body>

<div>
    <from action="guessNum" method="post">
        <span>请输入要猜的数字:</span>
        <input type="text" name="toGuess">
        <input type="submit" value="猜">
    </from>
</div>
<div>
    结果:<span th:text="${result}"></span>
</div>

</body>
</html>

    2. <span th:text="${result}"></span> 将 result 对象替换成该 span 标签的文本内容 2. result 这个值是从后台渲染而来,如果没网络(直接打开 html 文件)的时候静态数据为空,因为此时 span 标签中没有内容,你要是写了,那就由对应的内容。而如果通过网络访问那么内容将是程序员在 Servlet 中通过计算生成的一个变量
  1. 编写 Servlet 代码
    5. 初始化模板引擎对象 5. 创建解析器,并设置模板的参数,并将这个模板引擎对象关联这个解析器 5. 创建模板的上下文对象,用于对模板中要动态修改的数据进行设置 5. 执行模板引擎

</blockquote> <pre><span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>thymeleaf<span class="token punctuation">.</span></span><span class="token class-name">TemplateEngine</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>thymeleaf<span class="token punctuation">.</span>context<span class="token punctuation">.</span></span><span class="token class-name">WebContext</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>thymeleaf<span class="token punctuation">.</span>templateresolver<span class="token punctuation">.</span></span><span class="token class-name">ServletContextTemplateResolver</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span></span><span class="token class-name">ServletException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">WebServlet</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServlet</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletRequest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletResponse</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">WebConnection</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">ArrayList</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">List</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Random</span></span><span class="token punctuation">;</span>

<span class="token comment">// 猜数字</span>
<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">"/guessNum"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GuessNumServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{

<!-- --></span>
<span class="token keyword">private</span> <span class="token class-name">Random</span> random <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 初始化生成的随机数</span>
<span class="token keyword">private</span> <span class="token keyword">int</span> num <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token comment">// </span>
<span class="token keyword">private</span> <span class="token class-name">TemplateEngine</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TemplateEngine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 在 init 方法中初始化模板引擎</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span> <span class="token punctuation">{ 
<!-- --></span>
    创建一个 <span class="token class-name">ServletContextTemplateResolver</span> 对象,resolver 表示解析器,这个对象是的功能就是从磁盘上加载 html 模板文件
    <span class="token class-name">ServletContextTemplateResolver</span> resolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ServletContextTemplateResolver</span><span class="token punctuation">(</span><span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 设置模板所在的目录</span>
    resolver<span class="token punctuation">.</span><span class="token function">setPrefix</span><span class="token punctuation">(</span><span class="token string">"/WEB-INF/template/"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 设置模板的文件类型</span>
    resolver<span class="token punctuation">.</span><span class="token function">setSuffix</span><span class="token punctuation">(</span><span class="token string">".html"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 设置模板的编码方式</span>
    resolver<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">"utf-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 给模板引擎对象设置解析器,将模板引擎对象和模板关联起来</span>
    engine<span class="token punctuation">.</span><span class="token function">setTemplateResolver</span><span class="token punctuation">(</span>resolver<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 通过 doGet 从服务器获取到猜数字的初始界面和生成的随机数字</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">doGet</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{ 
<!-- --></span>
    <span class="token comment">// 设置请求的编码方式,</span>
    req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">"utf8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    resp<span class="token punctuation">.</span><span class="token function">setContentType</span><span class="token punctuation">(</span><span class="token string">"text/html;charset=utf8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    num <span class="token operator">=</span> random<span class="token punctuation">.</span><span class="token function">nextInt</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token class-name">WebContext</span> webContext <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">WebContext</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">,</span> <span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    engine<span class="token punctuation">.</span><span class="token function">process</span><span class="token punctuation">(</span><span class="token string">"guessNum"</span><span class="token punctuation">,</span>webContext<span class="token punctuation">,</span> resp<span class="token punctuation">.</span><span class="token function">getWriter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 通过 doPost 从服务器获取到猜完数字后的结果界面</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">doPost</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{ 
<!-- --></span>
    resp<span class="token punctuation">.</span><span class="token function">setContentType</span><span class="token punctuation">(</span><span class="token string">"text/html;charset=utf8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> toGuess <span class="token operator">=</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token function">parseInt</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">"toGuess"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> result <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>toGuess <span class="token operator">&gt;</span> num<span class="token punctuation">)</span><span class="token punctuation">{ 
<!-- --></span>
        result <span class="token operator">+=</span> <span class="token string">"猜大了!"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>toGuess <span class="token operator">&lt;</span> num<span class="token punctuation">)</span><span class="token punctuation">{ 
<!-- --></span>
        result <span class="token operator">+=</span> <span class="token string">"猜小了!"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span><span class="token punctuation">{ 
<!-- --></span>
        result <span class="token operator">+=</span> <span class="token string">"猜对了!"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token class-name">WebContext</span> webContext <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">WebContext</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">,</span> <span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    webContext<span class="token punctuation">.</span><span class="token function">setVariable</span><span class="token punctuation">(</span><span class="token string">"result"</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
    engine<span class="token punctuation">.</span><span class="token function">process</span><span class="token punctuation">(</span><span class="token string">"guessNum"</span><span class="token punctuation">,</span>webContext<span class="token punctuation">,</span> resp<span class="token punctuation">.</span><span class="token function">getWriter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token punctuation">}</span>

    5. TemplateEngine 对象表示模板引擎,用于进行页面的渲染 5. ServletContextTemplateResolver 对象表示“解析器”,用于加载 HTML 模板 5. getServletContext() 方法可以获取到这个 webapp 的上下文对象 ServletContext(每个 webapp 都有一个 ServletContext,并且一个 webapp 中可以有多个 Servlet,这多个 Servlet 中是可以共享 ServletContext 对象的,可以基于这个上下文对象来传递数据) 5. WebContext 对象表示模板上下文,本质是一个哈希表,里面有三个固定参数 req、resp、getServletContext() 。通过这个对象的 setVariable() 方法就可以动态替换模板中的可修改数据,该方法的第一个参数是模板中的要动态替换的变量,第二个参数是程序员自己计算生成的变量 5. TemplateEngine 类的 engine() 方法就可以启动模板引擎。该方法的第一个参数是模板文件名,第二个参数是模板上下文对象,第三个参数是 resp.getWriter()
  1. 代码效果展示
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://t4dmw.blog.csdn.net/article/details/124413431
-- 展开阅读全文 --
BUUCTF Web [极客大挑战 2019]Knife
« 上一篇 06-24
安全面试之XSS(跨站脚本攻击)
下一篇 » 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复