Spring MVC中基於自定義Editor的表單資料處理技巧分享

Spring MVC中基於自定義Editor的表單資料處理技巧分享
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

物件導向的程式設計方式極大地方便了程式設計師在管理資料上所花費的精力。在基於Spring MVC的Web開發過程當中,可以通過物件對映的方式來管理表單提交上來的資料,而不用去一個一個地從request中提取出來。另外,這一功能還支援基本資料型別的對映。例如in、long、float等等。這樣我們就能從傳統單一的String型別中解脫出來。然而,應用是靈活的。我們對資料的需求是千變萬化的。有些時候我們需要對錶單的資料進行相容處理。

例如日期格式的相容:

中國的日期標註習慣採用yyyy-MM-dd格式,歐美習慣採用MM/dd/yyyy。雖然兩種格式都是日期的標註方法,但是往往我們要想達到相容的目的必須做繁瑣的轉換。

例如價格的相容:

價格無非就是一串數字,我們經常用的就是0.00這種表達形式,而對於金額較大的價格我們還習慣採用0,000.00這樣帶有逗號分隔的價格表述形式。

其實Spring MVC中已經考慮到了這個問題,在Controller中可以在初始化繫結的時候註冊一個編輯器。當表單提交過來的資料對映到某一特定型別(甚至是特定引數)時可以按照自定義的方法進行轉換。(除二進位制方式傳輸過來的資料以外,通常我們認為所有傳過來的引數不論是什麼內容,一律認為是字串)

下面我虛構了一個需求:

我有一個表單,裡面需要填寫使用者名稱、生日和積分。這分別代表了String型別、Date型別和Long型別。下面是表單內容:
複製程式碼 程式碼如下:
<form action=”getObj.do” method=”post”>
 <table>
  <tr>
   <td>使用者名稱:</td>
   <td><input type=”text” name=”userName” value=”Name Test” /></td>
   <td>*普通字串</td>
  </tr>
  <tr>
   <td>生日:</td>
   <td><input type=”text” name=”birthday” value=”2013-3-7″ /></td>
   <td>*支援格式: yyyy-MM-dd 或 MM/dd/yyyy</td>
  </tr>
  <tr>
   <td>積分:</td>
   <td><input type=”text” name=”score” value=”1,000″ /></td>
   <td>*支援純數字或帶逗號分隔的數字</td>
  </tr>
  <tr>
   <td colspan=”3″><input type=”submit” value=”提交” /></td>
  </tr>
 </table>
</form>

這裡根據表單,我們對映了如下的一個表單物件,這裡物件的屬性名稱要和上面表單的欄位name一致:
複製程式碼 程式碼如下:
package blog.csdn.net.chaijunkun.formObjs;

import java.util.Date;

public class UserInfo {

 private String userName;

 private Date birthday;

 private Long score;

 //getters and setters…

}

那麼我們想接收這樣一個表單資料,可以寫一個對錶單處理的方法:
複製程式碼 程式碼如下:
package blog.csdn.net.chaijunkun.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import blog.csdn.net.chaijunkun.formObjs.UserInfo;

@Controller
public class ObjController {

 private static Logger logger= Logger.getLogger(ObjController.class);

 public ObjController(){
  logger.info(“物件對映控制器初始化”);
 }

 @RequestMapping(value=”/getObj.do”)
 public String modifyUser(HttpServletRequest request,
   HttpServletResponse response,Map<String, Object> model,
   UserInfo userInfo){
  logger.info(“收集物件資訊”);
  model.put(“userInfo”, userInfo);  
  return “user”;
 }

}

如果僅僅是這麼寫,當然還不能做到多格式相容。我們需要寫一個針對日期和Long型的格式相容編輯器。編輯器需要至少繼承自類:java.beans.PropertyEditorSupport。當然,也可以繼承Spring內建的一些編輯器,例如:org.springframework.beans.propertyeditors.CustomNumberEditor,這個是專門用來處理數字轉換的。無論是繼承哪一個,方法都是一樣的:

