chapter06_渲染Web视图_4_使用Thymeleaf

  • JSP的问题

    (1) JSP及其标签库缺乏良好的格式

    (2) JSP与Servlet紧耦合,应用场景受限

  • Thymeleaf

    (1) 原生模板,不依赖标签库

    (2) 不仅限于Servlet

  • 配置Thymeleaf视图解析器

    (1) 需要添加3个bean:ThymeleafViewResolver(将逻辑视图名称解析为Thymeleaf模板视图)、SpringTemplateEngine(处理模板并渲染结果)、TemplateResolver(加载Thymeleaf模板)

    (2) JavaConfig示例

    WebConfig.java

      @Configuration
      @EnableWebMvc
      @ComponentScan("spittr.web")
      public class WebConfig extends WebMvcConfigurerAdapter {
    
          @Bean
          public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
    
              ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
              viewResolver.setTemplateEngine(templateEngine);
      
              return viewResolver;
          }
    
          @Bean
          public SpringTemplateEngine templateEngine(TemplateResolver templateResolver) {
    
              SpringTemplateEngine templateEngine = new SpringTemplateEngine();
              templateEngine.setTemplateResolver(templateResolver);
      
              return templateEngine;
          }
    
          @Bean
          public TemplateResolver templateResolver() {
    
              TemplateResolver templateResolver = new ServletContextTemplateResolver();
      
              templateResolver.setPrefix("/WEB-INF/views/");
              templateResolver.setSuffix(".html");
              templateResolver.setTemplateMode("HTML5");
       
              return templateResolver;
          }
    
          ...
      }
    

    类似于InternalResourceViewResolver,templateResolver同样要设置prefix,suffix,并且要设置templateMode为html5

  • Thymeleaf模板

    (1) Thymeleaf很大程度上就是html文件。它没有标签,靠自定义的命名空间,为标准的html标签集合添加Thymeleaf属性实现功能(即声明了xmlns:th="http://www.thymeleaf.org"之后,用th:xxx来使用自定义元素).

    (2) Thymeleaf可以按照原始的方式进行编辑和渲染。即便不经过任何特殊的处理,包含了Thymeleaf模板的html文件也可以加载到浏览器上,不会产生和JSP文件一样的"奇怪"效果

    (3) 声明Thymeleaf命名空间

    home.html

      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:th="http://www.thymeleaf.org">
    
      ...
    

    (4) 示例1:home.html

      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:th="http://www.thymeleaf.org">
      <head>
          <title>Spitter</title>
          <link rel="stylesheet" type="text/css" th:href="@{/resources/style.css}"/>
      </head>
    
      <body>
    
          <div id="header" th:include="page::header"></div>
    
          <div id="content">
    
              <h1>Welcome to Spitter</h1>
    
              <a th:href="@{/spittles}">Spittles</a> |
              <a th:href="@{/spitter/register}">Register</a>
    
          <br/>
          </div>
    
          <div id="footer" th:include="page::copy">
          </div>
      </body>
    
      </html>
    

    th:href类似于<c:url>和原生的href,代表资源url;它可以包含Thymeleaf表达式,计算动态的值。 @{...}用来计算相对于URL的路径

    th:include类似于Apache Tiles的页面布局,对于通用页面page.html,可以引用过来。a::b中的b要在a.html中的 th:fragment 指定

    page.html

      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:th="http://www.thymeleaf.org">
      
      <body>
    
          <div th:fragment="header">
              <a th:href="@{/}">
                  <img th:src="@{/resources/images/spitter_logo_50.png}" border="0"/>
              </a>
          </div>
    
          <div>
              Content goes here
          </div>
    
          <div th:fragment="copy">
              Copyright &copy; Craig Walls
          </div>
    
      </body>
      </html>
    

    (5) 示例2:spittles.html

      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:th="http://www.thymeleaf.org">
    
      ...
    
      <body>
          <div id="header" th:include="page :: header"></div>
    
          <div id="content">
              
              ...
    
              <div class="listTitle">
                  <h1>Recent Spittles</h1>
                  <ul class="spittleList">
                      <li th:each="spittle : ${spittleList}" th:id="'spittle_' + ${spittle.id}">
                          <div class="spittleMessage" th:text="${spittle.message}">Spittle message
                          </div>
                          <div>
                              <span class="spittleTime" th:text="${spittle.time}">spittle timestamp
                              </span>
                              <span class="spittleLocation" th:text="'{' + ${spittle.latitude} + ', ' + ${spittle.longitude} + ')'">lat, long
                              </span>
                          </div>
                      </li>
                  </ul>
              </div>
          </div>
    
          <div id="footer" th:include="page :: copy"></div>
      </body>
      </html>
    

    {xxx}是变量表达式{spittleList}会得到model中key为"spittleList"的对象;

      <li>标签
    

    上的th:each属性可以从容器中取一个元素(这里面叫做spittle),然后在别的地方可以使用${spittle.xxx};

    th:text类似于<c:out>,用于输出文本,并且可以动态输出变量的值;

    对于动态字符串拼接,例如 th:text="'{' + {spittle.latitude} + ', ' +{spittle.longitude} + ')'",使用'xxx'代表某个子字符串,并且可以动态拼接变量的值(不一定是字符串,有toString()方法即可)

    (5) 示例3: registerForm.html

      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:th="http://www.thymeleaf.org">
    
      ....
    
      <body>
    
          <div id="header" th:include="page::copy">
          </div>
    
          <div id="content">
    
              <h1>Register</h1>
    
              <form method="POST" th:object="${spitter}">
    
                  <div class="errors" th:if="${#fields.hasErrors('*')}">
                      <ul>
                          <li th:each="err : ${#fields.errors('*')}" th:text="${err}">
                              Input is incorrect
                          </li>
                      </ul>
                  </div>
    
                  <label th:class="${#fields.hasErrors('firstName')}? 'error'">First Name</label>:
                  <input type="text" th:field="*{firstName}" th:class="${#fields.hasErrors('firstName')}? 'error'"/>
                  <br/>
    
                  <label th:class="${#fields.hasErrors('lastName')}? 'error'">Last Name</label>:
                  <input type="text" th:field="*{lastName}" th:class="${#fields.hasErrors('lastName')}? 'error'"/>
                  <br/>
    
                  <label th:class="${#fields.hasErrors('email')}? 'error'">Email</label>:
                  <input type="text" th:field="*{email}" th:class="${#fields.hasErrors('email')}? 'error'"/>
                  <br/>
    
                  <label th:class="${#fields.hasErrors('username')}? 'error'">Username</label>:
                  <input type="text" th:field="*{username}" th:class="${#fields.hasErrors('username')}? 'error'"/>
                  <br/>
    
                  <label th:class="${#fields.hasErrors('password')}? 'error'">Password</label>:
                  <input type="password" th:field="*{password}" th:class="${#fields.hasErrors('password')}? 'error'"/>
                  <br/>
    
                  <input type="submit" value="Register"/>
              </form>
          </div>
    
          <div id="footer" th:include="page :: copy">
          </div>
      </body>
      </html>
    

    th:object用于表单form的数据模型绑定,这里绑定了spitter;

    *{}是选择表达式,和${}不同,它是基于某一个选中对象计算的,因此

    th:field="*{firstName}代表 spitter.firstName;

      #fields是
    

    Thymeleaf内置对象,类似的还有HttpSession等,它可以用来检查是否有错误;

    <label th:class="${#fields.hasErrors('firstName')}? 'error'">会检查 spitter.firstName是否有错误,如果有错误,当前label的class置为label.error,然后根据css中的label.error渲染成错误显示的效果;

    th:field="*{email}"的效果是将value属性设置为spitter.email的值,同时name属性设置为email;

    th:if用于判断是否进入内部的渲染部分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值