將 Spring MVC 與 jQuery 整合以進行驗證規則

工程 | Michael Isvy | 2012 年 8 月 29 日 | ...

我很高興在最近的 zeroturnaround 調查 中看到 Spring MVC 被評為 Java 最流行的 Web 框架。

這個框架非常靈活,有很多種使用方法。與所有具有許多選項的靈活框架一樣,討論常用實踐非常重要。

我為這篇部落格文章建立的專案使用了許多 Spring MVC 應用程式中常見的特性。你會發現類似的東西

在控制器中,您會找到典型的 Spring MVC 特性,用於對映請求、透過註解提取請求資料、資料繫結、檔案上傳等。

另一方面,在 JSP 中,大多數 HTML 都是原生編寫的(而不是由 Spring MVC 標籤生成的)。此外,Spring MVC 標籤庫不生成任何 Javascript 程式碼。

我們首先將討論如何將 Spring MVC 與 jQuery 和 Bean Validation 整合。然後,我們將看到如何使這些 JSP 不那麼冗長。

Bean Validation?

JSR 303 Bean Validation 提供了一種宣告驗證規則的全面方法。這是一個例子

public class DiningForm {
  @Pattern(regexp="\\d{16}")

  private String creditCardNumber;

  @Size(1)
  private String merchantNumber;

  @Min(0)
  private double monetaryAmount;

  @NotNull
  private Date date;

  ...

}

當呼叫驗證時,將根據上面的註解驗證 DiningForm 的例項。

從 Spring 3.0 開始,Spring MVC 集成了 Bean 驗證以進行驗證規則(這不是使用 Spring @MVC 進行驗證的唯一方法,但它顯然正在成為最常見的方法)。

在控制器方法中,我們可以使用 @Valid,如下所示


@RequestMapping(value="/update", method=RequestMethod.POST)
  public String update(@Valid DiningForm diningForm, BindingResult result) {

    if (result.hasErrors()) {
      return “rewards/edit”;
    }

    // continue on success...

  }
}

在 JSP 級別,可以使用 <form:errors /> 顯示錯誤訊息


<form:form modelAttribute="diningForm">
  <form:input path="firstName"/>
  <form:errors path="firstName"/>
  …
</form:form>

上面的程式碼非常簡單並且執行良好。但它不生成任何 Javascript。因此,它不允許部分渲染或客戶端驗證。讓我們看看如何改進它!

新增 Javascript 以進行部分渲染

讓我們考慮一下當“first name”為空時會發生什麼。

在之前的示例中,每次提交表單時都會重新整理整個頁面。這是 HTML 響應的摘錄

我們的目標是最小化響應大小。我們應該能夠獲得這樣的響應(使用 json 語法)


{"status":"FAIL","result":[{"fieldName":"firstName","message":"firstName  may not be empty"}]}

首先,我們將使用 jQuery 表單提交來驗證表單。當表單被認為是有效時,將使用常規 HTML 表單提交來觸發表單提交(這樣我們就可以重定向到不同的頁面)。

讓我們首先建立一個簡單的 ValidationResponse 類,如下所示


public class ValidationResponse {
 private String status;
 private List errorMessageList;

 public String getStatus() {
   return status;
 }
 public void setStatus(String status) {
   this.status = status;
 }
 public List getErrorMessageList() {
   return this.errorMessageList;
 }
 public void setErrorMessageList(List errorMessageList) {
   this.errorMessageList = errorMessageList;
 }
}

在控制器類中,我們可以新增一個 action 方法


@RequestMapping(value="/user.json")
public @ResponseBody ValidationResponse processForm (Model model, @Valid User user, BindingResult result ) {
 ValidationResponse res = new ValidationResponse();
 if(!result.hasErrors()){
   res.setStatus("SUCCESS");
 }
 // …
 return res;
}

感謝 @ResponseBody 註解,返回的物件將被轉換為 JSON,如下圖所示

