Mais conteúdo relacionado Semelhante a Lessons learned from upgrading Thymeleaf (20) Mais de VMware Tanzu (20) Lessons learned from upgrading Thymeleaf2. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Broadleaf Commerce
• Open source, Spring-based eCommerce framework
• Enterprise features
• Order Management System
• Content Management System
• Multi-Tenant Single Schema
• Fortune 500 and IR Top 100 clients
• The Container Store
• The Buckle
• O'Reilly Auto Parts
• Customizable, flexible, and scalable
2
3. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf
• Open source server-side Java template engine
• Write pure HTML, CSS, and JS that can be displayed without processing
• Built-in Spring integrations
• Uses SpEL and OGNL
• Therefore you can use static class and object functions
• Full internationalization support
• Highly customizable
• Configurable parsed template cache
• Cache where the template is and, possibly, what it evaluates to
3
4. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Fragments
The old fragment expressions but expanded on
• Not only limited to use inside th:insert/th:replace/th:include
• <div th:include="home :: home_fragment"></div>
• <div th:include="~{home :: home_fragment}"></div>
• Same syntax as before i.e. ~{home :: home_fragment}
• Now available for use everywhere ${...}, *{...}, etc. can be used
• Use with th:with to use templates as variables or in an conditional
• Using fragments as parameters in other fragments
4
5. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples
~{commons::main}
<div th:insert="~{commons :: main}">...</div>
<div th:insert="${user.admin}? ~{adm :: admintools} :
~{common :: basictools}">...</div>
<div th:with="frag=~{footer :: #main/text()}">
<p th:insert="${frag}">
</div>
5
6. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples (base.html)
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">The awesome application</title>
<!-- Common styles and scripts -->
<link rel="stylesheet" type="text/css" media="all"
th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"/>
<!--/* Per-page placeholder for additional links */-->
<th:block th:replace="${links}" />
</head>
6
7. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples (main.html)
...
<head
th:replace="base :: common_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>
...
7
8. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples (resulting main.html)
...
<head>
<title>Awesome - Main</title>
<!-- Common styles and scripts -->
<link rel="stylesheet" type="text/css" media="all"
th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"/>
<!--/* Per-page placeholder for additional links */-->
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
...
8
9. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Decoupled Templating
...
<table id="usersTable">
<tr th:each="user : ${users}">
<td class="username" th:text="${user.name}">
Jeremy Grapefruit
</td>
<td class="usertype"
th:text="#{|user.type.${user.type}|}">
Normal User
</td>
</tr>
</table>
...
9
10. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Decoupled Templating
<!DOCTYPE html>
<html>
<body>
<table id="usersTable">
<tr>
<td class="username">Jeremy Grapefruit</td>
<td class="usertype">Normal User</td>
</tr>
<tr>
<td class="username">Alice Watermelon</td>
<td class="usertype">Administrator</td>
</tr>
</table>
</body>
</html>
10
11. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Decoupled Templating
<?xml version="1.0"?>
<thlogic>
<attr sel="#usersTable" th:remove="all-but-first">
<attr sel="/tr[0]" th:each="user : ${users}">
<attr sel="td.username" th:text="${user.name}" />
<attr sel="td.usertype"
th:text="#{|user.type.${user.type}|}" />
</attr>
</attr>
</thlogic>
11
12. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features
• Inline Expression
• <div th:inline="text">[[${user.name}]]</div> --> <div>[[${user.name}]]</div>
• Textual Template Mode - Ability to write Thymeleaf syntax without tags
[# th:each="item : ${items}"]
- [# th:utext="${item}" /]
[/]
• No longer dependent on Servlet API
• Enables Thymeleaf to run outside of a web container (i.e. email templating)
• Improves integration possibilities with reactive frameworks
• Supports engine throttling so that the Thymeleaf engine can execute partially and
on-demand to answer back-pressure requests
12
13. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features
• Parser change
• Originally used an XML parser, now uses an event-driven parser
• New parser called Attoparser 2.0 (written by the same guy behind Thymeleaf)
• Performance increase
• No longer requires HTML to be valid XML (Full HTML5 support)
• Small templating caveat
• <div th:text="${text}"/> --> if text is empty this results to <div/>
• The browser attempts to find a place for the closing div and it's always wrong
• In Thymeleaf 2 this would return <div></div>
• Simply change to <div th:text="${text}></div>
13
14. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Variable Expressions - Thymeleaf 2
public class BroadleafVariableExpressionEval extends
SpelVariableExpressionEvaluator {
@Override
protected Map<String,Object> computeAdditionalExpressionObjects(
final IProcessingContext processingContext) {
// Map expression objects to a string
}
}
14
15. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Variable Expressions - Thymeleaf 3
public class BroadleafVariableExpressionObjectFactory implements
IExpressionObjectFactory{
@Override
public Set<String> getAllExpressionObjectNames() {
// Return string names to be used to use variable expressions
}
@Override
public Object buildObject(IExpressionContext context,
String expressionObjectName) {
// Based on string given return object is relates to
}
}
15
16. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Variable Expressions - Difference
• Slightly different API but effectively setup the same way
• HTML usage remains identical
Thymeleaf 2 - https://git.io/vbTIr
Thymeleaf 3 - https://git.io/vbTIo
Both are capital "i"s following the "T"
16
17. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Dialects - Thymeleaf 2
public interface IDialect {
public String getPrefix();
public Set<IProcessor> getProcessors();
public Map<String,Object> getExecutionAttributes();
public Set<IDocTypeTranslation> getDocTypeTranslations();
public Set<IDocTypeResolutionEntry> getDocTypeResolutionEntries();
}
17
18. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Dialects - Thymeleaf 3
public abstract class TL3EquivalentDialect
extends AbstractProcessorDialect
implements IExpressionObjectDialect {
public String getName();
public String getPrefix();
public int getDialectProcessorPrecedence();
public Set<IProcessor> getProcessors(final String dialectPrefix);
public IExpressionObjectFactory getExpressionObjectFactory();
}
18
19. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Dialects - Difference
• Thymeleaf 3 refactored the API into a more modular way
• i.e. IProcessorDialect, IPreProcessorDialect, IPostProcessorDialect,
IExpressionObjectDialect, IExecutionAttributeDialect
• Replaced getExecutionAttributes with getExpressionObjectFactory
• This makes more sense since you're no longer mapping a magic string to an
object
• Hooking up the dialect to the engine is exactly the same
• Again a lot of similarities
• Thymeleaf 2 - https://git.io/vbTtM
• Thymeleaf 3 - https://git.io/vbTtD
19
20. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 2
public interface IProcessor extends Comparable<IProcessor> {
public IProcessorMatcher<? extends Node> getMatcher();
public ProcessorResult process(
final Arguments arguments,
final ProcessorMatchingContext processMatchContext,
final Node node);
}
• getMatcher - What type of HTML should this be ran on
• process - What are we doing on this HTML that matches
20
21. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 2
• AbstractProcessor implements IProcessor
• Provides methods to resolve internationalized messages and compareTo
• AbstractAttrProcessor extends AbstractProcessor
• Implements getMatcher to say this runs on tags with certain attribute name
• AbstractElementProcessor
• Implements getMatcher to say this runs on tags with certain tag name
21
22. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 3
public interface IProcessor {
public TemplateMode getTemplateMode(); // HTML, XML, etc.
public int getPrecedence();
}
public interface IElementProcessor extends IProcessor {
public MatchingElementName getMatchingElementName();
public MatchingAttributeName getMatchingAttributeName();
}
22
23. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 3
public interface IElementTagProcessor extends IElementProcessor {
public void process(
final ITemplateContext context,
final IProcessableElementTag tag,
final IElementTagStructureHandler structureHandler);
}
public interface IElementModelProcessor extends IElementProcessor {
public void process(
final ITemplateContext context,
final IModel model,
final IElementModelStructureHandler structureHandler);
}
23
24. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 3
Other interfaces (all extend IProcessor)
• ITemplateBoundariesProcessor
• ITextProcessor
• ICommentProcessor
• ICDATASectionProcessor
• IDocTypeProcessor
• IXMLDeclarationProcessor
All have their own StructureHandlers
24
25. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Differences
Thymeleaf 2
• getMatcher
• Method argument Arguments
• Not very defined. Hard to use
• Wild west on what you can do
inside a processor
25
Thymeleaf 3
• More granular APIs
• Method argument StructureHandler
• Very detailed API. Easy to use
• More structured on what you can do
inside a processor based on type
26. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Configuration - Maven POM
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
26
27. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Configuration - Spring Java Config
@Configuration
@EnableWebMvc
public class ThymeleafConfig extends WebMvcConfigurerAdapter implements
ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
...
27
28. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Configuration - Spring Java Config
...
@Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}
28
29. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Summary
• Not a lot to upgrading unless you have lots of processors
• Even then the new API is much simpler
• New features
• Better fragment expressions
• Decoupled templating
• Increased performance
• No more XML parser
• New sleeker APIs for Variable Expressions, Dialects, Processors
• Addition of pre/post processors
29
30. Resources
• Migration Guide
• http://www.thymeleaf.org/doc/articles/thymeleaf3migration.html
• Extension Guide
• http://www.thymeleaf.org/doc/tutorials/3.0/extendingthymeleaf.html
• My Blog
• http://www.broadleafcommerce.com/blog/broadleaf-commerce-upgrade-to-
thymeleaf-3
• Introduction to Thymeleaf Presentation
• http://www.nimret.org/seajug/past/2016/oct/slides.pdf
32. Learn More. Stay Connected.
jaisenbrey@broadleafcommerce.com
Github: cja769
Twitter: @broadleaf
32
#springone@s1p