Springカスタムプロパティエディタ
1前書き
簡単に言うと、Springは
String
値とカスタム
Object
型の間の変換を管理するためにプロパティエディタを多用しています。これはhttps://docs.oracle.com/javase/8/docs/api/java/beans/PropertyEditor.html[Java Beans PropertyEditor]に基づいています。
このチュートリアルでは、
自動プロパティエディタバインディングとカスタムプロパティエディタバインディング
のデモンストレーションについて、2つの異なるユースケースについて説明します。
2自動プロパティエディタバインディング
それらが扱うクラスと同じパッケージにある場合、標準の
JavaBeans
インフラストラクチャは自動的に
PropertyEditor
クラスを発見します。また、これらはそのクラスと同じ名前に
Editor
サフィックスを付けたものである必要があります。
たとえば、
CreditCard
モデルクラスを作成する場合は、エディタクラスに__CreditCardEditorという名前を付けます。
それでは、実際のプロパティバインディングの例を見てみましょう。
このシナリオでは、リクエストURLのパス変数としてクレジットカード番号を渡し、その値をCreditCardオブジェクトとしてバインドします。
最初に、
rawCardNumber、
Bank Identification Number(最初の6桁)、Account Number(7〜15の数字)、Check Code(最後の桁)の各フィールドを定義する
CreditCard
モデルクラスを作成します。
public class CreditCard {
private String rawCardNumber;
private Integer bankIdNo;
private Integer accountNo;
private Integer checkCode;
//standard constructor, getters, setters
}
次に、
CreditCardEditor
クラスを作成します。これは、
String
として与えられたクレジットカード番号を
CreditCard
オブジェクトに変換するためのビジネスロジックを実装します。
-
プロパティエディタクラスは
PropertyEditorSupport
を拡張し、
getAsText()
と
setAsText()
メソッドを実装する必要があります。
public class CreditCardEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
CreditCard creditCard = (CreditCard) getValue();
return creditCard == null ? "" : creditCard.getRawCardNumber();
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.isEmpty(text)) {
setValue(null);
} else {
CreditCard creditCard = new CreditCard();
creditCard.setRawCardNumber(text);
String cardNo = text.replaceAll("-", "");
if (cardNo.length() != 16)
throw new IllegalArgumentException(
"Credit card format should be xxxx-xxxx-xxxx-xxxx");
try {
creditCard.setBankIdNo( Integer.valueOf(cardNo.substring(0, 6)) );
creditCard.setAccountNo( Integer.valueOf(
cardNo.substring(6, cardNo.length() - 1)) );
creditCard.setCheckCode( Integer.valueOf(
cardNo.substring(cardNo.length() - 1)) );
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException(nfe);
}
setValue(creditCard);
}
}
}
-
getAsText()
メソッドは、オブジェクトを
Stringにシリアル化するときに呼び出され、
setAsText()
は
String__を別のオブジェクトに変換するために使用されます。
これらのクラスは同じパッケージ内にあるので、
Editor
を
CreditCard
型にバインドするために他に必要な作業はありません。
これをREST APIのリソースとして公開できます。操作はリクエストパス変数としてクレジットカード番号を取り、Springはそのテキスト値を
CrediCard
オブジェクトとしてバインドし、それをメソッド引数として渡します。
@GetMapping(value = "/credit-card/{card-no}",
produces = MediaType.APPLICATION__JSON__UTF8__VALUE)
public CreditCard parseCreditCardNumber(
@PathVariable("card-no") CreditCard creditCard) {
return creditCard;
}
たとえば、サンプルリクエストURL
/property-editor/credit-card/1234-1234-1111-0019の場合、
レスポンスが返されます。
{
"rawCardNumber": "1234-1234-1111-0011",
"bankIdNo": 123412,
"accountNo": 341111001,
"checkCode": 9
}
3カスタムプロパティエディタのバインディング
必要な型クラスとプロパティエディタクラスが同じパッケージに含まれていない場合、または想定される命名規則に従っていない場合は、必要な型とプロパティエディタの間にカスタムバインディングを定義する必要があります。
カスタムプロパティエディタのバインドシナリオでは、
String
値がパス変数としてURLに渡され、その値を単に属性として保持する
ExoticType
オブジェクトとしてバインドします。
セクション2のように、まずモデルクラス__ExoticTypeを作成しましょう。
public class ExoticType {
private String name;
//standard constructor, getters, setters
}
そして私たちのカスタムプロパティエディタクラス
CustomExoticTypeEditor
は、やはり
_PropertyEditorSupportを継承しています:
_
public class CustomExoticTypeEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
ExoticType exoticType = (ExoticType) getValue();
return exoticType == null ? "" : exoticType.getName();
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
ExoticType exoticType = new ExoticType();
exoticType.setName(text.toUpperCase());
setValue(exoticType);
}
}
Springはプロパティエディタを検出できないので、エディタを登録する
Controller
クラスに
@ InitBinder
というアノテーションを付けたメソッドが必要です。
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(ExoticType.class,
new CustomExoticTypeEditor());
}
その後、ユーザー入力を
ExoticType
オブジェクトにバインドできます。
@GetMapping(
value = "/exotic-type/{value}",
produces = MediaType.APPLICATION__JSON__UTF8__VALUE)
public ExoticType parseExoticType(
@PathVariable("value") ExoticType exoticType) {
return exoticType;
}
サンプルリクエストURL
__
/property-editor/exotic-type/passion-fruitについては、サンプルレスポンスを取得します。
{
"name": "PASSION-FRUIT"
}
4結論
このクイック記事では、自動およびカスタムのプロパティエディタバインディングを使用して、人間が読める
String
値を複雑なJava型に変換する方法を説明しました。
私たちの例の完全なソースコードは、いつものように、https://github.com/eugenp/tutorials/tree/master/spring-rest[GitHubでの使用]です。