2017/4/23
Spring Framework中使用者會啟動Controller,Controller透過View與使用者互動,View可以接受從Controller傳來的資料,也可以利用Form (或其他方式)傳送資料給Controller。
Spring Framework可以利用JSP或其他的View Engine來呈現View,在Spring Boot 1.5.1的參考手冊裡,建議不使用JSP為view engine,而是使用FreeMarker、Groovy、Thymeleaf、Mustache等view engine。如果要使用JSP,packaging的方式只能採用WAR而不是JAR。
要使用Thymeleaf,請在pom.xml中的<dependencies></dependencies>中加入以下的設定,加完之後,就可以了。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>Thymeleaf需要web,所以也需要
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>不過,要注意版本的相容性,目前最新版本是1.5.3,例如,如果Spring Boot的版本是1.5.2,因為,thymeleaf似乎只能使用1.5.1,所以,要把版本升級到1.5.3。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>或降回1.5.1。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>以Thymeleaf的話(副檔名為html,如:hello.html),寫法就有些不同,以Thymeleaf的觀點,當View設計時,可能還沒有連上Controller,所以,通常會給一個預設值,以下面的例子就是夾在span中間的「Wu」,當Controller沒有回傳值時,還能有預設值。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Hello!</title></head><body><h2>Hello! <span th:text="${name}">Wu</span></h2> </body></html>如果是以JSP或FreeMarker為例,${name}會顯示來自Controller,變數名稱為「name」的內容,以Spring Controller在傳參數給View的範例而言,以下的程式會顯示「Hello! ben」(JSP的副檔名為.jsp,FreeMarker的副檔名為.ftl):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <title>Hello!</title></head><body><h2>Hello! ${name}</h2> </body></html>接下來我們都會以Thymeleaf為例,想使用其他view engine的同學,請自行參考相關文件。
上面的例子都是接受單一變數,如果多變數的話,也可以透過物件的方式來傳送,以下面的例子而言,可以將姓名、住址、體重包在customer物件中傳送到view (傳遞部份的細節請參考Spring Controller)。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body>name: <span th:text="${customer.name}">Wu</span>address: <span th:text="${customer.address}">Fu Jen</span>weight: <span th:text="${customer.weight}">56</span></body></html>當View傳送資料給 Controller時,可以利用HTTP GET,也可以利用HTTP GET + Form,或HTTP POST+ Form。
以HTTP GET而言,我們可以直接以URL呼叫一個Controller (如"/HelloWithId"),並以Query的方式傳送一個參數(請參考:URI),如:
http://localhost:8080/helloWithId?id=Mary以利用HTTP POST + Form,而言,可以用以下的HTML(hi.html)呼叫同一個Controller,當使用以下的form,並按下Submit時,也會產生類似上述的URI (id的內容是使用者在id的文框中輸入的內容),並呼叫Controller:
<!DOCTYPE html><html><body><form action="helloWithId" method ="get"> id:<input type="text" name ="id"/><br> <input type="submit" value="Submit"/></form></body></html>傳送的資料可能不只一個變數,如:
<!DOCTYPE html><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body><form action="customerCreate" method ="post"> name:<input type="text" name="name"/><br/> address:<input type="text" name = "address"/><br/> weight:<input type="text" name ="weight"/><br/> <input type="submit" value="Submit"/></form></body></html>一般而言,當需要更新資料時,會顯示原資料,下面的範例會接受一個customer的物件,將對應的name, address, weight及id放到對應的欄位。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Update Customer</title></head><body><form action="customerUpdate" method ="post"> name:<input type="text" name="name" th:field="${customer.name}"/><br/> address:<input type="text" name = "address" th:field="${customer.address}"/><br/> weight:<input type="text" name ="weight" th:field="${customer.weight}"/><br/> <input type="hidden" name ="id" th:field="${customer.id}"/> <input type="submit" value="Submit"/></form></body></html>可以利用「object="${customer}」來簡化,就可以利用「*{name}」來取代「${customer.name}」。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Update Customer</title></head><body><form action="customerUpdate" th:object="${customer}" method ="post"> name:<input type="text" name="name" th:field="*{name}"/><br/> address:<input type="text" name = "address" th:field="*{address}"/><br/> weight:<input type="text" name ="weight" th:field="*{weight}"/><br/> <input type="hidden" name ="id" th:field="*{id}"/> <input type="submit" value="Submit"/></form></body></html>在Thymeleaf中,可以使用「if=」來設定條件,如: 「if="${#fields.hasErrors('name')}"」,下面的範例就是當有錯誤時,顯示後面對應變數的錯誤訊息 (完整範例請參考 Spring Validation)。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body><form action="customerCreate" th:object="${customer}" method ="post"> name:<input type="text" name="name" th:field="*{name}"/><br/> <div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div> address:<input type="text" name = "address" th:field="*{address}"/><br/> <div th:if="${#fields.hasErrors('address')}" th:errors="*{address}"></div> weight:<input type="text" name ="weight" th:field="*{weight}"/><br/> <div th:if="${#fields.hasErrors('weight')}" th:errors="*{weight}"></div> <input type="submit" value="Submit"/></form></body></html>在Thymeleaf中,可以使用「each=」來設定迴圈,如: each="customer : ${customers} ",表示將customers裡的每一個物件當做customer,並重複到每個物件都顯示出來。另外,還可以使用「href=」來設定URL,並利用「(id=${customer.id})」設定id的內容為「${customer.id}」(完整範例請參考 Spring JPA)。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body><a href="customerCreate">新增顧客</a><table> <tr> <th>編號</th> <th>姓名</th> <th>地址</th> <th>重量</th> <th></th> </tr> <tr th:each="customer : ${customers} "> <td th:text="${customer.id}">1</td> <td th:text="${customer.name}">Ben</td> <td th:text="${customer.address}">Fu Jen</td> <td th:text="${customer.weight}">56</td> <td><a th:href="@{customerUpdate(id=${customer.id})}">修改</a> <a th:href="@{customerDelete(id=${customer.id})}">刪除</a></td> </tr></table></body></html>可利用object簡化,如下例。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body><a href="customerCreate">新增顧客</a><table> <tr> <th>編號</th> <th>姓名</th> <th>地址</th> <th>重量</th> <th></th> </tr> <tr th:each="customer : ${customers} " th:object="${customer}"> <td th:text="*{id}">1</td> <td th:text="*{name}">Ben</td> <td th:text="*{address}">Fu Jen</td> <td th:text="*{weight}">56</td> <td><a th:href="@{customerUpdate(id=*{id})}">修改</a> <a th:href="@{customerDelete(id=*{id})}">刪除</a></td> </tr></table></body></html>