Spring MVC中基于自定義Editor的表單數(shù)據(jù)處理技巧分享
面向?qū)ο蟮木幊谭绞綐O大地方便了程序員在管理數(shù)據(jù)上所花費(fèi)的精力。在基于Spring MVC的Web開(kāi)發(fā)過(guò)程當(dāng)中,可以通過(guò)對(duì)象映射的方式來(lái)管理表單提交上來(lái)的數(shù)據(jù),而不用去一個(gè)一個(gè)地從request中提取出來(lái)。另外,這一功能還支持基本數(shù)據(jù)類(lèi)型的映射。例如in、long、float等等。這樣我們就能從傳統(tǒng)單一的String類(lèi)型中解脫出來(lái)。然而,應(yīng)用是靈活的。我們對(duì)數(shù)據(jù)的需求是千變?nèi)f化的。有些時(shí)候我們需要對(duì)表單的數(shù)據(jù)進(jìn)行兼容處理。
例如日期格式的兼容:
中國(guó)的日期標(biāo)注習(xí)慣采用yyyy-MM-dd格式,歐美習(xí)慣采用MM/dd/yyyy。雖然兩種格式都是日期的標(biāo)注方法,但是往往我們要想達(dá)到兼容的目的必須做繁瑣的轉(zhuǎn)換。
例如價(jià)格的兼容:
價(jià)格無(wú)非就是一串?dāng)?shù)字,我們經(jīng)常用的就是0.00這種表達(dá)形式,而對(duì)于金額較大的價(jià)格我們還習(xí)慣采用0,000.00這樣帶有逗號(hào)分隔的價(jià)格表述形式。
其實(shí)Spring MVC中已經(jīng)考慮到了這個(gè)問(wèn)題,在Controller中可以在初始化綁定的時(shí)候注冊(cè)一個(gè)編輯器。當(dāng)表單提交過(guò)來(lái)的數(shù)據(jù)映射到某一特定類(lèi)型(甚至是特定參數(shù))時(shí)可以按照自定義的方法進(jìn)行轉(zhuǎn)換。(除二進(jìn)制方式傳輸過(guò)來(lái)的數(shù)據(jù)以外,通常我們認(rèn)為所有傳過(guò)來(lái)的參數(shù)不論是什么內(nèi)容,一律認(rèn)為是字符串)
下面我虛構(gòu)了一個(gè)需求:
我有一個(gè)表單,里面需要填寫(xiě)用戶(hù)名、生日和積分。這分別代表了String類(lèi)型、Date類(lèi)型和Long類(lèi)型。下面是表單內(nèi)容:
<form action="getObj.do" method="post">
<table>
<tr>
<td>用戶(hù)名:</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>*支持純數(shù)字或帶逗號(hào)分隔的數(shù)字</td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="提交" /></td>
</tr>
</table>
</form>
這里根據(jù)表單,我們映射了如下的一個(gè)表單對(duì)象,這里對(duì)象的屬性名稱(chēng)要和上面表單的字段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...
}
那么我們想接收這樣一個(gè)表單數(shù)據(jù),可以寫(xiě)一個(gè)對(duì)表單處理的方法:
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("對(duì)象映射控制器初始化");
}
@RequestMapping(value="/getObj.do")
public String modifyUser(HttpServletRequest request,
HttpServletResponse response,Map<String, Object> model,
UserInfo userInfo){
logger.info("收集對(duì)象信息");
model.put("userInfo", userInfo);
return "user";
}
}
如果僅僅是這么寫(xiě),當(dāng)然還不能做到多格式兼容。我們需要寫(xiě)一個(gè)針對(duì)日期和Long型的格式兼容編輯器。編輯器需要至少繼承自類(lèi):java.beans.PropertyEditorSupport。當(dāng)然,也可以繼承Spring內(nèi)置的一些編輯器,例如:org.springframework.beans.propertyeditors.CustomNumberEditor,這個(gè)是專(zhuān)門(mén)用來(lái)處理數(shù)字轉(zhuǎn)換的。無(wú)論是繼承哪一個(gè),方法都是一樣的:
第一步:重寫(xiě)公有的void setAsText(String text)方法;
第二步:將轉(zhuǎn)換好的數(shù)據(jù)調(diào)用setValue(Object obj)進(jìn)行寫(xiě)入。
下面我們先實(shí)現(xiàn)一個(gè)日期兼容的編輯器:
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是表單傳入的數(shù)據(jù)內(nèi)容
*/
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;
}
}
//這一步將轉(zhuǎn)換好的數(shù)據(jù)寫(xiě)入到對(duì)象映射的屬性中
setValue(value);
}
}
然后我們?cè)賮?lái)寫(xiě)一個(gè)針對(duì)Long型的編輯器,可以支持帶逗號(hào)分隔和不帶逗號(hào)分隔的數(shù)值表達(dá)形式:
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{
//按照標(biāo)準(zhǔn)的數(shù)字格式嘗試轉(zhuǎn)換
value= Long.parseLong(text);
}catch(NumberFormatException e){
//嘗試去除逗號(hào) 然后再轉(zhuǎn)換
text= text.replace(",", "");
value= Long.parseLong(text);
}
//轉(zhuǎn)好之后將值返給被映射的屬性
setValue(value);
}
}
}
好了,這兩個(gè)編輯器寫(xiě)好了,如何讓它們發(fā)揮作用呢?這需要在Controller內(nèi)加一個(gè)數(shù)據(jù)轉(zhuǎn)換時(shí)的綁定方法:
@InitBinder
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder){
binder.registerCustomEditor(Date.class, new MyDateEditor());
binder.registerCustomEditor(Long.class, new MyLongEditor());
}
上面的代碼作用就是:當(dāng)接收到表單數(shù)據(jù),Spring發(fā)現(xiàn)參數(shù)名能夠與對(duì)象屬性相對(duì)應(yīng),而轉(zhuǎn)換的類(lèi)型恰好也是在上述代碼中注冊(cè)過(guò)的類(lèi)似,則會(huì)將數(shù)據(jù)內(nèi)容按照指定的編輯器來(lái)做轉(zhuǎn)換。
我們來(lái)試一下:
如下圖所示:

