1. 程式人生 > >Spring Boot入門教程(十九): Thymeleaf

Spring Boot入門教程(十九): Thymeleaf

一:Thymeleaf

Spring官方也推薦使用Thymeleaf,Thymeleaf最大的特點是能夠直接在瀏覽器中開啟並正確顯示模板頁面,而不需要啟動整個Web應用。

JSP技術Spring Boot官方是不推薦的,原因有三:

  • tomcat只支援war的打包方式,不支援可執行的jar。
  • Jetty 巢狀的容器不支援jsp
  • Undertow
  • 建立自定義error.jsp頁面不會覆蓋錯誤處理的預設檢視,而應該使用自定義錯誤頁面

1. pom.xml

<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> <dependency> <groupId>org.projectlombok</groupId
>
<artifactId>lombok</artifactId> <optional>true</optional> </dependency>

spring-boot-starter-thymeleaf會自動包含spring-boot-starter-web,所以我們就不需要單獨引入web依賴了

2. application.properties

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf
.encoding=UTF-8 spring.thymeleaf.mode=HTML5 spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=true spring.thymeleaf.enabled=true

預設的配置如下:

# THYMELEAF (ThymeleafAutoConfiguration)
#開啟模板快取(預設值:true)
spring.thymeleaf.cache=true 
#Check that the template exists before rendering it.
spring.thymeleaf.check-template=true 
#檢查模板位置是否正確(預設值:true)
spring.thymeleaf.check-template-location=true
#Content-Type的值(預設值:text/html)
spring.thymeleaf.content-type=text/html
#開啟MVC Thymeleaf檢視解析(預設值:true)
spring.thymeleaf.enabled=true
#模板編碼
spring.thymeleaf.encoding=UTF-8
#要被排除在解析之外的檢視名稱列表,用逗號分隔
spring.thymeleaf.excluded-view-names=
#要運用於模板之上的模板模式。另見StandardTemplate-ModeHandlers(預設值:HTML5)
spring.thymeleaf.mode=HTML5
#在構建URL時新增到檢視名稱前的字首(預設值:classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/
#在構建URL時新增到檢視名稱後的字尾(預設值:.html)
spring.thymeleaf.suffix=.html
#Thymeleaf模板解析器在解析器鏈中的順序。預設情況下,它排第一位。順序從1開始,只有在定義了額外的TemplateResolver Bean時才需要設定這個屬性。
spring.thymeleaf.template-resolver-order=
#可解析的檢視名稱列表,用逗號分隔
spring.thymeleaf.view-names=

3. controller

@Controller
public class SampleController {
    @GetMapping("/index")
    public ModelAndView index(Model model){
        ModelAndView modelAndView = new ModelAndView("index");

        List<Fans> fans = new ArrayList<>();
        fans.add(new Fans(1L, "zhangsan"));
        fans.add(new Fans(2L, "lis"));
        fans.add(new Fans(3L, "wangwu"));

        modelAndView.addObject("user", new User(1L, "mengday", "[email protected]", fans, true, new Date()));

        return modelAndView;
    }


    @Data
    @AllArgsConstructor
    public class User {
        private Long id;
        private String username;
        private String email;
        private List<Fans> fans;
        private Boolean isAdmin;
        private Date birthday;
    }

    @Data
    @AllArgsConstructor
    public class Fans {
        private Long id;
        private String name;
    }
}

4. index.html

注意:在html標籤中使用xmlns:th=”http://www.thymeleaf.org”

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<body>

