SpringBoot 後臺傳值給頁面展示Thymeleaf

開發傳統Java WEB工程時,我們可以使用JSP頁面模板語言,但是在SpringBoot中已經不推薦使用了。SpringBoot支持如下頁面模板語言

  • Thymeleaf
  • FreeMarker
  • Velocity
  • Groovy
  • JSP

上面並沒有列舉所有SpringBoot支持的頁面模板技術。其中Thymeleaf是SpringBoot官方所推薦使用的,下面來談談Thymeleaf一些常用的語法規則。

添加Thymeleaf依賴

要想使用Thhymeleaf,首先要在pom.xml文件中單獨添加Thymeleaf依賴。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Spring Boot默認存放模板頁面的路徑在src/main/resources/templates或者src/main/view/templates,這個無論是使用什麼模板語言都一樣,當然默認路徑是可以自定義的,不過一般不推薦這樣做。另外Thymeleaf默認的頁面文件後綴是.html

數據顯示

在MVC的開發過程中,我們經常需要通過Controller將數據傳遞到頁面中,讓頁面進行動態展示。

顯示普通文本

創建一個Controller對象,在其中進行參數的傳遞

@Controller
public class ThymeleafController {

    @RequestMapping(value = "show", method = RequestMethod.GET)
    public String show(Model model){
        model.addAttribute("uid","123456789");
        model.addAttribute("name","Jerry");
        return "show";
    }
}

在SpringBoot默認的頁面路徑下創建show.html文件,內容如下

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>SpringBoot模版渲染</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
    <p th:text="'用戶ID:' + ${uid}"/>
    <p th:text="'用戶名稱:' + ${name}"/>
</body>
</html>

可以看到在p標籤中有th:text屬性,這個就是thymeleaf的語法,它表示顯示一個普通的文本信息。

如果我們要顯示的信息是存在資源文件中的,同樣可以在頁面中顯示,例如資源文件中定義了內容welcome.msg=歡迎{0}光臨!。可以在頁面中將其顯示

<h2 th:text="#{welcome.msg('admin')}"/>

另外,在th:utext中還能做一些基礎的數學運算

<p th:text="'數學計算:1+2=' + (1 + 2)"/>

顯示帶有樣式的普通文本

如果我們想要傳遞到的頁面的信息,它本身是帶有CSS樣式的,這個時候如何在頁面中將攜帶的樣式信息也顯示出來?此時我們的控制器方法這樣寫。

@RequestMapping(value = "showStyle", method = RequestMethod.GET)
public String showStyle(Model model){
    model.addAttribute("uid","123456789");
    model.addAttribute("name","<span style='color:red'>Jerry</span>");
    return "show_style";
}

此時頁面中需要藉助th:utext屬性進行顯示

<p th:utext="'用戶名稱:' + ${name}"/>

通過瀏覽器查看頁面源碼可以看出th:utextth:text的區別是:th:text會對<>進行轉義,而th:utext不會轉義。

顯示對象

我們常常需要將一個bean信息展示在前端頁面當中。

  1. 用於前端展示的VO類
public class User implements Serializable {
    private Long uid ;
    private String name ;
    private Integer age ;
    private Date birthday ;
    private Double salary ;
    //省略get/set方法
}
  1. 控制器方法
@RequestMapping(value = "/message/member_show", method = RequestMethod.GET)
public String memberShow(Model model) {
    User vo = new User();
    vo.setUid(12345678L);
    vo.setName("尼古拉丁.趙四");
    vo.setAge(59);
    vo.setSalary(1000.00);
    vo.setBirthday(new Date());
    model.addAttribute("member", vo);
    return "message/member_show";
}
  1. 頁面展示
<div>
    <p th:text="'用戶編號:' + ${member.uid}"/>
    <p th:text="'用戶姓名:' + ${member.name}"/>
    <p th:text="'用戶年齡:' + ${member.age}"/>
    <p th:text="'用戶工資:' + ${member.salary}"/>
    <p th:text="'出生日期:' + ${member.birthday}"/>
    <p th:text="'出生日期:' + ${#dates.format(member.birthday,'yyyy-MM-dd')}"/>
</div>

<hr/>
<div th:object="${member}">
    <p th:text="'用戶編號:' + *{uid}"/>
    <p th:text="'用戶姓名:' + *{name}"/>
    <p th:text="'用戶年齡:' + *{age}"/>
    <p th:text="'用戶工資:' + *{salary}"/>
    <p th:text="'出生日期:' + *{birthday}"/>
    <p th:text="'出生日期:' + *{#dates.format(birthday,'yyyy-MM-dd')}"/>