在 JSP 中,會解析錯誤訊息並在適當的情況下顯示。您可以瀏覽 Javascript 程式碼 瞭解更多詳情。

根據 漸進增強 最佳實踐,所有 Javascript 程式碼都放置在 HTML 表單之外。如果客戶端的瀏覽器停用了 Javascript,則表單會回退到完整頁面重新整理。

現在我們已經讓部分重新整理可以用於驗證規則,還有 2 點需要改進

  • 這個頁面看起來不酷!
  • 這個 hello-world 風格的頁面已經有 100 行了。應該有一些方法可以使其更短。

讓我們使用 Bootstrap 使其更漂亮

即使這與 Spring MVC 沒有直接關係,我還是很難展示一個 UI 設計如此糟糕的示例應用程式。如果您還沒有聽說過,twitter Bootstrap 正在成為事實上的 CSS 框架。許多開發人員喜歡它,因為它允許以很少的努力為網站做一個可以接受的設計。在複製 Bootstrap CSS 和影像後,我只需要使用 Boostrap CSS 類(有關更多詳細資訊,請參見 JSP 原始碼)。我的表單現在看起來像這樣:

使用自定義標籤避免“JSP 湯”綜合症

這就是事情變得真正有趣的地方:即使我們已經有一些程式碼可以工作,它仍然很難閱讀。我們將 HTML、Javascript、CSS 和 JSP 表示式語言混合在一起。如果我的 JSP 程式碼看起來像這樣,它會更具可讀性


<html:form modelAttribute="user"  id="add-user-form" formUrl="/userAjaxCustomTag.htm">
 <html:inputField name="firstName" label="Enter your first name:" />
 <html:inputField name="lastName" label="Enter your last name:" />
 <div>
   <button type="submit">Save changes</button>
   <button type="reset">Cancel</button>
 </div>
</html:form>

自定義標籤是 Java EE 的一部分,並且在 Apache Tomcat 上也能很好地工作。建立自定義標籤非常容易。讓我們以表單輸入欄位為例。我們目前使用此語法(8 行)


<div id="firstName">
 <label>Enter your first name:</label>
 <div>
   <form:input path="firstName" />
   <span>
     <form:errors path="firstName" />
   </span>
 </div>
</div>

我們的目標是改為使用這個(1 行)


<html:inputField name="firstName" label="Enter your first name:" />

在 WEB-INF 資料夾中,我可以建立一個新的標籤檔案,如下所示

其內容如下


<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ attribute name="name" required="true" rtexprvalue="true" %>
<%@ attribute name="label" required="true" rtexprvalue="true" %>
<div id="${name}">
 <label>${label}</label>
<div>
  <form:input path="${name}"/>
  <span><form:errors path="${name}"/></span>
</div>

回到 userForm.jsp,我只需要宣告標籤資料夾


<%@ taglib prefix="html" tagdir="/WEB-INF/tags/html" %>

我可以按如下方式使用這個新建立的標籤


<html:inputField name="firstName" label="Enter your first name:" />

自定義標籤在 Eclipse/STS 中得到了很好的整合,我甚至可以訪問程式碼完成:

以類似的方式,我還可以將 JavaScript 程式碼外部化到一個標籤中,這樣我只需要一行程式碼來呼叫


<ajax:formPartialRefresh validateUrl="/userAjaxBootstrap.json" formName="add-user-form"/>

結論

我們已經討論了 Spring MVC 中表單驗證的部分渲染。在短短幾分鐘內,我們將 JSP 湯變成了一些更簡單、更易於理解的東西。

歡迎您檢視 github 上的相應 示例應用程式

鳴謝:我要感謝我的朋友 Nicholas Ding,他與我合作構建了這篇部落格文章的程式碼示例。

獲取 Spring 新聞通訊

與 Spring 新聞通訊保持聯絡

訂閱

取得領先

VMware 提供培訓和認證,以加速您的進步。

瞭解更多

獲得支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群中所有即將舉行的活動。

檢視全部