Spring Boot With Thymeleaf

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 57

Spring Boot with Thymeleaf

Prepared by Spring Team


Content

⎆ Spring Boot Thymeleaf


⎆ Standard Expression Syntax
⎆ Content Negotiation
⎆ Spring Hateoas

2
Spring Boot Thymeleaf

⎊ Thymeleaf is a Java template engine for processing and creating HTML, XML, JavaScript,
CSS, and text.
⎊ The library is extremely extensible and its natural templating capability ensures templates can
be prototyped without a back-end – which makes development very fast when compared with
other popular template engines such as JSP.
⎊ Dependency in Spring Boot:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
3
Spring Boot Thymeleaf (cont.)

⎊ Java Template View Engines


● Thymeleaf
● Apache Velocity
● Apache FreeMarker
● Pebble
● Java Server Page (JSP)
⎊ To use Thymeleaf with HTML, we need to add the following attributes in the html start HTML
element:

xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
4
Spring Boot Thymeleaf (cont.)

⎊ Thymeleaf Features
● Make the mapped method in your MVC @Controller objects forward to templates
managed by Thymeleaf.
● Use Spring Expression Language (Spring EL) instead of OGNL.
● Integrated with your form-backing beans and result bindings, including the use of property
editors, conversion services and validation error handling.
● Display internationalization messages from message files
● Support for template logic (condition, iteration, …)

5
Standard Expression Syntax

⎊ Simple expressions: ⎊ Literals:


● Variable Expressions: ${...} ● Text literals: 'one text', 'Another one!',…
● Selection Variable Expressions: *{...} ● Number literals: 0, 34, 3.0, 12.3,…
● Message Expressions: #{...} ● Boolean literals: true, false
● Link URL Expressions: @{...} ● Null literal: null
● Fragment Expressions: ~{...} ● Literal tokens: one, sometext, main,…

6
Standard Expression Syntax (cont.)

⎊ Text operations: ⎊ Comparison and equality:


● String concatenation: + ● Comparators: >, <, >=, <= (gt, lt, ge, le)
● Literal substitutions: |The name is $ ● Equality operators: ==, != (eq, ne)
{name}| ⎊ Conditional operations:
⎊ Boolean operations: ● If-then: (if) ? (then)
● Binary operators: and, or ● If-then-else: (if) ? (then) : (else)
● Boolean negation (unary operator): !, not ● Default: (value) ?: (defaultvalue)
⎊ Special tokens:
● No-Operation: _

7
Simple Expression

⎊ Variable Expression ${ }
// ⇒ Controller
@GetMapping("/home")
public String viewHomePage(ModelMap modelMap) {
modelMap.addAttribute("header", "Welcome to our website");
return "index";
}
@GetMapping(LIST_CATEGORIES_URL)
public String viewCategory(ModelMap modelMap) {
List<Category> categories = categoryService.findCategoryAndPrefixHRD();
modelMap.addAttribute("categories", categories); // object forward
return LIST_CATEGORIES_PATH;
}

-------------------------------------------------------------------------------------
-

// ⇒ Template
<p th:text="${header}">HEADER</p>
<p th:text="${categories}">Categories</p>
<p th:text="${#lists.size(categories)}">Size of Categories</p> 8
Simple Expression (cont.)

⎊ Selection Variable Expression *{ }


public class Category {
private int id;
private String name;
// setter & getter
}

----------------------------------------------------------------------------------------------
// ⇒ Controller
@GetMapping(LIST_CATEGORIES_URL)
public String viewCategory(ModelMap modelMap) {
List<Category> categories = categoryService.findCategoryAndPrefixHRD();
modelMap.addAttribute("categories", categories); // object forward
return LIST_CATEGORIES_PATH;
}

----------------------------------------------------------------------------------------------
// ⇒ Template
<tr th:each="category, state : ${categories}" th:object="${category}">
<td th:text="${state.count}">1.</td>
<td th:text="*{name}">Update software</td>
</tr>
9
Simple Expression (cont.)

