zoukankan      html  css  js  c++  java
  • Thymeleaf

    th:text及外化文本

    外化文本把模板代码从模板文件抽取出来,独立放到特定的文件中,例如.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 IWebContext

     

    WebContext比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} &gt; 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属性的工具方法

     

    链接URL

    URL在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 |
     
    • HTML5友好的属性及元素名
    <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>
  • 相关阅读:
    线性回归——梯度下降
    Python 实现 KNN(K-近邻)算法
    Python 增加博客园阅读量
    阿里云CentOS安装配置Python3.7及pip3
    OnlineJudge难度与正确度的相关性检验
    jsp、jQuery、servlet交互实现登录功能
    Java Web中提交表单之后跳转到WebContent目录下的子目录里的jsp文件
    python3爬虫——下载unsplash美图到本地
    defer原理、性能、优化
    Python生成器和迭代器
  • 原文地址:https://www.cnblogs.com/mark-chan/p/5491775.html
Copyright © 2011-2022 走看看