标签:
外化文本把模板代码从模板文件抽取出来,独立放到特定的文件中,例如.properties文件,可以很方便地替换为不同语言的文本表示,外化文本通常叫做消息。
使用#{…}来引用消息
模板文件与属性文件必须要放在同一个目录下,且文件名也要符合规范:
/WEB-INF/templates/home.html
/WEB-INF/templates/home_en.properties
/WEB-INF/templates/home_es.properties
/WEB-INF/templates/home_pt_BR.properties
/WEB-INF/templates/home.properties
 
可对消息使用参数:
home.welcome=?Bienvenido a nuestra tienda de comestibles, {0}! 消息的参数根据java.text.MessageFormat标准语法来指定:<p th:utext="#{home.welcome(${session.user.name})}">
  Welcome to our grocery store, Sebastian Pepper!
</p> 多个参数使用逗号分隔开 消息的键自身也是可以来自变量:<p th:utext="#{${welcomeMsgKey}(${session.user.name})}">
  Welcome to our grocery store, Sebastian Pepper!
</p>
 
上下文是实现接口org.thymeleaf.context.IContext的对象,它把所有模板引擎执行需要的数据包含在一个Map变量中,同时引用用于处理外化文本的Locale。
org.thymeleaf.context.IWebContext继承了org.thymeleaf.context.IContext:
public interface IWebContext extends IContext {
    
    public HttpSerlvetRequest getHttpServletRequest();
    public HttpSession getHttpSession();
    public ServletContext getServletContext();
    
    public VariablesMap<String,String[]> getRequestParameters();
    public VariablesMap<String,Object> getRequestAttributes();
    public VariablesMap<String,Object> getSessionAttributes();
    public VariablesMap<String,Object> getApplicationAttributes();
    
} 它们的实现有两个:
org.thymeleaf.context.Context implements IContext
org.thymeleaf.context.WebContext implements IWebContextWebContext比Context多做的工作有:
把所有请求属性添加到上下文map变量中
添加包含所有请求参数的param上下文变量
添加包含所有会话属性的session上下文变量
添加包含所有ServletContext属性的application上下文变量
 
在执行模板解析前,会设置一个叫执行信息(exeInfo)的特殊变量到所有的上下文对象(实现IContext接口,包括Context和WebContext)中,这个变量有两个可在模板中使用的数据:
${execInfo.templateName} 模板名称
${execInfo.now} 一个Calendar对象,表示引擎开始执行模板的时间
 
保留文本原样th:text标签默认会对标签内的特殊字符做转义处理
th:utext标签可以让标签值中的内容按原样输出
 
使用变量${…}会基于上下文的map变量执行,从map变量中使用OGNL语言获取变量值。
${person.father.name}
${person[‘father‘][‘name‘]}${countriesByCode.ES}
${personsByName[‘Stephen Zucchini‘].age}${personsArray[0].name}${person.createCompleteName()}
${person.createCompleteNameWithSeparator(‘-‘)} 在上下文变量上执行OGNL表达式时,有一些对象在表达式上是可用的,可通过使用#来引用:
#ctx 上下文对象#vars 上下文变量#locale 上下文locale#httpServletRequest (仅Web上下文)HttpServletRequest对象#httpSession (仅Web上下文)HttpSession对象例子:
Established locale country: <span th:text="${#locale.country}">US</span>. 变量表达式也可以写成*{…},所不同的是,星号语法会在一个选定的对象上进行运算,而不是在整个map上下文变量上运算。如果没有选定的对象,则${…}与*{…}所做的事情都是相同的。 使用th:object来选定对象:<div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
    <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div> 等价于:<div>
  <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div> 星号和美元可以混用:<div th:object="${session.user}">
  <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div> 当选定一个对象时,这个对象可以在${…}中通过#object表达式变量来引用:<div th:object="${session.user}">
  <p>Name: <span th:text="${#object.firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div> 如果不选择对象,则两者是等价的:<div>
  <p>Name: <span th:text="*{session.user.name}">Sebastian</span>.</p>
  <p>Surname: <span th:text="*{session.user.surname}">Pepper</span>.</p>
  <p>Nationality: <span th:text="*{session.user.nationality}">Saturn</span>.</p>