⎊ Message Expression #{ }
// ⇒ messages.properties
message = Hello

// ⇒ messages_kh.properties
message = សួសី្ដ

// ⇒ Template
<h1 th:text="#{message}">Message</h1>

// ⇒ Rendering (en)
<h1>Hello</h1>​

// ⇒ Rendering (kh)
<h1>សួសី<
្ដ /h1>

10
Simple Expression (cont.)

⎊ Message Expression #{ }
// ⇒ messages.properties
welcome.message = Hello {0}! Welcome to {1}

// ⇒ Template
<h1 th:text="#{welcome.message(‘Sreynich’,’Khmer Academy’)}">Start up message</h1>

// ⇒ Rendering
<h1>Hello Sreynich! Welcome to Khmer Academy</h1>​

11
Simple Expression (cont.)

⎊ Message Expression #{ }
● LanguageConfiguration.java
@Configuration
public class LanguageConfiguration implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(new Locale("kh"));
return slr;
}

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
12
Simple Expression (cont.)

⎊ Message Expression #{ }
● In order to change the default location of message properties file, we need to implement the
bean of MessageSource in LanguageConfiguration.
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("i18n/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}

● Or using the application.properties

spring.messages.basename=i18n/messages
spring.messages.encoding=UTF-8

13
Simple Expression (cont.)

⎊ Link URL Expression @{ }

// Absolute URLs
<a th:href="@{https://attacomsian.com/about}">About Me</a>
<a href="https://attacomsian.com/about">About Me</a>

// Context-relative URLs
<a th:href="@{/blog/what-is-thymeleaf}">What is Thymeleaf?</a>
<a href="/webapp/blog/what-is-thymeleaf">What is Thymeleaf?</a>

// Server-Relative URLs
<a th:href="@{~/topic/thymeleaf}">Thymeleaf 101</a>
<a href="topic/thymeleaf">Thymeleaf 101</a>

// Protocol-Relative URLs
<script th:src="@{//example.com/js/script.js}"></script>
<link th:href="@{//example.com/css/styles.css}" rel="stylesheet">
<script src="//example.com/js/script.js"></script>
<link href="//example.com/css/styles.css" rel="stylesheet">

14
Simple Expression (cont.)

⎊ Link URL Expression @{ }

// URLs With Parameters


<a th:href="@{https://www.google.com/search(q='thymeleaf')}">Search Thymeleaf</a>
<a th:href="@{https://www.google.com/search(q='thymeleaf',num=12,lang=en)}">Result</a>
<a href="https://www.google.com/search?q=thymeleaf">Search Thymeleaf</a>
<a href="https://www.google.com/search?q=thymeleaf&amp;num=12&amp;lang=en">Search Thymeleaf</a>

// Using Expressions in URLs


<a th:href="@{/posts/preview(id=${post.id})}">View Post</a>
<a href="/posts/preview?id=15">View Post</a>

// URLs with Path Variables


<a th:href="@{/posts/{id}/preview(id=${post.id})}">View Post</a>
<a th:href="@{/{username}/posts/{id}/preview/(username=${post.user.handle},id=${post.id})}">Hi</
a>
<a href="/posts/15/preview">View Post</a>
<a href="/attacomsian/posts/15/preview">View Post</a>

15
Simple Expression (cont.)

⎊ Fragment Expression ~{ }
● Will be detailed in Fragment part

16
Text Operations

⎊ String Concatenation & String Substitution

// Concatenation
<p th:text="'Hello ' + ${username} + '!, Nice to meet you'">Paragraph</p>
// Preprocessing
<p th:text="'Hello __${username}__!, Nice to meet you'">Paragraph</p>
// Literal Substitution
<p th:text="|Hello ${username}, Nice to meet you|">Paragraph</p>

// Concatenation
Hello Dara!, Nice to meet you

// Preprocessing
Hello Dara!, Nice to meet you

// Literal Substitution
Hello Dara!, Nice to meet you

17
Outputting Raw Values

⎊ Render HTML code

// ⇒ Controller
@GetMapping("/home")
public String viewHomePage(ModelMap modelMap) {
modelMap.addAttribute("htmlText", "<h1>Welcome to our website</h1>");
return "index";
}

// ⇒ Template
<p th:utext="${htmlText}">HEADER</p>

18
Text Inlining

// ⇒ Template
<h1 th:inline="text" >
[[${name}]],
it is our sincere pleasure...
</h1>

// ⇒ Rendering
<h1>
Chan Chhaya,
it is our sincere pleasure...
</h1>

19
JavaScript Inlining

⎊ Syntax

<script th:inline="javascript">
// write code here
</script>

⎊ Example

<script th:inline="javascript">
var name = [[${user.firstName + ' ' + user.lastName}]];
var email = [[${user.email}]];
var age = [[${user.age}]];
var createdAt = [[${#dates.format(user.created, 'EEE, MMMM dd, yyyy')}]];
</script>

20
JavaScript Inlining (cont.)

⎊ Example with unescaped expression:

// ⇒ Template
<script th:inline="javascript">
let number = [(${number})]
</script>
// ⇒ Rendering
<script>
let username = 1000
</script>

⎊ Be careful while using an unescaped expression in JavaScript mode. You might end up generating a
malformed JavaScript code.

21
JavaScript Inlining (cont.)

⎊ You can even specify default values for variables by wrapping the inline expressions in JavaScript
comments like below:

// ⇒ Template
<script th:inline="javascript">
var name = /*[[${user.firstName + ' ' + user.lastName}]]*/ "John
Deo";
var email = /*[[${user.email}]]*/ "[email protected]";
var age = /*[[${user.age}]]*/ 25;
var createdAt = /*[[${user.created}]]*/ "January 29, 2020";
</script>

⎊ More reference ⇒ JavaScript variable in Thymeleaf

22
Attribute Manipulation

⎊ Example:

<p th:class="${answer ? 'right' : 'wrong'}"


th:classappend="${!answer ? 'underline' : ''}"
th:attr="data-row-id=${answerId}"
th:text="${answerText}">Your answer</p>

<input type="text" th:disabled="${answer}">


<label><input type="checkbox" name="active" th:checked="${answer}">
Active</label>

<select name="gender" id="gender">


<option value="">Select gender from the list</option>
<option value="M" th:selected="${gender == 'M'}">Male</option>
<option value="F" th:selected="${gender == 'F'}">Female</option>
</select>
23
Attribute Manipulation (cont.)

⎊ Rendering:

<p class="right"
data-row-id="12020">Cambodia</p>
<input type="text" disabled="disabled">
<label><input type="checkbox" name="active" checked="checked">
Active</label>
<select name="gender" id="gender">
<option value="">Select gender from the list</option>
<option value="M" selected="selected">Male</option>
<option value="F">Female</option>
</select>

24
Condition Operation

⎊ if and unless
● The th:if=”${condition}” attribute is used to display a section of the view if the condition is
met.
● The th:unless=”${condition}” attribute is used to display a section of the view if the condition
is not met.
⎊ Example:

<td>
<span th:if="${student.gender} == 'M'" th:text="Male" />
<span th:unless="${student.gender} == 'M'" th:text="Female" />
</td>

25
Condition Operation

⎊ switch and case


● The th:switch and th:case attributes are used to display content conditionally using the switch
statement structure.
⎊ Example:

<td th:switch="${student.gender}">
<span th:case="'M'" th:text="Male" />
<span th:case="'F'" th:text="Female" />
<span th:case="*" th:text="Other" />
</td>

26
Condition Operation

⎊ th:each
● If the model attribute is a collection of objects, the th:each tag attribute can be used to iterate
over it.
⎊ Example:

<tbody>
<tr th:each="student: ${students}">
<td th:text="${student.id}" />
<td th:text="${student.name}" />
</tr>
</tbody>

27
Condition Operation

⎊ th:each (cont.)
● When using th:each, Thymeleaf offers a mechanism useful for keeping track of the status of
your iteration: the status variable.
● Status variables are defined within a th:each attribute and contain the following data: index,
count, size, current, first, last, and even/odd.
⎊ Example:

<tr
th:each="student, iStat : ${students}"
th:style="${iStat.odd}? 'font-weight: bold;'"
th:alt-title="${iStat.even}? 'even' : 'odd'">
<td th:text="${student.id}" />
<td th:text="${student.name}" />
</tr> 28
Handling User Input

⎊ Form input can be handled using the th:action=”@{url}” and th:object=”${object}” attributes.
⎊ The th:action is used to provide the form action URL and th:object is used to specify an object to
which the submitted form data will be bound.
⎊ Individual fields are mapped using the th:field=”*{name}” attribute, where the name is the matching
property of the object.
⎊ Controller to handle the form submission:

@RequestMapping(value = "/saveStudent", method = RequestMethod.POST)


public String saveStudent(@ModelAttribute Student student,
BindingResult errors, Model model) {
// logic to process input data
}
29
Handling User Input (cont.)

⎊ Example:

<form action="#" th:action="@{/saveStudent}" th:object="${student}"


method="post">
<table border="1">
<tr>
<td><label th:text="#{msg.id}" /></td>
<td><input type="number" th:field="*{id}" /></td>
</tr>
<tr>
<td><label th:text="#{msg.name}" /></td>
<td><input type="text" th:field="*{name}" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>
30
Handling User Input (cont.)

⎊ Displaying Validation Errors


● The #fields.hasErrors() function can be used to check if a field has any validation errors.
● The #fields.errors() function can be used to display errors for a particular field.
● The field name is the input parameter for both these functions.
● Example:

<ul>
<li th:each="err : ${#fields.errors('id')}" th:text="${err}" />
<li th:each="err : ${#fields.errors('name')}" th:text="${err}" />
</ul>

31
Thymeleaf Page Layouts

⎊ Usually websites share common page components like the header, footer, menu and possibly
many more.
⎊ These page components can be used by the same or different layouts.
⎊ There are two main styles of organizing layouts in projects:
○ Include style: are built by embedding common page component code directly within each
view to generate the final result.
○ Hierarchical style: are usually created with a parent-child relation, from the more general
part (layout) to the most specific ones (subviews; e.g. page content).

32
Fragment

⎊ Fragment in Thymeleaf is a small piece of code that can be included in other templates.
⎊ It is a common practice in web development to create reusable, small components like header,
footer, navigation menu and other parts of a website that repeated used on multiple pages.
⎊ To define a Thymeleaf fragment, you need to use the th:fragment attribute.

<div th:fragment=”fragmentName”>
<!-- Content here -->
</div>

33
Fragment (cont.)

⎊ You can easily include the fragment by using one of them:


○ th:insert - Inserts the fragment content inside the host tag
○ th:include - Similar to th:insert but it only inserts the content of the specified
fragment (depreciated since 3.0)
○ th:replace - Replaces the host tag with the specified fragment content
⎊ Syntax

<div th:insert="fragment_location/file_name :: fragment_name"></div>


<div th:include="fragment_location/file_name :: fragment_name"></div>
<div th:replace="fragment_location/file_name :: fragment_name"></div>

34
Fragment (cont.)

⎊ Including with DOM Selectors


○ You don’t need to explicit use th:fragment attribute to define fragments.
○ They can be included in another template by using just DOM selector like class name,
element ID, or tag name similar to do what we do in JavaScript.
<div th:insert="fragments/components ::
div.title"></div>
○ The above example will include a <div> element that has the .title CSS class from
the components.html file.

35
Fragment (cont.)

⎊ th:fragment attribute can specify arguments, just like methods, which called
Parameterized Fragments.
⎊ Example:

<div th:fragment="name(firstName, lastName)">


<p>
Hey! I'm <span th:text="${firstName + ' ' + lastName}"></span>!
</p>
</div>

<!--Option 1 to call parameterized fragment-->


<div th:replace="fragments/components :: name('John', 'Doe')"></div>
<!--Option 2 to call parameterized fragment-->
<div th:replace="fragments/components :: name(firstName='John', lastName='Doe')"></div>
<!--the order of the parameters is no longer important-->
<div th:replace="fragments/components :: name(lastName='Doe', firstName='John')"></div>
36
Fragment (cont.)

⎊ Thymeleaf fragment inclusion syntax fully supports conditional expressions to dynamically


load different fragments.

<div th:replace="fragments/footer :: ${user.admin} ? 'footer-admin' : 'footer'"></div>

⎊ If the fragments, you want to conditionally include, are defined in separate files, you have to
use the fragment expression syntax introduced in version 3.0:
<div th:replace="${user.admin} ? ~{fragments/footer :: footer} : ~{fragments/components :: footer}"></div>

37
Fragment (cont.)

⎊ Flexible Layouts
○ This allows us to create fragments that can be enhanced with the markup coming from the
calling templates, thus providing a very flexible layout technique.

<head th:fragment="baseHead(title, links)">

<title th:replace="${title}">Atta | Founder. Developer. Blogger.</title>

<!-- default styles and scripts -->


<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<script th:src="@{/js/jquery.min.js}"></script>

<!-- placeholder for additional links -->


<th:block th:replace="${links}" />

</head> 38
Fragment (cont.)

⎊ Flexible Layouts (cont.)

<head th:replace="fragments/base :: baseHead(~{::title}, ~{::link})">

<title>Introduction to Thymeleaf Fragments | Atta Blog</title>

<link rel="stylesheet" th:href="@{/css/font-awesome.min.css}">


<link rel="stylesheet" th:href="@{/css/jquery-ui.css}">

</head>

39
Fragment (cont.)

⎊ Flexible Layouts (cont.)

<head>

<title>Introduction to Thymeleaf Fragments | Atta Blog</title>

<!-- default styles and scripts -->


<link rel="shortcut icon" href="/images/favicon.ico">
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script src="/js/jquery.min.js"></script>

<!-- placeholder for additional links -->


<link rel="stylesheet" href="/css/font-awesome.min.css">
<link rel="stylesheet" href="/css/jquery-ui.css">

</head>

40
Fragment (cont.)

⎊ Layout Inheritance
○ You can create a single file called layout.html that has the following structure:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="layout(title, content)">
<head>
<meta charset="UTF-8">
<title th:replace="${title}">Layout Title</title>
</head>
<body>

<h1>Layout Main Heading</h1>

<section th:replace="${content}">
<p>Layout contents</p>
</section>

<footer>
<p>&copy; 2020 Layout footer</p>
</footer>

</body>
</html>

41
Fragment (cont.)

⎊ Layout Inheritance (cont.)


○ Both these parameters will be replaced with the calling template tags by using the
fragment expressions as shown below:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
th:replace="layout :: layout(~{::title}, ~{::section})">
<head>
<title>Welcome to My Site</title>
</head>
<body>

<section>
<p>This is just an extra text.</p>
<a th:href="@{/contact-us}">Contact Us</a>
</section>

</body>
</html>
42
Fragment (cont.)

⎊ Layout Inheritance (cont.)


○ Final HTML output
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome to My Site</title>
</head>
<body>
<h1>Layout Main Heading</h1>
<section>
<p>This is just an extra text.</p>
<a href="/contact-us">Contact Us</a>
</section>
<footer>
<p>&copy; 2020 Layout footer</p>
</footer>
</body>
</html>
43
Thymeleaf Layout Dialect

⎊ While fragments are good enough for working with small applications, they become hard to
maintain and update as the application grows to hundreds of views.
⎊ Thymeleaf Layout Dialect is an open-source dialect for Thymeleaf that lets you easily build
complex layouts and reusable templates to achieve higher code reusability in Spring Boot
applications.
⎊ Gradle & Maven Dependency:

implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'

<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
44
Thymeleaf Layout Dialect (cont.)

⎊ Thymeleaf Layout Dialect will introduce the layout namespace along with 5 new attribute
processors that you can use in your templates: decorate, title-pattern, insert,
replace, and fragment.
⎊ To use Layout Dialect attributes in a template, you need to add the layout namespace to the
<html> tag as shown below:

<!DOCTYPE html>
<html lang="en" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

</html>

45
Thymeleaf Layout Dialect (cont.)

⎊ layout:fragment - attribute marks sections in your layout or reusable templates that can be
replaced by sections with the same name in content templates.
⎊ Example:
<!DOCTYPE html>
<html lang="en" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<body>

<div layout:fragment="content">
<p>Body contents</p>
</div>

</body>
</html>

⎊ Note: Fragment names must be unique within a template, otherwise fragment mismatches will
occur and an exception will be thrown. 46
Thymeleaf Layout Dialect (cont.)

⎊ layout:decorate - is an important attribute processor that is used in content templates. It is


declared in the root tag (usually <html> in HTML document) as a fragment expression to
specify the layout template to decorate the current content template.
⎊ Example:

<!DOCTYPE html>
<html lang="en" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
<body>

<div layout:fragment="content">
<p>Welcome to Thymeleaf Layout Dialect</p>
</div>

</body>
</html>
47
Thymeleaf Layout Dialect (cont.)

⎊ layout:title-pattern - allows us to specify a pattern with some special tokens to control


the resulting <title> element.
⎊ Example:

<title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">Atta Blog</title>

48
Thymeleaf Layout Dialect (cont.)

⎊ Layout Dialect Example


○ Create layout template (Master Layout)
○ Create content template (home, about-us, contact)

49
Thymeleaf Ajax Fragment

⎊ How to implement Thymeleaf Ajax Fragment:


○ Create template file which contains the fragments

<div th:fragment="content1">
This is Content 1
</div>
<div th:fragment="content2">
This is Content 2
</div>

50
Thymeleaf Ajax Fragment (cont.)

⎊ How to implement Thymeleaf Ajax Fragment: (cont.)


○ Create mapping URL to return the fragment of your template file
@Controller
public class AjaxController {

@GetMapping("/ajax/content1")
public String fragmentContent1() {
return "user :: content1";
}

@GetMapping("/ajax/content2")
public String fragmentContent2() {
return "user :: content2";
}
}
51
Thymeleaf Ajax Fragment (cont.)

⎊ How to implement Thymeleaf Ajax Fragment: (cont.)


○ Using Ajax to request in your template file
$(function () {
$.ajax({
url:'/ajax/content1',
method:'GET',
success:function (response) {
console.log(response)
$('.content').html(response)
},
error: function (error) {
console.log(error)
}
})
})
52
Thymeleaf Security

⎊ Dependency

// Maven
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>

// Gradle
implementation group: 'org.thymeleaf.extras', name:
'thymeleaf-extras-springsecurity5', version: '3.0.4.RELEASE'

53
Thymeleaf Security (cont.)

⎊ Namespace

<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

⎊ Security Dialect
<p>Spring Security Thymeleaf tutorial</p>
<div sec:authorize="hasRole('USER')">Text visible to user.</div>
<div sec:authorize="hasRole('ADMIN')">Text visible to admin.</div>
<div sec:authorize="isAuthenticated()">
Text visible only to authenticated users.
</div>
Authenticated username:
<div sec:authentication="name"></div>
Authenticated user roles:
<div sec:authentication="principal.authorities"></div>

54
Thymeleaf Security (cont.)

⎊ Instruction ⇒ Spring Boot+Spring Security+Thymeleaf Simple Tutorial

55
References

• Setting up a JavaScript variable in Thymeleaf


• Introduction to Using Thymeleaf in Spring
• Thymeleaf Javascript Inline Example with Variable
• Working with Thymeleaf Layout Dialect in Spring Boot

56
THANKS!
Please try hard to study..!

57

You might also like