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>

參考資料