</div>   
标准表达式语法简单表达式${…} 变量表达式
*{…} 选择变量表达式
#{…} 消息表达式
@{…} 链接URL表达式
字面量文本字面量:‘one text’
<span th:text="‘working web application‘">template file</span>
数字字面量:0,34,3.0
<span th:text="2013 + 2">1494</span>
布尔字面量:true,false
“== false”写在花括号外面,则比较操作由Thymeleaf标准表达式引擎处理<div th:if="${user.isAdmin()} == false"> ...“== false”写在花括号里面,则由OGNL/SpEL引擎处理<div th:if="${user.isAdmin() == false}"> ...
Null字面量:null
<div th:if="${variable.something} == null"> ...
字面量标志:one,sometext,main,…
数字、布尔、Null三种字面量实际上是字面量token的特例。
这些token可以在标准表达式中得到一些简化,它们的工作原理与文本字面量完全相同(’…’),但只允许字母(A-Za-z)、数字(0-9)、方括号([])、点(.)、横线(-)、下划线(_),因此不能有空白符,不能有逗号等等。
token不需要使用任何引号包围,因此,可使用:<div th:class="content">...</div>替换:<div th:class="‘content‘">...</div>
文本操作字符串连接:+th:text="‘The name of the user is ‘ + ${user.name}"
字面量替换:|The name is ${name}|
字面量替换可以省略“+”操作符:<span th:text="|Welcome to our application, ${user.name}!|">等价于:<span th:text="‘Welcome to our application, ‘ + ${user.name} + ‘!‘">也可以结合其它类型的表达式使用:<span th:text="${onevar} + ‘ ‘ + |${twovar}, ${threevar}|">注意:只有变量表达式${…}才允许出现在|…|字面量替换中,其它的字面量’…’、布尔/数字token、条件表达式等等都不行
 