第一步:重寫公有的void setAsText(String text)方法;

第二步:將轉換好的資料呼叫setValue(Object obj)進行寫入。

下面我們先實現一個日期相容的編輯器:
複製程式碼 程式碼如下:
package blog.csdn.net.chaijunkun.editors;

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyDateEditor extends PropertyEditorSupport {

 @Override
 /**
  * text是表單傳入的資料內容
  */
 public void setAsText(String text){
  Date value= null;
  SimpleDateFormat sdf= new SimpleDateFormat();
  sdf.applyPattern(“yyyy-MM-dd”);
  try{
   value= sdf.parse(text);
  }catch(ParseException e1){
   sdf.applyPattern(“MM/dd/yyyy”);
   try {
    value= sdf.parse(text);
   } catch (ParseException e2) {
    value= null;
   }
  }
  //這一步將轉換好的資料寫入到物件對映的屬性中
  setValue(value);
 }

}

然後我們再來寫一個針對Long型的編輯器,可以支援帶逗號分隔和不帶逗號分隔的數值表達形式:
複製程式碼 程式碼如下:
package blog.csdn.net.chaijunkun.editors;

import org.springframework.beans.propertyeditors.CustomNumberEditor;

public class MyLongEditor extends CustomNumberEditor  {

 public MyLongEditor(){
  super(Long.class, true);
 }

 @Override
 public void setAsText(String text){
  if ((text== null) || text.trim().equals(“”)){
   setValue(null);
  }else{
   Long value= null;
   try{
    //按照標準的數字格式嘗試轉換
    value= Long.parseLong(text);
   }catch(NumberFormatException e){
    //嘗試去除逗號 然後再轉換
    text= text.replace(“,”, “”);
    value= Long.parseLong(text);
   }
   //轉好之後將值返給被對映的屬性
   setValue(value);   
  }
 }

}

好了,這兩個編輯器寫好了,如何讓它們發揮作用呢?這需要在Controller內加一個資料轉換時的繫結方法:
複製程式碼 程式碼如下:
@InitBinder
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder){
 binder.registerCustomEditor(Date.class, new MyDateEditor());
 binder.registerCustomEditor(Long.class, new MyLongEditor());
}

上面的程式碼作用就是:當接收到表單資料,Spring發現引數名能夠與物件屬性相對應,而轉換的型別恰好也是在上述程式碼中註冊過的類似,則會將資料內容按照指定的編輯器來做轉換。

我們來試一下:

如下圖所示:

同樣,資料被正確識別了。

通過以上方法,我們成功地相容了多種資料格式。

寫在後面:

其實針對日期格式,我開始的時候想寫成下面程式碼那樣來實現相容:
複製程式碼 程式碼如下:
@InitBinder
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder){
 binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(“yyyy-MM-dd”), true));
 binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(“MM/dd/yyyy”), true));
}

後來我發現,這樣寫之後只支援MM/dd/yyyy格式的日期,提交yyyy-MM-dd格式的日期後會丟擲異常。看來,對於同一型別,在一個控制器裡只能註冊一個編輯器,而且是最後一個被註冊的才起作用。

另外,在文章剛開始的時候寫到,不僅可以按型別,甚至是某一型別的某個屬性都可以按照自己的要求定製編輯器,同時不影響其它同型別的屬性。這個很容易,在registerCustomEditor方法中還有一個過載的方法,第二個引數可以指定具體的屬性名稱。這樣就很容易控制細粒度了。

您可能感興趣的文章:

Spring MVC—資料繫結和表單標籤詳解[Spring MVC] -簡單表單提交例項SpringMVC處理Form表單例項Spring學習筆記2之表單資料驗證、檔案上傳例項程式碼SpringMVC實現資料繫結及表單標籤

相關文章

程式語言 最新文章