1
1

Springで入力パラメータが数値の場合に入力文字種を半角文字に限定する

Posted at

はじめに

Springにて入力パラメータとしてFormに数値型(IntegerやLong)で定義した場合、全角数字で入力した場合も正常にバインドされます。
しかし、これだと、半角数字だけを許容したいという場面に対応出来ません。
入力チェックのためだけにフィールドをString型で定義して半角数字のみを許容するようにPatternアノテーションを付与して入力規則を定義するのも何だかな、と思っていました。
そこで、なんかいい方法がないか探していたところ、WebDataBinderを利用しCustomNumberEditorを拡張したクラスを登録すればよいことがわかりました。

やり方

まず、CustomNumberEditorを拡張したクラスを作成します。

CustomNumberEditorを拡張したクラス
public class SampleCustomNumberEditor extends CustomNumberEditor {

	private final Class<? extends Number> numberClass;
 
    public SampleCustomNumberEditor (Class<? extends Number> numberClass, boolean allowEmpty) {
        super(numberClass, allowEmpty);
        this.numberClass = numberClass;
    }
    
    @Override
    public void setAsText(String s) throws IllegalArgumentException {
        // 値が入力されている場合のみ処理する
        if (StringUtils.hasText(s)) {
            // 半角の整数の場合
            if (s.matches("^(\\+|\\-)?[0-9]*$")) {
                // スーパークラスのメソッドに処理を移譲
                super.setAsText(s);
                return;
            }
            // 小数点付きのクラスの場合
            if (numberClass == Float.class || numberClass == Double.class
                || numberClass == BigDecimal.class) {
                // 半角の小数点つき数値文字列以外の場合(この例では".9"のような表現も許容)
                if (!s.matches("^((\\+|\\-)?[0-9]+)?\\.[0-9]+$")) {
                    throw new IllegalArgumentException("半角数値以外が入力されています");
                }
            } else {
                    throw new IllegalArgumentException("半角の整数以外が入力されています");
            }
        }
        // 半角数値以外を弾いた後はスーパークラスのメソッドを呼び出し処理を移譲
        super.setAsText(s);
    }
}

Controllerクラス、もしくは、全処理で適応したい場合はControllerAdviceアノテーションを付与したクラスに、@InitBinderアノテーションを付与した以下のメソッドを作成し、WebDataBinderのregisterCustomEditorメソッドで、前述で作成したクラスを登録します。

Controllerクラス、もしくは、ControllerAdviceクラス
@ControllerAdvice
public class SampleControllerAdvice {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // Integer型を登録する
        binder.registerCustomEditor(Integer.class, new SampleCustomNumberEditor(Integer.class, true));
        // Long型を登録する
        binder.registerCustomEditor(Long.class, new SampleCustomNumberEditor(Long.class, true));

        // ...
        
        // Double型を登録する
        binder.registerCustomEditor(Double.class, new SampleCustomNumberEditor(Double.class, true));
        // BigDecimal型を登録する
        binder.registerCustomEditor(BigDecimal.class, new SampleCustomNumberEditor(BigDecimal.class, true));
    }
}

上記で登録したすべての数値型に関しては、Formに半角数値以外が入力された場合は、入力エラーとして処理されます。必要に応じて使う型だけ登録すればよいかと思います。
なお、デフォルトでは、CustomNumberEditorが有効になります。

その他

とりあえずInteger型だけ対応したい、というケースにおいては、わざわざEditorクラスを作成しなくても、以下のように匿名クラスで対応できます。

Controllerクラス、もしくは、ControllerAdviceクラス
@ControllerAdvice
public class SampleControllerAdvice {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // Integer型を登録する
        binder.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, true) {
            @Override
            public void setAsText(String s) throws IllegalArgumentException {
                // 値が入力されている場合のみ処理する
                if (StringUtils.hasText(s)) {
                    // 半角の整数以外の場合
                    if (!s.matches("^(\\+|\\-)?[0-9]*$")) {
                        throw new IllegalArgumentException("半角数値以外が入力されています");
                    }
                }
                super.setAsText(s);
            }
        });
    }
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1