將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 Validation的驗證規則(這不是使用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進行部分渲染

讓我們考慮一下“名字”為空時會發生什麼。

在前面的例子中,每次提交表單時都會重新整理整個頁面。這是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 社群所有即將舉行的活動。

檢視所有