• Thymeleaf模板的使用


    使用模板的要点:
        页面主体结构固定,具体参数可变,尽可能让参数动态化,才能提高模板的复用性

    ===================================================================
    Thymeleaf's core  is a DOM processing engine


    Processor: An Object which applies some logic to a DOM node


    Standard Dialect: a set of processor,provided by Thymeleaf core library


    Template Engine :  can be configured several dialects at a time,called  process chain

    ================================================================
    Template Resolver
    Template Resolvers are objects  that  implement an  interface  from  the Thymeleaf API called org.thymeleaf.templateresolver.ITemplateResolver

    public TemplateResolution resolveTemplate(final TemplateProcessingParameters    templateProcessingParameters);

    All implementaion class :
        -ClassLoaderTemplateResolver
        -FileTemplateResolver
        -ServletContextTemplateResolver
        -UrlTemplateResolver


    Initial Template Engine use ServletContextTemplateResolver
        private static void initializeTemplateEngine() {
            
            ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
            
            // XHTML is the default mode, but we will set it anyway for better understanding of code
            templateResolver.setTemplateMode("XHTML");
            
        // This will convert "home" to "/WEB-INF/templates/home.html"
        // 设置模板的前置路径
            templateResolver.setPrefix("/WEB-INF/templates/");
        //设置模板统一的后缀名
            templateResolver.setSuffix(".html");

            // Set template cache TTL to 1 hour. If not set, entries would live in cache until expelled by LRU
            templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
            
            // Cache is set to true by default. Set to false if you want templates to
            // be automatically updated when modified.
            templateResolver.setCacheable(true);
            
            templateEngine = new TemplateEngine();
            templateEngine.setTemplateResolver(templateResolver);
            
        }

    1.new one TemplateResolver instance
    2.config the resolver
    3.new Template engine
    4.set resolver to this engine
    5.invoke engine's process method to work

    ============================================================================

    <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd">

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


    或者使用下面的文档声明也可以,这样就没有Thymeleaf对文档的校验功能了,因为没有引入对应的DTD,而且IDE可能会提示错误,但是不影响对模板的解析。
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    ============================================================================
    #{}
    specify  that a  text should correspond  to a specific message
    引用外部文件(message)中的内容,进行替换
    首先,需要指定外部文件的位置,如果没有指定,则使用默认的Standard Message Resolver
    会到/WEB-INF/templates/下寻找properties文件
    home_en.properties文件是如何被定为到的呢?
    通过WebContext ctx = new WebContext(request, response, servletContext, request.getLocale());
    其中,request.getLocale()就说明了当前系统的所在地,就能确定读取en/zh_CN了。
    当然,可以配置外部文件的位置!

    th:text="#{home.welcome}"
    The th:text attribute, which evaluates its value expression and sets the result of this evaluation as the body of  the  tag  it is  in
    th:text 计算表达式的结果,并使用这个结果来替换当前标签中的内容

    ============================================================================
    public void process(
        final HttpServletRequest request, final HttpServletResponse response,
        final ServletContext servletContext, final TemplateEngine templateEngine) 
        throws Exception {

        WebContext ctx = new WebContext(request, response, servletContext, request.getLocale());
        ctx.setVariable("today", Calendar.getInstance());

        templateEngine.process("home", ctx, response.getWriter());

    }

    Thymeleaf中提供了2个实现IContext的实现类
        org.thymeleaf.context.Context   implements  IContext
        org.thymeleaf.context.WebContext   implements  IWebContext
    WebContext 提供了更多的方法可用

    =============================================================================
    Unescaped Text
    照原样对文本进行输出,不对> < 进行转义

    th:utext="<b>Big Character</b>" 将输出为:<b>Big Character</b>

    =============================================================================
    Using and displaying variables

    1.设置变量
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
        Calendar cal = Calendar.getInstance();
        WebContext ctx = new WebContext(request, servletContext, request.getLocale());
        ctx.setVariable("today", dateFormat.format(cal.getTime()));
        templateEngine.process("home", ctx, response.getWriter());
    2.在模板中使用变量
        th:text="${today}"
        
    3.使用Thymeleaf提供的内置变量,不用提前设置,直接在模板中使用
        th:text="${#calendars.format(today,'dd MMMM yyyy')}"
    ==============================================================================
     Thymeleaf Standard Dialect:  the Thymeleaf Standard Expression syntax

     Thymeleaf 支持的运算符和表达式的应用
     所有的操作符都可以嵌套使用,非常强大!

     1.Text literals: '...'
     2.Number literals: 0,1.0,12.3,etc

     Simple expression: 表达式语法
         1.Message expression : #{}
         2.Variable expression : ${}
         3.Link URL expression: @{}
         4.Selection Variable expression: *{}
            结合th:object使用,在某个范围内进行变量的查找,而不是在context中查找,缩小了查询的范围,效率如何呢?
            如何没有与th:object结合使用,*{}与${}效果一样,因为其范围自动扩展到context。

     Binary operations:  运算符
         1.String concatenation: +
         2.Arithetic operatiors : +, -, *, /, %
         3.Comparators: >, <, >=, <=
         4.Boolean operators: and, or
         5.Equality operators: ==, !=

     Unary operations:
         1.Minus sign(): -  负号
         2.Boolean negation: !, not 否定符

     Conditional operators: 条件表达式
         1.If-then-else: (if)?(then):else 三元运算符
         2.If-then: (if) ? (then) ,省略了else部分,如果条件不成立,返回null
         3.Default: (value)?:(defaultValue) , use second value only first is null 

    All  this operations can be combined and nested: 
        'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown')


    =================================================================================
    Message  在模板中获取消息
        动态指定message的内容/甚至可以动态指定访问哪个message
        th:utext="#{home.welcome(${session.user.name})}",其中${session.user.name}作为参数,替换home.welcome的映射文本中的{0}
        th:utext="#{${welcomeMsgKey}(${session.user.name})}",其中${welcomeMsgKey}动态指定message文件中的key

    ==================================================================================
    Variables  在模板中获取数据
         ${...}  expressions are  in  fact OGNL  (Object-Graph Navigation Language) expressions executed
    on  the map of variables contained  in  the context.

         模板中获取变量值的方式,使用${},针对不同类型数据,用法如下:

        /*
        * Access to properties using the point (.). Equivalent to calling property getters.
        * 通过.进行导航,相当于调用getters()
        */
        ${person.father.name}

        /*
        * Access to properties can also be made by using brackets ([]) and writing
        * the name of the property as a variable or between single quotes.
        * 使用[]等效于使用. ,但是[]在某些场合能完成.不能完成的任务
        */
        ${person['father']['name']}

        /*
        * If the object is a map, both dot and bracket syntax will be equivalent to
        * executing a call on its get(...) method.
        * 访问Map集合
        */
        ${countriesByCode.ES}
        ${personsByName['Stephen Zucchini'].age}

        /*
        * Indexed access to arrays or collections is also performed with brackets,
        * writing the index without quotes.
        * 访问数组
        */
        ${personsArray[0].name}

        /*
        * Methods can be called, even with arguments.
        * 调用对象的方法
        */
        ${person.createCompleteName()}
        ${person.createCompleteNameWithSeparator('-')}

    =======================================================================================
    Expression utility objects  在模板中使用内置对象
    内置对象,提供了很多方便的功能,日期格式化,字符串处理,数字格式化等
        #dates, formatting,component extraction,etc
        #calendars
        #numbers, formatting numeric objects.
        #strigns, contains,startsWith,prepending/appending,etc
        #bools
        #arrays
        #lists
        #sets
        #maps
        #aggregates, creating aggregates on arrays or collections
        #messages, equal to using #{}
        #ids, deal with id attributes, eg: as a result of an iteration
        #ctx等等,还有很多!

    ======================================================================================
    Link URLs  在模板中使用URL链接
        @{}
    Several types of URLs:
        1.Absolute URL,like http://localhost:8080/thymeleaf
        2.Relative URL,which can be:

            Page-relative,like: user/login.html 页面相对定位

            Context-relative,like: /itemdetails?id=1 (context name in server will be added automatically)项目根路径定位,模板解析时会自动加上应用程序的名称作为前缀

            Server-relative,like: ~/billing/processInvoice (allow calling URLs in another context in the same server) 相同服务器根目录下的定位

        如何要使用相对定位,必须指定一个实现了IWebcontext接口的对象,因为需要从其中获取httprequest对象,从而得到应用程序的根路径,才能处理相对路径

        相对路径,并且在URL上使用OGNL表达式取参数,而且themeleaf会自动对URL进行编码:
            <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
            <a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">view</a>

    =======================================================================================
    Literals    模板中使用简单文本
        字符串/数字
            a.原样输出
                <p>The year is <span th:text="2011">1492</span>.</p>
            b.字符串拼接
                th:text="'The name of the user is ' + ${user.name}"

    ========================================================================================
    Arithmetic operations 模板中对变量进行算数运算 
    + - * / %
    有两种计算方式,都可以。
        1.使用Thymeleaf进行运算--->先OGNL表达式取到变量值,然后thymeleaf再进行运算
            th:with="isEven=(${prodStat.count} % 2 == 0)"

        2.使用OGNL进行运算--->直接在OGNL表达式中进行运算
            th:with="isEven=${prodStat.count % 2 == 0}"

    ========================================================================================
    Comparators and Equality 模板中使用比较符和等号
        模板中不能直接使用 > < >= <=
        需要进行转义:
            > gt;
            < lt;
            >= ge; gte;
            <= le; lte;
            == eq;
            != ne; neq;

        th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"

    =======================================================================================
    Conditional expressions 三元运算,第一个表达式的结果为boolean类型

        if ? then : else ---> A ? B : C

        <tr th:class="${row.even}? 'even' : 'odd'"> 设置tr的class属性,用来控制行的显示效果很方便
        
        嵌套使用条件表达式:
        <tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'"> 灵活控制首行,偶数行,奇数行的class属性值,便于进行css样式定义

        还可以省略else部分,当表达式结果为false,返回null,否则返回'alt'
        <tr th:class="${row.even}? 'alt'">
            ...
        </tr>
    ======================================================================================
    Default Expression 具有默认值的表达式,第一个表达式的结果只要不为null,就取第一个表达式的结果
        
        being  the second one evaluated only  in  the case of  the first one  returning null .
        
        A ?: B  ---> A不为null,则取A,否则取B
        
        如果第一个表达式的计算结果为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>

            
    =========================================================================================
    静态方法的调用
        <p th:text="${@myapp.translator.Translator@translateToFrench('textVar')}">Some text here...</p>

    ==========================================================================================
    ******************************************************************************************
    Setting the value of any attribute 在模板中对目标设置任何属性,action, class, value, etc

    非常强大,不仅处理HTML模板方便,处理FO-XSL(PDF模板)一样通用。
        设置action属性
        <form action="subscribe.html" th:attr="action=@{/subscribe}">

        设置value属性
        <input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>

        一次设置多个属性
        <img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}"/>
        模板处理后的结果--->  <img src="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />

        设置属性更优雅的方式(仅在HTML模板中有效,处理PDF模板,只能用th:attr=""来实现,因为PDF模板中的属性在Thymeleaf中好像没有定义)
            <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>
            Themeleaf支持HTML中几乎所有的属性定义,使用时具体参考Thymeleaf的手册
            th:bgcolor,th:border,th:cellpadding,th:cellspacing, th:colspan,th:align,th:src,th:width,th:size 等等

    控制样式:
        第一种方式直接在tr上定义css样式,如bgcolor,border等
        第二种方式,在tr上定义class属性,通过外部css样式进行控制。(复杂样式,采用第二种方案)

    ============================================================================================
    Appending and prepending 在已有属性上追加属性
        th:attrappend  追加
        th:attrprepend 放到前面
        
        <input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />
        ---> <input type="button" value="Do it!" class="btn warning" />
        
        遍历prods集合,每次生成一行
        <tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">
            <td>${prod.name}</td>
        </tr>
    =============================================================================================
    Fixed-value boolean attributes  设置某些具有固定值的属性
    XHTML/HTML5中,有一些特殊的属性,要么没有值,要么为某个固定的值
        checked
        selected
        disabled
        mutiple
        readonly
    如果计算结果为true,则使用它的固定值,否则不处理。
    <input type="checkbox" name="active" th:checked="${user.active}" />

    还有:
        th:autofocus
        th:default
        th:hidden
        ...

    ===============================================================================================
    ***********************************************************************************************
    Iteration 循环遍历

    th:each="obj : ${objList}"  循环所在标签的片段,每次片段中用到的都是当前遍历到的对象

        后台准备数据
        public void process(
            HttpServletRequest request, HttpServletResponse response,
            ServletContext servletContext, TemplateEngine templateEngine) {
            ProductService productService = new ProductService();
            List<Product> allProducts = productService.findAll();
            WebContext ctx = new WebContext(request, servletContext, request.getLocale());
            ctx.setVariable("prods", allProducts);
            templateEngine.process("product/list", ctx, response.getWriter());
        }

        模板中进行遍历,每次遍历生成一个tr,td列取到的对象为当前遍历到的对象
        <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>

    Keeping    iteration status 跟踪迭代过程中的状态变化
        遍历过程中,提供了如下属性:
            index    starting with 0
            count    starting with 1
            size    total amount of elements in the iterated variables
            current    current object
            even/odd    boolean value,第偶数个/奇数个
            first/last    boolean value.第1个/最后1个

        在th:each中,在iter variable变量后面,定义一个status variable,通过该变量来获取遍历过程中的状态
        <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">

    prefix    前缀
    suffix    后缀
        If you don't explicitly set an  iteration variable, Thymeleaf will  always create one  for you by suffixing 'Stat' to  the name of  the iter variable。
        如果没有定义status variable,thymeleaf会自动为我们提供一个来使用,通过在iter variable后面添加后缀Stat来使用。
        <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">

    ================================================================================================
    ************************************************************************************************
    Conditional evaluation 条件语句

    Simple conditionals: "if" and "unless"
        在某种条件成立时,对某个fragment进行处理:

        当th:if条件成立时,该标签中其它th:*标签才会发挥作用,如果条件不成立,则th:*不会执行
        <a href="comments.html"
        th:href="@{/product/comments(prodId=${prod.id})}"
        th:if="${not #lists.isEmpty(prod.comments)}">view</a>

        th:if 判断表达式结果是否为真的规则:
        If value is not null:
            value is a boolean and is true;
            value is a number and is non-zero;
            value is a character and is non-zero;
            value is a String and is not "false", "off" or "no";
            value is not a boolean, a number, a character or a String;


        If value is null, th:if will evaluate to false;

        另外,还可以用th:unless,进行条件控制。如果条件为真,则不执行。
        <a href="comments.html"
        th:href="@{/comments(prodId=${prod.id})}"
        th:unless="${#lists.isEmpty(prod.comments)}">view</a>

    ====================================================================================
    Switch statement    Switch选择语句

    Note  that as soon as one  th:case  attribute  is evaluated as  true , every other  th:case  attribute  in  the same switch context is evaluated as  false .

    The defaul t option  is speci fied as  th:case="*" :

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

        
    ======================================================================================
    Template Layout  模板布局/模板重用

    Including template fragments
        th:fragment  
        th:include    
        用法:
            在某个标签中使用th:fragment属性定义一个变量名,然后在其他模板中通过th:include,即可引入。
        a.html 
            <div th:fragment="hello">   定义一个fragment,并取名为"hello"
                include me.!
            </div>

        b.html
            <div th:include="a :: hello">what?</div> 从名称为a.html的模板中引入名称为"hello"的fragment
        

        ***还可以不使用th:fragment属性进行引入,通过DOMSelector
        "templatename::[domselector]"    like XPath expressions.
        
        ***将模板整个引入
        "templatename" 
        
        th:include中同样可以嵌套使用表达式
        <div th:include="footer :: (${user.isAdmin}? #{footer.admin} : #{footer.normaluser})"></div>

        
        th:include 
            引入fragment中定义的内容
        th:substituteby 
            引入fragment所在标签和内容,并替换当前的标签
        
        如:
        footer.html
        <footer th:fragment="copy">
            &copy; 2011 The Good Thymes Virtual Grocery
        </footer>

        main.html
        --------------------------------------------> th:include只引入内容
        <div th:include="footer :: copy"></div>
        result:
        <div>
            &copy; 2011 The Good Thymes Virtual Grocery
        </div>
        
        --------------------------------------------> 整个引入,并替换掉host tag
        <div th:substituteby="footer :: copy"></div>
        result:
        <footer>
            &copy; 2011 The Good Thymes Virtual Grocery
        </footer>

    ============================================================================
    Removing template fragments
        th:remove 为了静态显示时提供充分的数据,但是在模板被解析后,又不需要这些模拟的数据,需要将其删除
        可选属性:
            th:remove="all", 删除所有
            th:remove="all-but-first",删除所有,但保留第一个
            th:remove="body", 删除内容,但保留标签
            th:remove="tag", 删除标签,但保留内容

    =============================================================================
    Local variables  模板中自定义变量
        th:with="fisrtPerson=${persons[0]}"
        使用自定义的变量:
        <span th:text="${firstPer.name}">

        <div th:with="firstPer=${persons[0]},secondPer=${persons[1]}">
            <p>The name of the first person is <span th:text="${firstPer.name}">Julius Caesar</span>.</p>
            <p>But the name of the second person is <span th:text="${secondPer.name}">Marcus Antonius</span>.</p>
        </div>
        
        
        原理:定义的变量将被添加到context的map中,这样就能像其它变量一样被使用到了。
        自定义变量的有效范围:仅在被定义的标签内有效,比如,上面的firstPerson,仅在当前div中有效

        另一个用途:
        定义变量存放message中的配置
        然后在表达式中用
        如,从message中获取date.format的配置,然后复制给变量df,然后在其它地方(自定义变量所在标签内)进行使用

        <p th:with="df=#{date.format}">
            Today is: <span th:text="${#calendars.format(today,df)}">13 february 2011</span>
        </p>
        
        也可以直接:
        <p>
            Today is: <span th:with="df=#{date.format}" th:text="${#calendars.format(today,df)}">13 february 2011</span>
        </p>

        优先级的问题:
        th:with 优先级高于 th:text 
        th:each 优先级高于 th:*

    ==============================================================================================
    Attribute precedence 属性的优先级问题

    Thymeleaf attributes have a numeric precedence:
        1  fragment inclusion            th:include
        2  fragment iteration            th:each
        3  condition evaluation            th:if/th:unless/th:switch/th:case
        4  Local variable definition        th:object, th:with
        5  General attribute modification    th:attr, th:attrprepend, th:attrappend
        6  Specific attribute modification    th:value, th:href, th:src, etc
        7  Text                    th:text, th:utext
        8  Fragment specification        th:fragment
        9  Fragment removal            th:remove    

        <ul th:each="item : ${items}">
            <li th:text="${item.description}">Item description here...</li>
        </ul>
        
        由于th:each的优先级高于其它th:*,所以可以简写为:

        <ul>
            <li th:each="item : ${items}" th:text="${item.description}">Item description here...</li>
        </ul>

        还可以这样写,将循环放到后面,只是阅读性不好,但不影响结果:
        <ul>
            <li th:text="${item.description}" th:each="item : ${items}">Item description here...</li>
        </ul>

    =======================================================================================
    Inlining

    Text inlining
        好处:简化书写
        弊端:以prototype呈现(静态地打开网页),将原样显示
        用法,在标签上定义th:inline="text"
        该标签中任意地方都可以使用内联样式获取数据

        <p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>
        简化为:
        <p>Hello, [[${session.user.name}]]!</p>

        parent tag中定义
        <body th:inline="text">
            ...
            <p>hello:[[${session.user.name}]]</p>
            ...
        <body>

    JavaScript inlining
        <script th:inline="javascript">
            /*<![CDATA[*/
            ...
            var username = [[${session.user}]];
            ...
            /*]]>*/
        </script>

        thymeleaf将自动对user对象进行转换,而且转换为javascript中的user对象

        <script th:inline="javascript">
            /*<![CDATA[*/
            ...
            var user = {'age':null,'firstName':'John','lastName':'Apricot','name':'John Apricot','nationality':'Antarctica'};
            ...
            /*]]>*/
        </script>
    =================================================================================
    Validation and Doctypes

    Validating templates 
        
        使用Thymeleaf的DTD进行校验和声明Thymeleaf的命名空间

        <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd">

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

    Doctype translation  Thymeleaf对模板处理完成后,会自动将DOCTYPE转换为正确的类型,这样浏览器端就能正常解析了!
        
        <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd">

        After Thymeleaf process the template, will automatically transformate the DOCTYPE to:
        
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    ===================================================================================
    Template Resolver

    org.thymeleaf.templateresolver.ClassLoaderTemplateResolver
        return Thread.currentThread().getContextClassLoader().getResourceAsStream(templateName);

    org.thymeleaf.templateresolver.FileTemplateResolver
        return new FileInputStream(new File(templateName));

    org.thymeleaf.templateresolver.UrlTemplateResolver 
        return (new URL(templateName)).openStream();

    --->

    Prefix and suffix:
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");

    Encoding  to be appl ied when  reading  templates:
        templateResolver.setEncoding("UTF-8");

    Defaul t  template mode, and patterns  for defining other modes  for speci fic  templates:
        // Default is TemplateMode.XHTML
        templateResolver.setTemplateMode("HTML5");
        templateResolver.getXhtmlTemplateModePatternSpec().addPattern("*.xhtml");

    Defaul t mode  for  template cache, and patterns  for defining whether speci fic  templates are cacheable or not:
        // Default is true
        templateResolver.setCacheable(false);
        templateResolver.getCacheablePatternSpec().addPattern("/users/*");

    TTL  in mi l l iseconds  for parsed  template cache entries originated  in  this  template  resolver.  If not set,  the only way  to
    remove an entry  from  the cache wi l l  be LRU  (cache max size exceeded and  the entry  is  the oldest).
        // Default is no TTL (only LRU would remove entries)
        templateResolver.setCacheTTLMs(60000L);

    Also, a Template Engine can be set several   template  resolvers,  in which case an order can be establ ished between  them  for
    template  resolution so  that,  if  the  first one  is not able  to  resolve  the  template,  the second one  is asked, and so on:
    When several   template  resolvers are applied,  it  is  recommended  to specify patterns  for each  template  resolver so  that
    Thymeleaf can quickly discard  those  template  resolvers  that are not meant  to  resolve  the  template, enhancing performance.
    Doing  this  is not a  requi rement, but an optimization:

        ClassLoaderTemplateResolver classLoaderTemplateResolver = new ClassLoaderTemplateResolver();
        classLoaderTemplateResolver.setOrder(Integer.valueOf(1));
        // This classloader will not be even asked for any templates not matching these patterns
        classLoaderTemplateResolver.getResolvablePatternSpec().addPattern("/layout/*.html");
        classLoaderTemplateResolver.getResolvablePatternSpec().addPattern("/menu/*.html");

        ServletContextTemplateResolver servletContextTemplateResolver = new ServletContextTemplateResolver();
        servletContextTemplateResolver.setOrder(Integer.valueOf(2));
    ===================================================================================
    Message Resolver 

        The implementation being used was an org.thymeleaf.messageresolver.StandardMessageResolver object as default in web application.

        you can create your own by  just  implementing  the  org.thymeleaf.messageresolver.IMessageResolver interface.
        And why would you want  to have more  than one message  resolver?  for  the same  reason as  template  resolvers: 
        message resolvers are ordered and  if  the  first one cannot  resolve a specific message, the second one will be asked, then the third, etc.
        
        // For setting only one
        templateEngine.setMessageResolver(messageResolver);

    ===================================================================================
    Template Cache 模板缓存管理

        // Default is 50
        StandardCacheManager cacheManager = new StandardCacheManager();
        cacheManager.setTemplateCacheMaxSize(100);
        ...
        templateEngine.setCacheManager(cacheManager);

        // Clear the cache completely
        templateEngine.clearTemplateCache();
        // Clear a specific template from the cache
        templateEngine.clearTemplateCacheFor("/users/userList");

  • 相关阅读:
    Android中Handler原理
    微软柯塔娜(Cortana)的一句名言
    C# 单例模式的五种写法
    HTTP Status 404
    PLSQL中显示Cursor、隐示Cursor、动态Ref Cursor差别
    Android 开发之集成百度地图的定位与地图展示
    iOS知识点汇总
    优化报表系统结构之报表server计算
    淘宝中间的一像素线(手机端)
    解决yum升级的问题“There was a problem importing one of the Python modules”
  • 原文地址:https://www.cnblogs.com/duyinqiang/p/5696516.html
Copyright © 2020-2023  润新知