지난 기사에서 봄 부팅 (2 개) : 웹 포괄적 인 개발 Thymeleaf에 대한 간단한 소개에서,이 문서는 Thymeleaf의 사용에 대한보다 포괄적이고 상세한 설명을 할 것이다. Thymeleaf는이에 Spring4.0에서 프런트 엔드 템플릿 엔진 Thymeleaf을 할 것을 권장합니다, 새로운 세대의 템플릿 엔진이다.
Thymeleaf 소개
단순히 속도, 프리 마커 유사한 템플릿 엔진, Thymeleaf을 넣어, 그것은 완전히 JSP를 교체 할 수 있습니다. 다른 템플릿 엔진에 비해 다음과 같은 세 가지 매우 매력적인 기능이 있습니다 :
- 1.Thymeleaf Jieke는 예술가 브라우저에서 정적 페이지의 효과를 볼 수 있습니다 네트워크와 비 네트워크의 환경에서 실행뿐만 아니라 서버에서 데이터를 동적 페이지의 효과를 볼 수있는 프로그래머를 할 수 있습니다. 이 HTML 프로토 타입을 지원하고 데이터의 HTML 태그 템플릿 + 디스플레이에 달성하기 위해 추가 속성을 추가 할 수 있기 때문입니다. Thymeleaf 템플릿을 정적으로 실행할 수 있도록 브라우저가 정의되지 않은 HTML 태그 속성의 해석을 무시합니다; 페이지로 반환 할 데이터가있는 경우, Thymeleaf 레이블은 동적 정적 콘텐츠, 동적 디스플레이 페이지를 교체합니다.
- 상자의 특성에서 2.Thymeleaf는-사용합니다. 그것은, 표준 및 봄 표준이 개 방언을 제공합니다 직접 템플릿 JSTL을 변경, 템플릿 매일 세트를 방지하기 위해 JSTL, OGNL 표현식 효과를 달성하기 위해 적용 할 수 레이블을 변경 괴롭혀. 동시에 개발자는 확장 및 사용자 정의 방언을 만들 수 있습니다.
- 3.Thymeleaf 봄이 표준 방언을 제공하며, SpringMVC 옵션 모듈과 완벽한 통합, 신속, 바인딩 속성 편집기, 국제 및 기타 기능의 양식을 얻을 수 있습니다.
표준 표현식 구문
그들은 네 가지 범주로 나누어집니다 :
- 1. 변수 표현식
- 표현식 또는 별표 (*)를 선택합니다
- 표현의 3. 국제 문자
- 4.URL 표현
변수 표현
가변 식 즉 (봄라고도 모델 속성 측면에서)이 EL 봄 OGNL 표현식 또는 표현식입니다. 다음과 같습니다 :
$ {session.user.name}
그들은 HTML 태그를 나타내는 속성합니다 :
<스팬 일 : 텍스트 = " $ {book.author.name} " > <LI 일 : 각 = " 책 : $ {책} " >
선택 (별표) 표현
표현과 같은 표현 변수를 선택하지만, 대신에 다음과 같이 (지도) 수행되는 환경 변수 용기의 미리 선택된 대상을 사용 :*{customer.name}
정의 된 개체 속성 다음 일까지 지정된 개체 :
<DIV 일 : 오브젝트 = " $ {책} " > ... <스팬 일 : 텍스트 = " * {제목} " > ... </ SPAN> ... </ DIV>
텍스트 국제화 표현
국제화 문자 표현은 우리가 외부 파일에서 텍스트 메시지 영역 (.properties 파일)을 얻을 수, 키 인덱스 값은 (선택 사항) 매개 변수의 집합을 제공 할 수 있습니다 사용합니다.
# {main.title}
# {message.entrycreated ($ {ENTRYID})}
이러한 표현 코드 템플릿 파일에서 찾을 수 있습니다 :
<표> ... <제 : 제 텍스트 = " # header.address.city {} " > .. </ 일> <번째 : 제 텍스트 = " # header.address.country {} " > .. </ 일> ... </ 테이블>
URL 표현식
URL 표현식은 유용한 상황 정보를 추가하거나,이 과정은 종종 URL 재 작성 호출되는 URL에 답변을 의미합니다.
@ {/ 주문 / 목록}
URL은 또한 매개 변수를 설정할 수 있습니다 :
@ {/ 주문 / 세부 사항 (아이디 = $ {주문 ID})}
상대 경로 :
@ {../ 문서 / 보고서}
의 이러한 표현을 살펴 보자 :
<form : 제 조치 = " @ {/ createOrder} " > <a href=의 "main.html"th:href= "@{/main}">
변수 표현과 표현 별표 어떤 차이가 있나요?
선택한 개체가 아닌 전체 맥락에서 평가 스타 구문 표현, 당신은 사건의 맥락, 두 개의 차이가 없습니다 고려하지 않으면
선택한 개체 무엇을? 다음과 같이 부모 레이블의 값은 다음과 같습니다
<DIV 일 : 오브젝트 = " $ {session.user} " > <P> 이름 : <스팬 일 : 텍스트 = " * {firstName을} " > 세바스찬 </ SPAN> </ P>. <P> 성 : <스팬 : 제 텍스트 = " * {이 lastName} " > 고추 </ SPAN> </ p>. <p> 국적 : <스팬 : 제 텍스트 = " * {국적} " .> 토성 </ SPAN> </ p> < / DIV>
이것은 정확히 동일합니다 :
<DIV 일 : 오브젝트 = " $ {session.user} " > <P> 이름 : <스팬 일 : 텍스트 = " $ {session.user.firstName} " >. 세바스찬 </ SPAN> </ P> <P> 성 <스팬 : 제 텍스트 = " $ {} session.user.lastName " > 고추 </ SPAN> </ p>. <p> 국적 : <스팬 : 제 텍스트 = " $ {} session.user.nationality " > 토성 </ SPAN>. </ p> </ div>
물론, 달러 기호 및 별표 구문은 혼합 될 수있다 :
<DIV 일 : 오브젝트 = " $ {session.user} " > <P> 이름 : <스팬 일 : 텍스트 = " * {firstName을} " > 세바스찬 </ SPAN> </ P>. <P> 성 : <스팬 : 제 텍스트 = " $ {} session.user.lastName " > 고추 </ SPAN> </ p>. <p> 국적 : <스팬 : 제 텍스트 = " * 국적 {} " .> 토성 </ SPAN> < / p> </ div>
표현 구문 지원
리터럴 (리터럴)
- 텍스트 텍스트 (문자 리터럴) :
'one text', 'Another one!',…
- 디지털 텍스트 (숫자 리터럴) :
0, 34, 3.0, 12.3,…
- 부울 텍스트 (부울 리터럴) :
true, false
- 빈 (널 문자) :
null
- 워드 마크 (리터럴 토큰) :
one, sometext, main,…
동작 텍스트 (텍스트 작업)
- 문자열 연결 (문자열 연결) :
+
- 텍스트 (리터럴 대체) 교체 :
|The name is ${name}|
산술 (연산)
- 바이너리 연산자 (이진 연산자) :
+, -, *, /, %
- 마이너스 (단항) 빼기 기호 (단항 연산자) :
-
부울 연산 (부울 작업)
- 바이너리 연산자 (이진 연산자) :
and, or
- 부울 부정 (단항) 부울 부정 (단항 연산자)
!, not
비교 및 등가물 (비교와 평등)
- (비교기)를 비교 :
>, <, >=, <= (gt, lt, ge, le)
- 등가 연산자 (평등 사업자) :
==, != (eq, ne)
조건 연산자 (조건 연산자)
- 만약-다음 :
(if) ? (then)
- 만약-당시 다른 :
(if) ? (then) : (else)
- 기본값) ?:
(defaultvalue)
이러한 모든 기능은 결합과 중첩 될 수 있습니다 :
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
공통 번째 태그들을입니까?
키워드 | 특징 | 경우 |
---|---|---|
일 : ID | ID를 교체 | <input th:id="'xxx' + ${collect.id}"/> |
일 : 텍스트 | 텍스트 교체 | <p th:text="${collect.description}">description</p> |
일 : utext | HTML 텍스트 교체 지원 | <p th:utext="${htmlcontent}">conten</p> |
일 : 객체 | 객체 교체 | <div th:object="${session.user}"> |
: 제 값 | 속성 할당 | <input th:value="${user.name}" /> |
일 :와 | 변수 할당 연산자 | <div th:with="isEven=${prodStat.count}%2==0"></div> |
일 : 스타일 | 스타일 설정 | th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''" |
일 : 온 클릭 | 이벤트를 클릭 | th:onclick="'getCollect()'" |
일 각 | 속성 할당 | tr th:each="user,userStat:${users}"> |
일 : 경우 | 조건을 결정 | <a th:if="${userId == collect.userId}" > |
일 :하지 않는 한 | 그리고 제 : 대향 판정 만약 | <a th:href="@{/login}" th:unless=${session.user != null}>Login</a> |
일 : HREF | 링크 주소 | <a th:href="@{/login}" th:unless=${session.user != null}>Login</a> /> |
일 : 스위치 | 경우 사용 : 차와 멀티플렉서 | <div th:switch="${user.role}"> |
일 : 경우 | 일 : 스위치의 지점 | <p th:case="'admin'">User is an administrator</p> |
제 : 절편 | 레이아웃 탭, 코드 조각을 정의, 다른 곳에서 편리 인용 | <div th:fragment="alert"> |
일 : 포함 | 도입 레이아웃 탭, 파일의 내용을 대체하는 | <head th:include="layout :: htmlhead" th:with="title='xx'"></head> /> |
일 : 교체 | 전체 태그 파일을 대체하기 위해 도입 레이아웃 탭, | <div th:replace="fragments/header :: title"></div> |
일 : 선택 | 선택 윤곽 선택 | th:selected="(${xxx.id} == ${configObj.dd})" |
일 : SRC | 사진 카테고리 도입 주소 | <img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" /> |
가는 선 | JS 스크립트는 변수 정의를 사용할 수 있습니다 | <script type="text/javascript" th:inline="javascript"> |
일 : 액션 | 주소 양식 제출 | <form action="subscribe.html" th:action="@{/subscribe}"> |
일 : 제거 | 속성 삭제 | <tr th:remove="all"> 1.all:删除包含标签和所有的孩子。2.body:不包含标记删除,但删除其所有的孩子。3.tag:包含标记的删除,但不删除它的孩子。4.all-but-first:删除所有包含标签的孩子,除了第一个。5.none:什么也不做。这个值是有用的动态评估。 |
일 : ATTR | label 속성 세트, 복수의 속성은 쉼표로 구분 될 수있다 | 예를 들어 th:attr="src=@{/image/aa.jpg},title=#{logo}" ,이 라벨은 덜 우아하고, 덜 일반적으로 사용하는 것입니다. |
X 속성, 효과에 우선 순위 : 태그가 일의 복수를 포함 할 수 있기 때문에 라벨의 많은 이름 가장 일반적으로 사용의 몇에있다 :include,each,if/unless/switch/case,with,attr/attrprepend/attrappend,value/href,src ,etc,text/utext,fragment,remove。
일반적인 용도
1, 할당, 문자열 연결
<p th:text="${collect.description}">description</p> <span th:text="'Welcome to our application, ' + ${user.name} + '!'">
字符串拼接还有另外一种简洁的写法
<span th:text="|Welcome to our application, ${user.name}!|">
2、条件判断 If/Unless
Thymeleaf中使用th:if和th:unless属性进行条件判断,下面的例子中,<a>
标签只有在th:if
中条件成立时才显示:
<a th:if="${myself=='yes'}" > </i> </a> <a th:unless=${session.user != null} th:href="@{/login}" >Login</a>
th:unless
于 th:if
恰好相反,只有表达式中的条件不成立,才会显示其内容。
也可以使用 (if) ? (then) : (else)
这种语法来判断显示的内容
3、for 循环
<tr th:each="collect,iterStat : ${collects}"> <th scope="row" th:text="${collect.id}">1</th> <td > <img th:src="${collect.webLogo}"/> </td> <td th:text="${collect.url}">Mark</td> <td th:text="${collect.title}">Otto</td> <td th:text="${collect.description}">@mdo</td> <td th:text="${terStat.index}">index</td> </tr>
iterStat称作状态变量,属性有:
- index:当前迭代对象的 index(从0开始计算)
- count: 当前迭代对象的 index(从1开始计算)
- size:被迭代对象的大小
- current:当前迭代变量
- even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
- first:布尔值,当前循环是否是第一个
- last:布尔值,当前循环是否是最后一个
4、URL
URL 在 Web 应用模板中占据着十分重要的地位,需要特别注意的是 Thymeleaf 对于 URL 的处理是通过语法 @{...}
来处理的。
如果需要 Thymeleaf 对 URL 进行渲染,那么务必使用 th:href
,th:src
等属性,下面是一个例子
<!-- Will produce 'http://localhost:8080/standard/unread' (plus rewriting) --> <a th:href="@{/standard/{type}(type=${type})}">view</a> <!-- Will produce '/gtvg/order/3/details' (plus rewriting) --> <a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
设置背景
<div th:style="'background:url(' + @{/<path-to-image>} + ');'"></div>
根据属性值改变背景
<div class="media-object resource-card-image" th:style="'background:url(' + @{(${collect.webLogo}=='' ? 'img/favicon.png' : ${collect.webLogo})} + ')'" ></div>
几点说明:
- 上例中 URL 最后的
(orderId=${o.id})
表示将括号内的内容作为 URL 参数处理,该语法避免使用字符串拼接,大大提高了可读性 @{...}
表达式中可以通过{orderId}
访问 Context 中的 orderId 变量@{/order}
是 Context 相关的相对路径,在渲染时会自动添加上当前 Web 应用的 Context 名字,假设 context 名字为 app,那么结果应该是/app/order
5、内联 js
内联文本:[[...]] 内联文本的表示方式,使用时,必须先用th:inline="text/javascript/none"
激活,th:inline
可以在父级标签内使用,甚至作为 body 的标签。内联文本尽管比th:text
的代码少,不利于原型显示。
<script th:inline="javascript"> /*<![CDATA[*/ ... var username = /*[[${sesion.user.name}]]*/ 'Sebastian'; var size = /*[[${size}]]*/ 0; ... /*]]>*/ </script>
js 附加代码:
/*[+ var msg = 'This is a working application'; +]*/
js 移除代码:
/*[- */ var msg = 'This is a non-working template'; /* -]*/
6、内嵌变量
为了模板更加易用,Thymeleaf 还提供了一系列 Utility 对象(内置于 Context 中),可以通过 # 直接访问:
- dates : java.util.Date的功能方法类。
- calendars : 类似#dates,面向java.util.Calendar
- numbers : 格式化数字的功能方法类
- strings : 字符串对象的功能类,contains,startWiths,prepending/appending等等。
- objects: 对objects的功能类操作。
- bools: 对布尔值求值的功能方法。
- arrays:对数组的功能类方法。
- lists: 对lists功能类方法
- sets
- maps
...
下面用一段代码来举例一些常用的方法:
dates
/* * Format date with the specified pattern * Also works with arrays, lists or sets */ ${#dates.format(date, 'dd/MMM/yyyy HH:mm')} ${#dates.arrayFormat(datesArray, 'dd/MMM/yyyy HH:mm')} ${#dates.listFormat(datesList, 'dd/MMM/yyyy HH:mm')} ${#dates.setFormat(datesSet, 'dd/MMM/yyyy HH:mm')} /* * Create a date (java.util.Date) object for the current date and time */ ${#dates.createNow()} /* * Create a date (java.util.Date) object for the current date (time set to 00:00) */ ${#dates.createToday()}
strings
/* * Check whether a String is empty (or null). Performs a trim() operation before check * Also works with arrays, lists or sets */ ${#strings.isEmpty(name)} ${#strings.arrayIsEmpty(nameArr)} ${#strings.listIsEmpty(nameList)} ${#strings.setIsEmpty(nameSet)} /* * Check whether a String starts or ends with a fragment * Also works with arrays, lists or sets */ ${#strings.startsWith(name,'Don')} // also array*, list* and set* ${#strings.endsWith(name,endingFragment)} // also array*, list* and set* /* * Compute length * Also works with arrays, lists or sets */ ${#strings.length(str)} /* * Null-safe comparison and concatenation */ ${#strings.equals(str)} ${#strings.equalsIgnoreCase(str)} ${#strings.concat(str)} ${#strings.concatReplaceNulls(str)} /* * Random */ ${#strings.randomAlphanumeric(count)}
使用 Thymeleaf 布局
Spring Boot 2.0 将布局单独提取了出来,需要单独引入依赖:thymeleaf-layout-dialect。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>nz.net.ultraq.thymeleaf</groupId> <artifactId>thymeleaf-layout-dialect</artifactId> </dependency>
定义代码片段
<footer th:fragment="copy"> © 2019 </footer>
在页面任何地方引入:
<body> <div th:insert="layout/copyright :: copyright"></div> <div th:replace="layout/copyright :: copyright"></div> </body>
th:insert 和 th:replace 区别,insert 只是加载,replace 是替换。Thymeleaf 3.0 推荐使用 th:insert 替换 2.0 的 th:replace。
返回的 HTML 如下:
<body> <div> © 2019 </div> <footer>© 2019 </footer> </body>
下面是一个常用的后台页面布局,将整个页面分为头部,尾部、菜单栏、隐藏栏,点击菜单只改变 content 区域的页面
<body class="layout-fixed"> <div th:fragment="navbar" class="wrapper" role="navigation"> <div th:replace="fragments/header :: header">Header</div> <div th:replace="fragments/left :: left">left</div> <div th:replace="fragments/sidebar :: sidebar">sidebar</div> <div layout:fragment="content" id="content" ></div> <div th:replace="fragments/footer :: footer">footer</div> </div> </body>
任何页面想使用这样的布局值只需要替换中见的 content 模块即可
<html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout"> <body> <section layout:fragment="content"> ...
也可以在引用模版的时候传参
<head th:include="layout :: htmlhead" th:with="title='Hello'"></head>
layout 是文件地址,如果有文件夹可以这样写fileName/layout:htmlhead
,htmlhead 是指定义的代码片段 如th:fragment="copy"
文章示例项目
文章内容已经升级到 Spring Boot 2.x
参考
thymeleaf官方指南
新一代Java模板引擎Thymeleaf
Thymeleaf基本知识
thymeleaf总结文章
Thymeleaf 模板的使用
thymeleaf 学习笔记