Welcome Thymeleaf 3.0! #jjug_ccc #ccc_f2

Welcome Thymeleaf 3.0! #jjug_ccc #ccc_f2

979f8815a9d4604d87f54b8394c503bd?s=128

Mitsuyuki Shiiba

May 21, 2016
Tweet

Transcript

  1. #jjug_ccc #ccc_f2 @bufferings Welcome Thymeleaf 3.0! 2016-05-21 JJUG CCC 2016

    Spring Mitsuyuki Shiiba
  2. #jjug_ccc #ccc_f2 @bufferings http://www.thymeleaf.org/

  3. #jjug_ccc #ccc_f2 @bufferings http://www.thymeleaf.org/ Have you ever used it?

  4. #jjug_ccc #ccc_f2 @bufferings Finally released on 2016-05-08! Welcome Thymeleaf 3.0!

    http://www.thymeleaf.org/
  5. #jjug_ccc #ccc_f2 @bufferings Agenda • Part1: Introducing Thymeleaf • Part2:

    What’s new in Thymeleaf 3.0?
  6. #jjug_ccc #ccc_f2 @bufferings Your tweets are welcomed! HashTag: #ccc_f2

  7. #jjug_ccc #ccc_f2 @bufferings • twitter: @bufferings • Java WebApp Engineer

    • #kanjava #devkan #kandddj Mitsuyuki Shiiba
  8. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf (ja) Mitsuyuki Shiiba http://www.thymeleaf.org/documentation.html

  9. #jjug_ccc #ccc_f2 @bufferings Special thanks to Daniel Fernández, who is

    a Founder and Lead Developer of Thymeleaf. He kindly gave me some advices for my presentation and allow me to use his session materials of Devoxx Belgium 2015 and Spring I/O 2016. Special Thanks! The Thymeleaf Artwork by The Thymeleaf Project is licensed under the Creative Commons CC BY-SA 3.0 License.
  10. #jjug_ccc #ccc_f2 @bufferings Part1: Introducing Thymeleaf

  11. #jjug_ccc #ccc_f2 @bufferings Part1: Introducing Thymeleaf • What is Thymeleaf?

    • Getting Started • Using Thymeleaf • My Tips
  12. #jjug_ccc #ccc_f2 @bufferings What is Thymeleaf? • A template engine

    for Java • Open Source — Apache 2.0 License • First version 2011 — Currently 3.0.0 • Processes HTML, XML, JavaScript, CSS, Text • View layer in Spring MVC apps • Also MVC 1.0, vert.x, ratpack, Spring Reactive
  13. #jjug_ccc #ccc_f2 @bufferings What does it look like? What is

    Thymeleaf? <table> <thead><tr> <th th:text="#{msgs.headers.name}">Name</th> <th th:text="#{msgs.headers.price}">Price</th> </tr></thead> <tbody> <tr th:each="prod : ${allProducts}"> <td th:text="${prod.name}">Oranges</td> <td th:text="${#numbers.formatDecimal(prod.price, 1,2)}">0.99</td> </tr> </tbody> </table>
  14. #jjug_ccc #ccc_f2 @bufferings to solve the design-development roundtrip issue Why

    was it started? What is Thymeleaf?
  15. #jjug_ccc #ccc_f2 @bufferings “the template can be a document as

    valid as the final result, the engine syntax doesn't break the document's structure” [Comparison of web template engines - Wikipedia, the free encyclopedia] Natural Templates What is Thymeleaf? https://en.wikipedia.org/wiki/Comparison_of_web_template_engines
  16. #jjug_ccc #ccc_f2 @bufferings Natural Templates What is Thymeleaf? http://www.thymeleaf.org/doc/articles/petclinic.html Statically

    Opened WebApp Output
  17. #jjug_ccc #ccc_f2 @bufferings Natural Templates What is Thymeleaf?

  18. #jjug_ccc #ccc_f2 @bufferings The trick What is Thymeleaf? • Use

    non-standard attributes <ul> <li th:each="f : ${fruits}" th:text="${f.name}">Apricot</li> </ul> • Browsers ignore them
  19. #jjug_ccc #ccc_f2 @bufferings HTML5 allows custom attributes What is Thymeleaf?

    <ul> <li data-th-each="f : ${fruits}" data-th-text="${f.name}">Apricot</li> </ul> <ul> <li>Apricot</li> </ul> browser display equivalent
  20. #jjug_ccc #ccc_f2 @bufferings Now we can prototype! What is Thymeleaf?

    <img src="../resources/images/logo.png" th:src="@{/images/logo.png}" /> <img src="/myapp/images/logo.png" /> <img src="../resources/images/logo.png" /> browser display equivalent output of running webapp
  21. #jjug_ccc #ccc_f2 @bufferings Yet prototyping is very optional What is

    Thymeleaf? • No need for double attributes: • src + th:src, href + th:href • No need for prototyping text • Expressions can be inlined <tr> <td><img th:src="@{/images/logo.png}"/></td> <td>Welcome to our e-shop, [[${session.user.name}]].</ td> </tr>
  22. #jjug_ccc #ccc_f2 @bufferings Part1: Introducing Thymeleaf • What is Thymeleaf?

    • Getting Started • Using Thymeleaf • My Tips
  23. #jjug_ccc #ccc_f2 @bufferings Getting Started Spring Boot is one of

    the easiest options.
  24. #jjug_ccc #ccc_f2 @bufferings Step1. SPRING INITIALIZR Open http://start.spring.io/ Getting Started

  25. #jjug_ccc #ccc_f2 @bufferings Step1. SPRING INITIALIZR Select Thymeleaf in dependencies

    box Getting Started
  26. #jjug_ccc #ccc_f2 @bufferings Step1. SPRING INITIALIZR Click “Generate Project” Getting

    Started
  27. #jjug_ccc #ccc_f2 @bufferings Step1. SPRING INITIALIZR Then you can get

    a project zip file Getting Started
  28. #jjug_ccc #ccc_f2 @bufferings Step2. Create Template File src/main/resources/templates/greeting.html Getting Started

    <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Greeting Demo</title> </head> <body> <p th:text="'Hello '+${name}">Hello World</p> </body> </html>
  29. #jjug_ccc #ccc_f2 @bufferings Step2. Create Template File src/main/resources/templates/greeting.html Getting Started

  30. #jjug_ccc #ccc_f2 @bufferings Step3. Create Controller src/main/java/com/example/GreetingController.java Getting Started @Controller

    public class GreetingController { @RequestMapping("/") public String hello(Model model) { model.addAttribute("name", "Mitsuyuki"); return "greeting"; } }
  31. #jjug_ccc #ccc_f2 @bufferings Step4. Run $ ./mvnw spring-boot:run Getting Started

  32. #jjug_ccc #ccc_f2 @bufferings Now we have Thymeleaf! Getting Started

  33. #jjug_ccc #ccc_f2 @bufferings +1. Disable Cache(for DEV) Getting Started src/main/resources/application.yml

    spring: thymeleaf: cache: false
  34. #jjug_ccc #ccc_f2 @bufferings +1. Disable Cache(for DEV) Getting Started src/main/resources/application.yml

    spring: thymeleaf: cache: false or <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
  35. #jjug_ccc #ccc_f2 @bufferings JerseyMVC? Getting Started If you are interested

    in using Thymeleaf with JerseyMVC, let’s join #ccc_cd4 Tada-san’s session!
  36. #jjug_ccc #ccc_f2 @bufferings Part1: Introducing Thymeleaf • What is Thymeleaf?

    • Getting Started • Using Thymeleaf • My Tips
  37. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf <p th:text="${user.name}">James Carrot</p>

  38. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf <p th:text="${user.name}">James Carrot</p> Expression

  39. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf <p th:text="${user.name}">James Carrot</p> Processor Expression

  40. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf <p th:text="${user.name}">James Carrot</p> Processor Expression

    + + etc… = Dialect
  41. #jjug_ccc #ccc_f2 @bufferings Standard Dialect Using Thymeleaf The out-of-the-box dialect

    in Thymeleaf • Standard Expressions • Standard Processors • etc… <p th:text="${user.name}">James Carrot</p>
  42. #jjug_ccc #ccc_f2 @bufferings Standard Dialect Using Thymeleaf The out-of-the-box dialect

    in Thymeleaf • Standard Expressions • Standard Processors • etc… <p th:text="${user.name}">James Carrot</p>
  43. #jjug_ccc #ccc_f2 @bufferings Standard Expressions Using Thymeleaf 1. Simple Expressions

    2. Expression Objects 3. Literals 4. Operators
  44. #jjug_ccc #ccc_f2 @bufferings 1. Simple Expressions Standard Expressions • Variable

    Expression: ${...}, *{...} • Link Expression: @{...} • Message Expression: #{...} • Fragment Expression: ~{...} <p th:text="${user.name}">James Carrot</p>
  45. #jjug_ccc #ccc_f2 @bufferings 2. Expression Objects Standard Expressions • #ctx,

    #vars, #root, #locale, #object • #request, #session,
 #response, #servletContext • #conversions, #uris <span th:text="${#locale.country}">US</span>
  46. #jjug_ccc #ccc_f2 @bufferings 2. Expression Objects Standard Expressions • #calendars,

    #dates, #bools, #numbers, #objects, #strings, #arrays, #lists, #sets, #maps, #aggregates, #messages, #ids, #execInfo <span th:text="${#calendars.format(today,'dd MMMM yyyy')}">13 May 2011</span>
  47. #jjug_ccc #ccc_f2 @bufferings 3. Literals(Tokens) Standard Expressions • Text: ‘Good

    Morning!’,’Hello’ + ‘World’ • Number: 2016, 2020 - 4, 3.14 • Boolean: true, false • Null: null • NO-OP: _ <div th:if="${user.isAdmin()} == false"> ...
  48. #jjug_ccc #ccc_f2 @bufferings 4. Operators Standard Expressions • +, -,

    *, /, div, %, mod • and, or, not, ! • ==, eq, !=, neq, ne • >, >=, <, <=, gt, ge, lt, le • A ? B : C, A ?: C th:with="isEven=(${prodStat.count} % 2 == 0)"
  49. #jjug_ccc #ccc_f2 @bufferings Standard Dialect Using Thymeleaf The out-of-the-box dialect

    in Thymeleaf • Standard Expressions • Standard Processors • etc… <p th:text="${user.name}">James Carrot</p>
  50. #jjug_ccc #ccc_f2 @bufferings Standard Processors Using Thymeleaf 1. th:text 2.

    th:attr 3. th:if 4. th:remove 5. th:each 6. Comments and Blocks etc…
  51. #jjug_ccc #ccc_f2 @bufferings 1. th:text Standard Processors <p th:text="${user.name}">James Carrot</p>

  52. #jjug_ccc #ccc_f2 @bufferings 1. th:text Standard Processors <p th:text="${user.name}">James Carrot</p>

    <p>Mitsuyuki Shiiba</p> output of running webapp
  53. #jjug_ccc #ccc_f2 @bufferings 1. th:text Standard Processors • <, >,

    &, " and ‘ will be escaped (in Html mode) • Unescaped processor is “th:utext” <p th:text="${user.name}">James Carrot</p> HtmlEscape.escapeHtml4Xml(unbescape) http://goo.gl/MDQr8E <p>Mitsuyuki Shiiba</p> output of running webapp
  54. #jjug_ccc #ccc_f2 @bufferings 1. th:text Standard Processors <p th:text="|Hello ${name.first}

    ${name.last}!|"></p>
  55. #jjug_ccc #ccc_f2 @bufferings 1. th:text Standard Processors <p th:text="|Hello ${name.first}

    ${name.last}!|"></p> <p>Hello Mitsuyuki Shiiba!</p> output of running webapp
  56. #jjug_ccc #ccc_f2 @bufferings 2. th:attr Standard Processors <p th:attr="class=${myCssClass}">100</p>

  57. #jjug_ccc #ccc_f2 @bufferings 2. th:attr Standard Processors <p th:attr="class=${myCssClass}">100</p> <p

    class="price">100</p> output of running webapp • <, >, &, " and ‘ will be escaped
  58. #jjug_ccc #ccc_f2 @bufferings 2. th:attr Standard Processors <p th:class="${myCssClass}">100</p> th:*

    attributes <img th:src="@{/images/logo.png}"/> <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" >view</a>
  59. #jjug_ccc #ccc_f2 @bufferings 3. th:if Standard Processors <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}"

    th:if="${not #lists.isEmpty(prod.comments)}" >view</a>
  60. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors <ol th:remove="all"> <li>First</li>

    <li>Second</li> </ol>
  61. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors <ol th:remove="all"> <li>First</li>

    <li>Second</li> </ol> output of running webapp
  62. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors • all •

    all-but-first • tag(tags) • body • none
  63. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors <ol th:remove="all"> <li>First</li>

    <li>Second</li> </ol> th:remove=“all” output of running webapp
  64. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors <ol th:remove="all-but-first"> <li>First</li>

    <li>Second</li> </ol> <ol> <li>First</li> </ol> th:remove=“all-but-first” output of running webapp
  65. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors <ol th:remove="tag"> <li>First</li>

    <li>Second</li> </ol> <li>First</li> <li>Second</li> th:remove=“tag” output of running webapp
  66. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors <ol th:remove="body"> <li>First</li>

    <li>Second</li> </ol> <ol></ol> th:remove=“body” output of running webapp
  67. #jjug_ccc #ccc_f2 @bufferings 4. th:remove Standard Processors th:remove=“none” is for

    conditional use. <a href="/something" th:remove="${condition}? tag : none">Link text not to be removed</a>
  68. #jjug_ccc #ccc_f2 @bufferings 5. th:each Standard Processors <ol> <li th:each="name:${names}"

    th:text="${name}">First</li> </ol> <ol> <li>Apple</li> <li>Banana</li> <li>Cake</li> </ol> output of running webapp
  69. #jjug_ccc #ccc_f2 @bufferings 5. th:each Standard Processors th:each + th:remove=“all-but-first”

    <ol th:remove="all-but-first"> <li th:each="name:${names}" th:text="${name}">First</li> <li>Second</li> <li>Third</li> </ol> <ol> <li>Apple</li> <li>Banana</li> <li>Cake</li> </ol> output of running webapp
  70. #jjug_ccc #ccc_f2 @bufferings 5. th:each Standard Processors Iteration Status <li

    th:each="name,iterStat:${names}" th:text="${name} + ${iterStat.count}" >First</li>
  71. #jjug_ccc #ccc_f2 @bufferings 5. th:each Standard Processors Iteration Status <li

    th:each="name,iterStat:${names}" th:text="${name} + ${iterStat.count}" >First</li> <li th:each="name:${names}" th:text="${name} + ${nameStat.count}" >First</li>
  72. #jjug_ccc #ccc_f2 @bufferings 5. th:each Standard Processors Iteration Status •

    index(from 0) • count(from 1) • size • current(current Object) • even/odd(boolean/start from 1) • first/last(boolean)
  73. #jjug_ccc #ccc_f2 @bufferings 6. Comments and Blocks Standard Processors Parser

    level comment blocks <!--/* This code will be removed at thymeleaf parsing time! */-->
  74. #jjug_ccc #ccc_f2 @bufferings 6. Comments and Blocks Standard Processors Parser

    level comment blocks <!--/*--> <div> you can see me only before thymeleaf processes me! </div> <!--*/-->
  75. #jjug_ccc #ccc_f2 @bufferings 6. Comments and Blocks Standard Processors Parser

    level comment blocks <table> <tr th:each="x : ${xs}">...</tr> <!--/*--> <tr>...</tr> <tr>...</tr> <!--*/--> </table>
  76. #jjug_ccc #ccc_f2 @bufferings 6. Comments and Blocks Standard Processors Prototype-only

    comment blocks <span>hello!</span> <!--/*/ <div th:text="${...}"> ... </div> /*/--> <span>goodbye!</span> <span>hello!</span> <div th:text="${...}"> ... </div> <span>goodbye!</span> output of running webapp
  77. #jjug_ccc #ccc_f2 @bufferings 6. Comments and Blocks Standard Processors th:block

    <table> <th:block th:each="user : ${users}"> <tr> <td th:text="${user.login}">...</td> <td th:text="${user.name}">...</td> </tr> <tr> <td colspan="2" th:text="${user.address}">...</td> </tr> </th:block> </table>
  78. #jjug_ccc #ccc_f2 @bufferings 6. Comments and Blocks Standard Processors th:block

    <table> <!--/*/ <th:block th:each="user : ${users}"> /*/--> <tr> <td th:text="${user.login}">...</td> <td th:text="${user.name}">...</td> </tr> <tr> <td colspan=“2" th:text="${user.address}">...</td> </tr> <!--/*/ </th:block> /*/--> </table>
  79. #jjug_ccc #ccc_f2 @bufferings Part1: Introducing Thymeleaf • What is Thymeleaf?

    • Getting Started • Using Thymeleaf • My Tips
  80. #jjug_ccc #ccc_f2 @bufferings My Tips • Keep natural templating •

    otherwise it would be stale soon
  81. #jjug_ccc #ccc_f2 @bufferings My Tips • Keep natural templating •

    otherwise it would be stale soon • Keep template simple • no tricky template • no logics in template • no mix of html and javascript
  82. #jjug_ccc #ccc_f2 @bufferings Part1: Introducing Thymeleaf • What is Thymeleaf?

    • Getting Started • Using Thymeleaf • My Tips
  83. #jjug_ccc #ccc_f2 @bufferings Part2: What’s new in Thymeleaf 3.0?

  84. #jjug_ccc #ccc_f2 @bufferings Part2: What’s new in Thymeleaf 3.0? •

    What is Thymeleaf 3.0? • Migration Guide • Using Thymeleaf 3.0 • Summary
  85. #jjug_ccc #ccc_f2 @bufferings What is Thymeleaf 3.0? • Dev of

    the 3.0 branch started July 2014 • AttoParser is started in late 2012 • Almost complete rewrite of the engine • 63K+ lines of code 85% new • 77K+ lines of test 40% new • 220 listres of coffee 100% arabica
  86. #jjug_ccc #ccc_f2 @bufferings A new architecture

  87. #jjug_ccc #ccc_f2 @bufferings Improved performance

  88. #jjug_ccc #ccc_f2 @bufferings Full HTML5 Support • New parsing system

    • No longer XML-based • Created from scratch with Thymeleaf in mind <div ng-app><p th:text=${mytext}>Whatever valid template! http://www.attoparser.org/
  89. #jjug_ccc #ccc_f2 @bufferings TEXT Mode Dear [(${customer.name})], This is the

    list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop
  90. #jjug_ccc #ccc_f2 @bufferings Part2: What’s new in Thymeleaf 3.0? •

    What is Thymeleaf 3.0? • Migration Guide • Using Thymeleaf 3.0 • Summary
  91. #jjug_ccc #ccc_f2 @bufferings Migration Guide • Templates • almost 100%

    compatible • (It is recommended to delete th:inline=“text”) • Configuration • a few modifications are needed
  92. #jjug_ccc #ccc_f2 @bufferings Migration Guide Configuration change for Spring Boot

    Application. I created thymeleaf3-spring-boot. You can use it until the official one is released. There are only 2 steps. 1. Modify pom.xml 2. Add an exclude paramter https://github.com/bufferings/thymeleaf3-spring-boot
  93. #jjug_ccc #ccc_f2 @bufferings Step1. Modify pom.xml Add repository https://github.com/bufferings/thymeleaf3-spring-boot Migration

    Guide <repository> <id>bufferings</id> <url>https://raw.github.com/bufferings/thymeleaf3- spring-boot/mvn-repo/</url> </repository>
  94. #jjug_ccc #ccc_f2 @bufferings Step1. Modify pom.xml Replace dependency https://github.com/bufferings/thymeleaf3-spring-boot Migration

    Guide <dependency> <groupId>jp.gr.java_conf.bufferings</groupId> <artifactId>thymeleaf3-spring-boot</artifactId> <version>0.0.1</version> </dependency>
  95. #jjug_ccc #ccc_f2 @bufferings Step1. Modify pom.xml Override “thymeleaf.version” of parent

    https://github.com/bufferings/thymeleaf3-spring-boot Migration Guide <thymeleaf.version>3.0.0.RELEASE</thymeleaf.version>
  96. #jjug_ccc #ccc_f2 @bufferings Step2. Add an exclude parameter To exclude

    default ThymeleafAutoConfiguration https://github.com/bufferings/thymeleaf3-spring-boot Migration Guide @SpringBootApplication( exclude = ThymeleafAutoConfiguration.class) public class DemoApplication {
  97. #jjug_ccc #ccc_f2 @bufferings Migration Guide Configuration change for those who

    create TemplateEngine class by yourself. private TemplateEngine templateEngine() { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix("/WEB-INF/templates/"); resolver.setTemplateMode("HTML5"); TemplateEngine templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(resolver); return templateEngine; } Thymeleaf 2.1
  98. #jjug_ccc #ccc_f2 @bufferings Migration Guide Configuration change for those who

    create TemplateEngine class by yourself. private TemplateEngine templateEngine() { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContext); resolver.setPrefix("/WEB-INF/templates/"); resolver.setTemplateMode(TemplateMode.HTML); TemplateEngine templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(resolver); return templateEngine; } Thymeleaf 3.0
  99. #jjug_ccc #ccc_f2 @bufferings Notes for Migration Migration Guide • Please

    make sure you don’t have any “[[xxx]]” syntax in your html and especially in your JavaScript code. • If you use extra libraries, please check it supports Thymeleaf 3.0
  100. #jjug_ccc #ccc_f2 @bufferings Part2: What’s new in Thymeleaf 3.0? •

    What is Thymeleaf 3.0? • Migration Guide • Using Thymeleaf 3.0 • Summary
  101. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  102. #jjug_ccc #ccc_f2 @bufferings 1. New Template Mode TemplateMode enum class

    is introduced • HTML, XML • TEXT, JAVASCRIPT, CSS • RAW
  103. #jjug_ccc #ccc_f2 @bufferings 1. New Template Mode Old modes are

    deprecated • HTML5, LEGACYHTML5, XHTML, VALIDXHTML
 -> HTML • VALIDXML
 -> XML
  104. #jjug_ccc #ccc_f2 @bufferings HTML Mode • From Java SAX parser(+nekoHTML)

    to AttoParser • AttoParser is an event-based parser with Thymeleaf in mind 1. New Template Mode http://www.attoparser.org/
  105. #jjug_ccc #ccc_f2 @bufferings HTML Mode • Full support of both

    XML and HTML5 (non XML-ized) markup 1. New Template Mode <div ng-app><p th:text=${mytext}>Whatever valid template!
  106. #jjug_ccc #ccc_f2 @bufferings HTML Mode • Validataion enabled parsing no

    longer exist in Thymeleaf 3.0 1. New Template Mode
  107. #jjug_ccc #ccc_f2 @bufferings HTML Mode • No need for <![CDATA[

    ... ]]> in <script> or <style> 1. New Template Mode <script> /*<![CDATA[*/ var user = ... if (user.signupYear < 1990) { alert('You\'ve been here for a long time!'); } /*]]>*/ </script> Thymeleaf 2.1
  108. #jjug_ccc #ccc_f2 @bufferings HTML Mode • No need for <![CDATA[

    ... ]]> in <script> or <style> 1. New Template Mode <script> var user = ... if (user.signupYear < 1990) { alert('You\'ve been here for a long time!'); } </script> Thymeleaf 3.0
  109. #jjug_ccc #ccc_f2 @bufferings Improved Inlining 1. New Template Mode •

    Output values without a supporting tag • Already existed th:inline=“text" in Thymeleaf 2.1 • Now a 1st-class citizen, no th:inline needed • In fact, better remove them <p> This is called [[${product.name}]] and it's great! </p>
  110. #jjug_ccc #ccc_f2 @bufferings Improved Inlining 1. New Template Mode <p

    th:inline="text"> This is called [[${product.name}]] and it's great! </p> <p> This is called [[${product.name}]] and it's great! </p> Thymeleaf 2.1 Thymeleaf 3.0
  111. #jjug_ccc #ccc_f2 @bufferings Improved Inlining Underneath, the template mode is

    used for default inline mode: 1. New Template Mode <p th:inline="html"> This is called [[${product.name}]] and it's great! </p>
  112. #jjug_ccc #ccc_f2 @bufferings Improved Inlining Replaced at parsing time with:

    1. New Template Mode <p> This is called <th:block th:text="${product.name}"/> and it's great! </p> <p> This is called [[${product.name}]] and it's great! </p>
  113. #jjug_ccc #ccc_f2 @bufferings Improved Inlining When you don’t want to

    parse “[[…]]”, you can set th:inline=“none”: 1. New Template Mode <p th:inline="none"> The expression for showing the product name is "[[$ {product.name}]]" and it's very simple. </p>
  114. #jjug_ccc #ccc_f2 @bufferings Improved Inlining For unescaped output, you can

    use “[(…)]” 1. New Template Mode <p>Description: [(${description})]</p>
  115. #jjug_ccc #ccc_f2 @bufferings Improved Inlining For unescaped output, you can

    use “[(…)]” 1. New Template Mode <p>Description: [(${description})]</p> <p>Description: <th:block th:utext="${description}"/></ p>
  116. #jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template

    Mode Dear [(${customer.name})], This is the list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop
  117. #jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template

    Mode Dear [(${customer.name})], This is the list of our products: [#th:block th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/th:block] Thanks, The Thymeleaf Shop
  118. #jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template

    Mode Dear [# th:utext="${customer.name}" /], This is the list of our products: [#th:block th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/th:block] Thanks, The Thymeleaf Shop
  119. #jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template

    Mode Dear [#th:block th:utext="${customer.name}" /], This is the list of our products: [#th:block th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/th:block] Thanks, The Thymeleaf Shop
  120. #jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template

    Mode Dear [(${customer.name})], This is the list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop
  121. #jjug_ccc #ccc_f2 @bufferings JavaScript natural templates 1. New Template Mode

    var greeter = function() { var username = /*[[${user.name}]]*/ 'John Apricot'; alert('Hello ' + username); }; var greeter = function() { var username ='Martin Grapefruit'; alert('Hello ' + username); }; both <script> and .js files processing result
  122. #jjug_ccc #ccc_f2 @bufferings RAW Mode 1. New Template Mode Mainly

    for inserting untouched resources (files, URL responses, etc.) into the templates being processed.
  123. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  124. #jjug_ccc #ccc_f2 @bufferings 2. Fragment Expressions In Standard Dialect •

    Template Layout(existing in Themeleaf 2.1) • Fragment Expressions(from Thymeleaf 3.0)
  125. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace
  126. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace • Define a template fragment with “th:fragment”
  127. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace • Define a template fragment with “th:fragment” <html xmlns:th="http://www.thymeleaf.org"> <body> <div th:fragment="footer"> &copy; 2011 The Good Thymes Virtual Grocery </div> </body> </html> include.html
  128. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace • Include it with “th:replace” <body> ... <div th:replace="include :: footer"></div> </body>
  129. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace • Include it with “th:replace” <body> ... <div> &copy; 2011 The Good Thymes Virtual Grocery </div> </body> processing result
  130. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace • Include it with “th:replace” <div th:replace="include :: footer"></div>
  131. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment +

    th:replace • Include it with “th:replace” <div th:replace="include :: footer"></div> Template Name Fragment Name
  132. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions You can

    write like this: <div th:replace="include :: (${user.isAdmin}? #{footer.admin} : #{footer.normaluser})"></div>
  133. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions You can

    specify fragment without “th:fragment” using DOM selector: <div th:replace="mytemplate :: div.content">...</div>
  134. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment can

    define parameters: <div th:fragment="frag (onevar,twovar)"> <p th:text="${onevar} + ' - ' + ${twovar}">...</p> </div> <div th:replace="::frag (${value1},${value2})">...</div>
  135. #jjug_ccc #ccc_f2 @bufferings Template Layout 2. Fragment Expressions th:fragment can

    define parameters: <div th:fragment="frag (onevar,twovar)"> <p th:text="${onevar} + ' - ' + ${twovar}">...</p> </div> <div th:replace="::frag (${value1},${value2})">...</div> And Thymeleaf 3.0 has Fragment Expressions.
  136. #jjug_ccc #ccc_f2 @bufferings Fragment Expressions: ~{...} Generalised syntax of th:insert,

    th:replace <div th:replace="include :: footer"></div> <div th:replace=“~{include :: footer}”></div> Thymeleaf 2.1 Thymeleaf 3.0 Please don’t worry. The older syntax still works. 2. Fragment Expressions
  137. #jjug_ccc #ccc_f2 @bufferings Fragment Expressions: ~{...} Can be used elsewhere...

    even as parameters! <head th:replace="base::header(~{::title},~{::link})"> <title>Awesome - Main</title> <link rel=“stylesheet" th:href="@{/css/bootstrap.min.css}"> <link rel=“stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}"> </head> 2. Fragment Expressions
  138. #jjug_ccc #ccc_f2 @bufferings Fragment Expressions: ~{...} Can be used elsewhere...

    even as parameters! <head th:fragment="common_header(title,links)"> <title th:replace="${title}">The awesome app</title> <!-- Common styles and scripts --> <link rel="shortcut icon” th:href="@{/images/favicon.ico}"> <!--/* Per-page placeholder for additional links */--> <th:block th:replace="${links}" /> </head> 2. Fragment Expressions base.html
  139. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  140. #jjug_ccc #ccc_f2 @bufferings • Ability for processors to do nothing

    • Expression result: underscore(‘_') • Use prototyping text as default values 3. No-Operation Token <span th:text="${user.name} ?: _">no user authenticated</span>
  141. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  142. #jjug_ccc #ccc_f2 @bufferings 4. Decoupled Templates <table id="detail"> <tr> <td>Green

    Plum</td> <td>Round-oval shape</td> </tr> </table> fruits.html <thlogic> <attr sel="#detail/tr" th:each="f : ${fruits}"> <attr sel="/td[0]" th:text="${f.name}"/> <attr sel="/td[1]" th:text="${f.description}"/> </attr> </thlogic> fruits.th.xml
  143. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  144. #jjug_ccc #ccc_f2 @bufferings Independence From Servlet API • Already in

    2.1 for non-web applications • Non-ServletAPI webs had unsolved needs • Non-absolute URL handling, context integration /* Customize the way URLs are handled: context, rewriting, etc. */ tempEngine.setLinkBuilder(new ILinkBuilder() {...}); /* Customize the way context variables are maintained */ tempEngine.setEngineContextFactory(new IEngineContextFactory() {...});
  145. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  146. #jjug_ccc #ccc_f2 @bufferings 6. Reactive Friendliness • Sorry, I will

    study spring reactive! • If you are interested in, please check this repo:
 https://github.com/thymeleaf/thymeleafsandbox- springreactive
  147. #jjug_ccc #ccc_f2 @bufferings Using Thymeleaf 3.0 1. New Template Mode

    2. Fragment Expressions 3. No-Operation Token 4. Decoupled Templates 5. Independence From Servlet API 6. Reactive Friendliness 7. StringTemplateResolver
  148. #jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • If you want to

    check Thymeleaf Standard Dialect, you can write codes like this: @Test public void test() { TemplateEngine engine = new TemplateEngine(); Context context = new Context(); context.setVariable("name", "Mitsuyuki"); String result = engine.process( "I'm [[${name}]].", context); assertThat(result, is("I'm Mitsuyuki.")); }
  149. #jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • Please note that if

    you use Spring, you should use SpringStandardDialect.: @Test public void test() { TemplateEngine engine = new TemplateEngine(); engine.setDialect(new SpringStandardDialect()); Context context = new Context(); context.setVariable("name", "Mitsuyuki"); String result = engine.process( "I'm [[${name}]].", context); assertThat(result, is("I'm Mitsuyuki.")); }
  150. #jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • Please note that if

    you use Spring, you should use SpringStandardDialect.: @Test public void test() { TemplateEngine engine = new TemplateEngine(); engine.setDialect(new SpringStandardDialect()); Context context = new Context(); context.setVariable("name", "Mitsuyuki"); String result = engine.process( "I'm [[${name}]].", context); assertThat(result, is("I'm Mitsuyuki.")); }
  151. #jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • StringTemplateResolver will consider the

    template being resolved as the template itself. • This is the default template resolver of TemplateEngine.
  152. #jjug_ccc #ccc_f2 @bufferings Part2: What’s new in Thymeleaf 3.0? •

    What is Thymeleaf 3.0? • Migration Guide • Using Thymeleaf 3.0 • Summary
  153. #jjug_ccc #ccc_f2 @bufferings Summary • You don’t need any big

    change for migrating from Thymeleaf 2.1 to 3.0. • On the other hand, inside was changed so much that you can get the performance improvement. • So why don’t you use Thymeleaf 3.0? Thank you!
  154. #jjug_ccc #ccc_f2 @bufferings Reference • Thymeleaf Web Site
 http://www.thymeleaf.org/ •

    Thymeleaf by Daniel Fernández
 https://youtu.be/GVq0uzpHYoQ • The Thymeleaf Artwork by The Thymeleaf Project is licensed under the Creative Commons CC BY-SA 3.0 License.