spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect

Thymeleaf简介

配置Thymeleaf

这个教程是基于maven环境进行配置的。

1.在resources文件夹之下新加两个文件夹,分别为templates和static,其中templates用于存放界面HTML文件,而static则用于存储静态文件比如js,css或img。目录格式如下:

-project
  -src
    -main
      -java
      -resources
        -templates
        -static
        -config
          -application.yml
          -application-test.yml
          -application-validate.yml
    -test
  -pom.xml

2.pom.xml文件中添加依赖:

     <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

3.在.properties文件或是.yml文件中添加thymeleaf配置
.properties文件中配置内容如下:

########################################################
###THYMELEAF (ThymeleafAutoConfiguration)
########################################################
#配置项目的HTML路径
spring.thymeleaf.prefix=classpath:/templates/
#后缀
spring.thymeleaf.suffix=.html
#会开启严格的HTML格式检查,因此如果想要关闭它,就将其值设置为LEGACYHTML5
#spring.thymeleaf.mode=HTML5 #LEGACYHTML5 如果想要关闭强制的语法检查
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
# 关闭了换从,从而支持热部署
spring.thymeleaf.cache=false

.yml文件中配置内容如下:

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    encoding: UTF-8
    content-type: text/html
    cache: false
    mode: LEGACYHTML5

至此环境配置完成。Spring支持多种方式配置Thymeleaf包括代码,XML等等。这里我们采用yml文件的方式。

4.编写demo
在resources/templates目录下新建一个hello.html文件,内容如下:

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Welcome Page</title>
</head>
<body>
<!--从上下文中获取name属性并填写到p标签中-->
    <p th:text="'hello, '+${name}">hello! my new friend!</p>
</body>
</html>

这里需要注意的是,要在html标签中加入xmlns:th="http://www.thymeleaf.org"

编写一个controller,内容如下:

@Controller
@RequestMapping("/")
public class TestController {

    @GetMapping("/hello")
    public String welcome(Model model){
        model.addAttribute("name", "小伙伴");
        return "hello";
    }
}

这一部分的内容涉及Spring-mvc,这里暂时不细讲,各位只需copy代码即可。

完成后运行Application.java启动spring-boot项目,Application.java内容如下:

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.Arrays;
@EnableJpaAuditing
@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter{

    public static void main(String[] args){
        SpringApplication.run(Application.class);
    }

    /**
     * 在启动时输出找到的所有的bean
     * @param ctx
     * @return
     */
    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {

            System.out.println("Let's inspect the beans provided by Spring Boot:");

            String[] beanNames = ctx.getBeanDefinitionNames();
            Arrays.sort(beanNames);
            for (String beanName : beanNames) {
                System.out.println(beanName);
            }

        };
    }

}

启动完毕后在浏览器中输入http://localhost:PORT/hello。这里的PORT是指端口号,可以在配置文件中使用server.port:8080配置。使用yaml配置的话请自行转化。

这是的界面显示如下:

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》

Thymeleaf basic

1.Thymeleaf支持多种模式(mode)

  • HTML(包括HTML5, HTML 4 and XHTML.)不会进行非常严格的语法检查
  • XML (严格的语法检查,如果不符合标准会抛出异常)
  • TEXT
  • JAVASCRIPT (意味着可以像在HTML中的语法一样在JS中使用)
  • CSS (同上)
  • RAW

2.Standard Dialect

An object that applies some logic to a markup artifact (a tag, some text, a comment, or a mere placeholder if templates are not markup) is called a processor, and a set of these processors – plus perhaps some extra artifacts – is what a dialect is normally comprised of.

dialect由processors和artifacts构成。processor是指将一些逻辑施加于markup元素之上。dialect将在后面继续介绍,它是thymeleaf的一个重要成分。这里想介绍一下,就是Thymeleaf对SpEL有非常良好的支持,而且之前使用ONGL语法的同志也可以非常快速的过渡。同时这种语法优于jsp的优点在于它支持原生的HTML语法,从而在预览的时候不会因为JSP语法而必须先通过服务器渲染。

Standard Dialect

th:text: 更换当前标签之下的text内容,例如
<p th:text="hello"></p>转化后成为
<p>hello</p>

th:utext: 非转义语法,也就是当存在如HTML语义中的标签
<span>不会将其转义为
&lt;span&rt;

