您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何使用Spring Boot+Thymeleaf技術(shù)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“如何使用Spring Boot+Thymeleaf技術(shù)”吧!
Thymeleaf 是新一代 Java 模板引擎,它類似于 Velocity、FreeMarker 等傳統(tǒng) Java 模板引擎,但是與傳統(tǒng) Java 模板引擎不同的是,Thymeleaf 支持 HTML 原型。
它既可以讓前端工程師在瀏覽器中直接打開查看樣式,也可以讓后端工程師結(jié)合真實(shí)數(shù)據(jù)查看顯示效果,同時(shí),SpringBoot 提供了 Thymeleaf 自動(dòng)化配置解決方案,因此在 SpringBoot 中使用 Thymeleaf 非常方便。
事實(shí)上, Thymeleaf 除了展示基本的 HTML ,進(jìn)行頁面渲染之外,也可以作為一個(gè) HTML 片段進(jìn)行渲染,例如我們?cè)谧鲟]件發(fā)送時(shí),可以使用 Thymeleaf 作為郵件發(fā)送模板。
另外,由于 Thymeleaf 模板后綴為 .html
,可以直接被瀏覽器打開,因此,預(yù)覽時(shí)非常方便。
Spring Boot 中整合 Thymeleaf 非常容易,只需要?jiǎng)?chuàng)建項(xiàng)目時(shí)添加 Thymeleaf 即可:
創(chuàng)建完成后,pom.xml 依賴如下:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-thymeleaf</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency>
當(dāng)然,Thymeleaf 不僅僅能在 Spring Boot 中使用,也可以使用在其他地方,只不過 Spring Boot 針對(duì) Thymeleaf 提供了一整套的自動(dòng)化配置方案,這一套配置類的屬性在 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
中,部分源碼如下:
@ConfigurationProperties(prefix = "spring.thymeleaf") public class ThymeleafProperties { private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8; public static final String DEFAULT_PREFIX = "classpath:/templates/"; public static final String DEFAULT_SUFFIX = ".html"; private boolean checkTemplate = true; private boolean checkTemplateLocation = true; private String prefix = DEFAULT_PREFIX; private String suffix = DEFAULT_SUFFIX; private String mode = "HTML"; private Charset encoding = DEFAULT_ENCODING; private boolean cache = true; //... }
首先通過 @ConfigurationProperties
注解,將 application.properties
前綴為 spring.thymeleaf
的配置和這個(gè)類中的屬性綁定。
前三個(gè) static
變量定義了默認(rèn)的編碼格式、視圖解析器的前綴、后綴等。
從前三行配置中,可以看出來,Thymeleaf
模板的默認(rèn)位置在 resources/templates
目錄下,默認(rèn)的后綴是 html
。
這些配置,如果開發(fā)者不自己提供,則使用 默認(rèn)的,如果自己提供,則在 application.properties
中以 spring.thymeleaf
開始相關(guān)的配置。
而我們剛剛提到的,Spring Boot 為 Thymeleaf 提供的自動(dòng)化配置類,則是 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
,部分源碼如下:
@Configuration @EnableConfigurationProperties(ThymeleafProperties.class) @ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class }) @AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class }) public class ThymeleafAutoConfiguration { }
可以看到,在這個(gè)自動(dòng)化配置類中,首先導(dǎo)入 ThymeleafProperties
,然后 @ConditionalOnClass
注解表示當(dāng)當(dāng)前系統(tǒng)中存在 TemplateMode
和 SpringTemplateEngine
類時(shí),當(dāng)前的自動(dòng)化配置類才會(huì)生效,即只要項(xiàng)目中引入了 Thymeleaf
相關(guān)的依賴,這個(gè)配置就會(huì)生效。
這些默認(rèn)的配置我們幾乎不需要做任何更改就可以直接使用了。如果開發(fā)者有特殊需求,則可以在 application.properties 中配置以 spring.thymeleaf 開頭的屬性即可。
接下來我們就可以創(chuàng)建 Controller 了,實(shí)際上引入 Thymeleaf 依賴之后,我們可以不做任何配置。新建的 IndexController 如下:
@Controller public class IndexController { @GetMapping("/index") public String index(Model model) { List<user> users = new ArrayList<>(); for (int i = 0; i < 10; i++) { User u = new User(); u.setId((long) i); u.setName("javaboy:" + i); u.setAddress("深圳:" + i); users.add(u); } model.addAttribute("users", users); return "index"; } } public class User { private Long id; private String name; private String address; //省略 getter/setter }
在 IndexController
中返回邏輯視圖名+數(shù)據(jù),邏輯視圖名為 index
,意思我們需要在 resources/templates
目錄下提供一個(gè)名為 index.html
的 Thymeleaf
模板文件。
創(chuàng)建 Thymeleaf
<meta charset="UTF-8"> <title>Title</title> <table border="1"> <tbody><tr> <td>編號(hào)</td> <td>用戶名</td> <td>地址</td> </tr> <tr th:each="user : ${users}"> <td th:text="${user.id}"></td> <td th:text="${user.name}"></td> <td th:text="${user.address}"></td> </tr> </tbody></table>
在 Thymeleaf
中,通過 th:each
指令來遍歷一個(gè)集合,數(shù)據(jù)的展示通過 th:text
指令來實(shí)現(xiàn),
注意 index.html
最上面引入 thymeleaf
名稱空間(最新版并無強(qiáng)制要求)。
配置完成后,就可以啟動(dòng)項(xiàng)目了,訪問 /index 接口,就能看到集合中的數(shù)據(jù)了:
前面我們說的是返回一個(gè) Thymeleaf 模板,我們也可以手動(dòng)渲染 Thymeleaf 模板,這個(gè)一般在郵件發(fā)送時(shí)候有用,例如我在 resources/templates 目錄下新建一個(gè)郵件模板,如下:
<meta charset="UTF-8"> <title>Title</title> <p>hello 歡迎 <span th:text="${username}"></span>加入 XXX 集團(tuán),您的入職信息如下:</p> <table border="1"> <tbody><tr> <td>職位</td> <td th:text="${position}"></td> </tr> <tr> <td>薪水</td> <td th:text="${salary}"></td> </tr> </tbody></table> <img src="https://oscimg.oschina.net/oscnet/javaboy.jpg" alt="">
這一個(gè) HTML 模板中,有幾個(gè)變量,我們要將這個(gè) HTML 模板渲染成一個(gè) String 字符串,再把這個(gè)字符串通過郵件發(fā)送出去,那么如何手動(dòng)渲染呢?
@Autowired TemplateEngine templateEngine; @Test public void test1() throws MessagingException { Context context = new Context(); context.setVariable("username", "javaboy"); context.setVariable("position", "Java工程師"); context.setVariable("salary", 99999); String mail = templateEngine.process("mail", context); //省略郵件發(fā)送 }
渲染時(shí),我們需要首先注入一個(gè) TemplateEngine 對(duì)象,這個(gè)對(duì)象就是在 Thymeleaf 的自動(dòng)化配置類中配置的(即當(dāng)我們引入 Thymeleaf 的依賴之后,這個(gè)實(shí)例就有了)。
然后構(gòu)造一個(gè) Context 對(duì)象用來存放變量。
調(diào)用 process 方法進(jìn)行渲染,該方法的返回值就是渲染后的 HTML 字符串,然后我們將這個(gè)字符串發(fā)送出去。
前面兩個(gè)案例讓小伙伴們大致上理解了在 Spring Boot 中要如何使用 Thymeleaf,接下來,松哥將詳細(xì)介紹 Thymeleaf 本身的一些具體用法。
${...}
直接使用 th:xx = "${}"
獲取對(duì)象屬性。這個(gè)在前面的案例中已經(jīng)演示過了,不再贅述。
*{...}
可以像 ${...}
一樣使用,也可以通過 th:object
獲取對(duì)象,然后使用 th:xx = "*{}"
獲取對(duì)象屬性,這種簡(jiǎn)寫風(fēng)格極為清爽,推薦大家在實(shí)際項(xiàng)目中使用。
<table border="1" th:object="${user}"> <tbody><tr> <td>用戶名</td> <td th:text="*{username}"></td> </tr> <tr> <td>地址</td> <td th:text="*{address}"></td> </tr> </tbody></table>
#{...}
通常的國(guó)際化屬性:#{...}
用于獲取國(guó)際化語言翻譯值。
在 resources 目錄下新建兩個(gè)文件:messages.properties 和 messages_zh_CN.properties,內(nèi)容如下:
messages.properties:
message = javaboy
messages_zh_CN.properties:
message = 江南一點(diǎn)雨
然后在 thymeleaf 中引用 message,系統(tǒng)會(huì)根據(jù)瀏覽器的語言環(huán)境顯示不同的值:
<div th:text="#{message}"></div>
@{...}
引用絕對(duì) URL:
<script type="text/javascript" th:src="@{http://localhost:8080/hello.js}"></script>
等價(jià)于:
<script type="text/javascript" src="http://localhost:8080/hello.js"></script>
上下文相關(guān)的 URL:
首先在 application.properties 中配置 Spring Boot 的上下文,以便于測(cè)試:
server.servlet.context-path=/myapp
引用路徑:
<script type="text/javascript" th:src="@{/hello.js}"></script>
等價(jià)于:
<script type="text/javascript" src="/myapp/hello.js"></script>
相對(duì) URL:
這個(gè)相對(duì)是指相對(duì)于服務(wù)器的 URL,例如如下引用:
<script type="text/javascript" th:src="@{~/hello.js}"></script>
等價(jià)于:
<script type="text/javascript" src="/hello.js"></script>
應(yīng)用程序的上下文 /myapp 將被忽略。
協(xié)議相對(duì) URL:
<script type="text/javascript" th:src="@{//localhost:8080/hello.js}"></script>
等價(jià)于:
<script type="text/javascript" src="//localhost:8080/hello.js"></script>
帶參數(shù)的 URL:
<script type="text/javascript" th:src="@{//localhost:8080/hello.js(name='javaboy',age=99)}"></script>
等價(jià)于:
<script type="text/javascript" th:src="//localhost:8080/hello.js?name=javaboy&age=99"></script>
~{...}
片段表達(dá)式是 Thymeleaf 的特色之一,細(xì)粒度可以達(dá)到標(biāo)簽級(jí)別,這是 JSP 無法做到的。片段表達(dá)式擁有三種語法:
~{ viewName }
:表示引入完整頁面
~{ viewName ::selector}
:表示在指定頁面尋找片段,其中 selector 可為片段名、jquery選擇器等
~{ ::selector}
: 表示在當(dāng)前頁尋找
舉個(gè)簡(jiǎn)單例子。
在 resources/templates 目錄下新建 my_fragment.html 文件,內(nèi)容如下:
<div th:fragment="javaboy_link"><a href="http://www.javaboy.org">www.javaboy</a></div> <div th:fragment="itboyhub_link"><a href="http://www.itboyhub.com">www.itboyhub.com</a></div>
這里有兩個(gè) div,通過 th:fragment 來定義片段,兩個(gè) div 分別具有不同的名字。
然后在另外一個(gè)頁面中引用該片段:
<table border="1" th:object="${user}" th:fragment="aaa"> <tbody><tr> <td>用戶名</td> <td th:text="*{username}"></td> </tr> <tr> <td>地址</td> <td th:text="*{address}"></td> </tr> </tbody></table> <hr> <div th:replace="my_fragment.html"></div> <hr> <div th:replace="~{my_fragment.html::javaboy_link}"></div> <hr> <div th:replace="~{::aaa}"></div>
通過 th:replace 來引用片段。第一個(gè)表示引用完整的 my_fragment.html
頁面;第二個(gè)表示引用 my_fragment.html
中的名為 javaboy_link
的片段;第三個(gè)表示引用當(dāng)前頁面名為 aaa 的片段,也就是上面那個(gè) table。
這些是一些可以直接寫在表達(dá)式中的字符,主要有如下幾種:
文本字面量: 'one text', 'Another one!',…
數(shù)字字面量: 0, 34, 3.0, 12.3,…
布爾字面量: true, false
Null字面量: null
字面量標(biāo)記:one, sometext, main,…
案例:
<div th:text="'這是 文本字面量(有空格)'"></div> <div th:text="javaboy"></div> <div th:text="99"></div> <div th:text="true"></div>
如果文本是英文,并且不包含空格、逗號(hào)等字符,可以不用加單引號(hào)。
文本可以使用 +
進(jìn)行拼接。
<div th:text="'hello '+'javaboy'"></div> <div th:text="'hello '+${user.username}"></div>
如果字符串中包含變量,也可以使用另一種簡(jiǎn)單的方式,叫做字面量置換,用 |
代替 '...' + '...'
,如下:
<div th:text="|hello ${user.username}|"></div> <div th:text="'hello '+${user.username}+' '+|Go ${user.address}|"></div>
算術(shù)運(yùn)算有:+
, -
, *
, /
和 %
。
<div th:with="age=(99*99/99+99-1)"> <div th:text="${age}"></div> </div>
th:with 定義了一個(gè)局部變量 age,在其所在的 div 中可以使用該局部變量。
二元運(yùn)算符:and, or
布爾非(一元運(yùn)算符):!, not
案例:
<div th:with="age=(99*99/99+99-1)"> <div th:text="9 eq 9 or 8 ne 8"></div> <div th:text="!(9 eq 9 or 8 ne 8)"></div> <div th:text="not(9 eq 9 or 8 ne 8)"></div> </div>
表達(dá)式里的值可以使用 >
, <
, >=
和 <=
符號(hào)比較。==
和 !=
運(yùn)算符用于檢查相等(或者不相等)。注意 XML
規(guī)定 <
和 >
標(biāo)簽不能用于屬性值,所以應(yīng)當(dāng)把它們轉(zhuǎn)義為 <
和 >
。
如果不想轉(zhuǎn)義,也可以使用別名:gt (>);lt (<);ge (>=);le (<=);not (!)。還有 eq (==), neq/ne (!=)。
舉例:
<div th:with="age=(99*99/99+99-1)"> <div th:text="${age} eq 197"></div> <div th:text="${age} ne 197"></div> <div th:text="${age} ge 197"></div> <div th:text="${age} gt 197"></div> <div th:text="${age} le 197"></div> <div th:text="${age} lt 197"></div> </div>
類似于我們 Java 中的三目運(yùn)算符。
<div th:with="age=(99*99/99+99-1)"> <div th:text="(${age} ne 197)?'yes':'no'"></div> </div>
其中,: 后面的部分可以省略,如果省略了,又同時(shí)計(jì)算結(jié)果為 false 時(shí),將返回 null。
基本內(nèi)置對(duì)象:
#ctx:上下文對(duì)象。
#vars: 上下文變量。
#locale:上下文區(qū)域設(shè)置。
#request:(僅在 Web 上下文中)HttpServletRequest 對(duì)象。
#response:(僅在 Web 上下文中)HttpServletResponse 對(duì)象。
#session:(僅在 Web 上下文中)HttpSession 對(duì)象。
#servletContext:(僅在 Web 上下文中)ServletContext 對(duì)象。
在頁面可以訪問到上面這些內(nèi)置對(duì)象,舉個(gè)簡(jiǎn)單例子:
<div th:text="${#session.getAttribute("name")}"></div>
實(shí)用內(nèi)置對(duì)象:
#execInfo:有關(guān)正在處理的模板的信息。
#messages:在變量表達(dá)式中獲取外部化消息的方法,與使用#{...}語法獲得的方式相同。
#uris:轉(zhuǎn)義URL / URI部分的方法
#conversions:執(zhí)行配置的轉(zhuǎn)換服務(wù)(如果有)的方法。
#dates:java.util.Date對(duì)象的方法:格式化,組件提取等
#calendars:類似于#dates但是java.util.Calendar對(duì)象。
#numbers:用于格式化數(shù)字對(duì)象的方法。
#strings:String對(duì)象的方法:contains,startsWith,prepending / appending等
#objects:一般對(duì)象的方法。
#bools:布爾評(píng)估的方法。
#arrays:數(shù)組方法。
#lists:列表的方法。
#sets:集合的方法。
#maps:地圖方法。
#aggregates:在數(shù)組或集合上創(chuàng)建聚合的方法。
#ids:處理可能重復(fù)的id屬性的方法(例如,作為迭代的結(jié)果)。
這是一些內(nèi)置對(duì)象以及工具方法,使用方式也都比較容易,如果使用的是 IntelliJ IDEA,都會(huì)自動(dòng)提示對(duì)象中的方法,很方便。
舉例:
<div th:text="${#execInfo.getProcessedTemplateName()}"></div> <div th:text="${#arrays.length(#request.getAttribute('names'))}"></div>
這個(gè)是給 HTML 元素設(shè)置屬性值。可以一次設(shè)置多個(gè),多個(gè)之間用 ,
分隔開。
例如:
<img th:attr="src=@{/1.png},title=${user.username},alt=${user.username}" src="">
會(huì)被渲染成:
<img src="/myapp/1.png" title="javaboy" alt="javaboy">
當(dāng)然這種設(shè)置方法不太美觀,可讀性也不好。Thymeleaf 還支持在每一個(gè)原生的 HTML 屬性前加上 th: 前綴的方式來使用動(dòng)態(tài)值,像下面這樣:
<img th:src="@{/1.png}" th:alt="${user.username}" th:title="${user.username}" src="">
這種寫法看起來更清晰一些,渲染效果和前面一致。
上面案例中的 alt 和 title 則是兩個(gè)特殊的屬性,可以一次性設(shè)置,像下面這樣:
<img th:src="@{/1.png}" th:alt-title="${user.username}" src="">
這個(gè)等價(jià)于前文的設(shè)置。
數(shù)組/集合/Map/Enumeration/Iterator 等的遍歷也算是一個(gè)非常常見的需求,Thymeleaf 中通過 th:each 來實(shí)現(xiàn)遍歷,像下面這樣:
<table border="1"> <tbody><tr th:each="u : ${users}"> <td th:text="${u.username}"></td> <td th:text="${u.address}"></td> </tr> </tbody></table>
users 是要遍歷的集合/數(shù)組,u 則是集合中的單個(gè)元素。
遍歷的時(shí)候,我們可能需要獲取遍歷的狀態(tài),Thymeleaf 也對(duì)此提供了支持:
index:當(dāng)前的遍歷索引,從0開始。
count:當(dāng)前的遍歷索引,從1開始。
size:被遍歷變量里的元素?cái)?shù)量。
current:每次遍歷的遍歷變量。
even/odd:當(dāng)前的遍歷是偶數(shù)次還是奇數(shù)次。
first:當(dāng)前是否為首次遍歷。
last:當(dāng)前是否為最后一次遍歷。
u 后面的 state 表示遍歷狀態(tài),通過遍歷狀態(tài)可以引用上面的屬性。
<table border="1"> <tbody><tr th:each="u,state : ${users}"> <td th:text="${u.username}"></td> <td th:text="${u.address}"></td> <td th:text="${state.index}"></td> <td th:text="${state.count}"></td> <td th:text="${state.size}"></td> <td th:text="${state.current}"></td> <td th:text="${state.even}"></td> <td th:text="${state.odd}"></td> <td th:text="${state.first}"></td> <td th:text="${state.last}"></td> </tr> </tbody></table>
只顯示奇數(shù)次的遍歷,可以使用 th:if,如下:
<table border="1"> <tbody><tr th:each="u,state : ${users}" th:if="${state.odd}"> <td th:text="${u.username}"></td> <td th:text="${u.address}"></td> <td th:text="${state.index}"></td> <td th:text="${state.count}"></td> <td th:text="${state.size}"></td> <td th:text="${state.current}"></td> <td th:text="${state.even}"></td> <td th:text="${state.odd}"></td> <td th:text="${state.first}"></td> <td th:text="${state.last}"></td> </tr> </tbody></table>
th:if 不僅僅只接受布爾值,也接受其他類型的值,例如如下值都會(huì)判定為 true:
如果值是布爾值,并且為 true。
如果值是數(shù)字,并且不為 0。
如果值是字符,并且不為 0。
如果值是字符串,并且不為 “false”, “off” 或者 “no”。
如果值不是布爾值,數(shù)字,字符或者字符串。
但是如果值為 null,th:if 會(huì)求值為 false。
th:unless 的判定條件則與 th:if 完全相反。
<table border="1"> <tbody><tr th:each="u,state : ${users}" th:unless="${state.odd}"> <td th:text="${u.username}"></td> <td th:text="${u.address}"></td> <td th:text="${state.index}"></td> <td th:text="${state.count}"></td> <td th:text="${state.size}"></td> <td th:text="${state.current}"></td> <td th:text="${state.even}"></td> <td th:text="${state.odd}"></td> <td th:text="${state.first}"></td> <td th:text="${state.last}"></td> </tr> </tbody></table>
這個(gè)顯示效果則與上面的完全相反。
當(dāng)可能性比較多的時(shí)候,也可以使用 switch:
<table border="1"> <tbody><tr th:each="u,state : ${users}"> <td th:text="${u.username}"></td> <td th:text="${u.address}"></td> <td th:text="${state.index}"></td> <td th:text="${state.count}"></td> <td th:text="${state.size}"></td> <td th:text="${state.current}"></td> <td th:text="${state.even}"></td> <td th:text="${state.odd}"></td> <td th:text="${state.first}"></td> <td th:text="${state.last}"></td> <td th:switch="${state.odd}"> <span th:case="true">odd</span> <span th:case="*">even</span> </td> </tr> </tbody></table>
th:case="*"
則表示默認(rèn)選項(xiàng)。
這個(gè)我們前面已經(jīng)涉及到了,使用 th:with 可以定義一個(gè)本地變量。
我們可以使用屬性將數(shù)據(jù)放入頁面模版中,但是很多時(shí)候,內(nèi)聯(lián)的方式看起來更加直觀一些,像下面這樣:
<div>hello [[${user.username}]]</div>
用內(nèi)聯(lián)的方式去做拼接也顯得更加自然。
[[...]]
對(duì)應(yīng)于 th:text (結(jié)果會(huì)是轉(zhuǎn)義的 HTML),[(...)]
對(duì)應(yīng)于 th:utext,它不會(huì)執(zhí)行任何的 HTML 轉(zhuǎn)義。
像下面這樣:
<div th:with="str='hello <strong>javaboy</strong>'"> <div>[[${str}]]</div> <div>[(${str})]</div> </div>
最終的顯示效果如下:
不過內(nèi)聯(lián)方式有一個(gè)問題。我們使用 Thymeleaf 的一大優(yōu)勢(shì)在于不用動(dòng)態(tài)渲染就可以直接在瀏覽器中看到顯示效果,當(dāng)我們使用屬性配置的時(shí)候確實(shí)是這樣,但是如果我們使用內(nèi)聯(lián)的方式,各種表達(dá)式就會(huì)直接展示在靜態(tài)網(wǎng)頁中。
也可以在 js 或者 css 中使用內(nèi)聯(lián),以 js 為例,使用方式如下:
<script th:inline="javascript"> var username=[[${user.username}]] console.log(username) </script>
js 中需要通過 th:inline="javascript"
開啟內(nèi)聯(lián)。
感謝各位的閱讀,以上就是“如何使用Spring Boot+Thymeleaf技術(shù)”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)如何使用Spring Boot+Thymeleaf技術(shù)這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。