1. 序章

簡単に言えば、SpringはString値とカスタムObjectタイプ間の変換を管理するためにプロパティエディターを多用します。 これは、 Java BeansPropertyEditorに基づいています。

このチュートリアルでは、自動プロパティエディターバインディングとカスタムプロパティエディターバインディングを示す2つの異なるユースケースについて説明します。

2. 自動プロパティエディタバインディング

標準のJavaBeansインフラストラクチャは、 PropertyEditor クラスが処理するクラスと同じパッケージにある場合、それらのクラスを自動的に検出します。 また、これらはそのクラスと同じ名前にEditorサフィックスを付けたものである必要があります。

たとえば、 CreditCard モデルクラスを作成する場合、エディタークラスにCreditCardEditor。という名前を付ける必要があります。

次に、実用的なプロパティバインディングの例を見てみましょう。

このシナリオでは、リクエストURLのパス変数としてクレジットカード番号を渡し、その値を aCreditCardオブジェクトとしてバインドします。

まず、 CreditCardモデルクラス定義フィールドrawCardNumber、銀行識別番号(最初の6桁)、アカウント番号(7〜15桁)、およびチェックコード(最後の桁)を作成しましょう。 :

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をに変換するために使用されます別のオブジェクト。

これらのクラスは同じパッケージに含まれているため、タイプCreditCardEditorをバインドするために他に何もする必要はありません。

これで、これをRESTAPIのリソースとして公開できます。 この操作では、クレジットカード番号をリクエストパス変数として受け取り、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タイプに変換する方法を説明しました。

ここでの例の完全なソースコードは、いつものように、GitHub上にあります。