SpringBoot從入門到放棄,第三章

SpringBoot從入門到放棄,第三章

一、靜態資源映射規則

在springBoot項目中,springmvc的相關配置都在WebMvcAutoConfiguration類中

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
    }
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    
    //===========webjars訪問===================
    if (!registry.hasMappingForPattern("/webjars/**")) {
        customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
                                             .addResourceLocations("classpath:/META-INF/resources/webjars/")
                                             .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    
    //===========靜態資源訪問================
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
        customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
                                             .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
                                             .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
}

//===========靜態資源存放文件路徑================
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", 
 "classpath:/static/", 
 "classpath:/public/" 
};

1、webjars訪問

所有/webjars/ ,都去classpath:/META-INF/resources/webjars/找資源

​ webjars:以jar包的方式引入靜態資源。官網

引入:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.4.1</version>
</dependency>

目錄結構:

在這裏插入圖片描述

訪問:

http://localhost:8080/webjars/jquery/3.4.1/jquery.js

2、靜態資源訪問

/**訪問當前項目的任何資源,靜態資源訪問文件目錄:

classpath:/META-INF/resources/,
classpath:/resources/,
classpath:/static/, 
classpath:/public/
/

訪問:

http://localhost:8080/abc

3、歡迎頁index的映射

靜態資源文件夾下所有index.html頁面,被/**映射

訪問:

http://localhost8080/index.html 或者 http://localhost8080/

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(...) {
    
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
        new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
        this.mvcProperties.getStaticPathPattern());
    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圖標

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

    private final ResourceProperties resourceProperties;

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

    @Bean
    public SimpleUrlHandlerMapping faviconHandlerMapping() {
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        //所有  **/favicon.ico 
        mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
                                                   faviconRequestHandler()));
        return mapping;
    }

    @Bean
    public ResourceHttpRequestHandler faviconRequestHandler() {
        ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
        requestHandler
            .setLocations(this.resourceProperties.getFaviconLocations());
        return requestHandler;
    }

}
spring.mvc.favicon.enabled=true默認啓用

存放位置:靜態資源文件夾下
favicon.ico

5、靜態資源參數設置

@ConfigurationProperties(prefix = "spring.resources")
public class ResourceProperties {
    //可以設置和資源有關的參數,如緩存時間等
}

如果想改變靜態資源文件夾的路徑,修改yml:
spring.resources.static-locations=classpath:/hello,classpath:/mystatic

二、模板引擎thymeleaf

在這裏插入圖片描述

1、引入thymeleaf

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

切換thymeleaf版本(舊版本的springboot切換)

<properties>
    <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>

2、Thymeleaf使用語法

官網地址

springboot對thymeleaf的自動配置文件

表示:只要我們把HTML頁面放在classpath:/templates/下,就可以自動渲染了

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

	private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

    //表示:只要我們把HTML頁面放在classpath:/templates/下,就可以自動渲染了
	public static final String DEFAULT_PREFIX = "classpath:/templates/";
	public static final String DEFAULT_SUFFIX = ".html";
}

2.1)、application.yml配置

###ThymeLeaf配置
spring:
  thymeleaf:
    #模板的模式,支持 HTML, XML TEXT JAVASCRIPT
    mode: HTML5
    #編碼 可不用配置
    encoding: UTF-8
    #內容類別,可不用配置
    content-type: text/html
    #開發配置爲false,避免修改模板還要重啓服務器
    cache: false
    #配置模板路徑,默認是templates,可以不用配置
    prefix: classpath:/templates
    
##實際項目中可能會有不太嚴格的HTML格式,此時設置mode=HTML5將會對非嚴格的報錯,可以參考以下配置:
spring.thymeleaf.mode=LEGACYHTML5
##你可能會發現在默認配置下,thymeleaf對.html的內容要求很嚴格,比如<meta charset="UTF-8" />,
##如果少最後的標籤封閉符號/,就會報錯而轉到錯誤頁。
#因此,建議增加下面這段:

spring.thymeleaf.mode = LEGACYHTML5
##spring.thymeleaf.mode的默認值是HTML5,其實是一個很嚴格的檢查,改爲LEGACYHTML5可以得到一個可能更友好
##親切的格式要求。

##需要注意的是,LEGACYHTML5需要搭配一個額外的庫NekoHTML纔可用。
<dependency>  
       <groupId>net.sourceforge.nekohtml</groupId>  
       <artifactId>nekohtml</artifactId>  
       <version>1.9.22</version>  
</dependency> 

