发布于2021-06-12 14:45 阅读(697) 评论(0) 点赞(4) 收藏(5)
引用百度百科的模板引擎解释:
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
在JavaEE领域有几中比较常用的模板引擎,分别是Jsp、Velocity、Freemarker、Thymeleaf,不过对于前端页面渲染效率来说,jsp其实还是最快的,Velocity次之。Thymeleaf虽然渲染效率不是很快,但是语法方面是比较轻巧的,Thymeleaf语法比Velocity轻巧,但是渲染效率不如Velocity
Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。具体参考Thymeleaf官网
官网提供了在线文档也有文件格式的各种文档
Thymeleaf适用于如下模板:
有两种标记模板模式(HTML 和 XML)、三种文本模板模式(TEXT、JAVASCRIPT 和 CSS)和一种无操作模板模式 (RAW)。
ok,下面给出一些比较重要的知识点
这是很常用的text标签,作用是Thymeleaf中设置文本的标签,分为两种,一种是th:text,另外一种是th:utext,两种最重要的区别就是会不会对特殊字符进行转义
注意:这里的特殊字符主要指html标签,/n、/t、etc.这些字符是不支持的
写个例子对比一下:
-
<span th:text="${'Welcome to our <b>fantastic</b> grocery store!'}">
</span>
<br/>
-
<span th:utext="${'Welcome to our <b>fantastic</b> grocery store!'}">
</span>
官方文档里有standard Expression Syntax这个章节,介绍的就是标准的表达式语法应用
-
<link th:href="@{/static/css/public.css}" rel="stylesheet" type="text/css" />
-
<link th:href="@{/static/css/index.css}" rel="stylesheet" type="text/css" />
-
<script type="text/javascript" th:src="@{/static/js/jquery-1.3.2.min.js}">
</script>
-
<script type="text/javascript" th:src="@{/static/js/html5.js}">
</script>
-
<script type="text/javascript" th:src="@{/static/js/popbox.js}">
</script>
* Fragment Expressions: ~{...} //片段引用的表达式 eg: `<div th:insert="~{commons :: main}">....</div>`
@{url/}+${id}
${name}
变量值No-Operation: _
All these features can be combined and neste:
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
翻译过来意思是,这些语法都可以组合使用,这个章节是Thymeleaf一个重要的基本使用章节,本博客对一些重要的知识点进行摘录同时介绍一下在SpringBoot里如何使用,当然自然没有官方文档详细的,不过官方并没有通过中文文档,英文水平不好的话,阅读起来比较困难,当然我也找了一篇国内翻译过来的Thymeleaf中文文档,读者详细的可以参考文档
遍历是Thymeleaf很常用的例子,支持的属性值有:
下面还是给下例子,比较容易理解,如下代码使用th:each,th:each="item : ${items}"
-
<!--最新上架-->
-
<div class="first-pannel clearfix">
-
<div class="index-f clearfix">
-
<h3 class="index-f-head"> 最新上架
<span>每天都有上新,每天都有惊喜
</span>
</h3>
-
<div class="index-f-body">
-
<div class="top-sales newProduct">
-
<ul class="top-sales-list clearfix">
-
<li class="top-sales-item newProduct" th:each="item : ${items}">
-
<p class="item-img">
<a th:href="@{'/portal/item/toDetail/'+${item.spuId}+'/'+${item.skuId}}">
<img th:src="@{${item.imgPath}}" />
</a>
</p>
-
<p class="item-buss">
<a th:href="@{'/portal/item/toDetail/'+${item.spuId}+'/'+${item.skuId}}">
</a>
</p>
-
<p class="item-name spec">
<a th:href="@{'/portal/item/toDetail/'+${item.spuId}+'/'+${item.skuId}}" th:text="${item.itemName}">
</a>
</p>
-
<p class="item-price spec">
<em th:text="${item.mPrice}">
</em>元
</p>
-
</li>
-
</ul>
-
</div>
-
</div>
-
</div>
-
</div>
-
<!--最新上架//-->
在项目开发中经常遇到一些可以重用的页面,这时候就可以Thymeleaf的Template Layout进行公共页面的复用
本博客以官方介绍的复用footer.html页面进行说明
使用步骤:
-
<!DOCTYPE html>
-
-
<html xmlns:th="http://www.thymeleaf.org">
-
-
<body>
-
-
<div th:fragment="copy">
-
© 2011 The Good Thymes Virtual Grocery
-
</div>
-
-
</body>
-
-
</html>
<div th:insert="~{footer :: copy}"></div>
-
<div th:insert="footer :: copy">
</div>
-
<div th:replace="footer :: copy">
</div>
-
<div th:include="footer :: copy">
</div
三种引入公共片段的th属性:
效果对比:
-
<div>
-
<footer>
-
© 2011 The Good Thymes Virtual Grocery
-
</footer>
-
</div>
-
<footer>
-
© 2011 The Good Thymes Virtual Grocery
-
</footer>
-
<div>
-
© 2011 The Good Thymes Virtual Grocery
-
</div
所谓行内写法就是没写在html对应的标签里的写法,直接在页面空白处,用[[....]]或者[(....)]的写法,然后[[....]]和[(....)]的区别其实就等同于th:text和th:utext的区别,一个会进行转义,一个不会转义特殊字符
-
<span>
-
The message is
[[${msg}]]
-
</span>
-
<br/>
-
<span>
-
The message is
[(${msg})]
-
</span>
引用尚桂谷老师的归纳:
maven配置
因为引入了SpringBoot的parent工程,所以不需要写版本号
-
<!-- Themeleaf -->
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-thymeleaf
</artifactId>
-
</dependency>
application.yml配置
注意:这里的属性大部分都可以不配置的,因为Springboot的自动配置因为做了很多自动配置,我们不配置,就使用默认的,不过下面的例子只是给读者了解一下有这些配置
-
#添加Thymeleaf配置,除了cache在项目没上线前建议关了,其它配置都可以不用配的,本博客只是列举一下有这些配置
-
thymeleaf:
-
# cache默认开启的,这里可以关了,项目上线之前,项目上线后可以开启
-
cache:
false
-
# 这个prefix可以注释,因为默认就是templates的,您可以改成其它的自定义路径
-
prefix:
classpath:/templates/
-
suffix:
.html
-
mode:
HTML5
-
# 指定一下编码为utf8
-
encoding:
UTF-8
-
# context-type为text/html,也可以不指定,因为boot可以自动识别
-
content-type:
text/html
ok,Springboot中Thymeleaf使用非常简单,因为Springboot已经为我们做了很多自动配置,其实,yaml都不需要配置的,直接引入对应的jar,然后就可以直接使用,在resources资源文件夹下面新建一个templates文件夹,所有的html文件都丢在这里,静态资源文件也丢在resources资源文件夹下面
新建一个html文件,然后注意加上<html xmlns:th="http://www.thymeleaf.org">
注意Thymeleaf语法要求比较严格 <meta charset="utf-8" >
,不如这样写是不可以的,必须加上斜杠的,<meta charset="utf-8" />
-
<!DOCTYPE html>
-
<html lang="en" xmlns:th="http://www.thymeleaf.org">
-
<head>
-
<meta charset="UTF-8">
-
<title>Title
</title>
-
</head>
-
<body>
-
-
<div>
-
<span th:text="${'Welcome to our <b>fantastic</b> grocery store!'}">
</span>
<br/>
-
<span th:utext="${'Welcome to our <b>fantastic</b> grocery store!'}">
</span>
-
</div>
-
-
-
<span>
-
The message is [[${msg}]]
-
</span>
-
<br/>
-
<span>
-
The message is [(${msg})]
-
</span>
-
</body>
-
</html>
ok,然后为什么我说直接引入对应pom配置就可以直接使用了?因为Springboot已经为项目做了很多自动配置,所以本博客简单跟一下源码,了解一下SpringbootThymeleaf的自动配置
SpringBoot的自动配置类在ThymeleafAutoConfiguration里
-
-
package org.springframework.boot.autoconfigure.thymeleaf;
-
....
-
-
@Configuration(proxyBeanMethods = false)
//定义这是一个配置类
-
@EnableConfigurationProperties(ThymeleafProperties.class)
//使用ThymeleafProperties属性类的属性
-
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
//指定TemplateMode、SpringTemplateEngine(模板引擎类)起效的情况,整个配置类才起作用
-
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
//必须在WebMvcAutoConfiguration(SpringMVC自动配置类,这个配置类会加载组装所有的视图解析器)、WebFluxAutoConfiguration类起效后,这个Thymeleaf自动配置类才起效
-
public
class ThymeleafAutoConfiguration {
-
-
//没有自定义的模板解析器类的情况,使用默认的模板解析器
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnMissingBean(name = "defaultTemplateResolver")
-
static
class DefaultTemplateResolverConfiguration {
-
-
private
static
final Log logger = LogFactory.getLog(DefaultTemplateResolverConfiguration.class);
-
//Thymeleaf的properties配置
-
private
final ThymeleafProperties properties;
-
-
private
final ApplicationContext applicationContext;
-
-
DefaultTemplateResolverConfiguration(ThymeleafProperties properties, ApplicationContext applicationContext) {
-
this.properties = properties;
-
this.applicationContext = applicationContext;
-
}
-
//用PostConstruct注解,在依赖注入完成之后,实现类的初始化配置,这个方法主要是检查模板引擎的资源文件路径是否有
-
@PostConstruct
-
void checkTemplateLocationExists() {
-
boolean checkTemplateLocation =
this.properties.isCheckTemplateLocation();
-
if (checkTemplateLocation) {
-
TemplateLocation location =
new TemplateLocation(
this.properties.getPrefix());
-
if (!location.exists(
this.applicationContext)) {
-
logger.warn(
"Cannot find template location: " + location +
" (please add some templates or check "
-
+
"your Thymeleaf configuration)");
-
}
-
}
-
}
-
//默认的Thymeleaf资源解析器
-
@Bean
-
SpringResourceTemplateResolver defaultTemplateResolver() {
-
SpringResourceTemplateResolver resolver =
new SpringResourceTemplateResolver();
-
//资源解析器的所有配置
-
resolver.setApplicationContext(
this.applicationContext);
-
resolver.setPrefix(
this.properties.getPrefix());
-
resolver.setSuffix(
this.properties.getSuffix());
-
resolver.setTemplateMode(
this.properties.getMode());
-
if (
this.properties.getEncoding() !=
null) {
-
resolver.setCharacterEncoding(
this.properties.getEncoding().name());
-
}
-
resolver.setCacheable(
this.properties.isCache());
-
Integer order =
this.properties.getTemplateResolverOrder();
-
if (order !=
null) {
-
resolver.setOrder(order);
-
}
-
resolver.setCheckExistence(
this.properties.isCheckTemplate());
-
return resolver;
-
}
-
-
}
-
//又是Thymeleaf的自动配置,自动配置模板引擎SpringTemplateEngine
-
@Configuration(proxyBeanMethods = false)
-
protected
static
class ThymeleafDefaultConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean(ISpringTemplateEngine.class)
-
SpringTemplateEngine templateEngine(ThymeleafProperties properties,
-
ObjectProvider<ITemplateResolver> templateResolvers, ObjectProvider<IDialect> dialects) {
-
SpringTemplateEngine engine =
new SpringTemplateEngine();
-
engine.setEnableSpringELCompiler(properties.isEnableSpringElCompiler());
-
engine.setRenderHiddenMarkersBeforeCheckboxes(properties.isRenderHiddenMarkersBeforeCheckboxes());
-
templateResolvers.orderedStream().forEach(engine::addTemplateResolver);
-
dialects.orderedStream().forEach(engine::addDialect);
-
return engine;
-
}
-
-
}
-
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnWebApplication(type = Type.SERVLET)
-
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
-
static
class ThymeleafWebMvcConfiguration {
-
-
@Bean
-
@ConditionalOnEnabledResourceChain
-
@ConditionalOnMissingFilterBean(ResourceUrlEncodingFilter.class)
-
FilterRegistrationBean<ResourceUrlEncodingFilter> resourceUrlEncodingFilter() {
-
FilterRegistrationBean<ResourceUrlEncodingFilter> registration =
new FilterRegistrationBean<>(
-
new ResourceUrlEncodingFilter());
-
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
-
return registration;
-
}
-
//比较重要的视图解析器配置
-
@Configuration(proxyBeanMethods = false)
-
static
class ThymeleafViewResolverConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean(name = "thymeleafViewResolver")
-
ThymeleafViewResolver thymeleafViewResolver(ThymeleafProperties properties,
-
SpringTemplateEngine templateEngine) {
-
ThymeleafViewResolver resolver =
new ThymeleafViewResolver();
-
//设置模板引擎
-
resolver.setTemplateEngine(templateEngine);
-
//字符编码设置
-
resolver.setCharacterEncoding(properties.getEncoding().name());
-
resolver.setContentType(
-
appendCharset(properties.getServlet().getContentType(), resolver.getCharacterEncoding()));
-
resolver.setProducePartialOutputWhileProcessing(
-
properties.getServlet().isProducePartialOutputWhileProcessing());
-
resolver.setExcludedViewNames(properties.getExcludedViewNames());
-
resolver.setViewNames(properties.getViewNames());
-
// This resolver acts as a fallback resolver (e.g. like a
-
// InternalResourceViewResolver) so it needs to have low precedence
-
resolver.setOrder(Ordered.LOWEST_PRECEDENCE -
5);
-
//Thymeleaf缓存
-
resolver.setCache(properties.isCache());
-
return resolver;
-
}
-
-
private String appendCharset(MimeType type, String charset) {
-
if (type.getCharset() !=
null) {
-
return type.toString();
-
}
-
LinkedHashMap<String, String> parameters =
new LinkedHashMap<>();
-
parameters.put(
"charset", charset);
-
parameters.putAll(type.getParameters());
-
return
new MimeType(type, parameters).toString();
-
}
-
-
}
-
-
}
-
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnWebApplication(type = Type.REACTIVE)
-
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
-
static
class ThymeleafReactiveConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean(ISpringWebFluxTemplateEngine.class)
-
SpringWebFluxTemplateEngine templateEngine(ThymeleafProperties properties,
-
ObjectProvider<ITemplateResolver> templateResolvers, ObjectProvider<IDialect> dialects) {
-
SpringWebFluxTemplateEngine engine =
new SpringWebFluxTemplateEngine();
-
engine.setEnableSpringELCompiler(properties.isEnableSpringElCompiler());
-
engine.setRenderHiddenMarkersBeforeCheckboxes(properties.isRenderHiddenMarkersBeforeCheckboxes());
-
templateResolvers.orderedStream().forEach(engine::addTemplateResolver);
-
dialects.orderedStream().forEach(engine::addDialect);
-
return engine;
-
}
-
-
}
-
//ThymeleafWebFluxConfiguration自动配置
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnWebApplication(type = Type.REACTIVE)
-
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
-
static
class ThymeleafWebFluxConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean(name = "thymeleafReactiveViewResolver")
-
ThymeleafReactiveViewResolver thymeleafViewResolver(ISpringWebFluxTemplateEngine templateEngine,
-
ThymeleafProperties properties) {
-
ThymeleafReactiveViewResolver resolver =
new ThymeleafReactiveViewResolver();
-
resolver.setTemplateEngine(templateEngine);
-
mapProperties(properties, resolver);
-
mapReactiveProperties(properties.getReactive(), resolver);
-
// This resolver acts as a fallback resolver (e.g. like a
-
// InternalResourceViewResolver) so it needs to have low precedence
-
resolver.setOrder(Ordered.LOWEST_PRECEDENCE -
5);
-
return resolver;
-
}
-
-
private void mapProperties(ThymeleafProperties properties, ThymeleafReactiveViewResolver resolver) {
-
PropertyMapper map = PropertyMapper.get();
-
map.from(properties::getEncoding).to(resolver::setDefaultCharset);
-
resolver.setExcludedViewNames(properties.getExcludedViewNames());
-
resolver.setViewNames(properties.getViewNames());
-
}
-
-
private void mapReactiveProperties(Reactive properties, ThymeleafReactiveViewResolver resolver) {
-
PropertyMapper map = PropertyMapper.get();
-
map.from(properties::getMediaTypes).whenNonNull().to(resolver::setSupportedMediaTypes);
-
map.from(properties::getMaxChunkSize).asInt(DataSize::toBytes).when((size) -> size >
0)
-
.to(resolver::setResponseMaxChunkSizeBytes);
-
map.from(properties::getFullModeViewNames).to(resolver::setFullModeViewNames);
-
map.from(properties::getChunkedModeViewNames).to(resolver::setChunkedModeViewNames);
-
}
-
-
}
-
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnClass(LayoutDialect.class)
-
static
class ThymeleafWebLayoutConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean
-
LayoutDialect layoutDialect() {
-
return
new LayoutDialect();
-
}
-
-
}
-
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnClass(DataAttributeDialect.class)
-
static
class DataAttributeDialectConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean
-
DataAttributeDialect dialect() {
-
return
new DataAttributeDialect();
-
}
-
-
}
-
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnClass({ SpringSecurityDialect.class })
-
static
class ThymeleafSecurityDialectConfiguration {
-
-
@Bean
-
@ConditionalOnMissingBean
-
SpringSecurityDialect securityDialect() {
-
return
new SpringSecurityDialect();
-
}
-
-
}
-
-
@Configuration(proxyBeanMethods = false)
-
@ConditionalOnClass(Java8TimeDialect.class)
-
static
class ThymeleafJava8TimeDialect {
-
-
@Bean
-
@ConditionalOnMissingBean
-
Java8TimeDialect java8TimeDialect() {
-
return
new Java8TimeDialect();
-
}
-
-
}
-
-
}
ThymeleafProperties是SpringBoot的属性配置类,使用ConfigurationProperties注解进行属性映射
-
@ConfigurationProperties(prefix =
"spring.thymeleaf")
-
public
class ThymeleafProperties {
-
-
private
static
final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
-
//默认的模板资源路径
-
public
static
final
String DEFAULT_PREFIX =
"classpath:/templates/";
-
//默认解析html资源
-
public
static
final
String DEFAULT_SUFFIX =
".html";
-
-
/**
-
* Whether to check that the template exists before rendering it.
-
*/
-
private
boolean checkTemplate =
true;
-
-
/**
-
* Whether to check that the templates location exists.
-
*/
-
private
boolean checkTemplateLocation =
true;
-
-
/**
-
* Prefix that gets prepended to view names when building a URL.
-
*/
-
private
String prefix = DEFAULT_PREFIX;
-
-
/**
-
* Suffix that gets appended to view names when building a URL.
-
*/
-
private
String suffix = DEFAULT_SUFFIX;
-
-
/**
-
* Template mode to be applied to templates. See also Thymeleaf's TemplateMode enum.
-
*/
-
//默认模式也是html的
-
private
String mode =
"HTML";
-
-
/**
-
* Template files encoding.
-
*/
-
private Charset encoding = DEFAULT_ENCODING;
-
-
/**
-
* Whether to enable template caching.
-
*/
-
//默认开启缓存,项目没上线建议通过配置关闭,然后按F9就可以自动编译,避免影响调试
-
private
boolean cache =
true;
-
-
....
-
}
ok,然后简单跟一下视图解析器的源码:Thymeleaf视图解析器类的关键代码,创建视图view的方法,如图,也是根据viewname进行重定向
从上面方法可以看出进行重定向或者forward等等方法,然后调一下redirect的,看看RedirectView类,翻下源码,找到如下关键代码:
同样在这个类里,进行了状态码设置,请求头设置,然后response.sendRedirect(encodedURL);
而forward的是通过如图方法进行页面跳转:
原文链接:https://blog.csdn.net/xiao190128/article/details/117729343
作者:长这么胖
链接:http://www.javaheidong.com/blog/article/222311/e6cc50f3a6be320f786a/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!