Standard Syntax Expression

在官网上列举了所有的标准的语法,有兴趣的可以戳文末的链接去了解。这里简单介绍一下其中的几种并举例说明。
为了便于理解,这里先介绍一下,th:text属性会将所在的标签的内容改变为th:text的值。而且th:text支持动态赋值。

Message Expression #{…}

假设我们现在想要把一些公共用语放在一个配置文件中,并且这个配置文件可以支持多国语言。那么我们就可以通过#{}获取配置文件中的内容。Thymeleaf默认每个HTML的配置文件位于同目录之下的同名的.properties文件中。现在我们来尝试一下,在之前的hello.html之中添加一段代码,内容如下:

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Welcome Page</title>
</head>
<body>
    <!--从上下文中获取name属性并填写到p标签中-->
    <p th:text="'hello, '+${name}">hello! my new friend!</p>
    
    <!--添加这一段代码-->
    <p th:utext="#{welcome.login}"></p>
</body>
</html>

然后在同目录下添加一个hello.properties文件,内容如下:

welcome.login:welcome to this <b>damn</b> website

这时开启项目就可以看见第二个<p>的text为配置文件中的内容。

假设这时有一个新需求,比如我们希望在欢迎词中包含用户名体现个性化,那么我们可以使用如下的方式:
hello.properties使用{}占位符

welcome.login:welcome to this <b>damn</b> website,{0}

hello.html ${session.user.name}从session中获取用户名作为参数传递给message,股关于${}会在下一小节详细介绍。如果有多个参数需要传递,可以用逗号隔开

<p th:utext="#{welcome.login(${session.user.name})}"></p>

Variable Expressions ${…}

${}属于OGNL语法,而在spring-mvc中会被替代为SpEL,但是二者的语法在大多数场景下基本相同。
下面是一些简单范例:

${person.father.name}: 相当于person.getFather().getName()

${personsByName['Stephen Zucchini'].age}: 获取map对象personByName中名称为Stephen Zucchini的人的年龄

${personsArray[0].name}: 获取personsArray数组对象中第一个对象的name

${person.createCompleteName()} : 允许直接调用对象中的方法

Thymeleaf还考虑到你可能需要在界面中调用到很多的上下文属性,或者是使用一些工具,因此内置了一下对象和方法供大家使用。这里直接摘抄了官网,有兴趣的可以直接去官网进行了解。

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》

Selection Variable *{…}

被标记为*{x}将不会再上下文中寻找x属性,而是会去最近选中的对象中寻找x属性。如果没有最近选中的对象,那么*{...}#{...}所执行的操作相同。
那么我们如何才能知道是否选中对象呢,这是需要使用th:object属性来标记被选中的对象。下面举个栗子:
比如现在我们有一本书,并且我们希望在界面中展示这本书的详细信息,包括书的ISBN,名称(name)和价格(price),那么我们的界面可以是酱的

<div th:object="${book}">
    <p th:text="*{ISBN}"></p>
    <p th:text="*{name}"></p>
    <p th:text="*{price}"></p>
</div>

这段代码等价于

<div>
    <p th:text="${book.ISBN}"></p>
    <p th:text="${book.name}"></p>
    <p th:text="${book.price}"></p>
</div>

可见*{...}可以帮我们省去很多冗余的选择代码

Link URL Expressions: @{…}

URL在WEB页面中可谓是错综复杂,有各式各样的URL。而且一旦项目重构,因为上下文的改变很可能造成相对路径甚至绝对路径的失效。Thymeleaf将URL归类为一下几种并分别给出了相应的支持。下面给出一些示例:

<a th:href="@{http://www.thymeleaf.org}"/>: 展示绝对路径
http://www.thymeleaf.org

<a th:href="@{/order/list}"/> : 和上下文相对路径,如果我们的项目部署在
<a th:href="@{/order/list}">,那么等价于
<a href="/myapp/order/list">

<a th:href="@{~/billing-app/showDetails.htm}">: 服务器相对路径,可以指向同一个服务器上另一个上下文的资源,如果我们的项目部署在
<a th:href="@{/order/list}">,那么等价于
<a href="/billing-app/showDetails.htm">

<script th:src="@{//scriptserver.example.net/myscript.js}">...</script>: 协议相关路径,本质上是绝对路径,会保证协议的一致性,通常用于引入静态资源如js或css等

