通過Spring-mvc的@InitBinder注釋的方法可以對WebDataBinder做一些初始化操作。
比如設置Validator。
我一直在想能不能為每個Request或者每個Action方法單獨設置Validator。
也就是說Controller里有多個被@InitBinder標注的方法。 在不同的Action時被分別調用。

我注意到了@InitBinder的value參數,

api docs里是這樣描述的:
The names of command/form attributes and/or request parameters that this init-binder method is supposed to apply to.

Default is to apply to all command/form attributes and all request parameters processed by the annotated handler class. Specifying model attribute names or request parameter names here restricts the init-binder method to those specific attributes/parameters, with different init-binder methods typically applying to different groups of attributes or parameters.

是乎是可以針對不同的Form對象或命令調用不同的InitBinder方法。

于是我寫了下面的Controller試了一下

@Controller
public?class?HomeController?{
????
????
private?static?final?Logger?logger?=?LoggerFactory.getLogger(HomeController.class);
????
????@InitBinder(
"action1")
????
public?void?initBinder1(WebDataBinder?binder){
????????logger.info(
"initBinder1");
????}
????
????@InitBinder(
"action2")
????
public?void?initBinder2(WebDataBinder?binder){
????????logger.info(
"initBinder2");
????}
????
????
/**
?????*?Simply?selects?the?home?view?to?render?by?returning?its?name.
?????
*/
????@RequestMapping(value?
=?"/",?method?=?RequestMethod.GET)
????
public?String?home(Model?model)?{????????
????????
????????Date?date?
=?new?Date();
????????DateFormat?dateFormat?
=?DateFormat.getDateTimeInstance(DateFormat.LONG,?DateFormat.LONG);
????????
????????String?formattedDate?
=?dateFormat.format(date);
????????
????????model.addAttribute(
"serverTime",?formattedDate?);
????????
????????
return?"home";
????}
????
????
/**
?????*?Simply?selects?the?home?view?to?render?by?returning?its?name.
?????
*/
????@RequestMapping(value?
=?"/doit",?method?=?RequestMethod.POST,?params="action1")
????
public?String?doit1(@RequestParam("value1")?int?value1,
????????????@RequestParam(
"action1")?String?action,?Model?model)?{????????
????????logger.info(
"value1={}",value1);
????????
????????Date?date?
=?new?Date();
????????DateFormat?dateFormat?
=?DateFormat.getDateTimeInstance(DateFormat.LONG,?DateFormat.LONG);
????????
????????String?formattedDate?
=?dateFormat.format(date);
????????
????????model.addAttribute(
"serverTime",?formattedDate?);
????????
????????
return?"home";
????}
????
????
/**
?????*?Simply?selects?the?home?view?to?render?by?returning?its?name.
?????
*/
????@RequestMapping(value?
=?"/doit",?method?=?RequestMethod.POST,?params="action2")
????
public?String?doit2(@RequestParam("value1")?int?value1,
????????????@RequestParam(
"action2")?String?action,?Model?model)?{????????
????????logger.info(
"value1={}",value1);
????????
????????Date?date?
=?new?Date();
????????DateFormat?dateFormat?
=?DateFormat.getDateTimeInstance(DateFormat.LONG,?DateFormat.LONG);
????????
????????String?formattedDate?
=?dateFormat.format(date);
????????
????????model.addAttribute(
"serverTime",?formattedDate?);
????????
????????
return?"home";
????}
}

畫面上的Form是這樣的


<form?action="doit"?method="post"?enctype="application/x-www-form-urlencoded">
????
<input?type="text"?name="value1"?value="100"/>
????
<input?type="submit"?name="action1"?value="Action1"/>
????
<input?type="submit"?name="action2"?value="Action2"/>
</form>

我的意愿是如果畫面上,點擊action1按鈕擇調用initBinder1方法。 如果點擊action2按鈕則調用initBinder2方法。

實際上也確實是這樣的。

當點擊action1時,logger.info("initBinder1"); 會執行

當點擊action2是,logger.info("initBinder2"); 會執行

是乎是可以實現“每個Action方法單獨設置Validator”這個目的。

但是其實并不是這樣的。

我調式進去了InitBinder相關的源代碼InitBinderDataBinderFactory, 結果發現它只是在對action這個參數綁定的時候調用了上面這個方法, 對value1綁定的時候那個方法都沒有調用。而我們常常要解決的是對同一個參數對于不同的action應用不同的Validator。

所以目前還是沒有好的方法能直接解決這個問題!

也許我們可以自己實現一個DataBinderFactory來解決這個問題。