閱讀1020 返回首頁    go 技術社區[雲棲]


《精通Spring MVC 4》——2.9 使用WebJars實現質感設計

本節書摘來自異步社區《精通Spring MVC 4》一書中的第2章,第2.9節,作者:【美】Geoffroy Warin著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

2.9 使用WebJars實現質感設計

現在,我們的應用已經很棒了,但是在美學方麵卻差得很多。你可能聽說過質感設計(material design),這是Google的扁平化設計。

如圖2-10所示,我們將會使用Materialize,這是一個非常漂亮的CSS和JavaScript庫,與Bootstrap類似。

screenshot

圖2-10

在第1章中,我們曾經簡單介紹過WebJars,現在要開始使用它們了。在依賴中,我們要添加jQuery和Materialize CSS:

compile 'org.webjars:materializecss:0.96.0'
compile 'org.webjars:jquery:2.1.4'

每個WebJar的結構都是標準的,每個庫的JS和CSS文件都會位於/webjars/{lib}/ {version}/*.js中。

例如,如果要添加jQuery到我們的頁麵中,那Web頁麵需要如下所示:

``
接下來修改一下控製器,讓它顯示所有Tweet對象的列表,而不是隻顯示簡單的文本:

package masterSpringMvc.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class TweetController {

    @Autowired
    private Twitter twitter;

    @RequestMapping("/")
    public String hello(@RequestParam(defaultValue =
"masterSpringMVC4") String search, Model model) {
        SearchResults searchResults = twitter.searchOperations().
search(search);
        List<Tweet> tweets = searchResults.getTweets();
        model.addAttribute("tweets", tweets);
        model.addAttribute("search", search);
        return "resultPage";
    }
}

在視圖中,將Materialize CSS包含進來:

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head lang="en">
    <meta charset="UTF-8"/>
    <title>Hello twitter</title>

    <link href="/webjars/materializecss/0.96.0/css/materialize.css"
type="text/css" rel="stylesheet" media="screen,projection"/>
</head>
<body>
<div >

    <h2  th:text="|Tweet results for
${search}|">Tweets</h2>

    <ul >
        <li  th:each="tweet :
${tweets}">
            <img th:src="${tweet.user.profileImageUrl}" alt=""
/>
            <span  th:text="${tweet.user.
name}">Username</span>
            <p th:text="${tweet.text}">Tweet message</p>
        </li>
    </ul>

</div>

<script src="/webjars/jquery/2.1.4/jquery.js"></script>
<script src="/webjars/materializecss/0.96.0/js/materialize.js"></
script>
</body>
</html>

如圖2-11所示結果看起來會好很多。

..\tu\0211.tif{}
screenshot

圖2-11

2.9.1 使用布局
我們最後想實現的就是將UI中可重用的代碼塊放到模板之中。為了實現該功能,我們需要使用thymeleaf-layout-dialect依賴,它已經包含在項目的spring-boot-starter-thymeleaf依賴裏麵。

我們會創建一個新的文件,名為default.html,並將其放在src/main/resources/templates/ layout之中,它包含了每個頁麵中都重複出現的代碼:

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org"
      xmlns:layout="https://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta http-equiv="Content-Type" content="text/html;
charset=UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-
scale=1, maximum-scale=1.0, user-scalable=no"/>
    <title>Default title</title>

    <link href="/webjars/materializecss/0.96.0/css/materialize.css"
type="text/css" rel="stylesheet" media="screen,projection"/>
</head>
<body>
<section layout:fragment="content">
    <p>Page content goes here</p>
</section>

<script src="/webjars/jquery/2.1.4/jquery.js"></script>
<script src="/webjars/materializecss/0.96.0/js/materialize.js"></
script>
</body>
</html>

現在,我們要修改resultPage.html文件,讓它使用布局,這會簡化它的內容:

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org"
      xmlns:layout="https://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="layout/default">
<head lang="en">
    <title>Hello twitter</title>
</head>
<body>
<div  layout:fragment="content">

    <h2  th:text="|Tweet results for
${search}|">Tweets</h2>

    <ul >
        <li  th:each="tweet :
${tweets}">

            <img th:src="${tweet.user.profileImageUrl}" alt=""
/>
            <span  th:text="${tweet.user.
name}">Username</span>

            <p th:text="${tweet.text}">Tweet message</p>
        </li>
    </ul>
</div>
</body>
</html>

其中,layout:decorator="layout/default"能夠表明去哪裏查找布局。這樣,我們可以將內容注入到布局的不同layout:fragment區域中。需要注意的是,每個模板都是合法的HTML文件,我們可以非常容易地重寫它的標題。

2.9.2 導航
我們現在已經有了一個很棒的用於展現Tweet的小應用,但是,我們的用戶需要提供一個“search”請求參數,這該如何實現呢(見圖2-12)?

screenshot

圖2-12

如果我們能夠在應用上增加一個小表單的話,那就非常完美了。

我們接下來要做的事情如下所示。

首先,我們需要修改TweetController,為應用增加第二個視圖。訪問應用的根目錄會展現出搜索頁麵,在search域中點擊回車鍵會展現結果頁麵:

@Controller
public class TweetController {

    @Autowired
    private Twitter twitter;

    @RequestMapping("/")
    public String home() {
        return "searchPage";
    }

    @RequestMapping("/result")
    public String hello(@RequestParam(defaultValue =
"masterSpringMVC4") String search, Model model) {
        SearchResults searchResults = twitter.searchOperations().
search(search);
        List<Tweet> tweets = searchResults.getTweets();
        model.addAttribute("tweets", tweets);
        model.addAttribute("search", search);
        return "resultPage";
    }
}

我們會添加另外一個頁麵到templates文件夾下,並將其命名為searchPage.html文件。這個頁麵會包含一個簡單的表單,它會通過get方法將要搜索的術語傳遞到結果頁麵:

<!DOCTYPE html>
<html xmlns:th="https://www.w3.org/1999/xhtml"
      xmlns:layout="https://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="layout/default">
<head lang="en">
    <title>Search</title>
</head>
<body>

<div  layout:fragment="content">

    <h4 >Please enter a search term</h4>

    <form action="/result" method="get" >
        <div >
            <div >
                <i ></i>
                <input  name="search" type="text"
/>
                <label for="search">Search</label>
            </div>
        </div>
    </form>
</div>

</body>
</html>

這是一個很簡單的HTML,但是已經可以正常運行了,你現在可以嚐試一下。

如果不允許展現某些搜索結果的話,該怎麼辦呢?假設如果用戶輸入struts的話,我們想展現一個出錯頁麵。

要實現該功能,最好的方式就是修改提交數據的表單。在控製器中,我們可以攔截提交的內容並實現該業務相關的規則。

首先,要修改searchPage中的表單,原來的內容如下所示:

<form action="/result" method="get" >
現在,我們將表單改成如下的形式:

<form action="/postSearch" method="post" >
我們還需要在服務器端處理該POST請求。在TweetController中添加如下的方法:

@RequestMapping(value = "/postSearch", method = RequestMethod.POST)
public String postSearch(HttpServletRequest request,
    RedirectAttributes redirectAttributes) {
        String search = request.getParameter("search");
        redirectAttributes.addAttribute("search", search);
        return "redirect:result";
}

在這裏,有幾項比較新鮮的內容:

在請求映射的注解中,指定了想要處理的HTTP方法,也就是POST;
在方法參數中,直接注入了兩個屬性,它們是request和RedirectAttributes;
檢索到請求中post提交過來的數據,並將其傳遞給下一個視圖;
現在不是直接返回視圖的名稱,而是重定向到另一個URL。
RedirectAttributes是一個Spring的模型,專門用於redirect場景下傳送值。

screenshot

在Java Web應用中,Redirect/Forward是典型的可選方案。它們都會改變展現給用戶的視圖,其中的區別在於Redirect會發送一個302頭信息,它會在瀏覽器內部觸發導航,而Forward則不會導致URL的變化。在Spring MVC中,我們可以任意使用這兩種方案,隻需在方法返回的字符串上添加“redirect:”或“forward:”前綴即可。在這兩種場景中,我們所返回的字符串都不會像前麵看到的那樣解析為視圖,而是觸發到特定URL的導航。
之前的樣例有些牽強,在下一章中會進行更加巧妙的處理。如果你在postSearch方法上添加一個斷點的話,就會發現它會在post表單之後進行調用。

那麼,該怎樣顯示錯誤信息呢?

我們改一下postSearch方法:

@RequestMapping(value = "/postSearch", method = RequestMethod.POST)
public String postSearch(HttpServletRequest request,
    RedirectAttributes redirectAttributes) {
        String search = request.getParameter("search");
        if (search.toLowerCase().contains("struts")) {
                redirectAttributes.addFlashAttribute("error", "Try
using spring instead!");
                return "redirect:/";
        }
        redirectAttributes.addAttribute("search", search);
        return "redirect:result";
}

如果用戶的搜索包含“struts”這個術語的話,我們會將其重定向到searchPage頁麵並且使用flash屬性添加一點錯誤信息。

這個特殊的屬性會在該請求的時間範圍內一直存活,直到頁麵渲染完成才消失。當使用POST-REDIRECT-GET模式的時候,它是非常有用的,就像剛剛做的這樣。

我們接下來需要在searchPage結果頁麵中展現這個錯誤信息:

<!DOCTYPE html>
<html xmlns:th="https://www.w3.org/1999/xhtml"
      xmlns:layout="https://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="layout/default">
<head lang="en">
    <title>Search</title>
</head>
<body>

<div  layout:fragment="content">

    <h4 >Please enter a search term</h4>

    <div >
        <div  
th:if="${error}">
            <span  th:text="${error}"></span>
        </div>
        <form action="/postSearch" method="post" >
            <div >
                <div >
                    <i ></i>
                    <input  name="search" type="text"
/>
                    <label for="search">Search</label>
                </div>
            </div>
        </form>
    </div>
</div>

</body>
</html>

現在,如果用戶試圖搜索包含“struts2”的Tweet,將會得到有用且合適的答案(見圖2-13)。

screenshot

圖2-13

最後更新:2017-05-27 16:01:32

  上一篇:go  《精通Spring MVC 4》——2.10 檢查點
  下一篇:go  獲取微信公眾號授權失敗,請稍後重試!公眾平台返回原始數據為:錯誤代碼-40164 40125等的解決方法