<a th:href="@{/order/details(id=3)}">:在URL中添加参数,等价于
<a href="/order/details?id=3">。如果需要传入多个参数,可以用逗号隔开

<a th:href="@{/order/{id}/details(id=3,action='show_all')}">:将传入的参数自动转化为路径变量,这里等价于
<a href="/order/3/details?action=show_all">

<a th:href="@{/home#all_info(action='show')}">定位到界面中id为all_info的部分,等价于
<a href="/home?action=show#all_info">

<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">view</a>URL本身也可以是一个变量定义的,也同样允许传入参数。

Fragment Expressions: ~{…}

允许将HTML代码块插入到多个地方。比如我们经常会需要将HTML页面分割为HEADER,SIDEBAR,FOOTER等部分,通过Fragment符号可以将他们分割成单独的文件并且插入到需要他们的页面中。提高了代码的复用性。它常常和th:insert以及th:replace一起使用。

Literals

text:
th:text="'working web application'"用单引号赋值,还支持字符串拼接操作
th:text="'The name of the user is ' + ${user.name}"

numeric:
th:text="2013 + 2"

boolean:
th:if="${user.isAdmin()} == false">

null:
th:if="${variable.something} == null"

Literals Replacement

在上一节提到了字符串拼接操作,这是一个很常用的操作。因此Thymeleaf也专门封装了一个字符串替换符来支持这个操作,因此上面的th:text="'The name of the user is ' + ${user.name}"等价于th:text="|The name of the user is ${user.name}|"从而增强了可读性。
需要注意的是,替换符||中只会对${...}, *{...}, #{...}进行转义,其它的都不会进行转义,因此当遇到如boolean常量时我们还是需要使用拼接符将其转化为如下格式th:text="${user.isAdmin()}==false + ' ' + |${twovar}, ${threevar}|"

运算符,比较符,条件符

+ - * /(div) %(mod)
gt (>), lt (<), ge (>=), le (<=), not (!) eq (==), neq/ne (!=)
? :
这些都在Thymeleaf具有良好的支持,这里要强调一个独特的用法就是
th:text="*{age}?: '(no age specified)'"等价于th:text="*{age != null}? *{age} : '(no age specified)',即?:会自动填入默认值

不进行任何操作_

<span th:text="${user.name} ?: _">no user authenticated</span>
等价于
<span th:text="${user.name} ?: 'no user authenticated'">...</span>
也就是说,当用户名不存在是,则显示span标签中原有的text

预处理 __${expression}__

目前举例的场景是可以在预处理阶段根据locale决定如何解读messages。例如现在有两个地区的.properties文件,可以在预处理阶段根据地区决定使用那个.properties文件。
<p th:text="${__#{article.text('textVar')}__}">Some text here...</p>
如果实在中国地区,就会读取后缀为ch.properties的文件中articale.text的内容

th标签记录

th:attr: 可以更改这个所在的标签的某个的属性的值,例如
th:attr="action=@{/subscribe}"就将action的属性改变为动态生成的@{/subscribe},还允许对多个属性赋值,每个属性之间用逗号隔开,如
<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

th:attr因为其丑陋而导致极少使用。大多数的HTML标签Thymeleaf都为其封装了专门的赋值th标签

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》

这是官网上给的具体封装的标签例子,基本上HTML已有的标签都被疯转为th标签,并且允许你在其中使用Standard Dialect语法。

如果你想对多个th标签赋予相同的值,Thymeleaf连这种情况都帮你想好了,你可以使用如下语法简化
th:alt-title="#{logo}"等价于th:alt="#{logo}" th:title="#{logo}"

th:attrappend: 添加值至某个attr,引申的有
th:classappend,
th:styleappend

th:whatever: 这个标签比较神奇,其实它的本质是自定义任何标签都可以。直接看例子
<span th:whatever="${user.name}">...</span>等价于
<span whatever="John Apricot">...</span>

目前刚刚整理完毕了Thymeleaf前误解的内容,会开下一个博客继续介绍(fanyi)后面的内容。内容尊的好多啊QAQ

Refernces

tymeleaf官网

《spring-boot周边游(三)Thymeleaf-1 一个简单的demo以及初识Standard Dialect》
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~

    原文作者:raledong
    原文地址: https://segmentfault.com/a/1190000012670550
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