模板引擎
模板引擎
为什么而产生
模板引擎(用于Web开发)是为了使用户界面与业务数据(内容)分离而产生的
可以做什么
它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
一、模板引擎分类
置换型模板引擎
就是将规定好的文本标记替换为目标内容。这种模板引擎实现简单,除了标签替换之外,很少支持诸如子模板引用、流程控制等功能。置换型模板引擎通常用于业务逻辑不是很复杂的项目,比如生成短信、生成电子邮件,甚至有很多代码生成器也在用它。可以说,置换型模板引擎的思想是整个模板引擎界的基础。
简而言之:把符合规则的内容进行替换
解释型模板引擎
解释型模板引擎的原理还是标记置换。只不过有了解释器的存在,可以支持更加复杂的标记语法。
编译型模板引擎
它通过解析引擎和一系列的算法将我们定义的模板转换为页面文件,然后直接访问页面文件即可。
二、常见模板引擎
jsp、freemarker、thymeleaf、velocity
JSP
一、简介
Java Server Page(java服务器端页面技术),是Sun公司制定的一种服务器端动态页面生成技术的规范;
二、结构
HTML标签+Java代码(在HTML页面中嵌入Java代码)
三、写法
Java代码片段:<%java代码片段;%>
Java代码表达式:<%=java代码表达式%>
Java方法:<%!java的方法%>
四、相关概念
三大指令
page指令
指令 | 含义 |
---|---|
import | 用于导包的,可以一次性导入多个包,中间用逗号隔开,也可以使用多次page指令来进行导包 |
pageEncoding | 告诉JSP引擎,JSP文件保存的时候应该采用的编码格式; |
contentType | 等价于response.setContentType(); |
errorPage | 指向错误处理页面(需要你手动书写错误页面) |
isErrorPage | 可以Strue/false,即定义这个页面是否是错误页面,默认是false;注意,这个属性和上面errorPage属性一般是成对出现的,成对并不是指在一个页面都出现,而是指关联着出现; |
session | 可以写true/false,默认为true,即表示当前页面是否支持session; |
isELigored | 可以写为true/false,表示这个JSP是否支持EL表达式,默认为true; |
include指令
这个指令里面最主要的属性是file,用来表示这个页面中要包含哪个页面
Taglib指令
Taglib指令是定义一个标签库以及其自定义标签的前缀
九大对象
隐含对象 | 类型 | 说明 |
---|---|---|
rrequest | HttpServletRequest | 代表请求对象 |
response | HttpServletResponse | 代表响应对象 |
out | JSPWriter | 输出的数据流 |
session | HttpSession | 会话 |
application | ServletContext | 全局的Servlet上下文对象 |
pageContext | PageContext | JSP页面上下文 |
page | Object | 代表JSP页面本身,即this |
config | ServletConfig | Servlet配置对象 |
exception | Throwable | 捕获的页面异常对象 |
七大动作
省略了<>和%
动作 | 说明 |
---|---|
jsp:include | 在页面被请求的时候引入一个文件。 |
jsp:useBean | 寻找或者实例化一个JavaBeano |
jsp:setProperty | 设置JavaBean的属性。 |
jsp:getProperty | 输出某个JavaBean的属性。 |
jsp:forward | 把请求转到一个新的页面。 |
jsp:plugin | 根据浏览器类型为Java插件生成OBJECT或EMBED标记。 |
JSTL 介绍
概念
JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。
分类
核心标签、格式化标签、SQL标签、XML标签、JSTL函数
使用
核心标签库:
导入方式:<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
具体演示
EL介绍
概念
expression language主要是用来简化JSP中的表达式的代码,可以很方便的以标签的形式来代替jsp中的部分java代码,以提高代码的可读性。
语法
${el语句}
隐含对象
类别 | 标识符 | 描述 |
---|---|---|
JSP | pageC0ntext | 当前页面 |
作用域 | pageScope | 页面作用域 |
requestScope | 请求作用域 | |
sessionScope | 会话作用域 | |
applicationScope | 应用程序作用域 | |
请求参数 | param | 存储请求参数 |
paramValues | 将请求参数的所有值作为string数组存储 | |
请求头 | header | 按名称存储请求头 |
headerValues | 将请求头的所有值作为String数组存储 | |
Cookie | cookie | 按名称存储请求附带的cookie |
初始化参数 | initParam | 按名称存储Web应用程序上下文初始化参数 |
运算符
算数运算符
算术运算符 | 说明 | 示例 | 结果 |
---|---|---|---|
+ | 加 | ${1 + 1} | 2 |
- | 减 | ${1 - 1 | 0 |
* | 乘 | ${1 * 2} | 2 |
/或div | 除 | ${3 / 2} | 1.5 |
%或mod | 取余 | ${3 % 2} | 1 |
关系运算符
关系运算符 | 说明 | 示例 | 结果 |
---|---|---|---|
== 或 eq | 等于 | 1==1 或 {1 eq 1} | true |
!= 或 ne | 不等于 | 1!=1 或 {1 ne 1} | false |
< 或 lt | 小于 | 1<2 或 {1 lt 1} | true |
> 或 gt | 大于 | 1>2 或 {1 gt 1} | false |
<= 或 le | 小于或者等于 | 1<=2 或 {1 le 1} | true |
>= 或 ge | 大于或者等于 | 1>=2 或 {1 ge 1} | false |
逻辑运算符
逻辑运算符 | 说明 | 示例 | 结果 |
---|---|---|---|
&& 或 and | 交集 | Tex parse error! {A and B} | 当A和B都为true时为true,其他情况为false |
|| 或 or | 并集 | A || B 或 {A or B} | 当A和B都为false时为false,其他情况为true |
! 或 not | 非 | !A 或 {not A} | 当A为true时,为false当A为false时,为true |
条件运算符
${empty 表达式}
演示
<c:foreach items="${recommendList}" var="item">
${item.desc}
</c:forEach>
<!--利用下标取出前四个元素 status -->
<c:forEach items="${split}" var="subString" varStatus="status">
<c:if test="${status.index < 4}">
<li class=""><img src="&{baseUrl}${subString}" alt="用户配图丢失">
</c:if>
</c:forEach>
<!--取出123 -->
<c:forEach var="x" begin="1" end="${pageProducyHot.extra.listPageCount}">
<a href="${baseUrl}product/jsp/indexForH5.jsp">${x}</a>
</c:forEach>
<!--取出前五个元素 -->
<c:forEach items="${pageProductHot.list}" var="item" varStatus="status">
<c:if test="${(status.index) < 5}">
${item.name}
</c:if>
</c:forEach>
<!-- 判断字符串是否为"" 判断是否为null -->
<c:if test="${not empty item.coverImgUrl || item.coverImgUrl eq null}">
</c:if>
<!-- 分割字符串 并且判断字符串长度 -->
<c:set value="${fn:split{item.imgUrls, ','}}" var="split" />
<c:if test="${fn:length('$split') == 1}"
<img src="${baseUrl}${split{0}]">
<c:if test="${fn:length{item.textContentShort} > 100}">
</c:if>
</c:if>
五、JSP的运行过程
六、Springboot下JSP的使用
依赖
https://mvnrepository.com/artifact/javax.servlet/jstl
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
目录
配置
application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
构建Jsp文件
project structure -> Modules -> Web ->右边上“+” -> web.xml -> 右边下“+” -> “ok” -> (出现警告是正常情况)->“ok”
设置完成后可生成jsp文件
代码
@Controller
public class WelcomeController {
@RequestMapping("/welcome")
public String toWelcome(HttpServletRequest servletRequest){
servletRequest.setAttribute("name","张三");
return "welcome";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>这是springboot下的jsp</title>
</head>
<body>
welcome!!!<%=request.getAttribute("name")%><br>
你好,${name}
</body>
</html>
JSTL 需要导包
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
FreeMarker
一、概念
描述
FreeMarker是一个模板引擎,是一种基于模板和要改变的数据,并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
与JSP的区别
FreeMarker是根据需求、模板来生成各种文件(HTML或者JAVA文件等)。
JSP需要用JSP引擎来解析成Servlet,将Servlet编译成字节码文件,最后再执行。
工作机制
OUTPUT
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome John Doe!</h1>
<p>Our latest Product:
<a href="products/greenmouse/html">green mouse</a>!
</body>
</html>
TEMPLATE
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest Product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
DATA MODEL
(root)
|
+—— user = "Big Joe"
|
+—— latestProduct
|
+—— url = "products/greenmouse/html"
|
+—— name = "green mouse"
Template + Data-Model = Output
特点
- 彻底的分离表现层和业务逻辑
- 性能好,提高了开发效率,使得开发过程中得人员分工更加明确。
- 学习成本低
- 支持表达式、宏定义(类似JSP标签)
二、语法
数据类型
- 标量:标量是最基本,最简单的数值类型
- 字符串:表示简单的文本
- 数字:整数和非整数是不区分的,只有单一的数字类型
- 布尔值:布尔值代表了逻辑上的对或错(是或否)
- 日期/时间(日期,时间或日期时间):日期变量可以存储和日期/时间相关的数据
- 容器:这些值存在的目的是为了包含其他变量
- 哈希表:类似于Java中的HashMap,不记录内部元素的顺序,仅仅通过名称来访问数据
- 序列:类似于java中的集合List,可以通过下标进行访问,从0开始。
- 集合:从模板设计者角度来看,集合是有限制的序列,不能获取集合的大小,也不能通过索引取出集合中的子变量,但是它们仍然可以通过list指令来遍历。
- 子程序:
- 方法和函数
- 用户自定义指令
算数运算符
数字运算
+:10 + 3 = 13
- :10 - 3 = 7
* :10 * 3 = 30
/ :10 / 3 = 3.333
%:10 % 3 = 1
字符串运算
可以使用${..}
在文本部分插入表达式的值,例如:${'Hello${user}!"}
可以使用 + 操作符获得同样的结果:${'Hello" + user + "!" }
${..}
只能用于文本部分,下面的代码是错误的:<#if ${isBig}> Wow!</#if>
应该写成:<#if isBig>Wow!</#if>
假设user的值为"zhangsan"
${user[0]}${user[4]}
结果是:zg
${user[1..4]}
结果是:hang
逻辑、比较运算符
逻辑运算符
- 逻辑 与 &&
- 逻辑 或 ||
- 逻辑非 !
比较运算符
运算符 | 含义 |
---|---|
>(gt) | 大于号,推荐使用gt |
<(lt) | 小于号,推荐使用gt |
>=(gte) | 大于等于,推荐使用glt |
<=(lte) | 小于等于,推荐使用lte |
== | 等于 |
!= | 不等于 |
空值运算符(针对为赋值的变量,和Java不同的是freeMarker没有null值)
- ??: 判断是否为空
- 这将检查对象的属性是否不为null:
<#if object.attribute??></#if>
- 这将检查对象的属性是否不为null:
<#if {object.attribute}??></#if>
- 这将检查对象的属性是否不为null:
- !: 指定缺失变量的默认值,如果不指定则默认值是空字符串、长度为0的序列或者长度为0的Map对象。
表达式 | 含义 |
---|---|
${aaa!} | 如果aaa变量没定义,不报错,默认没有任何输出 |
${aaa!’-’} | 如果aaa变量没定义,为空的话,就默认设置该表达式的值为横杠,这里不会为aaa变量赋值 |
${(user.name)}!“默认值” | 如果user或name为null,就输出默认值 |
$ {user.name!“默认值”} | 如果user为null会报错,如果name为null,就输出默认值 |
模板中的代码片段
- ${…}:
- FreeMarker将会输出真实的值来替换大括号内的表达式,这样的表达式被称为
inerpolation(插值),FreeMarker中的运算也是在该大括号中进行;
- FreeMarker将会输出真实的值来替换大括号内的表达式,这样的表达式被称为
- 注释:
- 注释和HTML的注释也很相似,但是它们使用<#–and–>来标识。不像HTML注释那样,FTL注释不会出现在输出中〈不出现在访问者的页面中),因为FreeMarker会跳过它们。
- FTL标签(FreeMarker Template Language):
- FTL标签和HTML标签有一些相似之处,但是它们是FreeMarker的指令,是不会在输出中打印的。这些标签的名字以#开头。(用户自定义的FTL标签则需要使用@来代替#)
基本指令 (常用,所有见上文官方文档)
if - elseif -else指令
<#if 条件1>
输出
<#else 条件2>
输出
<#else>
输出
</#if>
switch指令
<#switch var>
<#case 条件1>
输出
<#break>
<#case 条件2>
输出
<#break>
<#default>
输出
</#switch>
三、页面静态化
静态网页
- 静态网页的内容稳定,页面加载速度快
- 静态网页的没有数据库支持,在网站制作和维护方面的工作量较大。
- 静态网页的交互性差,有很大的局限性。
动态网页
- 交互性好。
- 动态网页的信息都需要从数据库中读取,每打开一个页面就需要去获取一次数据库,如果访问人数很多,也就会对服务器增加很大的荷载,从而影响这个网站的运行速度
页面静态化适用场景
- 高并发、要求用户响应速度快
- 适用于大规模且数据变化不太频繁的页面
示例
依赖
https://mvnrepository.com/artifact/org.freemarker/freemarker
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
文件结构
在resource目录下构建一个template的目录,在template目录下构建一个welcome的ftl文件并且书写间的模板内容。
书写加载ftl并且转换其他文件的类
转HTML
public class FreeMarker2Html {
step1、设置模板文件的存放位置以及生成文件的存放位置
private static final String TEMPLATE_PATH="src/main/resources/templates";
private static final String CLASS_PATH="src/main/resources/templates";
public static void main(String[] args) throws IOException, TemplateException {
step2、构建FreeMarker的实例对象,并且设置编码格式和指定模板路径
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
configuration.setDefaultEncoding("utf-8");
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
step3、创建数据模型
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("name","张三");
step4、加载模板文件
Template template = configuration.getTemplate("welcome.ftl");
step5、构建输出对象
File docFile = new File(CLASS_PATH + "\\" + "welcome.html");
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
step6、输出文件
template.process(dataMap,writer);
System.out.println("文件创建成功");
step7、关流
writer.close();
}
}
转JAVA
public class FreeMarker2Java {
step1、设置模板文件的存放位置以及生成文件的存放位置
private static final String TEMPLATE_PATH="src/main/resources/templates";
private static final String CLASS_PATH="src/main/java/javatemplates";
public static void main(String[] args) throws IOException, TemplateException {
step2、构建FreeMarker的实例对象,并且设置编码格式和指定模板路径
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
configuration.setDefaultEncoding("utf-8");
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
step3、创建数据模型
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("classPath","javatemplates");
dataMap.put("className","HelloFreeMarker");
dataMap.put("helloWorld","这是通过FreeMarker自动生成的代码!");
step4、加载模板文件
Template template = configuration.getTemplate("hello.ftl");
step5、构建输出对象
File docFile = new File(CLASS_PATH + "\\" + "HelloFreeMarker.java");
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
step6、输出文件
template.process(dataMap,writer);
System.out.println("文件创建成功");
step7、关流
writer.close();
}
}
四、List指令
语法
语法一:
<#list sequence as item> sequence:需要迭代的数据变量名 item:迭代项的变量名
Part repeated for each item
<#else> else:可选,代表如果没有迭代数据的话,就展示else的内容
Part executed when there are 0 items
</#list>
语法二:
<#list sequence>
Part executed once if we have more than 0 items
<#items as item>
Part repeated for each item
</#items>
Part executed once if we have more than 0 items
<#else>
Part executed once there are 0 items
</#list>
当你想在List指令里面使用列表、表格等标签时,若不嵌套items指令,当数据没内容,则会输出空列表,所以我们使用items来避免出现空列表和空表格在HTML页面上。
五、内建函数
概念
所谓内建函数,就是由语法规定存在的函数。这些函数,包含在编译器的运行时库中,程序员不必单独书写代码实现它,只需要调用既可,他们的实现,由该编译器对应的厂商完成。简单的说,就是不需要引入任何外部资源就可以使用的函数。
共同点:
- 都是书写在"?"号后面
- 都能实现某个功能(函数)
内建函数见上文官方文档链接。
六、在Web项目中的使用
配置
application.properties
spring.freemarker.suffix=.ftl
Thymeleaf
一、简介
Thymeleaf是面向Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Thymeleaf旨在提供一个优雅的、高度可维护的创建模板的方式。为了实现这一目标,Thymeleaf建立在自然模板的概念上,将其逻辑注入到模板文件中,不会影响模板设计原型。这改善了设计的沟通,弥合了设计和开发团队之间的差距。Thymeleaf从设计之初就遵循web标准一一特别是HTML5标准,如果需要,Thymeleaf允许您创建完全符合HTML5验证标准的模板。
SpringBoot体系内推荐使用Thymeleaf作为前端页面模板,并且SpringBoot2.0中默认使用ThymeIeaf3.0,性能提升幅度很大。
二、特点
- Thymeleaf在不管是否连接服务器的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。
- Thymeleaf开箱即用的特性。它支持标准方言和Spring方言,可以直接套用模板实现JSTLS、OGNL表达式效果,避免每天套模板、改JSTL、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言
- Thymeleaf提供Spring标准方言和一个与SpringMVC完美集成的可选模块,可以快速地实现表单绑定、属性编辑器、国际化等功能
三、基本语法
th属性
文本属性
文本属性 | 例子 |
---|---|
文本拼接 | / |
文本信息 | th:text, th:id, th:value… |
文本信息(可以解析html标记) | th:utext |
条件属性
条件属性 | 例子 |
---|---|
if判断 | th:if |
unless判断 | th:unless |
switch判断 | th:switch…th:case |
循环属性
循环属性 | 例子 |
---|---|
th:each | 迭代list |
th:each | 内置属性 |
th:each | 迭代map |
表达式语法
${...}
变量表达式
也叫OGNL表达式或者Spring EL表达式,用于调用各种属性和方法
- 可以获取对象的属性和方法
- 可以使用ctx,vars,local,request,response,session,servletContext内置对象
- 可以使用dates,numbers,strings,Objects,arrays,lists,sets,maps等内置方法。
@{...}
链接表达式
不管是静态资源的引用,form表单的请求,凡是链接都可以用@{...}
功能 | 表达式 |
---|---|
无参 | @{/xxx} |
有参 | @{/xxx(k1=v1,k2=v2)},对应url结构:xxx?k1&k2=v2 |
引入本地资源 | @{/项目本地的资源路径} |
引入外部资源 | @{/webjars/资源在jar包中的路径} |
#{...}
消息表达式
用于从消息源中提取消息内容实现国际化
- 语法和变量表达式相比多了个获取参数的方式;
- 消息源主要是properties文件
~{...}
代码块表达式
把某一段定义好的代码块插入到另外一个页面中,一般用于定义出一套通用的header或者footer
- 语法
~{templatename::fragmentname}
或者~{templatename::#id{}
,如果省略templatename,它将在当前页面进行寻找指定的代码块,注意:~{}
可以省略- templatename: 模板名,定义模板的写法:
<footer th:fragment="copy">
- fragmentname: 片段名,引入模板的写法:
<div th:insert="comm/foot::copy">
- id: HTML的id选择器,使用时要在前面加上#号,不支持class选择器
- templatename: 模板名,定义模板的写法:
- 代码块表达式需要配合th属性(th:insert,th:replace,th:include)一起使用。
- th:insert: 将代码块片段整个插入到使用了th:insert的HTML标签中。
- th:replace: 将代码块片段整个替换使用了th:replace的HTML标签中。
- th:include:将代码块片段包含的内容插入到使用了th:include的HTML标签中。
*{...}
选择表达式
是另一种类似${...}
,在某些时候,两者是等价的,选择变量表达式在执行时在选择的对象上求解(使用th:object来选择对象),而${...}
是在上下文的变量Map上求解。
表达式支持的语法
字面
字面 | 举例 |
---|---|
文本文字 | ‘one text’, ‘Another one!’ |
数字文字 | 0,34,3.0,12.3 |
布尔文字 | true,false |
空字面 | null |
文字操作
文字操作 | 举例 |
---|---|
字符串连接 | + |
文字替代 | |The name is ${name}| |
算术操作
算术操作 | 举例 |
---|---|
运算符 | +,-,*,/,% |
布尔运算
布尔运算 | 举例 |
---|---|
二元运算符 | and,or |
布尔否定(一元运算符) | !, not |
比较和相等
比较和相等 | 举例 |
---|---|
比较 | >,<,>=,<= (gt,lt,ge,le) |
相等判断 | ==,!=,(eq,ne) |
条件运算符
比较和相等 | 举例 |
---|---|
IF-THEN | (if)?(then) |
IF-THEN-ELSE | (if)?(then):(else) |
默认 | (value)?:(defaultvalue) |
基础对象(内置对象)
基础对象 | 含义 |
---|---|
#ctx | 上下文对象 |
#vars | 上下文对象(和#ctx相同,但是一般用#ctx) |
#local | 区域对象 |
↑ | 以上三个用来获取上下文对象 |
#request | (仅Web环境可用)HttpServletRequest对象 |
#response | (仅Web环境可用)HttpServletResponse 对象 |
#session | (仅Web环境可用)HttpSession对象 |
#servletContext | (仅Web环境可用)ServletContext 对象 |
↑ | 以上四个与JSP的内置对象的一样的使用方法 |
param | 获取请求的参数 |
session | 访问session属性 |
application | 获取应用程序/servlet上下文属性 |
注意:以上三个不带#的对象,都用拥有以下方法:size(),isEmpty(),containsKey(), .key
常用工具类
常用工具类 | 含义 |
---|---|
#strings | 字符串工具类 |
#lists | List工具类 |
#arrays | 数组工具类 |
#sets | Set工具类 |
#maps | 常用Map方法 |
#objects | 一般对象类,通常用来判断非空 |
#bools | 常用的布尔方法 |
#execInfo | 获取页面模板的处理信息 |
#messages | 在变量表达式中获取外部消息的方法,与使用#{...} 语法获取的方法相同 |
#uris | 转义部分URL/URL的方法 |
#conversions | 用于执行已配置的转换服务的方法 |
#dates | 时间操作和时间格式化等 |
#calendars | 用于更复杂时间的格式化 |
#numbers | 格式化数字对象的方法 |
#aggregates | 在数组或集合上创建聚合的方法 |
#ids | 处理可能重复的id属性的方法 |
内联标签
**含义:**可以不使用变量表达式,也能获取后端的信息
body内的内联
- 习惯:
- 更合适
<p>Hello,[[${session.user.name}]]</p>
- 而不是
<p>Hello,<span th:text="${session.user.name}">Sebastian</span>!</p>
- 更合适
- th属性和内联标签的对应关系:
- [[…]]等价于th:text(结果将被HTML转义)
- [(…)]等价于th:utext(结果不会执行HTML转义)。
js里的内联
- 在JavaScript中使用内联标签(默认不支持)
- 在script标签上引入对内联的支持:
<script tpye=”text/Javascript“ th:inline="javascript">
- 在script标签里书写[[]]、[()]来获取后端数据;
- 在script标签上引入对内联的支持:
- 在JavaScript中实现前后端分离(也称之为JavaScript自然模板)·
- Thymeleaf的目标就是希望前后端分离,即同一个Html文件前端人员以静态原型的方式打开时,看到的是它们的内容,而后端人员通过服务器打开时,看到的是动态的数据;
- 直接在数据上使用js注释即可实现前后端分离:
var msg = /*[[${name}]]*/'666666'
; - 当在服务器打开该页面时,就会展示${name}的值,当时在静态打开时,就展示666666
- 在JavaScript中自动进行象序列化:
- JavaScript内联的一个重要的特性是,内联表达式的计算结果不限于字符串,它能自动的将后台的数据序列化为javascript对象
**注:**js中开启内联标签模式只能是在Html文件内部的JavaScript代码,不能在引入的外部JavaScript文件中进行操作;
css里的内联
- 在CSS中使用内联标签(默认不支持):
- 在sty[e标签上引入对内联的支持:
<styleth:inline="css">
- 在sty[e标签里书写[[]]、[0]来获取后端数据;
- 在sty[e标签上引入对内联的支持:
- 在CSS中实现前后端分离(也称之为CSS自然模板):
- 与内联JavaScript一样,CSS内也允许
<style>
标签可以静态和动态地工作,即通过在注释中包含内联表达式作为CSS自然模板。 - 当服务器动态打开时,字体颜色为黄色;当以原型静态打开时,显示的是红色,因为Thymeleaf会自动忽略掉css注释之后和分号之前的代码。
在CSS中,因为CSS自然模板的问题,所以不能在css中像以前一样添加注释,因为Thymeleaf会将它们当做模板进行处理。
**注:**与内联JavaScript一样,内联CSS样只能Html内嵌的<style>
标签中进行使用,不能在外部关联的CSS文件中进行使用。
- 与内联JavaScript一样,CSS内也允许
四、快速入门
依赖与配置
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
application.properties
清除缓存的保存
spring.thymeleaf.cache=false
了解默认配置规则
在ThymeleafProperties类中
前缀为classpath:/template/
后缀为.html
在HTML中添加Thymeleaf的支持
<html lang="en" xmlns:th="http://www.thymeleaf.org">
示例
@Controller
public class BaseObjectController {
@RequestMapping("/base")
public String hello(ModelMap modelMap, HttpServletRequest request, HttpSession session){
modelMap.put("a",123);
modelMap.put("b","123");
request.setAttribute("request","333");
session.setAttribute("session","444");
return "base";
}
}
以下省略@Controller、public class 类名 以及 @RequestMapping
public String hello(ModelMap modelMap){
modelMap.put("msg","这是动态的数据");
return "hello";
}
public String hello(ModelMap modelMap){
modelMap.put("flag","yes");
modelMap.put("baidu","http://www.baidu.com");
modelMap.put("taobao","http://www.baidu.com");
modelMap.put("age",19);
return "if";
}
public String hello(ModelMap modelMap){
modelMap.put("name","张三");
modelMap.put("user",new User("李四",19,"123123"));
modelMap.put("flag",true);
ArrayList<User> users = new ArrayList<>();
Collections.addAll(users,new User("李四",19,"123123"),
new User("王五",29,"111111"),
new User("赵六",39,"222222"));
modelMap.put("list",users);
return "inner";
}
public String hello(ModelMap modelMap){
modelMap.put("id","这是id");
modelMap.put("value","这是value");
modelMap.put("utext","这是utext里面的内容<b>这里加粗了</b>");
modelMap.put("text","这是utext里面的内容<b>这里加粗了</b>");
return "text";
}
base
<h1>ctx上下文对象</h1>
<p th:text="${#ctx}"></p>
<h1>获取ctx中保存在map里的数据</h1>
<p th:text="${#ctx.getVariable('a')}"></p>
<h1>vars上下文对象</h1>
<p th:text="${#vars}"></p>
<h1>获取local区域对象</h1>
<p th:text="${#locale}"></p>
<p th:text="${#locale.country}"></p>
<h1>param的使用</h1>
<p th:text="|size:${param.size()},a:${param.a}|"> </p>
<h1>两个session的使用</h1>
<p th:text="${#session.getAttribute('session')}"> </p>
<p th:text="${session.session}"> </p>
hello
<p th:text="${msg}">这是静态段落文字</p>
if
<a th:if="${flag eq 'yes'}" th:href="@{${baidu}}">baidu1</a>
<a th:if="${flag eq 'yes'}" th:href="@{{baidusite}(baidusite=${baidu})}">baidu2</a>
<a th:unless="${flag eq 'no'}" th:href="@{${baidu}}">baidu3</a>
<div th:switch="${age}">
<p th:case="18">18岁</p>
<p th:case="19">19岁</p>
<p th:case="20">20岁</p>
<p th:case="*">未知岁数</p>
</div>
inner
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css" th:inline="css" th:with="color='yellow',
fontSize='25px'">
p{
color:/*[[${color}]]*/red;
font-size: [(${fontSize})];
}
</style>
<script th:inline="javascript">
/*var name = [[${name}]];
var userName = [[${user.name}]];
var userAge = [[${user.age}]];
var userPass = [[${user.pass}]];
alert("name:" + name + ",userName:" + userName+",userAge:"
+userAge+",userPass:"+userPass);*/
//静态动态分离技术
var msg = /*[[${name}]]*/'666666';
// alert(msg)
// js内联标签的序列化演示
var name = [[${name}]];
var user = [[${user}]];
var userAge = [[${user.age}]];
var flag = [[${flag}]];
var list = [[${list}]];
// alert("name:"+typeof name);
// alert("user:"+typeof user);
// alert("userAge"+typeof userAge);
// alert("flag"+typeof flag);
// alert("list"+list);
</script>
</head>
<body>
<p th:text="${msg}">这是静态段落文字</p>
<p>Hello China!!</p>
</body>
text
<body th:inline="none">
<p th:text="|welcome to china, ${text}|">这是静态段落文字</p>
<p th:text="'welcome to china,'+${text}">这是静态段落文字</p>
<input th:value="${value}" th:id="${id}">
<br>
<p th:text="${text}"></p>
<p th:utext="${utext}"></p>
<p>[[|welcome to china, ${text}|]]</p>
<p>[('welcome to china,' + ${text})]</p>
<p>[('welcome to china,' + ${text})]</p>
</body>