提及用Java語言來搭建Web項目,那麼最使人熟知,也應用最廣的框架就是Spring MVC了。不過,Spring MVC的Web項目搭建起來並非一件簡單的事,而若是你也像我這樣以前沒有接觸過Spring生態系統,那多半會感受到至關費勁。javascript
時代是變化的,如今咱們有了Spring Boot。css
Spring Boot是一個新的框架,但它並不生產新東西,而是做爲一個統籌者,整理好Spring生態系統的一系列庫,方便你快速搭建基於Spring的項目。html
相比傳統的Spring MVC,Spring Boot基本無需配置便可使用。這一點使得Spring Boot像許多腳本語言的簡潔框架(如PHP的Laravel,Node的Express)那樣親切友好。這就是現代Java 應用。前端
接下來,本文將講述用Spring Boot搭建一個簡單Web項目的流程。vue
在本文的時間點,Spring Boot的推薦版本是1.4.0。java
本文使用Java8(jdk1.8.0_60)。jquery
Spring Boot須要搭配Maven或Gradle任一構建工具使用。本文選擇Gradle,安裝版本爲2.8。git
Java項目須要搭配適當的IDE來開發,本文使用IntelliJ IDEA。github
到官方提供的Spring Initializer,生成符合本身須要的項目初始目錄,好比個人狀況:web
一方面選擇Gradle Project
,另外一方面在Dependencies
位置輸入並選擇所需的依賴模塊。這裏選擇Web
和Thymeleaf
就足夠搭建一個簡單的Web項目。其中,Thymeleaf是Spring Boot經常使用的模板引擎。附加的DevTools
如名所示,是Spring Boot的開發工具,它能夠提供自動刷新等有用功能。
事實上,Spring Boot的Thymeleaf
依賴包已經包含了Web
,所以準確地說,只用Thymeleaf
便可。
使用生成的初始目錄,就能夠建立好一個Spring Boot項目。在IntelliJ IDEA裏選擇File
→New
→Project from Existing Sources...
。
在打開的對話框裏繼續選擇Import project from external model (Gradle)
→Use default gradle wrapper (recommended)
。
點擊Finish
後,Gradle會當即運行,下載項目須要的依賴包。若是遇到錯誤,有多是網絡情況不佳,這時候能夠考慮到File
→Settings
裏找到HTTP Proxy
一欄設置適當的代理。
新建立的項目可能還須要到File
→Project Structure
裏設置正確的language level
:
如今能夠開始在項目裏寫東西了。參考官方的Code Structure建議,項目目錄能夠是這樣(由初始目錄演變獲得):
其中主應用類(這裏是SpringBootAcgtofeApplication.java
)建議放在圖示位置,以符合Spring Boot的默認結構要求,免除額外的配置須要。
建立一個簡單的視圖文件welcome.html
:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>spring boot for acgtofe</title> </head> <body> Welcome to acgtofe! </body> </html>
放置於templates/welcome
目錄下。
參照前文的目錄結構建立WelcomeController.java
,它的代碼也很簡單:
@Controller @RequestMapping("/welcome") public class WelcomeController { @RequestMapping("") String index(){ return "welcome/welcome"; } }
@Controller
標識這是一個controller類。@RequestMapping
用於指定訪問路徑,也就是路由。
index()
方法返回一個字符串welcome/welcome
,意思是返回路徑templates/welcome/welcome.html
的那個視圖。
不須要再作其餘任何配置,基於Spring Boot的簡單Web項目到此就能夠運行了。
在IntelliJ IDEA裏選擇Run
→Edit Configurations
。
在彈出的對話框裏點擊左上的+
選擇Spring Boot
。而後,在右邊的Main class
一欄點擊...
按鈕選擇主應用類:
點擊OK
保存運行配置,最後選擇Run
→Run
(或Debug
)運行應用。此時控制檯裏能夠看到Spring Boot的banner:
打開瀏覽器,訪問localhost:8080/welcome
,就能夠看到剛纔的視圖頁:
到此,一個簡單的Web項目就完成了。接下來,咱們看看如何讓這個Web項目更豐富,更符合實際項目的須要。
在前面的流程中,儘量使用了Spring Boot的默認配置,所以很是簡單。若是要改變Spring Boot項目的配置,就能夠修改初始提供的位於resources
下的application.properties
。
這個文件的內容初始是空的,表示所有使用Spring Boot的默認值。簡單按照.properties
的內容格式來添加內容就能夠了。下面是一些經常使用的例子。
這段代碼將更改服務器啓動的端口爲8001
(默認8080
):
server.port = 8001
你可能會發如今默認配置下,thymeleaf對.html
的內容要求很嚴格,好比<meta charset="UTF-8" />
,若是少最後的標籤封閉符號/
,就會報錯而轉到錯誤頁。也好比你在使用Vue.js這樣的庫,而後有<div v-cloak></div>
這樣的html代碼,也會被thymeleaf認爲不符合要求而拋出錯誤。
所以,建議增長下面這段:
spring.thymeleaf.mode = LEGACYHTML5
spring.thymeleaf.mode
的默認值是HTML5
,實際上是一個很嚴格的檢查,改成LEGACYHTML5
能夠獲得一個可能更友好親切的格式要求。
須要注意的是,LEGACYHTML5
須要搭配一個額外的庫NekoHTML纔可用。到項目根目錄的build.gradle
文件裏這樣添加它到dependencies
:
compile('net.sourceforge.nekohtml:nekohtml:1.9.22')
而後運行一次Gradle刷新(有任何Gradle改動,都應該這樣運行一次):
最後重啓項目就能夠感覺到不那麼嚴格的thymeleaf了。
相比.properties
格式,可能YAML格式看起來條理更清晰,也更有層次感。Spring Boot自己就支持YAML格式的應用配置文件,所以,你能夠建立文件application.yml
。
前面剛提到的兩項配置,寫成YAML是:
server: port: 8001 spring: thymeleaf: mode: LEGACYHTML5
應用配置文件application.[yml|properties]
除了初始位置,新建目錄resources/config
來放置也比較常見。
完整的配置參考請見官方的Common application properties。
css、js及圖片屬於靜態資源。在resources
目錄下的如下幾個位置的靜態資源文件,都將在啓動服務後能夠被直接訪問:
static
public
resources
META-INF/resources
如何把數據從controller傳遞到view呢?請看下面的例子。
model/Hoge.java
:
public class Hoge { public int id; public String value; }
controller/WelcomeController.java
:
@Controller @RequestMapping("/welcome") public class WelcomeController { @RequestMapping("") String index(Model model){ Hoge hoge = new Hoge(); hoge.id = 10; hoge.value = "hoge"; model.addAttribute("myData", hoge); return "welcome/welcome"; } }
templates/welcome/welcome.html
:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>spring boot for acgtofe</title> </head> <body> <p>id: <span th:text="${myData.id}">mock id</span></p> <p>value: <span th:text="${myData.value}">mock value</span></p> </body> </html>
這樣能夠獲得:
在視圖文件中使用thymeleaf,首先用xmlns:th
爲thymeleaf定義好名空間,而後以th:
名空間的自定屬性,來使用thymeleaf的功能。
在這個例子中,th:text
屬性表示標籤內部的文本,它會輸出指定的值,替換掉原來的靜態文本。而${...}
的表達式,能夠用於指定th:text
的值,以獲取controller傳遞過來的數據(經過model
)。
在前面的例子中,咱們好像爲了讓thymeleaf輸出數據,額外增長了<span>
標籤。這個標籤不是必須的,所以咱們可能不想要它。
thymeleaf有一個很是有用的屬性設置th:remove='tag'
。好比如今有一個數據變量name
的值是Rin
,那麼這段:
<p>Hello, <span th:remove="tag" th:text="${name}">Alice</span>!</p>
將輸出爲:
<p>Hello, Rin!</p>
是否是乾淨了許多?
詳細的thymeleaf模板引擎的用法,請參考Using Thymeleaf。
搭建一個Web站點常會面臨這樣一個問題:有不少不一樣的頁會有一些結構或內容是相同的,如何合理地管理它們以方便維護?
Thymeleaf Layout Dialect能夠幫助咱們應對這個問題。spring-boot-starter-thymeleaf
依賴包已經包含了它,能夠直接使用。
如今,咱們有一系列視圖,它們都有頁眉(header),頁腳(footer),及公共的css(common.css
)和js(common.js
),並且網頁標題有相同的後綴。那麼,能夠新建一個佈局視圖layout/default.html
:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <meta charset="UTF-8" /> <title layout:title-pattern="$CONTENT_TITLE - $DECORATOR_TITLE">acgtofe</title> <link rel="stylesheet" href="../../static/css/common/common.css" th:href="@{/css/common/common.css}" /> </head> <body> <header>public header</header> <section layout:fragment="content">page main content</section> <footer>public footer</footer> <script src="../../static/js/common/common.js" th:src="@{/js/common/common.js}"></script> </body> </html>
能夠看到,共用元素,包括<head>
內的<meta>
、<title>
等信息,都寫在了這個佈局視圖內。
而後修改以前的視圖welcome/welcome.html
以下:
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout/default"> <head> <title>welcome</title> <link rel="stylesheet" href="../../static/css/welcome/welcome.css" th:href="@{/css/welcome/welcome.css}" /> </head> <body> <section layout:fragment="content">Welcome to acgtofe!</section> </body> </html>
其中layout:decorator="layout/default"
是一個關鍵的屬性標記,它的意思是按照繼承的風格,取layout/default.html
視圖做爲佈局使用。
啓動應用並訪問,能夠看到結果是這樣:
thymeleaf-layout-dialect
默認會像這樣爲<head>
裏的內容進行合併,而<body>
裏的內容會按layout:fragment
分別進行覆蓋。
屬性layout:title-pattern
用於指定佈局視圖的標題如何與頁面視圖的標題拼合在一塊兒,這個例子也是用它實現了網頁標題的共同後綴。
你能夠查看thymeleaf-layout-dialect
的官方文檔瞭解更多的使用方法。
若是想要爲項目添加jQuery、Bootstrap這樣的前端庫,可使用WebJars。
例如,在build.gradle
裏添加這樣的依賴:
compile 'org.webjars:jquery:3.1.0' compile 'org.webjars:bootstrap:3.3.7'
運行Gradle刷新,而後就能夠這樣在視圖文件里加入它們:
<link rel="stylesheet" href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.7/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}" /> <script src="http://cdn.jsdelivr.net/webjars/jquery/3.1.0/jquery.min.js" th:src="@{/webjars/jquery/3.1.0/jquery.min.js}"></script> <script src="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.7/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script>
結合前面的佈局視圖,就可讓這些庫在任何地方均可用。
Spring Boot的Web用的就是Spring MVC,所以Spring MVC的知識點在Spring Boot項目裏是通用的。下面是一些經常使用功能。
@RestController @RequestMapping("/hello") public class HelloController { @RequestMapping(method=RequestMethod.GET) public String getMethod() { return "get"; } @RequestMapping(value="/hey", method=RequestMethod.POST) public String postMethod2() { return "hey post"; } }
除了返回視圖,某些controller多是用來返回通常數據(例如json格式數據),比較像API。@RestController
標記的類就是一個API風格的controller,其內部全部指定了訪問地址的方法,都將返回通常數據。通常來講,Ajax請求很適合和這樣的controller搭配。
若是在返回視圖的@Controller
標記的類裏也但願某單個方法返回通常數據,在這個方法前一行單獨添加註解@ResponseBody
便可。
@RequestMapping
的value
指定路徑,method
指定HTTP訪問方法。
@RequestMapping
能夠在路徑裏設置參數,而後在方法中被取到:
@RestController @RequestMapping("/hello") public class HelloController { @RequestMapping(value="/{id}/{name}", method=RequestMethod.GET) public void getMethod(@PathVariable int id, @PathVariable String name) { System.out.println("id=" + id + ", name=" + name); } }
這樣@PathVariable
搭配{...}
,就從路徑分別獲取了id
和name
兩個變量值。
此外, 一次請求的GET參數(位於URL的?
後的內容)或POST參數(做爲請求的Request Body),均可以用request.getParameter()
取到:
@RestController @RequestMapping("/hello") public class HelloController { @RequestMapping(method=RequestMethod.POST) public void getMethod(HttpServletRequest request) { System.out.println("userName=" + request.getParameter("userName")); } }
若是用Ajax向controller發送json字符串數據,controller這邊獲取起來要麻煩一些,大體像下面這樣。
例如,Ajax發送的內容是(注意須要指定內容格式爲json):
var person = { name: "Rin", age: 17 }, promise = $.ajax{ url: "/hello/submit", type: "POST", contentType: "application/json; charset=utf-8", data: JSON.stringify(person) };
而後接收的這邊須要先準備好一個一樣結構的類,如Person.java
:
public class Person { private String name; private int age; // getters & setters ... }
而後controller裏用帶@RequestBody
標記的參數就能夠獲取到:
@RestController @RequestMapping("/hello") public class HelloController { @RequestMapping(value="/submit", method=RequestMethod.POST) public void submit(@RequestBody Person person) { System.out.println("person.name=" + person.getName()); } }
若是json數據結構和數據類不能徹底匹配,controller將返回415錯誤(不支持的媒體類型)。
好久以前提到的依賴包DevTools
終於派上用場了。DevTools提供了自動刷新功能,可讓開發更快捷。下面是結合IntelliJ IDEA的使用流程:
在應用配置文件內設置spring.devtools.livereload.enabled
的值爲true
:
spring.devtools.livereload.enabled = true
接下來,爲瀏覽器安裝LiveReload插件,好比Chrome的狀況:
而後運行項目,並在瀏覽器中確認LiveReload插件爲運行狀態(單擊一下便可在運行狀態與中止狀態之間切換)。
修改任意文件後,按ctrl
+ F9
執行Make Project
,瀏覽器就會在編譯完成後自動刷新。
一路寫下來,發現篇幅意外地長,不過這也總算是有一點「手冊」的味道。若是你有考慮過Java語言來快速開發Web應用,相信本文和Spring Boot都會對你有所幫助。
(從新編輯自個人博客,原文地址:http://acgtofe.com/posts/2016...)