</div>

上面給出了兩種展現方式,一種是通過${屬性},另外一種是通過{屬性}。
關於“${屬性}”和“{屬性}”的區別?
$訪問完整信息,而
訪問指定對象中的屬性內容, 如果訪問的只是普通的內容兩者沒有區別;

數據處理

在 thymeleaf 之中提供有相應的集合的處理方法,例如:在使用 List 集合的時候可以考慮採用 get()方法獲取指定索引的數據,那麼在使用 Set 集合的時候會考慮使用 contains()來判斷某個數據是否存在,使用 Map 集合的時候也希望可以使用 containsKey()判斷某個 key 是否存在,以及使用get()根據 key 獲取對應的 value,而這些功能在之前並不具備,下面來觀察如何在頁面中使用此類操作

  1. 控制器方法向頁面傳遞一些數據,以供操作
@RequestMapping(value = "/user/set", method = RequestMethod.GET)
public String set(Model model) {
    Set<String> allNames = new HashSet<String>() ;
    List<Integer> allIds = new ArrayList<Integer>() ;
    for (int x = 0 ; x < 5 ; x ++) {
        allNames.add("boot-" + x) ;
        allIds.add(x) ;
    }
    model.addAttribute("names", allNames) ;
    model.addAttribute("ids", allIds) ;
    model.addAttribute("mydate", new java.util.Date()) ;
    return "user_set" ;
}
  1. 數據處理
<body>
    <p th:text="${#dates.format(mydate,'yyyy-MM-dd')}"/>
    <p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss.SSS')}"/>
    <hr/>
    <p th:text="${#strings.replace('www.baidu.cn','.','$')}"/>
    <p th:text="${#strings.toUpperCase('www.baidu.cn')}"/>
    <p th:text="${#strings.trim('www.baidu.cn')}"/>
    <hr/>
    <p th:text="${#sets.contains(names,'boot-0')}"/>
    <p th:text="${#sets.contains(names,'boot-9')}"/>
    <p th:text="${#sets.size(names)}"/>
    <hr/>
    <p th:text="${#sets.contains(ids,0)}"/>
    <p th:text="${ids[1]}"/>
    <p th:text="${names[1]}"/>
</body>

路徑處理

在傳統WEB工程開發時,路徑的處理操作是有點麻煩的。SpringBoot中爲我們簡化了路徑的處理。

  1. 在"src/main/view/static/js"中創建一個js文件

     

    js文件路徑

  2. 然後在頁面中可以通過“@{路徑}”來引用。
<script type="text/javascript" th:src="@{/js/main.js}"></script> 

頁面之間的跳轉也能通過@{}來實現

<a th:href="@{/show}">訪問controller方法</a>
<a th:href="@{/static_index.html}">訪問靜態頁面</a>

操作內置對象

雖然在這種模版開發框架裏面是不提倡使用內置對象的,但是很多情況下依然需要使用內置對象進行處理,所以下面來看下如何在頁面中使用JSP內置對象。

  1. 在控制器裏面增加一個方法,這個方法將採用內置對象的形式傳遞屬性。
@RequestMapping(value = "/inner", method = RequestMethod.GET)
public String inner(HttpServletRequest request, Model model) {
    request.setAttribute("requestMessage", "springboot-request");
    request.getSession().setAttribute("sessionMessage", "springboot-session");
    request.getServletContext().setAttribute("applicationMessage",
            "springboot-application");
    model.addAttribute("url", "www.baidu.cn");
    request.setAttribute("url2",
            "<span style='color:red'>www.baidu.cn</span>");
    return "show_inner";
}
  1. 在頁面之中如果要想訪問不同屬性範圍中的內容,則可以採用如下的做法完成:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>SpringBoot模版渲染</title>
    <script type="text/javascript" th:src="@{/js/main.js}"></script> 
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
    <p th:text="${#httpServletRequest.getRemoteAddr()}"/>
    <p th:text="${#httpServletRequest.getAttribute('requestMessage')}"/>
    <p th:text="${#httpSession.getId()}"/>
    <p th:text="${#httpServletRequest.getServletContext().getRealPath('/')}"/>
    <hr/>
    <p th:text="'requestMessage = ' + ${requestMessage}"/>
    <p th:text="'sessionMessage = ' + ${session.sessionMessage}"/>
    <p th:text="'applicationMessage = ' + ${application.applicationMessage}"/>
</body>
</html>

