• spring boot 与 thymeleaf (2): 常用表达式


    在asp.net mvc 中, 有一个视图解析器, 可以支持Razor语法. 使用起来, 是非常的方便, 并且, 写在前台页面的后台方法, 是可调试的. 

    但是在java中, 目前我还没有接触到, 像.net vs 那么强大的功能. 

    对于mvc来说, 视图的解析, 是必不可少的. 实现的功能, 和上面是一样的, 而且, 有很多种, 例如: jsp, freemarker, thymeleaf 等.

    这里, 我主要记录 thymeleaf 的一些学习笔记. 这里不牵涉原理, 只记录使用方法.

    一. 添加依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

     这里如果只添加到这里, 引用的版本, 是比较低的, 如果要使用自己特定的版本, 只需要在 pom.xml 的properties 中指定版本就行了.

    <thymeleaf.version>3.0.5.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>

    二. spring boot 中, thymeleaf 的默认配置

    这里首先看一下, 默认配置接收的类

    /*
     * Copyright 2012-2017 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.boot.autoconfigure.thymeleaf;
    
    import java.nio.charset.Charset;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.util.MimeType;
    
    /**
     * Properties for Thymeleaf.
     *
     * @author Stephane Nicoll
     * @since 1.2.0
     */
    @ConfigurationProperties(prefix = "spring.thymeleaf")
    public class ThymeleafProperties {
    
        private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");
    
        private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");
    
        public static final String DEFAULT_PREFIX = "classpath:/templates/";
    
        public static final String DEFAULT_SUFFIX = ".html";
    
        /**
         * Check that the template exists before rendering it (Thymeleaf 3+).
         */
        private boolean checkTemplate = true;
    
        /**
         * Check that the templates location exists.
         */
        private boolean checkTemplateLocation = true;
    
        /**
         * Prefix that gets prepended to view names when building a URL.
         */
        private String prefix = DEFAULT_PREFIX;
    
        /**
         * Suffix that gets appended to view names when building a URL.
         */
        private String suffix = DEFAULT_SUFFIX;
    
        /**
         * Template mode to be applied to templates. See also StandardTemplateModeHandlers.
         */
        private String mode = "HTML5";
    
        /**
         * Template encoding.
         */
        private Charset encoding = DEFAULT_ENCODING;
    
        /**
         * Content-Type value.
         */
        private MimeType contentType = DEFAULT_CONTENT_TYPE;
    
        /**
         * Enable template caching.
         */
        private boolean cache = true;
    
        /**
         * Order of the template resolver in the chain. By default, the template resolver is
         * first in the chain. Order start at 1 and should only be set if you have defined
         * additional "TemplateResolver" beans.
         */
        private Integer templateResolverOrder;
    
        /**
         * Comma-separated list of view names that can be resolved.
         */
        private String[] viewNames;
    
        /**
         * Comma-separated list of view names that should be excluded from resolution.
         */
        private String[] excludedViewNames;
    
        /**
         * Enable MVC Thymeleaf view resolution.
         */
        private boolean enabled = true;
    
        ......
    }

    从这里可以看到, 默认的是 html 格式的, 且放在 classpath:/templates/ 目录下. 一般情况下, 我们不需要再对thymeleaf进行配置, 但是在开发的过程中, 可能要屏蔽缓存功能.  最后我们要做的, 只是将路径拼接进去就行了.

    application.yml文件中, 可以禁用缓存.

    spring:
      thymeleaf:
        cache: false

    三. 基本使用

    1. 表达式

      变量表达式: ${...}   

      选择变量表达式: *{...}

      URL表达式: @{...}  

      消息表达式: #{...} 

      片段表达式: ~{...}

    2. 文字

      文本: '123', 'abc'

      数字: 1,2,0.5

      布尔: true, false

      空: null

    3. 文本操作

      字符串连接: +

      文本替换: |双竖线隔起来 ${name}|

    4. 算数运算符

      二进制运算法(加减乘除,取模): +    -    *    /    %

    5. 负号: -

    6. 布尔运算符

      and   or    not    !

    7. 比较和相等运算符

      比较运算符(这里建议使用英文字符代替 >  >=  <  <=)   gt    ge    lt     le

      相等运算符: ==   !=  

    8. 条件运算符

      三元运算符:  if(...)? 'then' : 'else'

      if(...)? 'then'  这里没有else, 因为else默认为 ''

      为空判断   (aaa)?:bbb   如果aaa为空, 则使用bbb的值, 否则使用aaa

    9. 哑操作符  _  (一个下划线)

    接下来对以上部分进行测试.

    controller:

    package org.elvin.learn.springboot.controller;
    
    import org.elvin.learn.springboot.pojo.Book;
    import org.joda.time.DateTime;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.thymeleaf.util.MapUtils;
    
    import java.util.*;
    
    @Controller
    @RequestMapping("thy")
    public class ThyController {
    
        @GetMapping("index")
        public String index(Model model) {
            model.addAttribute("book0", null);
    
            Book book = new Book("springmvc", new DateTime().toString("yyyy-MM-dd"), 10000L);
            model.addAttribute("book", book);
    
            Book book1 = new Book("springboot", new DateTime().toString("yyyy-MM-dd"), 21000L);
            model.addAttribute("book1", book1);
    
            model.addAttribute("color", "red");
            model.addAttribute("msg", "welcome");
            model.addAttribute("nowTime", new Date());       
    
            return "thy/index";
        }
    }

    html:

    大体框架

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>Title</title>
        <!--@ { } 链接网址表达式, 会自动加入虚拟路径-->
        <link th:href="@{/bootstrap-3.3.7/css/bootstrap.css}" rel="stylesheet"/>
        <link th:href="@{/bootstrap-3.3.7/css/bootstrap-theme.css}" rel="stylesheet"/>
        <style th:inline="css">
            /*通过[ [ $ { }]]的方式访问model中的属性*/
            .bgcolor {
                background-color: [[${color}]]
            }
        </style>
    </head>
    <body>
    
    
    <script th:src="@{/js/jquery1.11.1/jquery-1.11.1.js}" type="text/javascript"></script>
    <script th:src="@{/bootstrap-3.3.7/js/bootstrap.js}" type="text/javascript"></script>
    <script th:inline="javascript">
        $(function () {
            var book = [[${book}]];
            console.log(book.name);
        });
    </script>
    </body>
    </html>

    数据准备:

    在messages.properties中加入以下数据:

    welcome=welcome here! {0}
    hello={0} say hello to {1}
    startWorkd=start from here

    在templates中新建文件夹 common, 在下面建两个文件 footer.html, header.html

    <!DOCTYPE html>
    <html  xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8" />
        <title>Title</title>
    </head>
    <body>
        <div th:fragment="footerDiv">
            <p>common.footer 底部菜单</p>
        </div>
    </body>
    </html>
    
    <!DOCTYPE html>
    <html  xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8" />
        <title>Title</title>
    </head>
    <body>
        <div id="headerDiv">
            <p>common.header 头部菜单</p>
        </div>
    </body>
    </html>

    接下来, 就是在里面添加内容了.

    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">URL表达式 / 消息表达式</h3>
            <!--
                URL 表达式
            -->
            <a style="background-color: #0f0f0f" th:href="@{/thy/index(lang='en_US')}">English(US)</a>
            <a style="background-color: #0f0f0f"
               th:href="@{http://localhost:8080/springboot/thy/index?lang=zh_CN}">简体中文</a>
        </div>
        <div class="panel-body">
            <!--
           1. # { }消息表达式 : 替换文本
           1.1 文本中, 预留参数
           1.2 消息key用变量替换
       -->
            <!--1.1 在消息中加入参数, 多个参数, 在传值的时候用逗号隔开-->
            <p th:text="#{startWorkd}"></p>
            <p th:utext="#{welcome(${book.name})}">hahaha</p>
            <p th:utext="#{hello(${book.name}, ${bookList[1].name})}">hahaha</p>
            <!--1.2 消息用变量替换-->
            <p th:utext="#{${msg}(${book.name})}">hahaha</p>
        </div>
    </div>
    
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">选择变量表达式</h3>
        </div>
        <div class="panel-body">
            <!-- 选择变量表达式 * { } -->
            <p th:object="${book0 ?: book1}">
                <span th:text="*{name}"></span>
                <span th:text="*{price gt 10000}?'大于100元':'小于等于100元'"></span>
                <span th:text="*{publishTime.length() ge 10}?'时间长度过长'"></span>
            </p>
    
            <p>
                <!--星号语法计算所选对象而不是整个上下文的表达式,
                所以, 只要没有选定的对象, $ 和 * 语法就完全相同-->
                <span th:text="*{book.name}"></span>
                <span th:text="*{book.price} / 100 + '元'"></span>
                <span th:text="*{book.publishTime}"></span>
            </p>
        </div>
    </div>
    
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">选择变量表达式</h3>
        </div>
        <div class="panel-body">
            <div style="display:none">
                <!--assert 都成立才会执行, 否则抛出异常
                 th:assert="${!#strings.isEmpty(onevar)},${!#strings.isEmpty(twovar)}"
                -->
                <!--这里将模板定义成了函数的方式,
                temp1表示函数名, name1, name2 表示参数, 不同的是, 可以不写在这里, 直接在下面用的时候会写也可以-->
                <div th:fragment="temp1(name1, name2)">
                    <span th:utext="|book: ${name1} , book1: ${name2}|"></span>
                </div>
                <!--th:assert="${price > 100}, ${!#strings.isEmpty(name)}"-->
                <div th:fragment="temp2">
                    <span th:utext="'book: ' + ${name} + ', price: ' + ${price}"></span>
                </div>
            </div>
    
            <!--replace可以替换能成insert,但是他们之间是有区别的, insert会保留当前标签-->
            <div th:replace=":: temp1(${book.name}, ${book1.name})"></div>
            <div th:insert="~{:: temp2(name=${book.name}, price=${book.price})}"></div>
            <!--include官方3.0后不推荐使用-->
            <div th:include=":: temp1(name1=${book.name}, name2=${book1.name})"></div>
    
            <!--引入外部的文件中的某一部分内容-->
            <div th:insert="~{common/header :: #headerDiv}"></div>
            <div th:insert="~{common/footer :: footerDiv}"></div>
    
            <!--这里可以通过判断表达式来控制插入什么, 或者什么也不插入-->
            <div th:insert="_">啥也不插入, 也不替换任何东西</div>
            <div th:insert="${book0 == null}? ~{:: temp1(${book.name}, ${book1.name})}:~{}"></div>
        </div>
    </div>

    结果:

     

     

      

  • 相关阅读:
    AWR报告生成
    ios-html-get/post差额,简而言之(MS)CheckST
    2015第33周一
    2015第32周日
    2015第32周六
    2015第32周五
    2015第32周四
    2015第32周三
    2015第32周二
    2015第32周一
  • 原文地址:https://www.cnblogs.com/elvinle/p/8032394.html
Copyright © 2020-2023  润新知