Spring Boot 主要支持Thymeleaf、Freenrtarker、Mustache、Groovy Templates 等模板引擎。
Thymeleaf语法并不会破坏文档的结构,所以Thymeleaf模板依然是有效的HTML文档。模 板还可以被用作工作原型,Thymeleaf会在运行期内替换掉静态值。它的模板文件能直接在浏览器 中打开并正确显示页面,而不需要启动整个Web应用程序。
Thymeleaf解决了前端开发人员要和后端开发人员配置一样环境的尴尬和低效。它通过属性进 行模板渲染,不需要引入不能被浏览器识别的新的标签。页面直接作为HTML文件,用浏览器打开页面即可看到最终的效果,可以降低前后端人员的沟通成本。
要使用Thymeleaf,首先需要引入依赖。直接在pom.xml文件中加入以下依赖即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.7.RELEASE</version>
</dependency>
在模板文件中加入解析,在html文件中加入命名空间即可。
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
Spring Boot默认的页面映射路径(即模板文件存放的位置)为 "classpath: /templates/*.html" 。 静态文件路径为 "classpath:/static/",其中可以存放层叠样式表CSS( Cascading Style Sheets )、 JS (JavaScript)等模板共用的静态文件。在application.yml文件中,可以配置Thymeleaf模板解析器属性
spring:
thymeleaf:
mode: HTML5
encoding: UTF-8
servlet:
content-type: text/html
cache: false
spring.thymeleaf.mode:代表 Thymeleaf 模式。
spring.thymeleaf.encodmg:代表 Thymeleaf 编码格式。
thymeleaf.content-type:代表文档类型。
thymeleaf.cache:代表是否启用 Thymeleaf 的缓存。
要使用Thymeleaf,则需要先要加入依赖,然后在模板文件中引用命名空间,如下:
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
之后,会进行Thymeleaf模板标签的渲染。如果用Spring Security作为安全认证,且需要显示登录用户的信息,则可以先在视图中加入额外的thymeleaf-extras-springsecurity依赖
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity3</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
然后 在模板文件中加入thymeleaf-extras-springsecurity命名空间,具体见以下代码:
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/tyemeleaf-extras-springsecurity5">
<span sec:authorization="name"></span>
<span sec:authorize="hasRole('ROLE_ADMIN')">管理员</span>
<span sec:authorize="hasRole('ROLE_USER')">普通用户</span>
这里特别要注意查看 spring-boot—starter-thymeleaf 依赖和 thymeleaf-extras- springsecurity依赖的版本是否兼容。如果不兼容,则无法调用登录用户的信息。
(1)th:text
<div th:text="${name}">name</div>
它用于显示控制器传入的name值。
如果name不存在,要显示默认值,则使用以下代码:
<span th:text="${ame} ?:'默认值'"></span>
(2)th:object
它用于接收后台传过来的对象,如以下代码:
th:object="${user}"
(3)th:action
它用来指定表单提交地址。
<form th:action="@{/article/}+${article.id}" method="post"></form>
(4)th:value
它用对象将id的值替换为value的属性。
<input type="text" th:value="${article.id}" name="id"/>
(5)th:field
它用来绑定后台对象和表单数据。Thymeleaf里的"th:field"等同于"th:name"和"th: valued"其具体使用方法见以下代码:
<input type="text" id="title" name="title" th:field="${book.id}"/><input type="text" name="title" th:field="${fields}"/>
Thymeleaf是通过语法@{…}来处理URL的,需要使用"th:href"和"th:src"等属性,如以下代码
<a th:href="@{http://www.thymeleaf.org}">绝对路径</a>
<a th:href="@{/}">相对路径</a>
<a th:href="@{css/bootstrap.min.css}">默认访问static下的css文件夹</a>
Thymeleaf通过 "th:if" 和 "th:unless" 属性迸行条件判断。在下面的例子中,<a>标签只有 在 "th:if" 中的条件成立时才显示。
<a th:href="@{/login}" th:if="${session.user == null}">Login</a>
"th:unless" 与 "th:if" 恰好相反,只有当表达式中的条件不成立时才显示其内容。在下方代码中,如果用户session为空,则不显示登录(login )链接。
<a th:href="@{/login}" th:unless="${session.user == null}">Login</a>
<div th:switch="${book.getId()}">
<p th:case="ADMIN">管理员</p>
<p th:case="VIP">vip会员</p>
<p th:case="*">普通会员</p>
</div>
上述代码的意思是:如果用户角色(role)是admin,则显示“管理员”;如果用户角色是vip, 则显示"vip会员”;如果都不是,则显示“普通会员”,即使用“*”表示默认情况。
有时需要对文字中的某一处地方进行替换,可以通过字符串拼接操作完成,如以下代码:
<span th:text="'欢迎,'+${book.getUsername()}+'!'"></span>
或者:
<span th:text="|欢迎,${book.getUsername()}!|"></span>
上面的第2种形式限制比较多,|...|中只能包含变量表达式${...},不能包含其他常量、条件表达式等。
1.算数运算符。
如果要在模板中进行算数运算,则可以用下面的写法。以下代码表示求加和取余运算。
<span th:text="1+3"></span> <span th:text="9*3"></span>
2.条件运算符
下方代码演示了 if判断,表示:如果从控制器传来的role值等于“admin”,则显示 "欢迎您, 管理员";如果role值等于 "vip",则显示 "欢迎您,vip会员"
<div th:if="${book.getUsername()} eq admin">
<span>欢迎您,管理员</span>
</div>
<div th:if="${book.getUsername()} eq vip">
<span>欢迎您,vip</span>
</div>
eq是判断表达式,代表等于。其他的判断表达式如下。
gt:大于。
ge:大于或等于。
eq:等于。
It:小于。
le:小于或等于。
ne:不等于。
3.判断空值
可以使用if来判断值是否为空,如以下代码:
<span th:if="${book.getUsername()}==null">不为空</span>
<span th:if="${book.getUsername()}!=null">为空</span>
Thymeleaf还提供了一系列公用(utility)对象,可以通过"#"直接访问,如以下用法
格式化时间:
<td th:text="${#dates.format(data,'yyyy-MM-dd HH:mm:ss')}">格式化时间</td>
判断是不是空字符串:
<span th:if="${#strings.isEmpty(data)}">空</span>
是否包含(分大小写):
<span th:if="${#strings.contains(book.getUsername(),'admin')}">包含</span>
在开发过程中,经常会遇到遍历对象的情况,可以通过 th:each="Object:$(Objects}" 标签来处理。以下代码是遍历从控制器中传来的书籍对象。
<div th:each="book:${book}">
<li th:text="${book.getUsername()}">姓名</li>
<li th:text="${book.getPassword()}">密码</li>
</div>
分页也是极为常见的开发需求。在Thymeleaf中,可以通过 th:each="item : ${page.content}" 标签来处理page对象。如以下代码
<div th:each="item:${page.content}">
<li th:text="${item.id}">id</li>
<li th:text="${item.title}">title</li>
</div>
要处理list,也使用 th:each="item:${list}"标签来实现。
<div th:each="item:${list}">
<li th:text="${item.username}">id</li>
<li th:text="${item.password}">title</li>
</div>
使用 th:each="item:${arrays}"标签来遍历数组,如以下代码:
<div th:each="ArrayList:${ArrayList}">
<li th:text="${ArrayList}">id</li>
</div>
集合通过 th:text="${item.key}"显示集合的 key,通过 th:text="${item.value}" 显示集合的值,如以下代码:
<div th:each="map:${map}">
<li th:text="${map.key}"></li>
<li th:text="${map.value}"></li>
</div>
一个网页的结构基本可以分为上(header )、中(body )、下(footer)三个部分。在一般情况 下,header和footer的信息在各个页面都会重复显示,如果每个页面都复制一份代码则太麻烦了。设计Thymeleaf的团队也考虑到代码复用的问题,提供了 "th:fragment" "th:include" 和 "th:replace"标签用来处理重复的代码块。具体用法如下。
可以通过"th:fragment="header" 标签来标记重复代码块,如以下代码
<div class="footer" id="header" th:fragment="header">
公共header
</div>
<div class="footer" id="footer" th:fragment="footer">
公共footer
</div>
在需要调用的地方,用"th:include"或"th:replace"标签根据fragment值来调用,如以下代码:
其中~{html文件名:: 通过fragment起的别名}
<div th:replace="~{test :: header}"></div>
<div th:include="~{test :: footer}"></div>
"th:include"和 "th:replace" 标签都可以调用公共代码。它们的区别如下。
<div class="header">
公共header
</div>
<div>
公共footer
</div>
在MVC开发过程中,分页也是常用的功能。Thymeleaf可以处理由控制器传入的分页参数。
Pageable pageable = PageRequest.of(start,limit,sort);
Page<Book> page = articleRepository.findAll(pageable);
ModelAndView modelAndView = new ModelAndView("/index");
modelAndView.addObject("page",page);
return modelAndView;
<div>
<a th:href="@{/test(start=0)}">[首页]</a>
<a th:if="${not page.isFirst()}" th:href="@{/test(start=${page.number-1})}">[上页]</a>
<a th:if="${not page.isLast()}" th:href="@{/test(start=${page.number+1})}">[上页]</a>
<a th:href="@{/test(start=${page.totalPages-1})}">[末页]</a>
</div>
大多数表单信息都需要逬行字符串的验证,以及提供错误消息反馈。Thymeleaf提供了几种提示错误信息的方法。
<div>
<span>email:</span>
<span><input type="text" th:field="*{email}" /></span>
<span class="warn" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">邮箱错误</span>
</div>
<ul>
<li th:each="err:${#fields.errors('*')}" th:text="*{err}">邮箱错误</li>
</ul>
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
我刚刚看到whitehouse.gov正在使用drupal作为CMS和门户技术。drupal的优点之一似乎是很容易添加插件,而且编程最少,即重新发明轮子最少。这实际上正是Ruby-on-Rails的DRY理念。所以:drupal的缺点是什么?Rails或其他基于Ruby的技术有哪些不符合whitehouse.org(或其他CMS门户)门户技术的资格? 最佳答案 Whatarethedrawbacksofdrupal?对于Ruby和Rails,这确实是一个相当主观的问题。Drupal是一个可靠的内容管理选项,非常适合面向社区的站点。它
当音乐碰上区块链技术,会擦出怎样的火花?或许周杰伦已经给了我们答案。8月29日下午,B站独家首发周杰伦限定珍藏Demo独家访谈VCR,周杰伦在VCR里分享了《晴天》《青花瓷》《搁浅》《爱在西元前》四首经典歌曲Demo背后的创作故事,并首次公布18年前未发布的神秘作品《纽约地铁》的Demo。在VCR中,方文山和杰威尔音乐提及到“多亏了区块链技术,现在我们可以将这些Demos,变成独一无二具有收藏价值的艺术品,这些Demos可以在薄盒(国内数藏平台)上听到。”如何将音乐与区块链技术相结合,薄盒方面称:“薄盒作为区块链技术服务方,打破传统对于区块链技术只能作为数字收藏的理解。聚焦于区块链技术赋能,在
我感到有点困惑——大约24小时以来,我一直在考虑在我的项目中使用哪种组播技术。基本上,我需要的是:创建组(通过一些后端进程)任意客户端广播消息(1:N,N:N)(可能)直接消息(1:1)(重要)使用我自己的后端(例如,通过某种HTTPAPI)对客户端进行身份验证/授权能够通过后端进程(或服务器插件)踢出特定的客户端这是我要的:Ruby或Haxe中的后端相关流程JS+Haxe(Flash9)中的前端—在浏览器中,因此理想情况下通过80/443进行通信,但不一定。因此,这项技术必须能够在HaxeforFlash中轻松访问,最好是Ruby。我一直在考虑:RabbitMQ(或OpenAMQ)、
文章目录概述背景为何要存算分离优势**应用场景**存算分离产品技术流派华为JuiceFSHashDataXSKY概述背景Hadoop一出生就是奔存算一体设计,当时设计思想就是存储不动而计算(code也即是代码程序)动,负责调度Yarn会把计算任务尽量发到要处理数据所在的实例上,这也是与传统集中式存储最大的不同。为何当时Hadoop设计存算一体的耦合?要知道2006年服务器带宽只有100Mb/s~1Gb/s,但是HDD也即是磁盘吞吐量有50MB/s,这样带宽远远不够传输数据,网络瓶颈尤为明显,无奈之举只好把计算任务发到数据所在的位置。众观历史常言道天下分久必合合久必分,随着云计算技术的发展,数据
如果您希望在Spring中启用定时任务功能,则需要在主类上添加 @EnableScheduling 注解。这样Spring才会扫描 @Scheduled 注解并执行定时任务。在大多数情况下,只需要在主类上添加 @EnableScheduling 注解即可,不需要在Service层或其他类中再次添加。以下是一个示例,演示如何在SpringBoot中启用定时任务功能:@SpringBootApplication@EnableSchedulingpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.ru
软件特点部署后能通过浏览器查看线上日志。支持Linux、Windows服务器。采用随机读取的方式,支持大文件的读取。支持实时打印新增的日志(类终端)。支持日志搜索。使用手册基本页面配置路径配置日志所在的目录,配置后按回车键生效,下拉框选择日志名称。选择日志后点击生效,即可加载日志。windows路径E:\java\project\log-view\logslinux路径/usr/local/XX历史模式历史模式下,不会读取新增的日志。针对历史文件可以分页读取,配置分页大小、跳转。历史模式下,支持根据关键词搜索。目前搜索引擎使用的是jdk自带类库,搜索速度相对较低,优点是比较简单。2G日志全文搜
1.依赖导入org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-validation2.validation常用注解@Null被注释的元素必须为null@NotNull被注释的元素不能为null,可以为空字符串@AssertTrue被注释的元素必须为true@AssertFalse被注释的元素必须为false@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@D
文章目录华为OD面试流程1.mysql数据库建了两个字段,且设置了联合索引,如果其中有一个字段为空会出现什么问题?2.谈谈springIOC的理解,有什么好处,解决了什么问题3.谈谈springAOP的理解,切面编程有没有实际应用,有哪些注解,作用是什么,有那些应用场景?4.Erika和zookeeper有了解过吗,作用是什么,主要解决了什么问题5.谈谈JDK、JRE、JVM的理解,区别是什么6.谈谈对泛型的理解7.JVM的组成华为OD面试流程机试:三道算法题,关于机试,橡皮擦已经准备好了各语言专栏,可以直接订阅。性格测试:机试技术一面(本专栏核心)技术二面(本专栏核心)主管面试定级定薪发of