SpringフレームワークにはBinderという概念があります。Spring MVC(Boot)では@RequestParam
を使用してパラメータを受け取るときにこのBinderを使用するのですが実はこれ、簡単にカスタマイズすることができるんです。今回はこのBinderのオーバーライドの方法について書いてみます。
例
実際に自分が困った例です。フロントをMPAで実装し、HTMLのformを用いて日時を送信する処理を書きました。このとき未入力でsubmitした場合、空文字がセットされます。
<input type="date" name="bornAt">
@Controller
public class UserController {
@PostMapping
public String createUser(@RequestParam UserRequest user){
// 処理
}
}
public class UserRequest {
private final Date bornAt;
public UserRequest(Date bornAt){
this.bornAt = bornAt;
}
public Date getBornAt() {
return this.bornAt;
}
}
ここでbornAt
を空文字で送信した場合、user.bornAt
はうまく初期化を行うことができません。これはDate
クラスに対するBinder
に空文字に対する動作が定義されていないためであると言えます。
ここでuser.bornAt
をnullで初期化したい場合を例にとってやってみます。
Binderの登録
コントローラーに以下のようなメソッドを登録するとBinderを受け取れます。
@Controller
public class UserController {
@InitBinder
public void initBinder(WebdataBinder binder){
final var dateFormat = new SimpleDateFormat("yyyy/MM/dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
// 省略
このWebdataBinder
にCustomEditor
を登録することでBinder
の処理を書き換えていきます。
final var dateFormat = new SimpleDateFormat("yyyy/MM/dd");
として生成されたdateFormat
は空文字を受け取ったときにnull
を返します。
さらに
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
によりbinder
にDate
クラスのとき、CustomDateEditor
を使用することを伝えます。CustomDateEditor
は実際に変換を行うためのクラスであり、もちろんユーザーによる定義も可能です。その場合はPropertyEditorSupport
を継承したクラスを作成します。
Date
型のように一部の型についてはすでに用意されたものがあるので比較的簡単に実装可能です。
プロパティ名を指定する
上記の方法ではすべてのDate
が新しく定義したCustomEditor
でバインドされます。これを特定のフィールドのみに絞りたい場合、
binder.registerCustomEditor(Date.class, "user.bornAt", new CustomDateEditor(dateFormat, true));
とすることでuser
のbornAt
に限定することができます。