常見的一些可以被修改的配置:

# THYMELEAF (ThymeleafAutoConfiguration)
spring.thymeleaf.cache=true 
spring.thymeleaf.check-template=true 
spring.thymeleaf.check-template-location=true
spring.thymeleaf.enabled=true 
spring.thymeleaf.enable-spring-el-compiler=false 
spring.thymeleaf.encoding=UTF-8 
spring.thymeleaf.excluded-view-names= 
spring.thymeleaf.mode=HTML
spring.thymeleaf.prefix=classpath:/templates/ 
spring.thymeleaf.reactive.chunked-mode-view-names=
spring.thymeleaf.reactive.full-mode-view-names= 
spring.thymeleaf.reactive.media-types= 
spring.thymeleaf.suffix=.html 
spring.thymeleaf.template-resolver-order= 
spring.thymeleaf.view-names=

2.2)、導入thymeleaf的名稱空間

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

2.3)、語法

文本內容(覆蓋):<div th:text="${hello}">默認文本內容</div>

替換原生屬性值:<div id="aa" class="bb" th:id="#{cc}" th:class="${dd}"></div>
①、 賦值、字符串拼接

+:字符串拼接字體串

簡化字符中拼接操作:(使用”|”包圍字符串,不需要對字符串使用”’”)

<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>
等價於
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
②、數字輸出和計算
<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>
③、算術表達式

*二進制運算 +, -, , /, %

布爾表達式 true, false, !, not

以及 and, or

<span th:text="${user.age} % 2 == 0"> </span>			結果:true
<span th:text="true"> </span>							結果:true
<span th:text="!(${user.age} % 2 == 0)"> </span>		結果:false
<span th:text="(${user.age} % 2 == 0) and true"> </span>結果:true
④、比較操作符

比較 >, <, >=, <= (gt, lt, ge, le)

判斷 ==, != (eq, ne)

<span th:if="${user.age} &gt; 18"> 大人 </span>
<span th:if="${user.age} != 18"> 大人_no_equality </span>
⑤、條件操作符

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>
<span th:if="${member.name eq '啊三'}">
	歡迎小三來訪問!
</span>

##不滿足判斷條件
<span th:unless="${member.age gt 18}">
	你還不滿18歲,不能夠看電影!
</span>

##switch分支判斷
<span th:switch="${member.uid}">
    <p th:case="100">	uid爲101的員工來了	</p>
    <p th:case="99">	uid爲102的員工來了	</p>
    <p th:case="*">	沒有匹配成功的數據!	</p>
</span>
⑥、調用對象的成員變量的屬性
<input type="text" name="userName" th:value="${family.father.name}" />
⑦、調用map對象的屬性

通過map的key從hashMap獲取對象的屬性name值: 可以使用”.”或者使用”[]”獲取對象值

<input type="text" name="userName" th:value="${hashMap.hashMapKey.name}" />
等價於
<input type="text" name="userName" th:value="${hashMap['hashMapKey'].name}" />
⑧、調用list對象的屬性
<input type="text" name="userName" th:value="${family.childList[0].name}" />
⑨、調用屬性的方法
<input type="text" name="userName" th:value="${family.father.name.toUpperCase()}" />
⑩、獲取原生對象
<p th:text="${#httpServletRequest.getRemoteAddr()}"/>

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

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

<p th:text="${#httpServletRequest.getServletContext().getRealPath('/')}"/>
⑪、生成URL地址@{}

th:href生成的值替換的href值 @{}

url中加入變量值(orderId=${id})做爲url的請求參數

<!-- th:href生成的值替換<a>的href值; (orderId=${id})做爲url的請求參數 -->
<a th:href="@{http://localhost:8080/order/details(orderId=${id})}">view</a>
結果:
<a href="http://localhost:8080/order/details?orderId=123">view</a>


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


<!-- 替換url中變量值,生成/order/123/details -->
<a th:href="@{/order/{orderId}/details(orderId=${id})}">view</a>
結果:
<a href="/order/123/details">view</a>
⑫、表達式工具對象
<body>
    <p th:text="${#dates.format(mydate,'yyyy-MM-dd')}"/>
    <p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss.SSS')}"/>
    <hr/>
    <p th:text="${#strings.replace('www.baidu.cn','.','$')}"/>
    <p th:text="${#strings.toUpperCase('www.baidu.cn')}"/>
    <p th:text="${#strings.trim('www.baidu.cn')}"/>
    <hr/>
    <p th:text="${#sets.contains(names,'boot-0')}"/>
    <p th:text="${#sets.contains(names,'boot-9')}"/>
    <p th:text="${#sets.size(names)}"/>
    <hr/>
    <p th:text="${#sets.contains(ids,0)}"/>
    <p th:text="${ids[1]}"/>
    <p th:text="${names[1]}"/>
