@[TOC] Despite the popularity of back-end separation, back-end templates are useful in some key areas, such as mail templates, code templates, etc. Of course, some old project backends still use dynamic templates.
Thymeleaf is pretty, simple, easy to understand, and perfectly HTML5-friendly. You can open static pages without adding tags, just enhancing the properties, which also reduces learning costs.
So Songo takes a moment today to share with you Thymeleaf in detail.
1. The Thymeleaf profile
Thymeleaf is a next-generation Java templating engine that is similar to traditional Java templating engines such as Velocity and FreeMarker, but unlike traditional Java templating engines, Thymeleaf supports HTML prototyping.
It allows front-end engineers to directly open the browser to view the style, and also allows back-end engineers to view the display effect with real data. At the same time, SpringBoot provides Thymeleaf automatic configuration solution, so it is very convenient to use Thymeleaf in SpringBoot.
In fact, Thymeleaf can be rendered as an HTML fragment in addition to displaying basic HTML and rendering the page. For example, we can use Thymeleaf as the template for sending emails.
In addition, because the Thymeleaf template suffix is.html, it can be opened directly by the browser, so it is very convenient to preview.
2. Integrate Spring Boot
2.1 Basic Usage
It is very easy to integrate Thymeleaf in Spring Boot, just add Thymeleaf when creating a project:
After creation, pom.xml has the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Copy the code
Of course, Thymeleaf can be used in other places as well as in Spring Boot, but Spring Boot provides a full set of automated configuration solutions for Thymeleaf. This set of configuration class attribute in the org. Springframework. Boot. Autoconfigure. Thymeleaf. ThymeleafProperties, part of the source code is as follows:
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = DEFAULT_PREFIX;
private String suffix = DEFAULT_SUFFIX;
private String mode = "HTML";
private Charset encoding = DEFAULT_ENCODING;
private boolean cache = true;
/ /...
}
Copy the code
- First of all by
@ConfigurationProperties
Annotations,application.properties
The prefix forspring.thymeleaf
Is bound to properties in this class. - The first three
static
Variables define the default encoding format, the view parser prefix, suffix, and so on. - As you can see from the first three lines of configuration,
Thymeleaf
The default location of the template isresources/templates
Directory, the default suffix ishtml
。 - These configurations, if not provided by the developer, are used by default, if provided by the developer, in
application.properties
In order tospring.thymeleaf
The configuration starts.
And the automatic configuration classes that Spring Boot provides for Thymeleaf that we just mentioned, Is the org. Springframework. Boot. Autoconfigure. Thymeleaf. ThymeleafAutoConfiguration, part of the source code is as follows:
@Configuration
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration {}Copy the code
As you can see, in this automated configuration class, we import ThymeleafProperties, and then the @conditionalonClass annotation indicates that when TemplateMode and SpringTemplateEngine classes are currently in the system, The current automated configuration class will only take effect, that is, as soon as thymeleaf-related dependencies are introduced into the project.
These default configurations can be used with very little change. If the developer has special requirements, you can configure a property starting with Spring.thymeleaf in application.properties.
Now we can create the Controller, and we can actually do nothing with the Thymeleaf dependency. Create the following IndexController:
@Controller
public class IndexController {
@GetMapping("/index")
public String index(Model model) {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User u = new User();
u.setId((long) i);
u.setName("javaboy:" + i);
u.setAddress("Shenzhen." + i);
users.add(u);
}
model.addAttribute("users", users);
return "index"; }}public class User {
private Long id;
private String name;
private String address;
/ / omit getter/setter
}
Copy the code
Return the logical view name + data in IndexController. The logical view name is index, which means we need to provide a Thymeleaf template file named index.html in the Resources/Templates directory.
- Create Thymeleaf
<! DOCTYPEhtml>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>Serial number</td>
<td>The user name</td>
<td>address</td>
</tr>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.address}"></td>
</tr>
</table>
</body>
</html>
Copy the code
In Thymeleaf, a set is traversed by the TH :each instruction, and the display of data is realized by the TH :text instruction.
Note that index.html introduces the Thymeleaf namespace at the top (it is not mandatory in the latest version).
After the configuration is complete, you can start the project, access the /index interface, and see the data in the collection:
2.2 Manual Rendering
We can also render the Thymeleaf template manually, which is useful for sending emails. For example, I created a new email template in the Resources /templates directory, as follows:
<! DOCTYPEhtml>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>Hello, welcome to<span th:text="${username}"></span>To join XXX Group, your entry information is as follows:</p>
<table border="1">
<tr>
<td>position</td>
<td th:text="${position}"></td>
</tr>
<tr>
<td>salary</td>
<td th:text="${salary}"></td>
</tr>
</table>
<img src="http://www.javaboy.org/images/sb/javaboy.jpg" alt="">
</body>
</html>
Copy the code
In this HTML template, there are several variables, we want to render the HTML template as a String String, and then send the String by email, so how do we render manually?
@Autowired
TemplateEngine templateEngine;
@Test
public void test1(a) throws MessagingException {
Context context = new Context();
context.setVariable("username"."javaboy");
context.setVariable("position"."Java Engineer");
context.setVariable("salary".99999);
String mail = templateEngine.process("mail", context);
// omit message sending
}
Copy the code
- To render, we first need to inject a TemplateEngine object, which is configured in Thymeleaf’s automated configuration class (that is, we have this instance when we introduce Thymeleaf’s dependencies).
- We then construct a Context object to hold variables in.
- The render is called to the process method, which returns the rendered HTML string, which we then send out.
3. The Thymeleaf details
The first two examples give you a general idea of how to use Thymeleaf in Spring Boot.
3.1 Standard expression syntax
3.1.1 Simple expressions
The ${... }
Get object attributes directly with th:xx = “${}”. This has already been demonstrated in the previous case and will not be repeated.
* {... }
Can like ${… }, you can also use th:object to obtain the object, and then use th:xx = “*{}” to obtain the object attributes, this style is very clean, recommended for practical projects.
<table border="1" th:object="${user}">
<tr>
<td>The user name</td>
<td th:text="*{username}"></td>
</tr>
<tr>
<td>address</td>
<td th:text="*{address}"></td>
</tr>
</table>
Copy the code
# {... }
The usual internationalization attribute: #{… } to get the internationalized language translation value.
Create two new files in the Resources directory: messages.properties and messages_zh_cn.properties, with the following contents:
Messages. The properties:
message = javaboy
Copy the code
Messages_zh_CN. Properties:
message = A little rain in the South
Copy the code
We then reference message in thymeleaf, and the system displays different values depending on the browser’s locale:
<div th:text="#{message}"></div>
Copy the code
@ {... }
- Reference absolute URLS:
<script type="text/javascript" th:src="@{http://localhost:8080/hello.js}"></script>
Copy the code
Is equivalent to:
<script type="text/javascript" src="http://localhost:8080/hello.js"></script>
Copy the code
- Context-sensitive urls:
First configure the Spring Boot context in application.properties to facilitate testing:
server.servlet.context-path=/myapp
Copy the code
Reference path:
<script type="text/javascript" th:src="@{/hello.js}"></script>
Copy the code
Is equivalent to:
<script type="text/javascript" src="/myapp/hello.js"></script>
Copy the code
- Relative URL:
Relative refers to the URL relative to the server, as in the following reference:
<script type="text/javascript" th:src="@{~/hello.js}"></script>
Copy the code
Is equivalent to:
<script type="text/javascript" src="/hello.js"></script>
Copy the code
The application context/myApp is ignored.
- Protocol relative URL:
<script type="text/javascript" th:src="@{//localhost:8080/hello.js}"></script>
Copy the code
Is equivalent to:
<script type="text/javascript" src="//localhost:8080/hello.js"></script>
Copy the code
- Urls with parameters:
<script type="text/javascript" th:src="@{//localhost:8080/hello.js(name='javaboy',age=99)}"></script>
Copy the code
Is equivalent to:
<script type="text/javascript" th:src="//localhost:8080/hello.js? name=javaboy&age=99"></script>
Copy the code
~ {... }
Fragment expressions are one of the features of Thymeleaf, and can be as fine-grained as tags in a way that JSPS can’t. Fragment expressions have three syntax:
~{ viewName }
: Displays a complete page~{ viewName ::selector}
: to find a fragment on a specified page, where selector can be the fragment name, jquery selector, etc~{ ::selector}
: indicates search on the current page
Let’s take a simple example.
Go to the resources/templates directory and create a new my_fragment.html file with the following contents:
<div th:fragment="javaboy_link"><a href="http://www.javaboy.org">www.javaboy</a></div>
<div th:fragment="itboyhub_link"><a href="http://www.itboyhub.com">www.itboyhub.com</a></div>
Copy the code
Here are two divs, with fragments defined by th:fragment, each with a different name.
Then quote the paragraph on another page:
<table border="1" th:object="${user}" th:fragment="aaa">
<tr>
<td>The user name</td>
<td th:text="*{username}"></td>
</tr>
<tr>
<td>address</td>
<td th:text="*{address}"></td>
</tr>
</table>
<hr>
<div th:replace="my_fragment.html"></div>
<hr>
<div th:replace="~{my_fragment.html::javaboy_link}"></div>
<hr>
<div th:replace="~{::aaa}"></div>
Copy the code
The fragment is referenced by th:replace. The first refers to the complete my_fragment.html page; The second refers to a fragment named javaboy_link from my_fragment.html; The third represents a fragment that references the current page named AAA, which is the table above.
3.1.2 literal
These are some characters that can be written directly into expressions. There are mainly the following characters:
- Text literals: ‘one text’, ‘Another one! ‘,…
- Numeric literals: 0, 34, 3.0, 12.3…
- Boolean literals: true, false
- Null literal: Null
- Literal markers: one, sometext, main…
Case study:
<div th:text="' This is text literal (with Spaces)'"></div>
<div th:text="javaboy"></div>
<div th:text="99"></div>
<div th:text="true"></div>
Copy the code
If the text is in English and does not contain Spaces or commas, you do not need to add single quotation marks.
3.1.3 Text operation
Text can be concatenated using +.
<div th:text="'hello '+'javaboy'"></div>
<div th:text="'hello '+${user.username}"></div>
Copy the code
If the string contains variables, also can use another kind of simple way, is called a literal replacement, substitute | ‘… ‘+’… ‘, as follows:
<div th:text="|hello ${user.username}|"></div>
<div th:text="'hello '+${user.username}+' '+|Go ${user.address}|"></div>
Copy the code
3.1.4 Arithmetic operations
The arithmetic operations are: +, -, *, /, and %.
<div th:with="age=(99*99/99+99-1)">
<div th:text="${age}"></div>
</div>
Copy the code
Th :with defines a local variable age that can be used in its div.
3.1.5 Boolean operation
- Binary operators: and, or
- Boolean (unary operator) :! , not
Case study:
<div th:with="age=(99*99/99+99-1)">
<div th:text="9 eq 9 or 8 ne 8"></div>
<div th:text=! "" (9 eq 9 or 8 ne 8)"></div>
<div th:text="not(9 eq 9 or 8 ne 8)"></div>
</div>
Copy the code
3.1.6 Comparison and equality
Values in expressions can be compared using the >, <, >= and <= symbols. = = and! The = operator is used to check for equality (or inequality). Note that XML states that < and > tags cannot be used for attribute values, so you should escape them to < And & gt; .
If you do not want to escape, you can also use an alias: gt (>); Lt (<); Ge (> =); Le (< =); not (!) . Eq (==), neq/ne (! =).
For example:
<div th:with="age=(99*99/99+99-1)">
<div th:text="${age} eq 197"></div>
<div th:text="${age} ne 197"></div>
<div th:text="${age} ge 197"></div>
<div th:text="${age} gt 197"></div>
<div th:text="${age} le 197"></div>
<div th:text="${age} lt 197"></div>
</div>
Copy the code
3.1.7 Conditional operators
Similar to our Java ternary operator.
<div th:with="age=(99*99/99+99-1)">
<div th:text="(${age} ne 197)? 'yes':'no'"></div>
</div>
Copy the code
The following part of: can be omitted. If omitted and the result is false, null is returned.
3.1.8 Built-in Objects
Basic built-in objects:
- # CTX: context object.
- # Vars: context variables.
- #locale: context locale.
- #request :(in Web context only) HttpServletRequest object.
- #response :(in Web context only) HttpServletResponse object.
- #session :(in Web context only) HttpSession object.
- #servletContext :(in Web context only) the servletContext object.
These built-in objects can be accessed on the page, as a simple example:
<div th:text='${#session.getAttribute("name")}'></div>
Copy the code
Utility built-in objects:
- #execInfo: Information about the template being processed.
- #messages: Method of getting externalized messages in variable expressions, as opposed to using # {… } Syntax is obtained in the same way.
- #uris: a method to escape the URL/URI part
- #conversions: a method to perform configured transformation services (if any).
- #dates: Java.util. Date object methods: formatting, component extraction, etc
- Calendars: a java.util.Calendar object similar to #dates.
- #numbers: The method used to format a number object.
- Strings: contains, startsWith, prepending/appending, etc
- #objects: Methods for general objects.
- # Bools: Boolean evaluation methods.
- # Arrays: array methods.
- #lists: Method of lists
- #sets: sets of methods.
- #maps.
- # Aggregates: The method by which aggregates are created on an array or collection.
- # IDS: Methods for handling id attributes that may duplicate (for example, as a result of iteration).
These are some built-in objects and tool methods, and the way to use them is relatively easy. If you use IntelliJ IDEA, it will automatically prompt the method in the object, very convenient.
For example:
<div th:text="${#execInfo.getProcessedTemplateName()}"></div>
<div th:text="${#arrays.length(#request.getAttribute('names'))}"></div>
Copy the code
3.2 Setting An Attribute Value
This sets the attribute value for the HTML element. You can set more than one at a time, separated by,.
Such as:
<img th:attr="src=@{/1.png},title=${user.username},alt=${user.username}">
Copy the code
Will be rendered as:
<img src="/myapp/1.png" title="javaboy" alt="javaboy">
Copy the code
Of course, this setup is not very beautiful or readable. Thymeleaf also supports using dynamic values by prefixing each native HTML attribute with th:, as follows:
<img th:src="@{/1.png}" th:alt="${user.username}" th:title="${user.username}">
Copy the code
This way it looks a little bit clearer and renders the same as before.
Alt and title in the above example are two special attributes that can be set once, as follows:
<img th:src="@{/1.png}" th:alt-title="${user.username}">
Copy the code
This is equivalent to the previous setup.
3.3 traversal
Array/collection/Map/Enumeration/Iterator traversal is a very common requirement, Thymeleaf by th: each to implement traversal, as follows:
<table border="1">
<tr th:each="u : ${users}">
<td th:text="${u.username}"></td>
<td th:text="${u.address}"></td>
</tr>
</table>
Copy the code
Users is the collection/array to iterate over, and u is a single element in the collection.
When traversing, we might need to get the traversal state, which Thymeleaf also supports:
- Index: current traversal index, starting from 0.
- Count: current traversal index, starting from 1.
- Size: the number of elements in the iterated variable.
- Current: traversal variable of each traversal.
- Even /odd: The current traversal is an even or odd number of times.
- First: Indicates whether this is the first traversal.
- Last: indicates whether the current traversal is the last one.
The state after u represents the traversal state by which the above attributes can be referenced.
<table border="1">
<tr th:each="u,state : ${users}">
<td th:text="${u.username}"></td>
<td th:text="${u.address}"></td>
<td th:text="${state.index}"></td>
<td th:text="${state.count}"></td>
<td th:text="${state.size}"></td>
<td th:text="${state.current}"></td>
<td th:text="${state.even}"></td>
<td th:text="${state.odd}"></td>
<td th:text="${state.first}"></td>
<td th:text="${state.last}"></td>
</tr>
</table>
Copy the code
3.4 Branch Statements
Display only an odd number of traversals, you can use th:if as follows:
<table border="1">
<tr th:each="u,state : ${users}" th:if="${state.odd}">
<td th:text="${u.username}"></td>
<td th:text="${u.address}"></td>
<td th:text="${state.index}"></td>
<td th:text="${state.count}"></td>
<td th:text="${state.size}"></td>
<td th:text="${state.current}"></td>
<td th:text="${state.even}"></td>
<td th:text="${state.odd}"></td>
<td th:text="${state.first}"></td>
<td th:text="${state.last}"></td>
</tr>
</table>
Copy the code
Th :if not only accepts Boolean values, but also accepts other types of values, such as the following:
- If the value is Boolean and true.
- If the value is a number and not 0.
- If the value is a character and is not 0.
- If the value is a string and not “false”, “off”, or “no”.
- If the value is not a Boolean, a number, a character, or a string.
But if the value is null, th:if evaluates to false.
Th :unless is the exact opposite of th:if.
<table border="1">
<tr th:each="u,state : ${users}" th:unless="${state.odd}">
<td th:text="${u.username}"></td>
<td th:text="${u.address}"></td>
<td th:text="${state.index}"></td>
<td th:text="${state.count}"></td>
<td th:text="${state.size}"></td>
<td th:text="${state.current}"></td>
<td th:text="${state.even}"></td>
<td th:text="${state.odd}"></td>
<td th:text="${state.first}"></td>
<td th:text="${state.last}"></td>
</tr>
</table>
Copy the code
This display is the exact opposite of the one above.
Switch can also be used when there is more possibility:
<table border="1">
<tr th:each="u,state : ${users}">
<td th:text="${u.username}"></td>
<td th:text="${u.address}"></td>
<td th:text="${state.index}"></td>
<td th:text="${state.count}"></td>
<td th:text="${state.size}"></td>
<td th:text="${state.current}"></td>
<td th:text="${state.even}"></td>
<td th:text="${state.odd}"></td>
<td th:text="${state.first}"></td>
<td th:text="${state.last}"></td>
<td th:switch="${state.odd}">
<span th:case="true">odd</span>
<span th:case="*">even</span>
</td>
</tr>
</table>
Copy the code
Th :case=”*”
3.5 Local Variables
We’ve already covered this, using th:with to define a local variable.
3.6 the inline
We can use properties to put data into a page template, but many times it is more intuitive to use inline methods like this:
<div>hello [[${user.username}]]</div>
Copy the code
Using inline way to do splicing also seems more natural.
[[…]] corresponds to th:text (the result will be escaped HTML), [(…)] Corresponding to th: UText, it does not perform any HTML escapes.
Something like this:
<div th:with="str='hello <strong>javaboy</strong>'">
<div>[[${str}]]</div>
<div>[(${str})]</div>
</div>
Copy the code
The final display looks like this:
But there’s a problem with inlining. One of the advantages of using Thymeleaf is that we can see it directly in the browser without dynamic rendering. This is true when we use property configuration, but when we use inline, expressions are displayed directly in static web pages.
You can also use inline in JS or CSS. Take JS as an example.
<script th:inline="javascript">
var username=[[${user.username}]]
console.log(username)
</script>
Copy the code
Js requires th:inline=”javascript” to enable inline.
4. Summary
Well, Thymeleaf is pretty much the same as everyone else, and should be able to handle daily work. If you’re interested in Thymeleaf, you can also check out its official documentation: www.thymeleaf.org.
Finally, Songgo also collected more than 50 project requirements documents, if you want to do a project to practice friends can look at it
Requirements documentation address: gitee.com/lenve/javad…