thymeleaf 考慮到了實際的開發情況,因爲 request 傳遞屬性是最爲常用的,但是 session 也有可能使用,例如:用戶登錄之後需要顯示用戶 id,那麼就一定要使用到 session,所以現在必須增加屬性範圍的形式後才能夠正常使用。在 thymeleaf 裏面也支持有 JSP 內置對象的獲取操作,不過一般很少這樣使用。

邏輯處理

所有的頁面模版都存在各種基礎邏輯處理,例如:判斷、循環處理操作。在 Thymeleaf 之中對於邏輯可以使用如下的一些運算符來完成,例如:and、or、關係比較(>、<、>=、<=、==、!=、lt、gt、le、ge、eq、ne)。

通過控制器傳遞一些屬性內容到頁面之中:

<span th:if="${member.age lt 18}">
未成年人!
</span>
<span th:if="${member.name eq '啊三'}">
歡迎小三來訪問!
</span>

不滿足條件的判斷

<span th:unless="${member.age gt 18}">
你還不滿18歲,不能夠看電影!
</span>

通過swith進行分支判斷

<span th:switch="${member.uid}">
<p th:case="100">uid爲101的員工來了</p>
<p th:case="99">uid爲102的員工來了</p>
<p th:case="*">沒有匹配成功的數據!</p>
</span>

數據遍歷

在實際開發過程中常常需要對數據進行遍歷展示,一般會將數據封裝成list或map傳遞到頁面進行遍歷操作。

  1. 定義控制器類,向頁面傳遞List數據和Map數據
@Controller
public class UserController {
    @RequestMapping(value = "/user/map", method = RequestMethod.GET)
    public String map(Model model) {
        Map<String,User> allMembers = new HashMap<String,User>();
        for (int x = 0; x < 10; x++) {
            User vo = new User();
            vo.setUid(101L + x);
            vo.setName("趙四 - " + x);
            vo.setAge(9);
            vo.setSalary(99999.99);
            vo.setBirthday(new Date());
            allMembers.put("mldn-" + x, vo);
        }
        model.addAttribute("allUsers", allMembers);
        return "user_map";
    }

    @RequestMapping(value = "/user/list", method = RequestMethod.GET)
    public String list(Model model) {
        List<User> allMembers = new ArrayList<User>();
        for (int x = 0; x < 10; x++) {
            User vo = new User();
            vo.setUid(101L + x);
            vo.setName("趙四 - " + x);
            vo.setAge(9);
            vo.setSalary(99999.99);
            vo.setBirthday(new Date());
            allMembers.add(vo) ;
        }
        model.addAttribute("allUsers", allMembers);
        return "user_list";
    }
}
  1. list類型數據遍歷
<body>
    <table>
        <tr><td>No.</td><td>UID</td><td>姓名</td><td>年齡</td><td>偶數</td><td>奇數</td></tr>
        <tr th:each="user,memberStat:${allUsers}">
            <td th:text="${memberStat.index + 1}"/>
            <td th:text="${user.uid}"/>
            <td th:text="${user.name}"/>
            <td th:text="${user.age}"/>
            <td th:text="${memberStat.even}"/>
            <td th:text="${memberStat.odd}"/>
        </tr>
    </table>
</body>
  1. map類型數據遍歷
<body>
    <table>
        <tr><td>No.</td><td>KEY</td><td>UID</td><td>姓名</td><td>年齡</td><td>偶數</td><td>奇數</td></tr>
        <tr th:each="memberEntry,memberStat:${allUsers}">
            <td th:text="${memberStat.index + 1}"/>
            <td th:text="${memberEntry.key}"/>
            <td th:text="${memberEntry.value.uid}"/>
            <td th:text="${memberEntry.value.name}"/>
            <td th:text="${memberEntry.value.age}"/>
            <td th:text="${memberStat.even}"/>
            <td th:text="${memberStat.odd}"/>
        </tr>
    </table>
</body>

頁面引入

我們常常需要在一個頁面當中引入另一個頁面,例如,公用的導航欄以及頁腳頁面。thymeleaf中提供了兩種方式進行頁面引入。

  • th:replace
  • th:include
  1. 新建需要被引入的頁面文件,路徑爲"src/main/view/templates/commons/footer.html"
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<footer th:fragment="companyInfo">
    <p>設爲首頁 ©2018 SpringBoot 使用<span th:text="${projectName}"/>前必讀
        意見反饋 京ICP證030173號 </p>
</footer>

可以看到頁面當中還存在一個變量projectName,這個變量的值可以在引入頁面中通過th:with="projectName=百度"傳過來。

  1. 引入頁面中只需要添加如下代碼即可
<div th:include="@{/commons/footer} :: companyInfo" th:with="projectName=百度"/>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章