<div th:object="${user}">
    <span th:text="*{id}"></span><br/>
    <span th:text="'nickname:' + *{username}"></span><br/>
    <span th:text="|email: ${user.email}|"></span><br/>
    <span th:if="${user.isAdmin}">超級管理員</span><br/>
    <span th:unless="${user.isAdmin == true}">普通使用者</span><br/>
    <span> [[${#dates.format(user.birthday,'yyyy-MM-dd HH:mm:ss')}]] </span><br/>
    <table border="1px" >
        <tr> <td>index</td> <td>id</td> <td>name</td> <td>length</td></tr>
        <tr th:each="item, stat : ${user.fans}" th:style="'background-color:' + ${stat.even == true ? 'bisque' : 'gray'}">
            <td>[[${stat.index}]]</td>
            <td>[[${item.id}]]</td>
            <td>
                <a th:href="@{/fans/{id}(id=${item.id})}">[[${item.name}]]</a>
            </td>
            <td>[[${#strings.length(user.username)}]]</td>
        </tr>
    </table>
</div>
<br/>
</body>
</html>

src/resources/static/css/style.css
一般靜態資源(js、css、image等)都放在static目錄下

body {
    color: red;
}

這裡寫圖片描述

二:靜態資源的存放位置

Spring Boot 提供了對靜態資源的支援,在建立Spring Boot專案時預設只建立了一個存放靜態資源的目錄src/main/resources/static,一共有四個,其它三個如果需要可以手動創建出目錄,而且這四個是有優先順序,當同一個資源出現在靜態目錄的多個地方時是按照優先順序獲取的,先獲取優先順序高的。

  1. classpath:/META-INF/resources
  2. classpath:/resources
  3. classpath:/static
  4. classpath:/public

這裡寫圖片描述

1. application.properties配置

對應的原始碼:spring-configuration-metadata.json

{
  "sourceType": "org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties",
  "defaultValue": "\/**",
  "name": "spring.mvc.static-path-pattern",
  "description": "Path pattern used for static resources.",
  "type": "java.lang.String"
},

{
  "sourceType": "org.springframework.boot.autoconfigure.web.ResourceProperties",
  "defaultValue": [
    "classpath:\/META-INF\/resources\/",
    "classpath:\/resources\/",
    "classpath:\/static\/",
    "classpath:\/public\/"
  ],
  "name": "spring.resources.static-locations",
  "description": "Locations of static resources. Defaults to classpath:[\/META-INF\/resources\/,\n \/resources\/, \/static\/, \/public\/].",
  "type": "java.lang.String[]"
},

對應application.properties的預設配置

spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

在應用程式啟動的時候會有日誌列印,可以看到

  • /** 對映到 /static (或/public、/resources、/META-INF/resources)
  • /webjars/** 對映到 classpath:/META-INF/resources/webjars/

這裡寫圖片描述

假如 在src/main/resources/static目錄下放一個index.html, 通過http://localhost:8080/index.html就能直接訪問,路徑中不用在包含static子路徑了。

如果訪問靜態資源想在路徑上有體現,也可以自定義,如將static-path-pattern配置成spring.mvc.static-path-pattern=/static/**就需要用http://localhost:8080/static/index.html來訪問
同樣如果對於系統定義的靜態資源的存放位置不滿意也可以通過spring.resources.static-locations來定義,一般靜態資源都放在src/main/resource下面。

2. JavaConfig - WebMvcConfigurationSupport

addResourceHandlers用於配置spring.mvc.static-path-pattern。

傳統Spring MVC開發經常將jsp頁面放置在webapp/WEB-INF下,這樣要想訪問頁面就需要寫一個controller對應的方法,即使方法中沒什麼業務邏輯,只僅僅用於頁面跳轉也不得不寫,感覺有點low,在Spring Boot中通過配置addViewControllers,配置一個路徑和一個檢視名稱的對映即可,也不用再controller中寫頁面跳轉的RequestMapping方法了。囉嗦一句:看到addViewControllers這個方法感覺突然好熟悉,原來在iOS中有個addChildViewController方法,而且在iOS中有UIViewController這種類,類似於Java中的Controller的概念

@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurationSupport {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/html/");
        // addResourceLocations也可以指定一個系統中的一個目錄
        // registry.addResourceHandler("/static/**").addResourceLocations("file:/Users/xxx/Documents/demo/static");
        super.addResourceHandlers(registry);
    }

    // http://localhost:8080/home
    @Override
    protected void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        super.addViewControllers(registry);
    }
}

webjars

webjars 就是將web開發中常用的靜態資源放到classpath:/META-INF/resources/webjars/ 中,然後打包成.jar釋出到maven倉庫中,使用時通過maven來引入,假如專案中用到bootstrap,常規的做法就是手動去官網下載,然後手動將bootstrap放到靜態目錄。一般常用的像jquery、bootstrap、angularjs、react、vue、swagger-ui等都有相應的maven依賴,目前有92個這種依賴。

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.0.0</version>
</dependency>

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

這裡寫圖片描述

在頁面上通過/webjars/jquery/3.3.1/jquery.js 來引入,Spring Boot 預設將 /webjars/** 對映到 classpath:/META-INF/resources/webjars/,可以通過http://localhost:8080/webjars/jquery/3.3.1/jquery.js來驗證一下看是否能獲取到。

<script src="${pageContext.request.contextPath}/webjars/jquery/3.3.1/jquery.js"></script>

webjars-locator

在上面訪問靜態資源時路徑中包含了版本號(http://localhost:8080/webjars/jquery/3.3.1/jquery.js),假如版本升級需要全域性替換所有引入的檔案,當然也不太費事一個全域性替換就搞定了,當然也可以防止於未然,webjars提供了一個webjars-locator的依賴,目的是讓前端頁面引入的靜態資源不包含路徑,當請求一個靜態資源時會自動幫你對映到對的版本對應的資源。

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
    <version>0.33</version>
</dependency>
@Controller
public class WebJarsController {

    private final WebJarAssetLocator assetLocator = new WebJarAssetLocator();

    @ResponseBody
    @RequestMapping("/webjarslocator/{webjar}/**")
    public ResponseEntity<Object> locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) {
        try {
            // /webjarslocator/jquery/
            String mvcPrefix = "/webjarslocator/" + webjar + "/"; // This prefix must match the mapping path!
            // /webjarslocator/jquery/jquery.js
            String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
            // META-INF/resources/webjars/jquery/3.3.1/jquery.js
            String fullPath = assetLocator.getFullPath(webjar, mvcPath.substring(mvcPrefix.length()));
            return new ResponseEntity<>(new ClassPathResource(fullPath), HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }
}
<script src="${pageContext.request.contextPath}/webjarslocator/jquery/jquery.js"></script>

假如前端訪問http://localhost:8080/webjarslocator/jquery/jquery.js(此地址中不包含版本號),地址對映到WebJarsController,返回META-INF/resources/webjars/jquery/3.3.1/jquery.js對應的資源。這樣就達到前端引入的靜態資源中不包含具體版本號,當需要升級的時候直接修改maven對應的依賴版本即可,前端也不用全域性替換版本號操作了。感覺這個功能不實用,版本升級很久才會一次,而且全域性替換也很簡單,也是秒秒鐘搞定的事情。

靜態資源瀏覽器快取

開發時,業務對應的js經常會變動,一般瀏覽器會快取靜態資源,一般防止瀏覽器快取靜態資源的做法是在地址後面使用版本號引數,或者在地址後面使用時間戳,Spring Boot 給出了自己的解決方案。

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
@ControllerAdvice
public class ResourceUrlProviderController {

    @Autowired
    private ResourceUrlProvider resourceUrlProvider;

    @ModelAttribute("urls")
    public ResourceUrlProvider urls() {
        return this.resourceUrlProvider;
    }
}

common.js放在 src/main/resources/static/js/目錄下

<script src="${pageContext.request.contextPath }${urls.getForLookupPath('/js/common.js') }"></script>

當我們訪問頁面後,HTML中實際生成的程式碼為common-<md5>.js, 每當common.js內容發生變化時MD5值就會重新生成,當js檔案沒有時md5值不變,當js檔案內容發生改變時,md5值發生變化,js檔案的內容也隨之改變。這樣就保證了js檔案始終是最新的。

<script src="/js/common-c6b7da8fffc9be141b48c073e39c7340.js"></script>

三: Interceptor攔截器

攔截器的使用分兩步:

  1. 宣告攔截器,實現HandlerInterceptor
  2. 配置攔截器,在WebMvcConfigurerAdapter#addInterceptors配置
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println(request.getRequestURI() + "-------------");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("------------postHandle------------");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("------------afterCompletion------------");
    }
}
@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");

        super.addResourceHandlers(registry);
    }

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/");
        super.addInterceptors(registry);
    }
}

相關推薦

Spring Boot入門教程(): Thymeleaf

一:Thymeleaf Spring官方也推薦使用Thymeleaf,Thymeleaf最大的特點是能夠直接在瀏覽器中開啟並正確顯示模板頁面,而不需要啟動整個Web應用。 JSP技術Spring Boot官方是不推薦的,原因有三: tomcat只支援wa

Spring Boot入門教程(四): Dubbo

一:簡介 Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高效能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向介面的遠端方法呼叫,智慧容錯和負載均衡,以及服務自動註冊和發現。 二:安裝dubbo管理控制檯(dubbo-admin)

Spring Boot入門教程(四六): @Async

一:簡介 ThreadPoolTaskExecutor 用於定義執行緒池,是對java.util.concurrent.ThreadPoolExecutor類的包裝。可以通過@EnableAsync來開啟非同步支援,通過@Async來宣告一個非同步方法 二:示例 @Confi

Spring Boot入門教程(四五): 事務@Transactional

一:簡介 在Spring中事務可以通過兩種方式來管理,一種是程式設計式事務另一種是宣告式事務 宣告式事務:@Transactional 在方法的開頭開始事務,在方法的結束提交事務 程式設計式事務:TransactionTemplate或者PlatformTransa

Spring Boot入門教程(四八):初始化操作 CommandLineRunner和ApplicationRunner

CommandLineRunner和ApplicationRunner在SpringApplication.run()之前,在所有的beans載入完成之後執行,用於執行一些初始化操作(如載入快取、讀取配置檔案、建立執行緒池等) CommandLineRunner和Applicatio

Spring Boot入門教程(五): httpclient

在開發中經常會遇到呼叫第三方的介面,這裡介紹一下在spring boot中如何使用httpclient來發送get和post請求。 引入依賴 <dependency> <groupId>org.apache.httpco

Spring Boot入門教程(四):微信支付整合-刷卡支付

一:準備工作 使用微信支付需要先開通服務號,然後還要開通微信支付,最後還要配置一些開發引數,過程比較多。 二:支付方式 刷卡支付(MICROPAY) :刷卡支付是使用者展示微信錢包內的“刷卡條碼/二維碼”給商戶系統掃描後直接完成支付的模式。主要應

Spring Boot入門教程(五二): 在Docker上執行Spring Boot

一:基礎示例 1.1 安裝JDK和Maven 安裝openjdk: yum -y install java-1.8.0-openjdk* export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_

Spring Boot入門教程(五一): JSON Web Token(JWT)

一:認證 在瞭解JWT之前先來回顧一下傳統session認證和基於token認證。 1.1 傳統session認證 http協議是一種無狀態協議,即瀏覽器傳送請求到伺服器,伺服器是不知道這個請求是哪個使用者發來的。為了讓伺服器知道請求是哪個使用者發來的,需要讓使用者提供

Spring Boot入門教程(四四): Sharding-JDBC+JPA|MyBatis+Druid分庫分表實現

一:資料庫分片方案 客戶端代理: 分片邏輯在應用端,封裝在jar包中,通過修改或者封裝JDBC層來實現。 噹噹網的 Sharding-JDBC 、阿里的TDDL是兩種比較常用的實現。 中介軟體代理: 在應用和資料中間加了一個代理層。分片邏輯統一維護在中介軟體

Spring Boot入門教程(三一): 自定義Starter

在springboot中,使用的最多的就是starter。starter可以理解為一個可拔插式的外掛,例如,你想使用jdbc外掛,那麼可以使用spring-boot-starter-jdbc;如果想使用mongodb,可以使用spring-boot-starte

Spring Boot2 系列教程()Spring Boot 整合 JdbcTemplate

在 Java 領域,資料持久化有幾個常見的方案,有 Spring 自帶的 JdbcTemplate 、有 MyBatis,還有 JPA,在這些方案中,最簡單的就是 Spring 自帶的 JdbcTemplate 了,這個東西雖然沒有 MyBatis 那麼方便,但是比起最開始的 Jdbc 已經強了很多了,它沒有

Spring Boot參考教程)配置上傳下載

.net blog 不想 center src 默認 tps servlet odi 7.配置上傳下載 使用上傳下載的功能我們需要配置multipartResolver,先啟動工程,不做配置。 訪問端點/beans: Spring Boot默認實例化了一個Multip

Spring Boot系列教程一: Mybatis使用分頁外掛PageHelper

一.前言 上篇部落格中介紹了spring boot整合mybatis的方法,基於上篇文章這裡主要介紹如何使用分頁外掛PageHelper。在MyBatis中提供了攔截器介面,我們可以使用PageHelp最為一個外掛裝入到SqlSessionFactory,實現攔截器功能。

Spring Boot入門二:使用ThymeLeaf+表單驗證

Thymeleaf提供了一個用於整合Spring MVC的可選模組,在應用開發中,你可以使用Thymeleaf來完全代替JSP,或其他模板引擎,如Velocity、FreeMarker等。Thymeleaf的主要目標在於提供一種可被瀏覽器正確顯示的、格式良

spring boot最新教程():在spring boot中使用攔截器

       前一篇博文對過濾器的定義做了說明,過濾器屬於Servlet範疇的API,與Spring 沒什麼關係。Web開發中,我們除了使用 Filter 來過濾請web求外,還可以使用Spring提供的HandlerInterceptor(攔截器)。HandlerInte

Spring Boot 入門教程學習 (按照spring boot官方文件和自己理解整理)

建立Spring Boot maven專案   1. 在spring 官網中建立專案到本地   首先選擇maven project  java 之後 填寫 group id Artifactid  完成之後,  點選 generate Project 生成本地專

Spring Boot入門教程(四十三): API介面設計之token、timestamp、sign

一:token 簡介 Token:訪問令牌access token, 用於介面中, 用於標識介面呼叫者的身份、憑證,減少使用者名稱和密碼的傳輸次數。一般情況下客戶端(介面呼叫方)需要先向伺服器端申請一個介面呼叫的賬號,伺服器會給出一個appId和一個key,

Spring Boot入門教程(四):配置檔案

配置方式 每個starter都有自己預設的配置,如果需要改變預設值,可以在其他地方配置來覆蓋掉預設的值,覆蓋預設的配置有多種方式,每種方式的優先順序也不同,如果在多個地方配置則優先使用優先順序高的值,其中命令列引數優先順序最高, 其中大部分引數一般都配置在屬性

Spring boot 入門教程-token驗證

我們在做專案時比如商城專案,有的頁面的開啟是需要登陸的而有的頁面則不需要,所以這裡就需要一種驗證是否登入,或者登入是否過期,這裡說一種token令牌+攔截器的方式。 生成token 使用JWT。 1.引入 <dependency>