這一節咱們主要學習如何整合視圖層技術:html
在以前的案例中,咱們都是經過 @RestController
來處理請求,因此返回的內容爲json對象。那麼若是須要渲染html頁面的時候,要如何實現呢?java
Spring Boot推薦使用模板引擎web
模板引擎實現僞html 達到seo優化 使動態頁面靜態化spring
在動態html上實現Spring Boot依然能夠完美勝任,而且提供了多種模板引擎的默認配置支持,因此在推薦的模板引擎下,咱們能夠很快的上手開發動態網站。apache
Spring Boot提供了默認配置的模板引擎主要有如下幾種:json
Thymeleaf瀏覽器
FreeMarkertomcat
Velocityspringboot
Groovybash
Mustache
Spring Boot建議使用這些模板引擎,避免使用jsp。
建立 war 項目,編寫pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot</groupId> <artifactId>springboot-view</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>springboot-view Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <dependencies> <!-- Web 組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Boot不推薦使用 jsp,因此須要手動導入 jstl 和 jasper 依賴 --> <!-- jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- jasper --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> </dependencies> </project>
resources/application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp
User.java
package com.springboot.pojo; import java.io.Serializable; public class User implements Serializable { private Integer id; private String username; private Integer age; public User() { } public User(Integer id, String username, Integer age) { this.id = id; this.username = username; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", age=" + age + '}'; } }
UserController.java
package com.springboot.controller; import com.springboot.pojo.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.util.ArrayList; import java.util.List; @Controller public class UserController { @RequestMapping("/showUser") public String showUser(Model model) { List<User> list = new ArrayList<>(); list.add(new User(1, "張三", 18)); list.add(new User(2, "李四", 20)); list.add(new User(3, "王五", 22)); model.addAttribute("list", list); // 跳轉視圖 return "userList"; } }
userList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>用戶展現</title> </head> <body> <table border="1" cellspacing="0" align="center" width="50%"> <tr> <th>ID</th> <th>Name</th> <th>Age</th> </tr> <c:forEach items="${list}" var="user"> <tr> <td>${user.id}</td> <td>${user.username}</td> <td>${user.age}</td> </tr> </c:forEach> </table> </body> </html>
App.java
package com.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
結果
建立 war 項目,編寫pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot</groupId> <artifactId>springboot-view</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>springboot-view Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <dependencies> <!-- web 組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- freemarker 組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> </dependencies> </project>
該文件內容不必定非得須要,能夠不添加,不添加使用默認值。
resources/application.properties
# FREEMARKER (FreeMarkerAutoConfiguration) spring.freemarker.allow-request-override=false spring.freemarker.allow-session-override=false spring.freemarker.cache=true spring.freemarker.charset=UTF-8 spring.freemarker.check-template-location=true spring.freemarker.content-type=text/html spring.freemarker.enabled=true spring.freemarker.expose-request-attributes=false spring.freemarker.expose-session-attributes=false spring.freemarker.expose-spring-macro-helpers=true spring.freemarker.prefer-file-system-access=true spring.freemarker.suffix=.ftl spring.freemarker.template-loader-path=classpath:/templates/ spring.freemarker.settings.template_update_delay=0 spring.freemarker.settings.default_encoding=UTF-8 spring.freemarker.settings.classic_compatible=true spring.freemarker.order=1
User.java
package com.springboot.pojo; import java.io.Serializable; public class User implements Serializable { private Integer id; private String username; private Integer age; public User() { } public User(Integer id, String username, Integer age) { this.id = id; this.username = username; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", age=" + age + '}'; } }
UserController.java
package com.springboot.controller; import com.springboot.pojo.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.util.ArrayList; import java.util.List; @Controller public class UserController { @RequestMapping("/showUser") public String showUser(Model model) { List<User> list = new ArrayList<>(); list.add(new User(1, "張三", 18)); list.add(new User(2, "李四", 20)); list.add(new User(3, "王五", 22)); model.addAttribute("list", list); // 跳轉視圖 return "userList"; } }
Spring Boot要求模板形式的視圖層技術的文件必需要放到 src/main/resources 目錄下的 templates 目錄。
該目錄內的模板文件名稱必須是 ftl
的後綴結尾。
userList.ftl
<!DOCTYPE html> <html> <head> <title>用戶展現</title> <meta charset="UTF-8"></meta> </head> <body> <table border="1" cellspacing="0" align="center" width="50%"> <tr> <th>ID</th> <th>Name</th> <th>Age</th> </tr> <#list list as user > <tr> <td>${user.id}</td> <td>${user.username}</td> <td>${user.age}</td> </tr> </#list> </table> </body> </html>
App.java
package com.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
結果
建立 war 項目,編寫pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot</groupId> <artifactId>springboot-view</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>springboot-view Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <dependencies> <!-- web 組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- thymeleaf 組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> </project>
ThymeleafController.java
package com.springboot.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ThymeleafController { @RequestMapping("/show") public String showMsg(Model model) { model.addAttribute("msg", "Thymeleaf 入門案例"); return "msg"; } }
Spring Boot要求模板形式的視圖層技術的文件必需要放到 src/main/resources 目錄下的 templates 目錄。
msg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Thymeleaf</title> </head> <body> <span th:text="Thymeleaf"></span> <hr/> <span th:text="${msg}"></span> </body> </html>
App.java
package com.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
運行結果出現異常(若是是 Spring Boot 1.X.X 版本纔會出現此異常):
org.xml.sax.SAXParseException: 元素類型 "meta" 必須由匹配的結束標記 "</meta>" 終止。
若是是 Spring Boot 1.X.X 版本須要如下操做,本案例是 Spring Boot 2.1.6 版本,因此不須要更改。
<meta charset="UTF-8"/>
thymeleaf.jar:更新爲 3.0 以上的版本
<properties> <thymeleaf.version>3.0.11.RELEASE</thymeleaf.version> </properties>
Thymeleaf 內置對象語法:
#
s
結尾 strings
、numbers
、dates
User.java
package com.springboot.pojo; import java.io.Serializable; public class User implements Serializable { private Integer id; private String username; private Integer age; public User() { } public User(Integer id, String username, Integer age) { this.id = id; this.username = username; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", age=" + age + '}'; } }
ThymeleafController.java
package com.springboot.controller; import com.springboot.pojo.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; @Controller public class ThymeleafController { @RequestMapping("/show") public String showMsg(Model model, HttpServletRequest request, HttpServletResponse response) { // 字符串 model.addAttribute("msg", "Thymeleaf 入門案例"); // 日期時間 model.addAttribute("myDate", new Date()); // 條件判斷if model.addAttribute("sex", 1); // 條件判斷switch model.addAttribute("id", 1); // 對象 model.addAttribute("user", new User(1, "張三", 20)); // 迭代遍歷list List<User> userList = new ArrayList<>(); userList.add(new User(1, "張三", 20)); userList.add(new User(2, "李四", 22)); userList.add(new User(3, "王五", 24)); model.addAttribute("userList", userList); // 迭代遍歷map Map<String, User> userMap = new HashMap<>(); userMap.put("u1", new User(1, "張三", 20)); userMap.put("u2", new User(2, "李四", 22)); userMap.put("u3", new User(3, "王五", 24)); model.addAttribute("userMap", userMap); // 域對象操做 request.setAttribute("req", "HttpServletRequest"); request.getSession().setAttribute("sess", "HttpSession"); request.getSession().getServletContext().setAttribute("app", "Application"); return "msg"; } /** * URL表達式-相對路徑 * @return */ @RequestMapping("/index") public String index() { return "index"; } /** * URL表達式-普通傳參 * @param id * @param username * @return */ @RequestMapping("/user") public String user(Integer id, String username) { System.out.println("id:" + id + " username:" + username); return "user"; } /** * URL表達式-restful傳參 * @param id * @param username * @return */ @RequestMapping("/person/{id}/{username}") public String person(@PathVariable Integer id, @PathVariable String username) { System.out.println("id:" + id + " username:" + username); return "person"; } }
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Thymeleaf</title> </head> <body> index </body> </html>
user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Thymeleaf</title> </head> <body> user </body> </html>
person.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Thymeleaf</title> </head> <body> person </body> </html>
th:text
:在頁面中輸入值
<span th:text="Thymeleaf"></span>
th:value
:能夠將一個值設置至input標籤的value中
<input type="text" th:value="${msg}" />
${#strings.isEmpty(key)}
:判斷字符串是否爲空
<span th:text="${#strings.isEmpty(msg)}"></span>
${#strings.contains(msg, 'T')}
:判斷字符串是否包含子串
<span th:text="${#strings.contains(msg, 'T')}"></span>
${#strings.startsWith(msg, 'T')}
:判斷字符串是否以子串開頭
<span th:text="${#strings.startsWith(msg, 'T')}"></span>
${#strings.endsWith(msg, 'T')}
:判斷字符串是否以子串結尾
<span th:text="${#strings.endsWith(msg, 'T')}"></span>
${#strings.length(msg)}
:返回字符串的長度
<span th:text="${#strings.length(msg)}"></span>
${#strings.indexOf(msg, 'T')}
:查找子串的位置,並返回該子串的下標,若是沒找到則返回-1
<span th:text="${#strings.indexOf(msg, 'T')}"></span>
${#strings.substring(msg, 5)}
:截取子串,從指定下標開始截止到末尾結束
${#strings.substring(msg, 5, 12)}
:截取子串,從指定下標開始截止到指定下標結束
<span th:text="${#strings.substring(msg, 5)}"></span> <span th:text="${#strings.substring(msg, 5, 12)}"></span>
${#strings.toUpperCase(msg)}
:將字符串轉大寫
<span th:text="${#strings.toUpperCase(msg)}"></span>
${#strings.toLowerCase(msg)}
:將字符串轉小寫
<span th:text="${#strings.toLowerCase(msg)}"></span>
${#dates.format(key)}
:格式化日期,以瀏覽器默認語言爲格式化標準
<span th:text="${#dates.format(myDate)}"></span>
${#dates.format(key,'yyy/MM/dd')}
:自定義格式日期轉換
<span th:text="${#dates.format(myDate, 'yyyy年MM月dd日 HH:mm:ss')}"></span>
${#dates.year(myDate)}
:獲取年份,還能夠獲取月份、日、時、分、秒
<span th:text="${#dates.year(myDate)}"></span>年 <span th:text="${#dates.month(myDate)}"></span>月 <span th:text="${#dates.day(myDate)}"></span>日 <span th:text="${#dates.hour(myDate)}"></span>時 <span th:text="${#dates.minute(myDate)}"></span>分 <span th:text="${#dates.second(myDate)}"></span>秒
th:if
:單選擇
性別:<span th:if="${sex} == 1">男</span> <span th:if="${sex} == 2">女</span>
th:switch
:多選擇(若是要實現 if else if else 判斷表達式,在 Thymeleaf 要使用 th:switch 代替)
編號:<span th:switch="${id}"> <span th:case="1">1 張三</span> <span th:case="2">2 李四</span> <span th:case="3">3 王五</span> </span>
<input th:value="${user.username}"/> <span th:text="${user.age}"></span>
th:each
:迭代遍歷
<table border="1" cellspacing="0"> <tr> <th>ID</th> <th>NAME</th> <th>AGE</th> </tr> <tr th:each="user : ${userList}"> <td th:text="${user.id}"></td> <td th:text="${user.username}"></td> <td th:text="${user.age}"></td> </tr> </table>
th:each
:狀態變量屬性
<table border="1" cellspacing="0"> <tr> <th>Id</th> <th>Name</th> <th>Age</th> <th>Index</th> <th>Count</th> <th>Size</th> <th>Even</th> <th>Odd</th> <th>First</th> <th>Last</th> </tr> <tr th:each="user, state : ${userList}"> <td th:text="${user.id}"></td> <td th:text="${user.username}"></td> <td th:text="${user.age}"></td> <td th:text="${state.index}"></td> <td th:text="${state.count}"></td> <td th:text="${state.size}"></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:each
:迭代 Map
<table border="1" cellspacing="0"> <tr> <th>Id</th> <th>Name</th> <th>Age</th> </tr> <tr th:each="user : ${userMap}"> <td th:text="${user}"></td> </tr> </table> <table border="1" cellspacing="0"> <tr> <th>Id</th> <th>Name</th> <th>Age</th> </tr> <tr th:each="user : ${userMap}"> <td th:each="entry : ${user}" th:text="${entry.value.id}" ></td> <td th:each="entry : ${user}" th:text="${entry.value.username}"></td> <td th:each="entry : ${user}" th:text="${entry.value.age}"></td> </tr> </table>
${#httpServletRequest.getAttribute(key)}
:HttpServletRequest
Request:<span th:text="${#httpServletRequest.getAttribute('req')}"></span>
${session.key}
:HttpSession
Session:<span th:text="${session.sess}"></span>
${application.key}
:ServletContext
Application:<span th:text="${application.app}"></span>
URL表達式的基本語法:@{}
th:href
:絕對路徑
<a th:href="@{http://www.baidu.com}">絕對路徑</a>
th:href
:相對路徑,相對於當前項目的根路徑
<a th:href="@{/index}">相對於當前項目的根路徑</a>
th:href
:相對路徑, 相對於服務器的根路徑
<a th:href="@{~/project/resourcename}">相對於服務器的根路徑</a>
<a th:href="@{/user(id=1, username=zhagnsan)}">相對路徑-普通傳參</a> <a th:href="@{/person/1/zhangsan}">相對路徑-restful傳參</a> <a th:href="@{/person/{id}/{name}(id=2, name=lisi)}">相對路徑-restful傳參</a>
✍️本章節到這裏就結束了,喜歡的話就點贊🤗加轉發💞吧,咱們下章節再見👋。