</body>
⑬、迭代
<!-- 常用的迭代 th:each 用法 -->
<tr th:each="user : ${userList}">
    <td th:text="${user.name}"></td>
    <td th:text="${user.age}"></td>
    <td th:text="${user.isAdmin}"></td>
</tr>


##獲取迭代的中間的狀態,定義在iterStat中
    index :當前節點的索引,從0開始
    size : 迭代節點總數
    even/odd:當前是偶數/奇數行,boolean值
    first/last:當前是每天/最後一個元素

<!-- 獲取迭代的中間的狀態,定義在iterStat中-->
<tr th:each="user,iterStat : ${userList}">
    <!-- index: 當前迭代的索引 -->
    <td th:text="${iterStat.index }"></td>
    <!-- first: 當前元素是第一個元素; last: 當前元素是最後個元素 -->
    <td th:text="${iterStat.first } ? '第一個元素':(${iterStat.last} ? '最後一個元素':'')" ></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>

</tr>

⑭、條件語法

**th:if th:unless **

<!-- th:if:如果值是true,則打印<span>整個節點  -->
<span th:if="${user.isAdmin}" th:text="${user.name} + '是管理員'">  </span>


<!-- th:unless: 和th:if是相反功能,如果值爲false,則打印<span>整個節點  -->
<span th:unless="not ${user.isAdmin}" th:text="${user.name} + '是管理員'"> </span>


<!-- th:switch / th:case -->
<div th:switch="${user.name}">
  <p th:case="'admin'">User is an administrator</p>
  <!-- *: case的默認的選項 -->
  <p th:case="*">User is some other thing</p>
</div>
⑮、模板template

在web開發中,我們經常會將公共頭,公共尾,菜單等部分提取成模板供其它頁面使用。在thymeleaf中,通過th:fragment、th:include、th:replace、參數化模板配置、css選擇器加載代碼塊等實現。

公共頁 /templates/template/footer.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<meta charset="UTF-8" />
<body>
    
    <!-- th:fragment 定義用於加載的塊 -->
    <span th:fragment="copy"> 2017 hry loaded by fragment=copy</span>

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

    <!-- 定義模板時,可以傳入參數 -->
    <span th:fragment="frag(month, date) "> 
        <span th:text="'welcome hry come in ' + ${month} + '-' + ${date}"></span>
	</span>

</body>
</html>

通過th:include在本頁中加載以上的代碼塊copy :

templatename::selector:”::”前面是模板文件名,後面是選擇器

::selector:只寫選擇器,這裏指fragment名稱,則加載本頁面對應的fragment

templatename:只寫模板文件名,則加載整個頁面

<!--  語法說明  "::"前面是模板文件名,後面是選擇器 -->
<div th:include="template/footer::copy"></div>

<!-- 只寫選擇器,這裏指fragment名稱,則加載本頁面對應的fragment -->
<div th:include="::#thispage"></div>

<!-- 只寫模板文件名,則加載整個頁面 -->
<div th:include="template/footer"></div>

<!--本頁面的加載塊-->
<span id="thispage">
    div in this page.
</span>

通過th:fragment和css選擇器加載代碼塊

<!-- 這裏加載”th:fragment 定義用於加載的塊“ -->
<div th:include="template/footer::copy"></div>

<!-- 這裏加載”id=copy-section“的節點 -->
<div th:include="template/footer::#copy-section"></div> 

th:include 和 th:replace

## th:include:加載模板的內容: 讀取加載節點的內容(不含節點名稱),替換div內容
## th:replace:替換當前標籤爲模板中的標籤,加載的節點會整個替換掉加載他的div

<!-- 加載模板的內容: 讀取加載節點的內容(不含節點名稱),替換<div>的內容 -->
<div th:include="template/footer::copy">1</div>
結果:
<div> 2017 hry loaded by fragment=copy</div>


<!-- 替換當前標籤爲模板中的標籤: 加載的節點會整個替換掉加載他的<div>  -->
<div th:replace="template/footer::copy">2</div>
結果:
<span> 2017 hry loaded by fragment=copy</span>

調用模板時傳遞參數

<div th:include="template/footer::frag(${month},${date})">...</div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章