算法操作二元操作符:+,-,*,/(div),%(mod)
由Thymeleaf标准表达式引擎处理运算
th:with="isEven=(${prodStat.count} % 2 == 0)"由OGNL引擎处理运算th:with="isEven=${prodStat.count % 2 == 0}"
负号(一元操作符):-布尔操作二元操作符:and,or布尔取反(一元操作符):!,not比较及相等操作比较操作符:>,<,>=,<=(gt,lt,ge,le)th:if="${prodStat.count} > 1"
相等操作符:==,!=(eq,ne)th:text="‘Execution mode is ‘ + ( (${execMode} == ‘dev‘)? ‘Development‘ : ‘Production‘)"
条件操作符if-then: (if)?(then)if-then-else:(if)?(the):(else)<tr th:class="${row.even}? ‘even‘ : ‘odd‘"> ... </tr>条件表达式中的三个部分自身也是表达式,也可以是变量(${...},*{...}), 消息(#{...}), URL (@{...}) 或字面量 (‘...‘)条件表达式也可以使用括号来嵌套:<tr th:class="${row.even}? (${row.first}? ‘first‘ : ‘even‘) : ‘odd‘"> ... </tr>else表达式也可以省略,当条件为false时,会返回null:<tr th:class="${row.even}? ‘alt‘"> ... </tr>
default:(value)?:(defaultValue)
这是没有then部分的特殊的条件表达式,又叫做Elvis操作,只有在第一个表达式返回null时,第二个表达式才会运算:<div th:object="${session.user}"> ... <p>Age: <span th:text="*{age}?: ‘(no age specified)‘">27</span>.</p> </div>等价于:<p>Age: <span th:text="*{age != null}? *{age} : ‘(no age specified)‘">27</span>.</p>也可以包含嵌套的表达式:<p> Name: <span th:text="*{firstName}?: (*{admin}? ‘Admin‘ : #{default.username})">Sebastian</span> </p>
综合案例‘User is of type ‘ + (${user.isAdmin()} ? ‘Administrator‘ : (${user.type} ?: ‘Unknown‘)) 
表达式工具对象#dates 与java.util.Date对象的方法对应,格式化、日期组件抽取等等#calendars 类似#dates,与java.util.Calendar对象对应#numbers 格式化数字对象的工具方法#strings 与java.lang.String对应的工具方法:contains、startsWith、prepending/appending等等#objects 用于对象的工具方法#bools 用于布尔运算的工具方法#arrays 用于数组的工具方法#lists 用于列表的工具方法#sets 用于set的工具方法#maps 用于map的工具方法#aggregates 用于创建数组或集合的聚合的工具方法#messages 用于在变量表达式内部获取外化消息的工具方法,与#{…}语法获取的方式相同#ids 用于处理可能重复出现(例如,作为遍历的结果)的id属性的工具方法 
链接URLURL在web模板中是一级重要元素,使用@{…}表示
URL的类型:
绝对URL:http://www.thymeleaf.org相对URL:页面相对: user/login.html上下文相对:/itemdetails?id=3 (服务器上下文名称会被自动添加)服务器相对:~/billing/processInvoice(允许调用同一服务器上的另一个上下文中的URL)协议相对://code.jquery.com/jquery-2.0.3.min.js 
Thymeleaf在任何情况下都可以处理绝对URL,对于相对URL,则需要使用一个实现了IWebContext接口的上下文对象,这个对象包含了来自HTTP请求的信息,这些信息用于创建相对链接。
 
<!-- Will produce ‘http://localhost:8080/gtvg/order/details?orderId=3‘ (plus rewriting) -->
<a href="details.html" 
   th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
<!-- Will produce ‘/gtvg/order/details?orderId=3‘ (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
<!-- Will produce ‘/gtvg/order/3/details‘ (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a> 
Thymeleaf提供预处理表达式的功能。
它是在表壳式正常执行前执行的操作,允许修改最终将要被执行的表达式。
预处理表达式跟正常的一样,但被两个下划线包围住,例如:__${expression}__
假设有一个i18n消息文件Message_fr.properties,里面有一个条目包含了一个调用具体语言的静态方法的OGNL表达式:
article.text=@myapp.translator.Translator@translateToFrench({0}) Messages_es.properties中的等价条目:article.text=@myapp.translator.Translator@translateToSpanish({0})  可以根据locale先创建用于运算表达式的标记片段,本例中,先通过预处理选择表达式,然后让Thymeleaf处理这个选择出来的表达式:<p th:text="${__#{article.text(‘textVar‘)}__}">Some text here...</p> 对于locale为French的情况,上面的表达式经过预处理后,得出的等价物如下:<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">Some text here...</p> 
设置属性值th:attr任何属性值
<form action="subscribe.html" th:attr="action=@{/subscribe}"> <fieldset> <input type="text" name="email" /> <input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/> </fieldset> </form>多个属性一起设置<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
设置指定属性
<input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/><form action="subscribe.html" th:action="@{/subscribe}"><li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>所有的指定属性:| |th:abbr|th:accept|th:accept-charset| |th:accesskey|th:action|th:align| |th:alt|th:archive|th:audio| |th:autocomplete|th:axis|th:background| |th:bgcolor|th:border|th:cellpadding| |th:cellspacing|th:challenge|th:charset| |th:cite|th:class|th:classid| |th:codebase|th:codetype|th:cols| |th:colspan|th:compact|th:content| |th:contenteditable|th:contextmenu|th:data| |th:datetime|th:dir|th:draggable| |th:dropzone|th:enctype|th:for| |th:form|th:formaction|th:formenctype| |th:formmethod|th:formtarget|th:frame| |th:frameborder|th:headers|th:height| |th:high|th:href|th:hreflang| |th:hspace|th:http-equiv|th:icon| |th:id|th:keytype|th:kind| |th:label|th:lang|th:list| |th:longdesc|th:low|th:manifest| |th:marginheight|th:marginwidth|th:max| |th:maxlength|th:media|th:method| |th:min|th:name|th:optimum| |th:pattern|th:placeholder|th:poster| |th:preload|th:radiogroup|th:rel| |th:rev|th:rows|th:rowspan| |th:rules|th:sandbox|th:scheme| |th:scope|th:scrolling|th:size| |th:sizes|th:span|th:spellcheck| |th:src|th:srclang|th:standby| |th:start|th:step|th:style| |th:summary|th:tabindex|th:target| |th:title|th:type|th:usemap| |th:value|th:valuetype|th:vspace| |th:width|th:wrap|th:xmlbase| |th:xmllang|th:xmlspace| |
<input type="button" value="Do it!" class="btn" th:attrappend="class=${‘ ‘ + cssStyle}" /><tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? ‘odd‘">
 
修复的布尔属性<input type="checkbox" name="active" th:checked="${user.active}" />所有修复的布尔属性:-| |th:async|th:autofocus|th:autoplay| |th:checked|th:controls|th:declare| |th:default|th:defer|th:disabled| |th:formnovalidate|th:hidden|th:ismap| |th:loop|th:multiple|th:novalidate| |th:nowrap|th:open|th:pubdate| |th:readonly|th:required|th:reversed| |th:scoped|th:seamless|th:selected|
<table> <tr data-th-each="user : ${users}"> <td data-th-text="${user.login}">...</td> <td data-th-text="${user.name}">...</td> </tr> </table>
data-{prefix}-{name}是编写HTML5自定义属性的标准语法,不需要开发者使用th:*这样的命名空间,Thymeleaf让这种语法自动对所有dialect都可用。
  
遍历基础<tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> </tr>可遍历的对象:实现java.util.Iterable、java.util.Map(遍历时取java.util.Map.Entry)、array、任何对象都被当作只有对象自身一个元素的列表
状态当前遍历索引,从0开始,index属性当前遍历索引,从1开始,count属性总元素数量,size属性每一次遍历的iter变量,current属性当前遍历是even还是odd,even/odd布尔属性当前遍历是第一个,first布尔属性当前遍历是最后一个,last布尔属性<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? ‘odd‘"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> </tr>
 若不指定状态变量,Thymeleaf会默认生成一个名为“变量名Stat”的状态变量:<tr th:each="prod : ${prods}" th:class="${prodStat.odd}? ‘odd‘">
    <td th:text="${prod.name}">Onions</td>
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
  </tr> 
条件运算<tr th:each="prod : ${prods}" th:class="${prodStat.odd}? ‘odd‘"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> <td> <span th:text="${#lists.size(prod.comments)}">2</span> comment/s <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a> </td> </tr>
 
<a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a>
 th:if不只运算布尔条件,它对以下情况也运算为true:
值不为null值为boolean且为true值为数字且非0值为字符且非0值是字符串且不是:“false”,“off”,“no”值不是boolean、数字、字符、字符串如果值为null,则th:if运算结果为false 
<a href="comments.html" th:href="@{/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}">view</a>
th:if的反面是th:unless 
<div th:switch="${user.role}"> <p th:case="‘admin‘">User is an administrator</p> <p th:case="#{roles.manager}">User is a manager</p> </div>
 
<div th:switch="${user.role}"> <p th:case="‘admin‘">User is an administrator</p> <p th:case="#{roles.manager}">User is a manager</p> <p th:case="*">User is some other thing</p> </div>
标签:
原文地址:http://www.cnblogs.com/mark-chan/p/5491775.html