美文网首页
chapter06_渲染Web视图_4_使用Thymeleaf

chapter06_渲染Web视图_4_使用Thymeleaf

作者: 米都都 | 来源:发表于2019-01-15 17:38 被阅读0次
    • 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用于判断是否进入内部的渲染部分

    相关文章

      网友评论

          本文标题:chapter06_渲染Web视图_4_使用Thymeleaf

          本文链接:https://www.haomeiwen.com/subject/vpnydqtx.html