整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Java后端應該掌握的前端知識Vue入門(上)

          ue初探

          聲明

          本文題材來自于狂神說https://www.bilibili.com/video/BV18E411a7mC

          1、大前端知識體系

          1.1、前端三要素

          • HTML(結構):超文本標記語言(Hyper Text Markup Language),決定網頁的結構和內容。
          • CSS(表現):層疊樣式表(Cascading Style Sheets),設定網頁的表現樣式。
          • JavaScript(行為):是一種弱類型腳本語言,其源碼不需經過編譯,而是由瀏覽器解釋運行,用于控制網頁的行為動作。

          1.2、結構層HTML

          主要涉及網頁的結構和內容。

          1.3、表現層CSS

          css主要用來設置網頁的表現樣式,css的層疊樣式表只是一門標記語言,也就是說沒有任何的語法支持,用過的人都知道css應該有如下的缺點:

          • css選擇完標簽后需要反復寫一些css樣式,重復工作量大,代碼冗余度高。
          • css樣式無復用的機制,所以代碼的可維護性極差。

          基于如上的缺點誕生了【css預處理器】

          什么是CSS預處理器

          CSS預處理器定義了一種新的語言,其基本思想是,用一種專門的編程語言,為CSS增加了一些編程的特性,將CSS作為目標生成文件,然后開發者就只需要使用這種語言進行CSS的編碼工作。轉化成通俗易懂的話來說就是用一種專門的編程語言,進行Web頁面樣式設計,再通過編譯器轉化為正常的CSS文件,以供項目使用。

          市面上常見的CSS預處理器

          • Sass:基于Ruby ,通過服務端處理,功能強大。解析效率高。需要學習Ruby語言,上手難度高于Less。
          • Less:基于NodeJS,通過客戶端處理,使用簡單。功能比Sass簡單,解析效率也低于Sass,但在實際開發中足夠了,所以如果我們后臺人員如果需要的話,建議使用LESS。
          • Stylus:基于nodejs,Stylus比Less更強大,而且基于nodejs比Sass更符合我們的思路,作為比較年輕的新型語言,Stylus 可以以近似腳本的方式去寫css代碼,創建健壯的、動態的、富有表現力的css。

          1.4、行為層JavaScript

          JavaScript一門弱類型腳本語言,其源代碼在發往客戶端運行之前不需要經過編譯,而是將文本格式的字符代碼發送給瀏覽器,由瀏覽器解釋運行。

          原生JS開發

          我們日常開發都是按照【ECMAScript】標準的開發方式,簡稱ES特點是所有瀏覽器都支持此規范,我們需要知道的是ES5規范對所有的游覽器都支持,但是ES6是市面上用最多的規范版本,主流游覽器支持,所以為了兼容某些游覽器,需要將ES6規范通過webpack降級為ES5。

          TypeScript出現的背景

          TypeScript 起源于使用JavaScript開發的大型項目 。由于JavaScript語言本身的局限性,難以勝任和維護大型項目開發。因此微軟開發了TypeScript ,使得其能夠勝任開發大型項目。

          • TypeScript是一種由微軟開發的自由和開源的編程語言。它是JavaScript的一個超集, 而且本質上向這個語言添加了可選的靜態類型和基于類的面向對象編程。由安德斯·海爾斯伯格(C#、Delphi、TypeScript之父; .NET創立者) 主導。
          • 該語言的特點就是除了具備ES的特性之外還納入了許多不在標準范圍內的新特性,所以會導致很多瀏覽器不能直接支持TypeScript語法, 需要編譯后(編譯成JS) 才能被瀏覽器正確執行。

          1.4.1、JavaScript框架

          • JQuery:大家熟知的JavaScript庫,優點就是簡化了DOM操作,缺點就是DOM操作太頻繁,影響前端性能;在前端眼里使用它僅僅是為了兼容IE6,7,8。
          • Angular:Google收購的前端框架,由一群Java程序員開發,其特點是將后臺的MVC模式搬到了前端并增加了模塊化開發的理念,與微軟合作,采用了TypeScript語法開發;對后臺程序員友好,對前端程序員不太友好;最大的缺點是版本迭代不合理(如1代–>2 代,除了名字,基本就是兩個東西;截止發表博客時已推出了Angular6)。
          • React:Facebook 出品,一款高性能的JS前端框架;特點是提出了新概念 【虛擬DOM】用于減少真實 DOM 操作,在內存中模擬DOM操作,有效的提升了前端渲染效率;缺點是使用復雜,因為需要額外學習一門【JSX】語言。
          • Vue:一款漸進式 JavaScript 框架,所謂漸進式就是逐步實現新特性的意思,如實現模塊化開發、路由、狀態管理等新特性。其特點是綜合了 Angular(模塊化)和React(虛擬 DOM) 的優點。
          • Axios:前端通信框架;因為 Vue 的邊界很明確,就是為了處理 DOM,所以并不具備通信能力,此時就需要額外使用一個通信框架與服務器交互;當然也可以直接選擇使用jQuery 提供的AJAX 通信功能。

          對于后端來學Vue的小伙伴是不是有個疑問,什么叫做DOM呢?有什么用處呢?

          什么叫DOM?

          DOM全稱 Document Object Model,即文檔對象模型,它允許腳本(js)控制Web頁面、窗口和文檔,通俗就是js操作html時的API。

          1.4.2、UI框架

          • Ant-Design:阿里巴巴出品,基于React的UI框架。
          • ElementUI、iview、ice:餓了么出品,基于Vue的UI框架。
          • BootStrap:Teitter推出的一個用于前端開發的開源工具包。
          • AmazeUI:又叫“妹子UI”,一款HTML5跨屏前端框架。

          1.4.3、JavaScript構建工具

          • Babel:JS編譯工具,主要用于瀏覽器不支持的ES新特性,比如用于編譯TypeScript。
          • WebPack:模塊打包器,主要作用就是打包、壓縮、合并及按序加載。

          1.5、三端同一

          1.5.1、混合開發(Hybrid App)

          主要目的是實現一套代碼三端統一(PC、Android:.apk、iOS:.ipa)并能夠調用到設備底層硬件(如:傳感器、GPS、攝像頭等),打包方式主要有以下兩種:

          • 云打包:HBuild -> HBuildX,DCloud 出品;API Cloud。
          • 本地打包: Cordova(前身是 PhoneGap)。

          1.6、微信小程序

          詳見微信官網,這里就是介紹一個方便微信小程序UI開發的框架:WeUI。

          1.7、后端技術NodeJS

          前端人員為了方便開發也需要掌握一定的后端技術但我們Java后臺人員知道后臺知識體系極其龐大復雜,所以為了方便前端人員開發后臺應用,就出現了Node JS這樣的技術。

          Node JS的作者已經聲稱放棄Node JS(說是架構做的不好再加上笨重的node modules,可能讓作者不爽了吧)開始開發全新架構的Deno

          既然是后臺技術,那肯定也需要框架和項目管理工具, Node JS框架及項目管理工具如下:

          • Express:Node JS框架
          • Koa:Express簡化版
          • NPM:項目綜合管理工具,類似于Maven
          • YARN:NPM的替代方案,類似于Maven和Gradle的關系

          1.8、主流前端框架

          1.8.1、Vue.js

          1.8.2、iView

          iview是一個強大的基于Vue的UI庫, 有很多實用的基礎組件比element ui的組件更豐富, 主要服務于PC界面的中后臺產品。使用單文件的Vue組件化開發模式基于npm+webpack+babel開發, 支持ES 2015高質量、功能豐富友好的API, 自由靈活地使用空間。

          • 官網地址
          • Github
          • iview-admin

          備注:屬于前端主流框架,選型時可考慮使用,主要特點是移動端支持較多

          1.8.3、Element UI

          Element是餓了么前端開源維護的Vue UI組件庫, 組件齊全, 基本涵蓋后臺所需的所有組件,文檔講解詳細, 例子也很豐富。主要用于開發PC端的頁面, 是一個質量比較高的Vue UI組件庫。

          • 官網地址
          • Github
          • vue-element-admin

          備注:屬于前端主流框架,選型時可考慮使用,主要特點是桌面端支持較多

          1.8.4、ICE

          飛冰是阿里巴巴團隊基于React/Angular/Vue的中后臺應用解決方案, 在阿里巴巴內部, 已經有270多個來自幾乎所有BU的項目在使用。飛冰包含了一條從設計端到開發端的完整鏈路,幫助用戶快速搭建屬于自己的中后臺應用。

          • 官網地址
          • Github

          備注:主要組件還是以React為主, 截止2019年02月17日更新博客前對Vue的支持還不太完善,目前尚處于觀望階段

          1.8.5、VantUI

          Vant UI是有贊前端團隊基于有贊統一的規范實現的Vue組件庫, 提供了-整套UI基礎組件和業務組件。通過Vant, 可以快速搭建出風格統一的頁面,提升開發效率。

          • 官網地址
          • Github

          1.8.5、AtUI

          at-ui是一款基于Vue 2.x的前端UI組件庫, 主要用于快速開發PC網站產品。它提供了一套n pm+web pack+babel前端開發工作流程, CSS樣式獨立, 即使采用不同的框架實現都能保持統一的UI風格。

          • 官網地址
          • Github

          1.8.6、Cube Ul

          cube-ui是滴滴團隊開發的基于Vue js實現的精致移動端組件庫。支持按需引入和后編譯, 輕量靈活;擴展性強,可以方便地基于現有組件實現二次開發。

          • 官網地址
          • Github

          1.8.7、混合開發

          1.8.7.1、Flutter

          Flutter是谷歌的移動端UI框架, 可在極短的時間內構建Android和iOS上高質量的原生級應用。Flutter可與現有代碼一起工作, 它被世界各地的開發者和組織使用, 并且Flutter是免費和開源的。

          • 官網地址
          • Github

          備注:Google出品, 主要特點是快速構建原生APP應用程序, 如做混合應用該框架為必選框架

          1.8.7.2、lonic

          lonic既是一個CSS框架也是一個Javascript UI庫, lonic是目前最有潛力的一款HTML 5手機應用開發框架。通過SASS構建應用程序, 它提供了很多UI組件來幫助開發者開發強大的應用。它使用JavaScript MV VM框架和Angular JS/Vue來增強應用。提供數據的雙向綁定, 使用它成為Web和移動開發者的共同選擇。

          • 官網地址
          • 官網文檔
          • Github

          1.8.8、微信小程序

          1.8.8.1、mpvue

          mpvue是美團開發的一個使用Vue.js開發小程序的前端框架, 目前支持微信小程序、百度智能小程序,頭條小程序和支付寶小程序??蚣芑?/span>Vue.js, 修改了的運行時框架runtime和代碼編譯器compiler實現, 使其可運行在小程序環境中, 從而為小程序開發引入了Vue.js開發體驗。

          • 官網地址
          • Git hub

          備注:完備的Vue開發體驗, 井且支持多平臺的小程序開發, 推薦使用

          1.8.8.2、WeUI

          WeUI是一套同微信原生視覺體驗一致的基礎樣式庫, 由微信官方設計團隊為微信內網頁和微信小程序量身設計, 令用戶的使用感知更加統一。包含button、cell、dialog、toast、article、icon等各式元素。

          • 官網地址
          • Github

          2、前后端分離史

          2.1、以后端為主的MVC時代

          為了降低開發的復雜度, 以后端為出發點, 比如:Struts、Spring MVC等框架的使用, 就是后端的MVC時代以SpringMVC流程為例:

          優點

          • 在這期間(2005年以前) , 包括早期的JSP、PHP可以稱之為Web 1.0時代,MVC是一個非常好的協作模式, 能夠有效降低代碼的耦合度,為了讓View更純粹, 還可以使用Thymeleaf、Frreemarker等模板引擎,讓前端只關注模板中的視圖層邏輯。

          缺點

          • 前后端分離不純粹,前端寫好代碼后需要后端去套模板,填充數據進去,有時因為套模板的過程中操作失誤就會導致樣式錯亂,增加前后端溝通的成本。

          2.2、基于AJAX帶來的SPA時代

          時間回到2005年AJAX(Asynchronous JavaScript And XML, 異步JavaScript和XML,老技術新用法)被正式提出并開始使用CDN作為靜態資源存儲, 于是出現了JavaScript王者歸來(在這之前JS都是用來在網頁上貼狗皮膏藥廣告的) 的SPA(Single Page Application) 單頁面應用時代。

          優點
          這種模式下, **前后端的分工非常清晰, 前后端的關鍵協作點是AJAX接口。**看起來是如此美妙, 但回過頭來看看的話, 這與JSP時代區別不大。復雜度從服務端的JSP里移到了瀏覽器的JavaScript,瀏覽器端變得很復雜。類似Spring MVC,
          這個時代開始出現瀏覽器端的分層架構

          缺點

          • 前后端接口的約定:如果后端的接口一塌糊涂或者后端的業務模型不夠穩定,那么前端的開發成本會大大增加。
          • 前端開發的復雜度控制:SPA應用大多以功能交互型為主,JavaScript代碼過十萬行很正常。大量JS代碼的組織,與View層的綁定等,都不是容易的事情。

          2.3、前端為主的MVC時代

          此處的MVC模式如下:

          • MVC(同步通信為主) :Model、View、Controller
          • MVP(異步通信為主) :Model、View、Presenter
          • MVVM(異步通信為主):Model、View、View Model為了降低前端開發復雜度,涌現了大量的前端框架,比如:Angular JS、React、Vue.jsEmber JS等, 這些框架總的原則是先按類型分層, 比如Templates、Controllers、Models, 然后再在層內做切分,如下圖:

          優點

          • 前后端職責很清晰:前端工作在瀏覽器端,后端工作在服務端。清晰的分工可以讓開發并行,前端可以依靠模擬數據在本地開發。后端則可以專注于業務邏輯的處理, 輸出RESTful等接口。
          • 前端開發的復雜度可控:前端代碼很重,但合理的分層,讓前端代碼能各司其職。
          • 部署相對獨立:可以快速迭代開發。

          缺點

          • 代碼不能復用。比如后端依舊需要對數據做各種校驗,校驗邏輯無法復用瀏覽器端的代碼。如果可以復用,那么后端的數據校驗可以相對簡單化。
          • 全異步, 對SEO(搜索引擎優化)不利。往往還需要服務端做同步渲染的降級方案。
          • 性能并非最佳,特別是移動互聯網環境下。
          • SPA不能滿足所有需求, 依舊存在大量多頁面應用。URL Design需要后端配合, 前端無法完全掌控。

          2.4、Node JS帶來的全棧時代

          前端為主的MVC模式解決了很多很多問題, 但如上所述, 依舊存在不少不足之處。隨著Node JS的興起, JavaScript開始有能力運行在服務端。這意味著可以有一種新的研發模式:

          在這種研發模式下,前后端的職責很清晰。對前端來說,兩個UI層各司其職:

          • Front-end Ul layer處理瀏覽器層的展現邏輯。通過CSS渲染樣式, 通過JavaScript添加交互功能, HTML的生成也可以放在這層, 具體看應用場景。
          • Back-end Ul layer處理路由、模板、數據獲取、Cookie等。通過路由, 前端終于可以自主把控URL Design, 這樣無論是單頁面應用還是多頁面應用, 前端都可以自由調控。后端也終于可以擺脫對展現的強關注,轉而可以專心于業務邏輯層的開發。

          通過Node, WebServer層也是JavaScript代碼, 這意味著部分代碼可前后復用, 需要SEO的場景可以在服務端同步渲染,由于異步請求太多導致的性能問題也可以通過服務端來緩解。前一種模式的不足,通過這種模式幾乎都能完美解決掉。

          與JSP模式相比, 全棧模式看起來是一種回歸, 也的確是一種向原始開發模式的回歸, 不過是一種螺旋上升式的回歸。

          3、MVVM

          3.1、什么是MVVM

          MVVM(Model-View-ViewModel)是一種軟件設計模式,由微軟WPF(用于替代WinForm,以前就是用這個技術開發桌面應用程序的)和Silverlight(類似于Java Applet,簡單點說就是在瀏覽器上運行WPF)的架構師Ken Cooper和Ted Peters開發,是一種簡化用戶界面的事件驅動編程方式。由John Gossman(同樣也是WPF和Sliverlight的架構師)與2005年在他的博客上發表。

          MVVM源自于經典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel層,負責轉換Model中的數據對象來讓數據變得更容易管理和使用。其作用如下:

          • 該層向上與視圖層進行雙向數據綁定
          • 向下與Model層通過接口請求進行數據交互

          MVVM已經相當成熟了,主要運用但不僅僅在網絡應用程序開發中。當下流行的MVVM框架有Vue.jsAnfular JS

          3.2、為什么要使用MVVM

          MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model),有幾大好處

          • 低耦合:視圖(View)可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的View上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。
          • 可復用:你可以把一些視圖邏輯放在一個ViewModel里面,讓很多View重用這段視圖邏輯。
          • 獨立開發:開發人員可以專注于業務邏輯和數據的開發(ViewMode),設計人員可以專注于頁面設計。
          • 可測試:界面素來是比較難以測試的,而現在測試可以針對ViewModel來寫。

          View

          View是視圖層, 也就是用戶界面。前端主要由HTH L和csS來構建, 為了更方便地展現viewModel或者model層的數據, 已經產生了各種各樣的前后端模板語言, 比如FreeMarker,Thyme leaf等等, 各大MVVM框架如Vue.js.Angular JS, EJS等也都有自己用來構建用戶界面的內置模板語言。

          Model

          Model是指數據模型, 泛指后端進行的各種業務邏輯處理和數據操控, 主要圍繞數據庫系統展開。這里的難點主要在于需要和前端約定統一的接口規則

          ViewModel

          ViewModel是由前端開發人員組織生成和維護的視圖數據層。在這一層, 前端開發者對從后端獲取的Model數據進行轉換處理, 做二次封裝, 以生成符合View層使用預期的視圖數據模型。
          ??需要注意的是View Model所封裝出來的數據模型包括視圖的狀態和行為兩部分, 而Model層的數據模型是只包含狀態的

          • 比如頁面的這一塊展示什么,那一塊展示什么這些都屬于視圖狀態(展示)
          • 頁面加載進來時發生什么,點擊這一塊發生什么,這一塊滾動時發生什么這些都屬于視圖行為(交互)

          視圖狀態和行為都封裝在了ViewModel里。這樣的封裝使得ViewModel可以完整地去描述View層。由于實現了雙向綁定, ViewModel的內容會實時展現在View層, 這是激動人心的, 因為前端開發者再也不必低效又麻煩地通過操縱DOM去更新視圖
          ??MVVM框架已經把最臟最累的一塊做好了, 我們開發者只需要處理和維護ViewModel, 更新數據視圖就會自動得到相應更新,真正實現
          事件驅動編程。
          ??View層展現的不是
          Model層的數據, 而是ViewModel的數據, 由ViewModel負責與Model層交互, 這就完全解耦了View層和Model層, 這個解耦是至關重要的, 它是前后端分離方案實施的重要一環。

          4、Vue

          4.1、什么是Vue

          Vue(讀音/vju/, 類似于view)是一套用于構建用戶界面的漸進式框架, 發布于2014年2月。與其它大型框架不同的是, Vue被設計為可以自底向上逐層應用。Vue的核心庫只關注視圖層, 不僅易于上手, 還便于與第三方庫(如:vue-router,vue-resource,vue x) 或既有項目整合。

          4.2、MVVM模式的實現者

          • Model:模型層, 在這里表示JavaScript對象
          • View:視圖層, 在這里表示DOM(HTML操作的元素)
          • ViewModel:連接視圖和數據的中間件, Vue.js就是MVVM中的View Model層的實現者

          在MVVM架構中, 是不允許數據Model和視圖View直接通信的, 只能通過ViewModel來通信, 而ViewModel就是定義了一個Observer觀察者(俗稱雙向綁定)

          • ViewModel能夠觀察到數據的變化,并對視圖對應的內容進行更新
          • ViewModel能夠監聽到視圖的變化,并能夠通知數據發生改變

          至此, 我們就明白了, Vue.js就是一個MVVM的實現者, 他的核心就是實現了DOM監聽與數據綁定

          4.3、為什么要使用Vue.js

          • 輕量級, 體積小是一個重要指標。Vue.js壓縮后有只有20多kb(Angular壓縮后56kb+,React壓縮后44kb+)
          • 移動優先。更適合移動端, 比如移動端的Touch事件
          • 易上手,學習曲線平穩,文檔齊全
          • 吸取了Angular(模塊化) 和React(虛擬DOM) 的長處, 并擁有自己獨特的功能,如:計算屬性
          • 開源,社區活躍度高

          5、第一個Vue程序

          5.1、注意點

          Vue不支持IE 8及以下版本, 因為Vue使用了IE 8無法模擬的ECMAScript 5特性。但它支持所有兼容ECMAScript 5的瀏覽器

          5.2、開發環境配置

          如果是Java開發的小伙伴喜歡用idea的那么可以直接安裝vue的插件即可。

          **可能出現的問題:**安裝完插件右鍵新建文件發現沒有vue的模板。

          解決辦法:

          5.3、代碼編寫

          5.3.1、新建html文件

          略!

          5.3.2、導入cdn

          • <script src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js”></script>
          • <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

          5.3.3、創建vue實例

          <script type="text/javascript">
              var vm = new Vue({
                  el:"#app",
                  data:{
                      message:"hello,vue!"
                  }
              });
          </script>
          

          5.3.4、完整代碼

          <!doctype html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Document</title>
          </head>
          <body>
          
          <!--引用參數-->
          <div id="app">{{message}}</div>
          
          <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
          
          <script>
              // 定義一個vue實例對象
              var vue = new Vue({
                  // 綁定元素
                  el:'#app',
                  // 定義參數并且賦值
                  data:{
                      message:"hello vue"
                  }
              });
          </script>
          </body>
          </html>
          

          5.4、測試

          為了能夠更直觀的體驗Vue帶來的數據綁定功能, 我們需要在瀏覽器測試一番, 操作流程如下:

          1. 在瀏覽器上運行第一個Vue應用程序, F12進入開發者工具。
          2. 在控制臺輸入vue.message=‘HelloWorld’, 然后回車, 你會發現瀏覽器中顯示的內容會直接變成HelloWorld。
          3. 此時就可以在控制臺直接輸入vue.message來修改值, 中間是可以省略data的, 在這個操作中, 我并沒有主動操作DOM, 就讓頁面的內容發生了變化, 這就是借助了Vue的數據綁定功能實現的; MVVM模式中要求ViewModel層就是使用觀察者模式來實現數據的監聽與綁定, 以做到數據與視圖的快速響應。

          合實戰

          關于 Web 方面的配置比較多,值得慶幸的是,Spring Boot 已經幫我們預置初始化了很多基礎組件。但在實踐的過程中,某些基礎的組件并不能滿足我們的實際需求,這時就需要我們重新初始化相應組件,甚至在某些極端的情況下需要完全接管 Spring Boot 的默認配置。

          本節將基于對前端模板框架 Thymeleaf 的集成,逐步向大家演示如何自定義 ViewResolver以及如何進一步 擴展 Spring MVC 配置。本實例涉及集成 Thymeleaf、自定義初始化ThymeleafViewResolver 以及擴展 Spring MVC。

          Thymeleaf 是一個 Java 類庫,能夠處理 HTML/HTML5、XML、JavaScript、CSS, 甚至純文本類型的文件。通常可以用作MVC中的View層,它可以完全替代 JSP。該框架是SpringBoot 首推的前端展示框架。

          首先我們創建一個集成 Thymeleaf 的 SpringBootWeb 項目。集成 Thymeleaf 的核心操作就是引入對應的 starter,對應項目中 pom.xml 的依賴如下。

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

          通過前面的學習我們已經得知引入該 starter 之后,Spring Boot 便會進行一個初始化的基本配置,因此針對 Thymeleaf 的最簡單集成便完成了,關于頁面展示和基礎配置我們暫時先不考慮。當集成 Thymeleaf 之后,Thymeleaf 對應的自動配置類 ThymeleafAutoConfiguration 中會初始化一個 ThymeleafViewResolver, 用來對 Thymeleaf 的頁面進行解析和渲染。這一操作本質上同默認的 BeanNameViewResolver 作用-樣,都實現了 ViewResolver 接口。

          此時,如果官方提供的 ThymeleafViewResolver 的默認設 置無法滿足我們的需求,可以通過 兩 種 途 徑 進 行 自 定 義 設 置 : 通 過 application 配 置 文 件 配 置 和 自 行 創 建ThymeleafViewResolver 對象。

          通過 application 配置對應的屬性定義位于 ThymeleafProperties 類中,我們已經做過多次類似的配置,不再贅述。

          我們可以通過以下方式自行創建 ThymeleafViewResolver 對象。先定義一個配置類ViewResolverConfig,并在類內部通過@Bean 注解對實例化的 ThymeleafViewResolver對象進行注入容器的操作。

          @Configuration
          public class ViewResolverConfig {
          @Bean
          public ThymeleafViewResolver thymeleafViewResolver() {
          Thyme leafViewResolver resolver = new ThymeleafViewResolver();
          //設置 ViewResolver 對應的屬性 值
          resolver. setCharacterEncoding("UTF-8");
          resolver. setCache(false);
          return resolver;
          }
          }

          @Bean 默 認 會 將 方 法 thymeleafViewResolver 作 為 Bean 的 key, 將 返 回 的Thymeleaf-ViewResolver 對 象 作 為 Value 存 入 容 器 當 中 。 在 方 法 內 部 , 可 通 過ThymeleafViewResolver 對應的方法進行屬性的初始化設置。通過以上代碼我們便完成了自定義 Thymeleaf-ViewResolver 的注入。

          那么,原來默認的 ThymeleafViewResolver 會怎么處理呢? 我們知道幾乎所有的自動配置類都是通過注解設置初始化條件的,比如 ThymeleafViewResolver 默認實例化的條件是當容器中不存在名稱為 thymeleafViewResolver 時才會使用默認的初始化。當自定義的ThymeleafViewResolver 類完成初始化之后,默認配置的初始化條件便不再滿足了。

          上面針對 SpringMVC 中 Thymeleaf 的 ViewResolver 的自定義進行了講解。

          其實在 Spring Boot 中,大多數組件都可以采用同樣的方式對默認配置進行覆蓋。除了上述方法,在 Spring Boot 項目中還可以通過實現 WebMvcConfigurer 接口來進行更靈活地自定義配置。

          通過 WebMvcConfigurer 接口實現自定義配置是 Spring 內部的一-種配置方式,它替代了傳統的 XML 形式的配置。通過對該接口具體方法的實現,可以自定義一些 Handler、Interceptor 、ViewResolver 、MessageConverter 等參 數 。 以 上 面 配 置ThymeleafViewResolver 為例,我們也可以通過實現該接口的 configureViewResolvers 方法來進行配置,達到同樣的效果,具體示例代碼如下:

          @Configuration
          public class MyMvcConfig implements WebMvcConfigurer {
          @Override
          public void configureViewResolvers (ViewResolverRegistry registry) {
          Thyme leafViewResolver resolver = new ThymeleafViewResolver();
          //設置 ViewResolver 對應的屬 性值
          resolver. setCharacterEncoding("UTF-8");
          resolver . setCache(false);
          registry . viewResolver(resolver);
          }
          }

          使用 WebMvcConfigurer 接口時需注意 Spring Boot 版本,以上代碼是基于 Spring Boot 2.0以后的版本。WebMvcConfigurer 接口還提供 了其他關于擴展 SpringMVC 配置的接口,使用方法與上述示例基本一樣,大家可以查閱對應的代碼進一步了解, 這里就不再逐一舉例了。

          最后,關于 SpringMVC 自定義配置的最徹底操作就是完全接管 SpringBoot 關于 SpringMVC的默認配置,具體操作就是在 WebMvcConfigurer 的實現類上使用@EnableWebMvc 注解,示例如下。

          @EnableWebMvc

          @Configuration

          public class MyMvcConfig implements WebMvcConfigurer {

          使用該注解等于擴展了 WebMvcConfigurationSupport,但是沒有重寫任何方法,因此所需的功能都需要開發人員自行實現。-般情況下不推薦使用這種方式,該方式更適合基于 SpringBoot 提供的默認配置,針對特別需求進行有針對性拓展的場景。

          其實,本節內容的重點并不只是讓大家學會簡單的 Web 自定義配置,更深的用意是希望大家了解在 Spring Boot 默認自動配置的基礎上,我們可以通過什么方式以及如何進行自定義的拓展。本節中提到但未列出實例的內容,大家可以根據已經學習到的思路相應練習。

          小結

          本章重點針對 Spring Boot 中 Web 應用的自動配置和 Spring MVC 的自動配置展開,并以Spring MVC 中的一些典型配置為例進行了源碼講解。

          其 實 圍 繞 Web 應 用 還 有 一 系 列 的 自 動 配 置 比 如HttpEncodingAutoConfigurationMultipartAutoConfiguration和HttpMessageConvertersAutoConfiguration 等。我們只需領悟自動配置的精髓:這些相關配置只不過是將之前通過 xml 來配置 Bean,轉換成了基于類的形式來配置而已。讀者可按照以上方法對其他 Web 相關的配置項進行相應的閱讀和分析。

          本文給大家講解的內容是SpringBootWeb應用源碼解析:綜合實戰

          1. 下篇文章給大家講解的是SpringBoot內置Servlet容器源碼解析;
          2. 覺得文章不錯的朋友可以轉發此文關注小編;
          3. 感謝大家的支持!
          • 1. Thymeleaf 簡介
          • 2. 整合 Spring Boot2.1 基本用法2.2 手動渲染
          • 3. Thymeleaf 細節3.1 標準表達式語法3.2 設置屬性值3.3 遍歷3.4 分支語句3.5 本地變量3.6 內聯
          • 4. 小結

          雖然現在流行前后端分離,但是后端模版在一些關鍵地方還是非常有用的,例如郵件模版、代碼模版等。當然也不排除一些古老的項目后端依然使用動態模版。


          Thymeleaf 簡潔漂亮、容易理解,并且完美支持 HTML5,可以直接打開靜態頁面,同時不新增標簽,只需增強屬性,這樣也降低了學習成本。

          因此松哥今天花點時間和大家仔細分享一下 Thymeleaf。

          1. Thymeleaf 簡介

          Thymeleaf 是新一代 Java 模板引擎,它類似于 Velocity、FreeMarker 等傳統 Java 模板引擎,但是與傳統 Java 模板引擎不同的是,Thymeleaf 支持 HTML 原型。

          它既可以讓前端工程師在瀏覽器中直接打開查看樣式,也可以讓后端工程師結合真實數據查看顯示效果,同時,SpringBoot 提供了 Thymeleaf 自動化配置解決方案,因此在 SpringBoot 中使用 Thymeleaf 非常方便。

          事實上, Thymeleaf 除了展示基本的 HTML ,進行頁面渲染之外,也可以作為一個 HTML 片段進行渲染,例如我們在做郵件發送時,可以使用 Thymeleaf 作為郵件發送模板。

          另外,由于 Thymeleaf 模板后綴為 .html,可以直接被瀏覽器打開,因此,預覽時非常方便。

          2. 整合 Spring Boot

          2.1 基本用法

          Spring Boot 中整合 Thymeleaf 非常容易,只需要創建項目時添加 Thymeleaf 即可:

          創建完成后,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>
          

          當然,Thymeleaf 不僅僅能在 Spring Boot 中使用,也可以使用在其他地方,只不過 Spring Boot 針對 Thymeleaf 提供了一整套的自動化配置方案,這一套配置類的屬性在 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties 中,部分源碼如下:

          @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;
                  //...
          }
          
          1. 首先通過 @ConfigurationProperties 注解,將 application.properties 前綴為 spring.thymeleaf 的配置和這個類中的屬性綁定。
          2. 前三個 static 變量定義了默認的編碼格式、視圖解析器的前綴、后綴等。
          3. 從前三行配置中,可以看出來,Thymeleaf 模板的默認位置在 resources/templates 目錄下,默認的后綴是 html 。
          4. 這些配置,如果開發者不自己提供,則使用 默認的,如果自己提供,則在 application.properties 中以 spring.thymeleaf 開始相關的配置。

          而我們剛剛提到的,Spring Boot 為 Thymeleaf 提供的自動化配置類,則是 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration ,部分源碼如下:

          @Configuration
          @EnableConfigurationProperties(ThymeleafProperties.class)
          @ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
          @AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
          public class ThymeleafAutoConfiguration {
          }
          

          可以看到,在這個自動化配置類中,首先導入 ThymeleafProperties ,然后 @ConditionalOnClass 注解表示當當前系統中存在 TemplateModeSpringTemplateEngine 類時,當前的自動化配置類才會生效,即只要項目中引入了 Thymeleaf 相關的依賴,這個配置就會生效。

          這些默認的配置我們幾乎不需要做任何更改就可以直接使用了。如果開發者有特殊需求,則可以在 application.properties 中配置以 spring.thymeleaf 開頭的屬性即可。

          接下來我們就可以創建 Controller 了,實際上引入 Thymeleaf 依賴之后,我們可以不做任何配置。新建的 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("深圳:" + i);
                      users.add(u);
                  }
                  model.addAttribute("users", users);
                  return "index";
              }
          }
          public class User {
              private Long id;
              private String name;
              private String address;
              //省略 getter/setter
          }
          

          IndexController 中返回邏輯視圖名+數據,邏輯視圖名為 index ,意思我們需要在 resources/templates 目錄下提供一個名為 index.htmlThymeleaf 模板文件。

          • 創建 Thymeleaf
          <!DOCTYPE html>
          <html lang="en" xmlns:th="http://www.thymeleaf.org">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
          <table border="1">
              <tr>
                  <td>編號</td>
                  <td>用戶名</td>
                  <td>地址</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>
          

          Thymeleaf 中,通過 th:each 指令來遍歷一個集合,數據的展示通過 th:text 指令來實現,

          注意 index.html 最上面引入 thymeleaf 名稱空間(最新版并無強制要求)。

          配置完成后,就可以啟動項目了,訪問 /index 接口,就能看到集合中的數據了:

          2.2 手動渲染

          前面我們說的是返回一個 Thymeleaf 模板,我們也可以手動渲染 Thymeleaf 模板,這個一般在郵件發送時候有用,例如我在 resources/templates 目錄下新建一個郵件模板,如下:

          <!DOCTYPE html>
          <html lang="en" xmlns:th="http://www.thymeleaf.org">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
          <p>hello 歡迎 <span th:text="${username}"></span>加入 XXX 集團,您的入職信息如下:</p>
          <table border="1">
              <tr>
                  <td>職位</td>
                  <td th:text="${position}"></td>
              </tr>
              <tr>
                  <td>薪水</td>
                  <td th:text="${salary}"></td>
              </tr>
          </table>
          <img src="http://www.javaboy.org/images/sb/javaboy.jpg" alt="">
          </body>
          </html>
          

          這一個 HTML 模板中,有幾個變量,我們要將這個 HTML 模板渲染成一個 String 字符串,再把這個字符串通過郵件發送出去,那么如何手動渲染呢?

          @Autowired
          TemplateEngine templateEngine;
          @Test
          public void test1() throws MessagingException {
              Context context = new Context();
              context.setVariable("username", "javaboy");
              context.setVariable("position", "Java工程師");
              context.setVariable("salary", 99999);
              String mail = templateEngine.process("mail", context);
              //省略郵件發送
          }
          
          1. 渲染時,我們需要首先注入一個 TemplateEngine 對象,這個對象就是在 Thymeleaf 的自動化配置類中配置的(即當我們引入 Thymeleaf 的依賴之后,這個實例就有了)。
          2. 然后構造一個 Context 對象用來存放變量。
          3. 調用 process 方法進行渲染,該方法的返回值就是渲染后的 HTML 字符串,然后我們將這個字符串發送出去。

          3. Thymeleaf 細節

          前面兩個案例讓小伙伴們大致上理解了在 Spring Boot 中要如何使用 Thymeleaf,接下來,松哥將詳細介紹 Thymeleaf 本身的一些具體用法。

          3.1 標準表達式語法

          3.1.1 簡單表達式

          ${...}

          直接使用 th:xx = "${}" 獲取對象屬性。這個在前面的案例中已經演示過了,不再贅述。

          *{...}

          可以像 ${...} 一樣使用,也可以通過 th:object 獲取對象,然后使用 th:xx = "*{}" 獲取對象屬性,這種簡寫風格極為清爽,推薦大家在實際項目中使用。

          <table border="1" th:object="${user}">
          <tr>
              <td>用戶名</td>
              <td th:text="*{username}"></td>
          </tr>
          <tr>
              <td>地址</td>
              <td th:text="*{address}"></td>
          </tr>
          </table>
          

          #{...}

          通常的國際化屬性:#{...} 用于獲取國際化語言翻譯值。

          在 resources 目錄下新建兩個文件:messages.properties 和 messages_zh_CN.properties,內容如下:

          messages.properties:

          message = javaboy
          

          messages_zh_CN.properties:

          message = 江南一點雨
          

          然后在 thymeleaf 中引用 message,系統會根據瀏覽器的語言環境顯示不同的值:

          <div th:text="#{message}"></div>
          

          @{...}

          • 引用絕對 URL:
          <script type="text/javascript" th:src="@{http://localhost:8080/hello.js}"></script>
          

          等價于:

          <script type="text/javascript" src="http://localhost:8080/hello.js"></script>
          
          • 上下文相關的 URL:

          首先在 application.properties 中配置 Spring Boot 的上下文,以便于測試:

          server.servlet.context-path=/myapp
          

          引用路徑:

          <script type="text/javascript" th:src="@{/hello.js}"></script>
          

          等價于:

          <script type="text/javascript" src="/myapp/hello.js"></script>
          
          • 相對 URL:

          這個相對是指相對于服務器的 URL,例如如下引用:

          <script type="text/javascript" th:src="@{~/hello.js}"></script>
          

          等價于:

          <script type="text/javascript" src="/hello.js"></script>
          

          應用程序的上下文 /myapp 將被忽略。

          • 協議相對 URL:
          <script type="text/javascript" th:src="@{//localhost:8080/hello.js}"></script>
          

          等價于:

          <script type="text/javascript" src="//localhost:8080/hello.js"></script>
          
          • 帶參數的 URL:
          <script type="text/javascript" th:src="@{//localhost:8080/hello.js(name='javaboy',age=99)}"></script>
          

          等價于:

          <script type="text/javascript" th:src="//localhost:8080/hello.js?name=javaboy&age=99"></script>
          

          ~{...}

          片段表達式是 Thymeleaf 的特色之一,細粒度可以達到標簽級別,這是 JSP 無法做到的。片段表達式擁有三種語法:

          • ~{ viewName }:表示引入完整頁面
          • ~{ viewName ::selector}:表示在指定頁面尋找片段,其中 selector 可為片段名、jquery選擇器等
          • ~{ ::selector}: 表示在當前頁尋找

          舉個簡單例子。

          在 resources/templates 目錄下新建 my_fragment.html 文件,內容如下:

          <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>
          

          這里有兩個 div,通過 th:fragment 來定義片段,兩個 div 分別具有不同的名字。

          然后在另外一個頁面中引用該片段:

          <table border="1" th:object="${user}" th:fragment="aaa">
          <tr>
              <td>用戶名</td>
              <td th:text="*{username}"></td>
          </tr>
          <tr>
              <td>地址</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>
          

          通過 th:replace 來引用片段。第一個表示引用完整的 my_fragment.html 頁面;第二個表示引用 my_fragment.html 中的名為 javaboy_link 的片段;第三個表示引用當前頁面名為 aaa 的片段,也就是上面那個 table。

          3.1.2 字面量

          這些是一些可以直接寫在表達式中的字符,主要有如下幾種:

          • 文本字面量: 'one text', 'Another one!',…
          • 數字字面量: 0, 34, 3.0, 12.3,…
          • 布爾字面量: true, false
          • Null字面量: null
          • 字面量標記:one, sometext, main,…

          案例:

          <div th:text="'這是 文本字面量(有空格)'"></div>
          <div th:text="javaboy"></div>
          <div th:text="99"></div>
          <div th:text="true"></div>
          

          如果文本是英文,并且不包含空格、逗號等字符,可以不用加單引號。

          3.1.3 文本運算

          文本可以使用 + 進行拼接。

          <div th:text="'hello '+'javaboy'"></div>
          <div th:text="'hello '+${user.username}"></div>
          

          如果字符串中包含變量,也可以使用另一種簡單的方式,叫做字面量置換,用 | 代替 '...' + '...',如下:

          <div th:text="|hello ${user.username}|"></div>
          <div th:text="'hello '+${user.username}+' '+|Go ${user.address}|"></div>
          

          3.1.4 算術運算

          算術運算有:+, -, *, /%

          <div th:with="age=(99*99/99+99-1)">
              <div th:text="${age}"></div>
          </div>
          

          th:with 定義了一個局部變量 age,在其所在的 div 中可以使用該局部變量。

          3.1.5 布爾運算

          • 二元運算符:and, or
          • 布爾非(一元運算符):!, not

          案例:

          <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>
          

          3.1.6 比較和相等

          表達式里的值可以使用 >, <, >=<= 符號比較。==!= 運算符用于檢查相等(或者不相等)。注意 XML規定 <> 標簽不能用于屬性值,所以應當把它們轉義為 <>。

          如果不想轉義,也可以使用別名:gt (>);lt (<);ge (>=);le (<=);not (!)。還有 eq (==), neq/ne (!=)。

          舉例:

          <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>
          

          3.1.7 條件運算符

          類似于我們 Java 中的三目運算符。

          <div th:with="age=(99*99/99+99-1)">
              <div th:text="(${age} ne 197)?'yes':'no'"></div>
          </div>
          

          其中,: 后面的部分可以省略,如果省略了,又同時計算結果為 false 時,將返回 null。

          3.1.8 內置對象

          基本內置對象:

          • #ctx:上下文對象。
          • #vars: 上下文變量。
          • #locale:上下文區域設置。
          • #request:(僅在 Web 上下文中)HttpServletRequest 對象。
          • #response:(僅在 Web 上下文中)HttpServletResponse 對象。
          • #session:(僅在 Web 上下文中)HttpSession 對象。
          • #servletContext:(僅在 Web 上下文中)ServletContext 對象。

          在頁面可以訪問到上面這些內置對象,舉個簡單例子:

          <div th:text='${#session.getAttribute("name")}'></div>
          

          實用內置對象:

          • #execInfo:有關正在處理的模板的信息。
          • #messages:在變量表達式中獲取外部化消息的方法,與使用#{...}語法獲得的方式相同。
          • #uris:轉義URL / URI部分的方法
          • #conversions:執行配置的轉換服務(如果有)的方法。
          • #dates:java.util.Date對象的方法:格式化,組件提取等
          • #calendars:類似于#dates但是java.util.Calendar對象。
          • #numbers:用于格式化數字對象的方法。
          • #strings:String對象的方法:contains,startsWith,prepending / appending等
          • #objects:一般對象的方法。
          • #bools:布爾評估的方法。
          • #arrays:數組方法。
          • #lists:列表的方法。
          • #sets:集合的方法。
          • #maps:地圖方法。
          • #aggregates:在數組或集合上創建聚合的方法。
          • #ids:處理可能重復的id屬性的方法(例如,作為迭代的結果)。

          這是一些內置對象以及工具方法,使用方式也都比較容易,如果使用的是 IntelliJ IDEA,都會自動提示對象中的方法,很方便。

          舉例:

          <div th:text="${#execInfo.getProcessedTemplateName()}"></div>
          <div th:text="${#arrays.length(#request.getAttribute('names'))}"></div>
          

          3.2 設置屬性值

          這個是給 HTML 元素設置屬性值??梢砸淮卧O置多個,多個之間用 , 分隔開。

          例如:

          <img th:attr="src=@{/1.png},title=${user.username},alt=${user.username}">
          

          會被渲染成:

          <img src="/myapp/1.png" title="javaboy" alt="javaboy">
          

          當然這種設置方法不太美觀,可讀性也不好。Thymeleaf 還支持在每一個原生的 HTML 屬性前加上 th: 前綴的方式來使用動態值,像下面這樣:

          <img th:src="@{/1.png}" th:alt="${user.username}" th:title="${user.username}">
          

          這種寫法看起來更清晰一些,渲染效果和前面一致。

          上面案例中的 alt 和 title 則是兩個特殊的屬性,可以一次性設置,像下面這樣:

          <img th:src="@{/1.png}" th:alt-title="${user.username}">
          

          這個等價于前文的設置。

          3.3 遍歷

          數組/集合/Map/Enumeration/Iterator 等的遍歷也算是一個非常常見的需求,Thymeleaf 中通過 th:each 來實現遍歷,像下面這樣:

          <table border="1">
              <tr th:each="u : ${users}">
                  <td th:text="${u.username}"></td>
                  <td th:text="${u.address}"></td>
              </tr>
          </table>
          

          users 是要遍歷的集合/數組,u 則是集合中的單個元素。

          遍歷的時候,我們可能需要獲取遍歷的狀態,Thymeleaf 也對此提供了支持:

          • index:當前的遍歷索引,從0開始。
          • count:當前的遍歷索引,從1開始。
          • size:被遍歷變量里的元素數量。
          • current:每次遍歷的遍歷變量。
          • even/odd:當前的遍歷是偶數次還是奇數次。
          • first:當前是否為首次遍歷。
          • last:當前是否為最后一次遍歷。

          u 后面的 state 表示遍歷狀態,通過遍歷狀態可以引用上面的屬性。

          <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>
          

          3.4 分支語句

          只顯示奇數次的遍歷,可以使用 th:if,如下:

          <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>
          

          th:if 不僅僅只接受布爾值,也接受其他類型的值,例如如下值都會判定為 true:

          • 如果值是布爾值,并且為 true。
          • 如果值是數字,并且不為 0。
          • 如果值是字符,并且不為 0。
          • 如果值是字符串,并且不為 “false”, “off” 或者 “no”。
          • 如果值不是布爾值,數字,字符或者字符串。

          但是如果值為 null,th:if 會求值為 false。

          th:unless 的判定條件則與 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>
          

          這個顯示效果則與上面的完全相反。

          當可能性比較多的時候,也可以使用 switch:

          <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>
          

          th:case="*" 則表示默認選項。

          3.5 本地變量

          這個我們前面已經涉及到了,使用 th:with 可以定義一個本地變量。

          3.6 內聯

          我們可以使用屬性將數據放入頁面模版中,但是很多時候,內聯的方式看起來更加直觀一些,像下面這樣:

          <div>hello [[${user.username}]]</div>
          

          用內聯的方式去做拼接也顯得更加自然。

          [[...]] 對應于 th:text (結果會是轉義的 HTML),[(...)]對應于 th:utext,它不會執行任何的 HTML 轉義。

          像下面這樣:

          <div th:with="str='hello <strong>javaboy</strong>'">
              <div>[[${str}]]</div>
              <div>[(${str})]</div>
          </div>
          

          最終的顯示效果如下:

          不過內聯方式有一個問題。我們使用 Thymeleaf 的一大優勢在于不用動態渲染就可以直接在瀏覽器中看到顯示效果,當我們使用屬性配置的時候確實是這樣,但是如果我們使用內聯的方式,各種表達式就會直接展示在靜態網頁中。

          也可以在 js 或者 css 中使用內聯,以 js 為例,使用方式如下:

          <script th:inline="javascript">
              var username=[[${user.username}]]
              console.log(username)
          </script>
          

          js 中需要通過 th:inline="javascript" 開啟內聯。

          4. 小結

          好啦,Thymeleaf 跟大家也介紹的差不多了,應付日常的工作應該是可以了。對 Thymeleaf 感興趣的小伙伴,也可以看看它的官方文檔: https://www.thymeleaf.org。

          最后,松哥還搜集了 50+ 個項目需求文檔,想做個項目練練手的小伙伴不妨看看哦~

          需求文檔地址:https://gitee.com/lenve/javadoc


          主站蜘蛛池模板: 精品国产一区二区三区AV性色| 综合一区自拍亚洲综合图区| 日韩一区二区三区在线| 亚洲第一区香蕉_国产a| 亚洲乱码一区av春药高潮| 中文无码AV一区二区三区| 无码一区二区三区视频| 亲子乱AV视频一区二区| 亚洲一区电影在线观看| 无码精品人妻一区二区三区影院| 一区视频在线播放| 久久精品无码一区二区app| 一区二区三区四区视频| 日韩a无吗一区二区三区| 中文字幕在线观看一区二区| 国产福利精品一区二区| 精品国产一区二区三区久| 亚洲AV福利天堂一区二区三| 在线观看精品一区| 一区二区三区亚洲| 伊人色综合一区二区三区| 国产成人无码aa精品一区| 亚洲av无码一区二区三区观看| 精品久久久久一区二区三区| 国产欧美色一区二区三区| 久久99精品波多结衣一区| 国产在线精品一区二区在线观看| 国产人妖视频一区二区破除| 久久精品成人一区二区三区| 亚洲av鲁丝一区二区三区| 亚洲国产一区国产亚洲| 久久国产午夜精品一区二区三区 | 88国产精品视频一区二区三区| 一区二区三区高清视频在线观看| 成人一区二区三区视频在线观看| 精品少妇一区二区三区视频| 亚洲国产精品一区第二页 | 国产精品 视频一区 二区三区| 精品无码国产一区二区三区麻豆| 五十路熟女人妻一区二区| 精品国产日韩一区三区|