SpringBoot from getting started to giving up, Chapter 3

I. static resource mapping rules

In the springBoot project, the relevant configuration of springmvc is in the webmvcauautoconfiguration class

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    //===========webjars access===================
    if (!registry.hasMappingForPattern("/webjars/**")) {
    //===========Static resource access================
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {

//===========Static resource storage file path================
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",

1. webjars access

All / webjars /, go to classpath:/META-INF/resources/webjars / to find resources

webjars: introduce static resources as jar packages. Official website



Directory structure:



2. Static resource access

/**Access any resources of the current project, and static resources access the file directory:




3. Mapping of welcome page index

All index.html pages in the static resource folder are mapped by / *


http://localhost8080/index.html perhaps http://localhost8080/

public WelcomePageHandlerMapping welcomePageHandlerMapping(...) {
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
        new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
    welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    return welcomePageHandlerMapping;

private Optional<Resource> getWelcomePage() {
			String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
			return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();

4. favicon Icon

@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
public static class FaviconConfiguration {

    private final ResourceProperties resourceProperties;

    public FaviconConfiguration(ResourceProperties resourceProperties) {
        this.resourceProperties = resourceProperties;

    public SimpleUrlHandlerMapping faviconHandlerMapping() {
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        //All * * / favicon.ico 
        return mapping;

    public ResourceHttpRequestHandler faviconRequestHandler() {
        ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
        return requestHandler;

spring.mvc.favicon.enabled=true enabled by default

Storage location: under static resource folder

5. Static resource parameter setting

@ConfigurationProperties(prefix = "spring.resources")
public class ResourceProperties {
    //You can set parameters related to resources, such as cache time, etc

If you want to change the path of the static resource folder, modify the yml:

Template engine thymeleaf

1. Introduction of thmeleaf


Switch the thymeleaf Version (old version of springboot switch)


2. Syntax of Thymeleaf

Official website address

Automatic configuration file of springboot for thymeleaf

As long as we put the HTML page under classpath:/templates /, it will render automatically

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

    //As long as we put the HTML page under classpath:/templates /, it will render automatically
	public static final String DEFAULT_PREFIX = "classpath:/templates/";
	public static final String DEFAULT_SUFFIX = ".html";

2.1) application.yml configuration

###Thymeliaf configuration
    #Template mode, support HTML, XML TEXT JAVASCRIPT
    mode: HTML5
    #No configuration for coding
    encoding: UTF-8
    #Content category, can not be configured
    content-type: text/html
    #The development configuration is false to avoid modifying the template and restarting the server
    cache: false
    #Configure the template path. The default is templates, which can be used without configuration
    prefix: classpath:/templates
##There may be less strict HTML format in the actual project. At this time, setting mode=HTML5 will report errors for the non strict. Please refer to the following configuration:
##You may find that in the default configuration, thmeleaf has strict requirements for. html content, such as < meta charset = "UTF-8" / >,
##If the last label closing symbol / is missing, an error will be reported and the error page will be moved.
#Therefore, it is suggested to add the following paragraph:

spring.thymeleaf.mode = LEGACYHTML5
##The default value of spring.thymeleaf.mode is HTML5, which is actually a very strict check. Changing to legacy HTML5 can get a more friendly result
##Friendly format requirements.

##Note that legacy HTML 5 requires an additional library, NekoHTML, to be available.

Common configurations that can be modified:

# THYMELEAF (ThymeleafAutoConfiguration)

2.2) import the namespace of thymeleaf

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

2.3) grammar

Text content (overlay): < div th: text = "${Hello}" > default text content < / div >

Replace native attribute values: < div id = "AA" class = "BB" th: id = "{CC}" th: class = "${DD}" > < / div >

①. Assignment and string splicing

+: string concatenation font string

Simplify the splicing operation in characters: (use "|" to surround the string, instead of "'")

<input type="text" name="userName" value="James Carrot" th:value="${user.name}" />
<span th:text="'The name of the user is ' + ${user.name}" ></span>
<span th:text="'The name of the user is ' + ${user.name} + '_' + ${user.age}"> </span>
<span th:text="|Welcome to our application, ${user.name}!|"></span>
//Equivalent to
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">

② digital output and calculation

<span th:text="2013">1492</span>
<span th:text="2013 + 2">1494</span>
<span th:if="${user.isAdmin()} == false"> false </span>
<span th:if="${user.other} == null"> null</span>

③ arithmetic expression

*Binary operation +, -, /,%

Boolean expression true, false,!, not

and, or

<span th:text="${user.age} % 2 == 0"> </span>			Result: true
<span th:text="true"> </span>							Result: true
<span th:text="!(${user.age} % 2 == 0)"> </span>		Result: false
<span th:text="(${user.age} % 2 == 0) and true"> </span>Result: true

④ comparison operator

Compare >, [,] =, [= (GT, lt, Ge, Le)

Judgment = =,! = (eq, ne)

<span th:if="${user.age} &gt; 18"> Adult </span>
<span th:if="${user.age} != 18"> Adult_no_equality </span>

⑤ condition operator

If-then: (if) ? (then)

If-then-else: (if) ? (then) : (else)

<span th:text="${user.age}%2 == 0 ? 'even'"> </span>
<span th:text="${user.age}%2 == 0 ? 'even' : 'odd'"> </span>

<span th:if="${member.age lt 18}">
<span th:if="${member.name eq 'Ah three'}">
	//Welcome to visit!

##Fail to meet the judgment conditions
<span th:unless="${member.age gt 18}">
	//You're under 18 and can't see a movie!

##switch branch judgment
<span th:switch="${member.uid}">
    <p th:case="100">	uid For 101 employees	</p>
    <p th:case="99">	uid For 102 employees	</p>
    <p th:case="*">	No matching data!	</p>

⑥. Properties of calling object's member variables

<input type="text" name="userName" th:value="${family.father.name}" />

⑦. Call the properties of map object

Get the property name value of the object from the hashMap through the key of the map: you can use ".." or "[]" to get the object value

<input type="text" name="userName" th:value="${hashMap.hashMapKey.name}" />
Equivalent to
<input type="text" name="userName" th:value="${hashMap['hashMapKey'].name}" />

⑧ call the properties of list object

<input type="text" name="userName" th:value="${family.childList[0].name}" />

⑨ method of calling attribute

<input type="text" name="userName" th:value="${family.father.name.toUpperCase()}" />

Get the native object

<p th:text="${#httpServletRequest.getRemoteAddr()}"/>

<p th:text="${#httpServletRequest.getAttribute('requestMessage')}"/>

<p th:text="${#httpSession.getId()}"/>

<p th:text="${#httpServletRequest.getServletContext().getRealPath('/')}"/>

(13) generate URL address @ {}

Th: the value generated by the href replaces the value @ {}

Add the variable value (orderId=${id}) to the url as the request parameter of the url

<!-- th:href Generated value substitution<a>Of href value; (orderId=${id})Do as url Request parameters for -->
<a th:href="@{http://localhost:8080/order/details(orderId=${id})}">view</a>
<a href="http://localhost:8080/order/details?orderId=123">view</a>

<!-- Generation:/order/details?orderId=123 -->
<a th:href="@{/order/details(orderId=${id})}">view</a>
<a href="/order/details?orderId=123">view</a>

<!-- replace url Medium variable values, generating/order/123/details -->
<a th:href="@{/order/{orderId}/details(orderId=${id})}">view</a>
<a href="/order/123/details">view</a>

⑫. Expression tool object

    <p th:text="${#dates.format(mydate,'yyyy-MM-dd')}"/>
    <p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss.SSS')}"/>
    <p th:text="${#strings.replace('www.baidu.cn','.','$')}"/>
    <p th:text="${#strings.toUpperCase('www.baidu.cn')}"/>
    <p th:text="${#strings.trim('www.baidu.cn')}"/>
    <p th:text="${#sets.contains(names,'boot-0')}"/>
    <p th:text="${#sets.contains(names,'boot-9')}"/>
    <p th:text="${#sets.size(names)}"/>
    <p th:text="${#sets.contains(ids,0)}"/>
    <p th:text="${ids[1]}"/>
    <p th:text="${names[1]}"/>


<!-- Common iterations th:each usage -->
<tr th:each="user : ${userList}">
    <td th:text="${user.name}"></td>
    <td th:text="${user.age}"></td>
    <td th:text="${user.isAdmin}"></td>

##Gets the intermediate state of the iteration, defined in iterStat
    index : Index of current node, starting from 0
    size :  Total number of iteration nodes
    even/odd: Currently even/Odd row boolean value
    first/last: Today is every day/Last element

<!-- Gets the intermediate state of the iteration, defined in iterStat in-->
<tr th:each="user,iterStat : ${userList}">
    <!-- index: Index of the current iteration -->
    <td th:text="${iterStat.index }"></td>
    <!-- first: Current element is the first element; last: Current element is last element -->
    <td th:text="${iterStat.first } ? 'First element':(${iterStat.last} ? 'Last element':'')" ></td>
    <!--  -->
    <td th:text="${iterStat.odd} ? 'odd' : 'even'" ></td>
    <td th:text="${user.name}"></td>
    <td th:text="${user.age}"></td>
    <td th:text="${user.isAdmin}"></td>


⑭. Conditional grammar

**th:if th:unless **

<!-- th:if: If the value is true,Then print<span>Whole node  -->
<span th:if="${user.isAdmin}" th:text="${user.name} + 'It's the administrator.'">  </span>

<!-- th:unless: and th:if Is the opposite function, if the value is false,Then print<span>Whole node  -->
<span th:unless="not ${user.isAdmin}" th:text="${user.name} + 'It's the administrator.'"> </span>

<!-- th:switch / th:case -->
<div th:switch="${user.name}">
  <p th:case="'admin'">User is an administrator</p>
  <!-- *: case Default options for -->
  <p th:case="*">User is some other thing</p>

⑮. template

In web development, we often extract common header, common tail, menu and other parts into templates for other pages to use. In thmeleaf, it is realized by th:fragment, th:include, th:replace, parameterized template configuration, css selector loading code block, etc.

Public page / templates/template/footer.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<meta charset="UTF-8" />
    <!-- th:fragment Define blocks for loading -->
    <span th:fragment="copy"> 2017 hry loaded by fragment=copy</span>

    <span id="copy-section"> 2017 hry loaded by id=copy-section</span>

    <!-- When defining a template, you can pass in parameters -->
    <span th:fragment="frag(month, date) "> 
        <span th:text="'welcome hry come in ' + ${month} + '-' + ${date}"></span>


Load the above code block copy in this page through th:include:

templatename::selector:: "preceded by the template file name, followed by the selector

: selector: write only the selector. Here it refers to the fragment name. Then the corresponding fragment of this page will be loaded

templatename: write only the template file name, then load the entire page

<!--  Syntax specification  "::"Template file name followed by selector -->
<div th:include="template/footer::copy"></div>

<!-- Write only selector fragment Name, the corresponding fragment -->
<div th:include="::#thispage"></div>

<!-- Write only the template file name, the entire page will be loaded -->
<div th:include="template/footer"></div>

<!--Load block for this page-->
<span id="thispage">
    div in this page.

Loading code blocks with th:fragment and css selectors

<! -- load "th:fragment here to define the block to load" -- >
<div th:include="template/footer::copy"></div>

<! -- load the node with id = copy section -- >
<div th:include="template/footer::#copy-section"></div> 

th:include and th:replace

##th:include: content of load template: read the content of load node (excluding node name), replace div content
##th:replace: replace the current label with the label in the template. The loaded node will replace the entire div loaded

Content of load template: read the content of load node (excluding node name), replace the content of < div > -- >
<div th:include="template/footer::copy">1</div>
<div> 2017 hry loaded by fragment=copy</div>

<! -- replace the current label with the label in the template: the loaded node will replace the whole < div > -- >
<div th:replace="template/footer::copy">2</div>
<span> 2017 hry loaded by fragment=copy</span>

Pass parameters on template call

<div th:include="template/footer::frag(${month},${date})">...</div>

Keywords: Programming Thymeleaf Spring Fragment html5

Added by themistral on Wed, 13 Nov 2019 12:02:12 +0200