可能是最全的Thymeleaf参考手册(三):标准表达式语法(二)

 

选择变量

 

变量表达式不仅可以写成  ${...},而且还可以写成  *{...}

但是,有一个重要的区别:星号语法针对选定的对象进行评估,而不是整个上下文上。也就是说,只要没有选定的对象,$ 和 * 的语法就完全一样。

什么是选定的对象?就是使用 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>

其中,firstName、lastName、nationality均为user对象中的属性。而选的的对象,正是 ${session.user} 表达式的结果,即用户信息对象。

其等同于:

<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>

此时,#object 表达式变量即等同于 ${session.user}

如前面所说,如果没有任何对象选定,则 $ 和 * 语法是等效的。

<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

 

由于URL在web应用程序中非常重要,Thymeleaf标准方言对其专门有一种特殊语法@,即@{...}。

URL有几种不同的类型:

  • 绝对URL:http://www.thymeleaf.org

  • 相对URL:可以是如下类型:

    • 相对页面:user/login.html

    • 上下文相关:/itemdetails?id=3(服务器上下文根将会自动添加)

    • 相对于服务器:~/oa/userprofile(允许在同一服务器中的另一个上下文(应用程序)中调用URL)

    • 相对于网址协议://code.jquery.com/jquery-2.0.3.min.js

这些表达式的实际处理以及它们到URL的转换是通过注册到 ITemplateEngine 的实现了org.thymeleaf.linkbuilder.ILinkBuilder 接口的对象来完成的。

默认情况下,类 org.thymeleaf.linkbuilder.StandardLinkBuilder 会作为该接口的单个实现被注册,这对于脱机(非Web)和基于Servlet API的Web场景都足够应对。其他场景(例如与非ServletAPI Web框架集成)可能需要链接构建器接口的特定实现。

现在,让我们看看新语法吧,即 th:href 属性

<!-- Will produce 'http://localhost:8080/mall/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" 
   th:href="@{http://localhost:8080/mall/order/details(orderId=${o.id})}">view</a>
​
<!-- Will produce '/mall/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
​
<!-- Will produce '/mall/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>

需要注意:

  • th:href 是修饰符属性,处理后,它将会转换为链接URL,并将该值设置为 <a> 标签的 href 属性的值。

  • 允许URL参数使用表达式(如 orderId=${o.id}),其所需的URL参数编码操作也将会自动执行。

  • 如果参数为多个,这些参数将以逗号分:@{/order/details(id=${orderId},type='FAST')}

  • URL路径中也允许使用变量模板:@{/order/{orderId}/details(orderId=${orderId})}

  • 以 (如 /order/details)开头的相对URL 将自动添加应用程序上下文名称作为前缀。

  • 如果未启用Cookie或尚不知道,则 ";jsessionid=..." 可能会作为后缀添加到相对URL中,以便保留会话。这称为URL重写,Thymeleaf允许通过使用Servlet API中的 response.encodeURL(...) 机制,可针对所有url,以实现自己的重写过滤器。

  • th:href 属性允许在模板中存在有效的 href 静态属性(可选),以便当直接打开原型进行原型设计时,模板链接仍可被浏览器导航。

与消息语法(#{...})一样,URL基也可以是另一个表达式的评估结果:

<a th:href="@{${url}(orderId=${o.id})}">view</a>
<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">view</a>

 

来个例子

我们结合前面已介绍的变量、表达式基础对象、实用对象、链接URL等综合运用一下,做一个左侧导航栏。

<nav class="navbar-default navbar-static-side" role="navigation" th:fragment="left">
  <div class="nav-close"><i class="fa fa-times-circle"></i>
  </div>
  <div class="sidebar-collapse">
    <ul class="nav" id="side-menu">
      <li>
        <a class="J_menuItem" href="index.html" th:href="@{/index}" data-index="0">
          <i class="fa fa-home"></i>
          <span class="nav-label">主页</span>
        </a>
      </li>   
      <li th:each="func : ${funcs}">
        <th:block th:if="${#sets.isEmpty(func.childs)}">
          <a class="J_menuItem" th:href="@{${#strings.startsWith(func.url, '/') ? func.url : '/' + func.url}(g=${func.id})}">
            <i class="fa" th:classappend="${func.icon} ?: 'fa-wrench'"></i>
            <span class="nav-label" th:text="${func.name}">一级功能菜单</span>
          </a>
        </th:block>
        <th:block th:unless="${#sets.isEmpty(func.childs)}">
          <a href="#">
            <i class="fa" th:classappend="${func.icon} ?: 'fa-wrench'"></i>
            <span class="nav-label" th:text="${func.name}">一级功能菜单</span>
            <span class="fa arrow"></span>
          </a>
          <ul class="nav nav-second-level">
            <li th:each="funcChild : ${func.childs}">
              <th:block th:if="${#sets.isEmpty(funcChild.childs)}">
                <a class="J_menuItem" th:href="@{${#strings.startsWith(funcChild.url, '/') ? funcChild.url : '/' + funcChild.url}(g=${funcChild.id})}" th:text="${funcChild.name}">二级功能菜单</a>
              </th:block>
              <th:block th:unless="${#sets.isEmpty(funcChild.childs)}">
                <a href="#"><span class="nav-label" th:text="${funcChild.name}">二级功能菜单</span><span class="fa arrow"></span></a>
                <ul class="nav nav-third-level">
                  <li th:each="funcChildChild : ${funcChild.childs}">
                    <a class="J_menuItem" th:href="@{${#strings.startsWith(funcChildChild.url, '/') ? funcChildChild.url : '/' + funcChildChild.url}(g=${funcChildChild.id})}" th:text="${funcChildChild.name}">三级功能菜单</a>
                  </li>
                </ul>
              </th:block>
            </li>
          </ul>
        </th:block>
      </li>
    </ul>
  </div>
</nav>

 

笔者开通了个人微信公众号【银河架构师】,分享工作、生活过程中的心得体会,填坑指南,技术感悟等内容,会比博客提前更新,欢迎订阅。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值