同樣,數(shù)據(jù)被正確識(shí)別了。
通過(guò)以上方法,我們成功地兼容了多種數(shù)據(jù)格式。
寫(xiě)在后面:
其實(shí)針對(duì)日期格式,我開(kāi)始的時(shí)候想寫(xiě)成下面代碼那樣來(lái)實(shí)現(xiàn)兼容:
@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));
}
后來(lái)我發(fā)現(xiàn),這樣寫(xiě)之后只支持MM/dd/yyyy格式的日期,提交yyyy-MM-dd格式的日期后會(huì)拋出異常。看來(lái),對(duì)于同一類(lèi)型,在一個(gè)控制器里只能注冊(cè)一個(gè)編輯器,而且是最后一個(gè)被注冊(cè)的才起作用。
另外,在文章剛開(kāi)始的時(shí)候?qū)懙剑粌H可以按類(lèi)型,甚至是某一類(lèi)型的某個(gè)屬性都可以按照自己的要求定制編輯器,同時(shí)不影響其它同類(lèi)型的屬性。這個(gè)很容易,在registerCustomEditor方法中還有一個(gè)重載的方法,第二個(gè)參數(shù)可以指定具體的屬性名稱(chēng)。這樣就很容易控制細(xì)粒度了。
- layui 圖片上傳+表單提交+ Spring MVC的實(shí)例
- SpringMVC實(shí)現(xiàn)表單驗(yàn)證功能詳解
- springMVC中基于token防止表單重復(fù)提交方法
- SpringMVC中使用bean來(lái)接收f(shuō)orm表單提交的參數(shù)時(shí)的注意點(diǎn)
- SpringMVC實(shí)現(xiàn)數(shù)據(jù)綁定及表單標(biāo)簽
- Spring MVC---數(shù)據(jù)綁定和表單標(biāo)簽詳解
- [Spring MVC] -簡(jiǎn)單表單提交實(shí)例
- SpringMVC處理Form表單實(shí)例
- SpringMVC表單提交參數(shù)400錯(cuò)誤解決方案
相關(guān)文章
RocketMQ4.5.2 修改mqnamesrv 和 mqbroker的日志路徑操作
這篇文章主要介紹了RocketMQ 4.5.2 修改mqnamesrv 和 mqbroker的日志路徑操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07SpringBoot?項(xiàng)目的創(chuàng)建與啟動(dòng)步驟詳解
這篇文章主要介紹了SpringBoot?項(xiàng)目的創(chuàng)建與啟動(dòng),本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03從零開(kāi)始Java實(shí)現(xiàn)Parser?Combinator
這篇文章主要為大家介紹了從零開(kāi)始Java實(shí)現(xiàn)Parser?Combinator過(guò)程及原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05JAVA解決在@autowired,@Resource注入為null的情況
這篇文章主要介紹了JAVA解決在@autowired,@Resource注入為null的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10使用webservice自定義注解處理參數(shù)加解密問(wèn)題
這篇文章主要介紹了使用webservice自定義注解處理參數(shù)加解密問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java8的default和static關(guān)鍵字的使用講解
今天小編就為大家分享一篇關(guān)于Java8的default和static關(guān)鍵字的使用講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01