錄
?1. Thymeleaf是適用于Web和獨立環境的現代服務器端Java模板引擎。
?2. Thymeleaf的主要目標是為您的開發工作流程帶來優雅的自然模板 -HTML可以在瀏覽器中正確顯示,也可以作為靜態原型工作,從而可以在開發團隊中加強協作。
?3. Thymeleaf擁有適用于Spring Framework的模塊,與您喜歡的工具的大量集成以及插入您自己的功能的能力,對于現代HTML5 JVM Web開發而言,Thymeleaf是理想的選擇-盡管它還有很多工作要做。
?1. thymeleaf在有網絡無網絡的環境下都可以運行,所以可以直接在瀏覽器打開查看靜態頁面效果。它支持HTML原型,可以在HTML標簽里面添加其他屬性來實現數據渲染。
?2. thymeleaf具有開箱即用的特性,Thymeleaf是Spring boot推薦使用的模版引擎,直接以html顯示,前后端可以很好的分離。
?1. 國際化,渲染不同國家的語言
?2. 共同頁面顯示,比如統一異常頁面處理,共同的頁面處理
?新建一個Springboot web項目,然后添加以下依賴。
<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>
?然后在配置文件里面添加如下依賴。
spring:
thymeleaf:
cache: false
prefix: classpath:/templates/
encoding: UTF-8 #編碼
suffix: .html #模板后綴
mode: HTML #模板
配置說明:
?cache這一行是將頁面的緩存關閉,不然我們改變頁面之后可能不能及時看到更改的內容,默認是true。
?prefix是配置thymeleaf模板所在的位置。
?encoding 是配置thymeleaf文檔的編碼,后面的就不說了
?上面我們配置好了環境之后就可以創建一個controller文件夾,然后寫一個controller,來測試我們的thymeleaf是否成功引入。順便創建一個對象。 代碼:
@Controller
public class ThymeleafController {
@GetMapping("/getStudents")
public ModelAndView getStudent(){
List<Student> students = new LinkedList<>();
Student student = new Student();
student.setId(1);
student.setName("全棧學習筆記");
student.setAge(21);
Student student1 = new Student();
student1.setId(2);
student1.setName("張三");
student1.setAge(22);
students.add(student);
students.add(student1);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("students",students);
modelAndView.setViewName("students");
return modelAndView;
}
}
?代碼解釋 :我們創建一個list,然后在list里面添加數據,一遍一次將數據傳到頁面使用。然后我們創建一個ModelAndView的對象,將list放入這個modeAndView對象中,第一個參數是需要放到model中的屬性名稱相當于是一個鍵,第二個是值,是一個對象。然后利用setViewName方法,設置要跳轉的頁面或者說是將數據傳到對應的頁面。
?最外層我們使用了一個 @Controller,這個注解是用來返回一個頁面或者視圖層的。
?當然,返回ModelAndView對象只是一種方法,還有其他的方法,比如說下面這樣
@RequestMapping("/getString")
public String getString(HttpServletRequest request){
String name = "全棧學習筆記";
request.setAttribute("name",name);
return "index.html";
}
利用http的request傳值。 然后還有這樣
@RequestMapping("/getModel")
public String getModel(Model model){
model.addAttribute("key","這是一個鍵");
return "index.html";
}
?去掉末尾的.html也可以,因為我們在配置文件里面設置了文件的格式為HTML文件。return的字符串都是對應的HTML文件的名稱。
?實體類代碼如下:
/**
* (Student)實體類
*
* @author 全棧學習筆記
* @since 2020-04-14 11:39:10
*/
public class Student {
private static final long serialVersionUID = -91969758749726312L;
/**
* 唯一標識id
*/
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 年齡
*/
private Integer age;
//省略get,set方法,自己加上
}
?寫好代碼就等頁面了,在templates文件夾下面創建一個students.html文件,編寫如下代碼
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>ID</td>
<td>姓名</td>
<td>年齡</td>
</tr>
<tr th:each="student:${students}">
<td th:text="${student.id}"></td>
<td th:text="${student.name}"></td>
<td th:text="${student.age}"></td>
</tr>
</table>
</body>
</html>
?這里有一個很重要的事情就是,我們使用thymeleaf模板之前必須先引入thymeleaf,如下。
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
?這個很關鍵,不然你就用不了這個thymeleaf語法規則。
?代碼說明:你可以看到th:each 這個語法,是用來遍歷的,類似于for循環,然后我們通過th:text 這個語法來渲染文字。
?運行項目,瀏覽器輸入localhost:8089/getStudents
常用的語法:
<!-- 對象 -->
<div th:object="${student}">
<p th:text="id"></p>
<p th:text="name"></p>
<p th:text="age"></p>
</div>
<!-- 邏輯判斷 -->
th:if
th:else
<!-- 分支控制 -->
th:switch
th:case
<!--循環 -->
th:each
<!-- 運算 -->
<p th:text="${age}%2 == 0"></p>
<!-- 賦制value -->
th:value
<!-- 鏈接 -->
th:href
本期講解就到這里,如果你覺得本文對你有用,可以點個贊,點個關注哦!下一期更精彩!wx search 全棧學習筆記!點個關注不迷路。
文地址:https://dwz.cn/2UR4feq8
作者:yizhiwazi
溫馨提示:Thymeleaf 最為顯著的特征是增強屬性,任何屬性都可以通過th:xx 來完成交互,例如th:value最終會覆蓋value屬性。
一、基礎語法
變量表達式 ${}
使用方法:直接使用th:xx = "${}" 獲取對象屬性 。例如:
<form id="userForm"> <input id="id" name="id" th:value="${user.id}"/> <input id="username" name="username" th:value="${user.username}"/> <input id="password" name="password" th:value="${user.password}"/> </form> <div th:text="hello"></div> <div th:text="${user.username}"></div>
選擇變量表達式 *{}
使用方法:首先通過th:object 獲取對象,然后使用th:xx = "*{}"獲取對象屬性。
這種簡寫風格極為清爽,推薦大家在實際項目中使用。 例如:
<form id="userForm" th:object="${user}"> <input id="id" name="id" th:value="*{id}"/> <input id="username" name="username" th:value="*{username}"/> <input id="password" name="password" th:value="*{password}"/> </form>
鏈接表達式 @{}
使用方法:通過鏈接表達式@{}直接拿到應用路徑,然后拼接靜態資源路徑。例如:
<script th:src="@{/webjars/jquery/jquery.js}"></script> <link th:href="@{/webjars/bootstrap/css/bootstrap.css}" rel="stylesheet" type="text/css">
片段表達式 ~{}
片段表達式是Thymeleaf的特色之一,細粒度可以達到標簽級別,這是JSP無法做到的。
片段表達式擁有三種語法:
使用方法:首先通過th:fragment定制片段 ,然后通過th:replace 填寫片段路徑和片段名。例如:
<!-- /views/common/head.html--> <head th:fragment="static"> <script th:src="@{/webjars/jquery/3.3.1/jquery.js}"></script> </head> <!-- /views/your.html --> <div th:replace="~{common/head::static}"></div>
在實際使用中,我們往往使用更簡潔的表達,去掉表達式外殼直接填寫片段名。例如:
<!-- your.html --> <div th:replace="common/head::static"></div>
值得注意的是,使用替換路徑th:replace 開頭請勿添加斜杠,避免部署運行的時候出現路徑報錯。(因為默認拼接的路徑為spring.thymeleaf.prefix = classpath:/templates/)
消息表達式
即通常的國際化屬性:#{msg} 用于獲取國際化語言翻譯值。例如:
<title th:text="#{user.title}"></title>
其它表達式
在基礎語法中,默認支持字符串連接、數學運算、布爾邏輯和三目運算等。例如:
<input name="name" th:value="${'I am '+(user.name!=null?user.name:'NoBody')}"/>
二、內置對象
官方文檔: 附錄A: Thymeleaf 3.0 基礎對象
官方文檔: 附錄B: Thymeleaf 3.0 工具類
七大基礎對象:
常用的工具類:
三、迭代循環
想要遍歷List集合很簡單,配合th:each 即可快速完成迭代。例如遍歷用戶列表:
<div th:each="user:${userList}"> 賬號:<input th:value="${user.username}"/> 密碼:<input th:value="${user.password}"/> </div>
在集合的迭代過程還可以獲取狀態變量,只需在變量后面指定狀態變量名即可,狀態變量可用于獲取集合的下標/序號、總數、是否為單數/偶數行、是否為第一個/最后一個。例如:
<div th:each="user,stat:${userList}" th:class="${stat.even}?'even':'odd'"> 下標:<input th:value="${stat.index}"/> 序號:<input th:value="${stat.count}"/> 賬號:<input th:value="${user.username}"/> 密碼:<input th:value="${user.password}"/> </div>
如果缺省狀態變量名,則迭代器會默認幫我們生成以變量名開頭的狀態變量 xxStat, 例如:
<div th:each="user:${userList}" th:class="${userStat.even}?'even':'odd'"> 下標:<input th:value="${userStat.index}"/> 序號:<input th:value="${userStat.count}"/> 賬號:<input th:value="${user.username}"/> 密碼:<input th:value="${user.password}"/> </div>
四、條件判斷
條件判斷通常用于動態頁面的初始化,例如:
<div th:if="${userList}"> <div>的確存在..</div> </div>
如果想取反則使用unless 例如:
<div th:unless="${userList}"> <div>不存在..</div> </div>
五、日期格式化
使用默認的日期格式(toString方法) 并不是我們預期的格式:Mon Dec 03 23:16:50 CST 2018
<input type="text" th:value="${user.createTime}"/>
此時可以通過時間工具類#dates來對日期進行格式化:2018-12-03 23:16:50
<input type="text" th:value="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}"/>
六、內聯寫法
<script th:inline="javascript"> var user = [[${user}]];` var APP_PATH = [[${#request.getContextPath()}]]; var LANG_COUNTRY = [[${#locale.getLanguage()+'_'+#locale.getCountry()}]]; </script>
七、國際化
需要了解更多關于國際化的精彩描述請前往 SpringBoot 快速實現國際化i18n 。
例如在國際化文件中編寫了user.title這個鍵值,然后使用#{}讀取這個KEY即可獲取翻譯。
<title th:text="#{user.title}">用戶登陸</title>
八、詳細教程
======== 有了上述基礎后 下面正式開始Thymeleaf 的詳細教程 ==============
首先通過Spring Initializr創建項目,如圖所示:
然后在POM文件引入web 、thymeleaf等依賴:
<dependencies> <dependency><!--Web相關依賴--> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency><!--頁面模板依賴--> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency><!--熱部署依賴--> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> </dependencies>
然后在src/main/resources/application.yml 配置頁面路徑:
spring: thymeleaf: cache: false #關閉緩存 prefix: classpath:/views/ #調整頁面路徑
接著在src/main/java/com/hehe/web/UserController 獲取用戶信息:
@RestController public class UserController { private List<User> userList = new ArrayList<>(); { userList.add(new User("1", "socks", "123456", new Date())); userList.add(new User("2", "admin", "111111", new Date())); userList.add(new User("3", "jacks", "222222", null)); } @GetMapping("/") public ModelAndView index() { return new ModelAndView("user/user", "userList", userList); } } public class User { private String id; private String username; private String password; private Date createTime; //請讀者自行補充 構造器和 get/set方法.. }
開始編寫公共頁面:src/main/resources/views/common/head.html ,其中static為頁面片段:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <!--聲明static為頁面片段名稱--> <head th:fragment="static"> <link th:href="@{/webjars/bootstrap/css/bootstrap.css}" rel="stylesheet" type="text/css"/> <script th:src="@{/webjars/jquery/jquery.js}"></script> </head> </html>
接著編寫用戶列表頁:src/main/resources/views/user/user.html 配合th:each顯示用戶列表信息。
使用說明:這里 th:replace="common/head::static" 表示將引用${spring.thymeleaf.prefix}/common/head.html的static頁面片段,值得注意的是由于替換路徑默認會拼接前綴路徑,所以開頭切勿在添加斜杠,否則在打包成JAR部署運行時將提示報Templates not found... 。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title th:text="用戶信息">User</title> <!--默認拼接前綴路徑,開頭請勿再添加斜杠,防止部署運行報錯!--> <script th:replace="common/head::static"></script> </head> <body> <div th:each="user,userStat:${userList}" th:class="${userStat.even}?'even':'odd'"> 序號:<input type="text" th:value="${userStat.count}"/> 賬號:<input type="text" th:value="${user.username}"/> 密碼:<input type="password" th:value="${user.password}"/> 時間:<input type="text" th:value="${user.createTime}"/> 時間:<input type="text" th:value="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}"/> </div> <script th:inline="javascript"> //通過內聯表達式獲取用戶信息 var userList = [[${userList}]]; console.log(userList) </script> </body> </html>
然后編寫單個用戶頁面:
至此大功告成,然后快速啟動項目,如圖所示:
快速啟動項目
然后訪問用戶列表: http://localhost:8080 ,如圖所示:
然后訪問單個用戶: http://localhost:8080/user/1 ,如圖所示:
<!--引入thymeleaf與Spring Security整合的依賴--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> <version>3.0.2.RELEASE</version> </dependency> <!--引入Spring Security依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!--引入Thymeleaf依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
@EnableWebSecurity public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { //攔截請求 @Override protected void configure(HttpSecurity http) throws Exception { //設置哪些url允許被某種角色訪問 http.authorizeRequests().antMatchers("/").permitAll() .antMatchers("/bronze").hasRole("英勇黃銅") .antMatchers("/silver").hasRole("不屈白銀") .antMatchers("/gold").hasRole("榮耀黃金") .antMatchers("/platinum").hasRole("華貴鉑金") .antMatchers("/diamond").hasRole("璀璨鉆石") .antMatchers("/master").hasRole("超凡大師") .antMatchers("/challenger").hasRole("最強王者"); //啟用登錄功能,可以使用默認的登錄頁,這里使用自定義的login.html頁面 http.formLogin().loginPage("/login"); //啟用注銷功能,(需要提供一個action為/logout的form)并設置注銷后訪問的url,這里注銷后跳轉到首頁 http.logout().logoutSuccessUrl("/"); //啟用rememberMe功能,將用戶信息保存在cookie中 http.rememberMe(); } //授權認證 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //inMemoryAuthentication表示使用基于內存的驗證,還可以使用基于數據庫的驗證等,使用BCrypt編碼對密碼進行加密 //,否則報錯java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("bronze") .password(new BCryptPasswordEncoder().encode("0110")).roles("英勇黃銅") .and().withUser("silver").password(new BCryptPasswordEncoder() .encode("0110")).roles("不屈白銀").and().withUser("gold") .password(new BCryptPasswordEncoder().encode("0110")).roles("榮耀黃金") .and().withUser("platinum").password(new BCryptPasswordEncoder() .encode("0110")).roles("華貴鉑金").and().withUser("diamond") .password(new BCryptPasswordEncoder().encode("0110")).roles("璀璨鉆石") .and().withUser("master").password(new BCryptPasswordEncoder() .encode("0110")).roles("超凡大師").and().withUser("challenger") .password(new BCryptPasswordEncoder().encode("0110")).roles("最強王者"); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
<div align="center" style="margin-top: 15px" sec:authorize="!isAuthenticated()"> <h4 style="color: blue;">歡迎您,親愛的召喚師!<a th:href="@{/login}"> 請登錄</a></h4> </div> <div align="center" style="margin-top: 15px" sec:authorize="isAuthenticated()"> <h4 style="color: blue;">召喚師 <span sec:authentication="name"></span> ! 您的段位為:<span sec:authentication="principal.authorities"></span> </h4> <form th:action="@{/logout}" method="post"> <input type="submit" th:value="注銷登錄"> </form> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('英勇青銅')"> <a th:href="@{/bronze}">點擊領取英勇青銅段位獎勵</a> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('不屈白銀')"> <a th:href="@{/silver}">點擊領取不屈白銀段位獎勵</a> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('榮耀黃金')"> <a th:href="@{/gold}">點擊領取榮耀黃金段位獎勵</a> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('華貴鉑金')"> <a th:href="@{/platinum}">點擊領取華貴鉑金段位獎勵</a> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('璀璨鉆石')"> <a th:href="@{/diamond}">點擊領取璀璨鉆石段位獎勵</a> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('超凡大師')"> <a th:href="@{/master}">點擊領取超凡大師段位獎勵</a> </div> <div align="center" style="margin-top: 100px" sec:authorize="hasRole('最強王者')"> <a th:href="@{/challenger}">點擊領取最強王者段位獎勵</a> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
<div align="center" style="margin-top: 20px"> <a th:href="@{/}">返回首頁</a> </div> <div align="center" style="margin-top: 100px"> <h3>您在本賽季段位為:<span style="color: aqua;font-style: italic">英勇黃銅</span></h3> <h4>獲得皮膚獎勵:<span style="color: peru">銹跡斑斑 布里茨</span></h4> </div> 1 2 3 4 5 6 7 8
<div align="center" style="margin-top: 60px"> <form th:action="@{/login}" method="post"> <p> <label>Username</label> <input type="text" th:name="username"> </p> <p> <label>Password</label> <input type="password" th:name="password"> </p> <p> <label>Remember Me</label> <input type="checkbox" th:name="remember-me"> </p> <div align="center"> <input type="submit" th:value="登錄"> </div> </form> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*請認真填寫需求信息,我們會在24小時內與您取得聯系。