Spring View
Spring View
2017/4/23
基本概念
Spring Framework中使用者會啟動Controller,Controller透過View與使用者互動,View可以接受從Controller傳來的資料,也可以利用Form (或其他方式)傳送資料給Controller。
View Engine
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>
以Form傳送資料
當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>
參考資料
- http://freemarker.org/
- http://www.thymeleaf.org/
- http://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html
- https://www.mkyong.com/spring-boot/spring-boot-hello-world-example-jsp/
- https://hellokoding.com/spring-boot-hello-world-example-with-jsp/
- https://hellokoding.com/spring-boot-hello-world-example-with-freemarker/
- https://hellokoding.com/spring-boot-hello-world-example-with-thymeleaf/