Formに入力された値が全て全角スペース、全て半角スペース、全てTAB、等の不可視文字のみで構成されていた場合、それらの項目は入力チェックエラーとしたいという仕様に対する対応方法の紹介です。入力チェックをJSR-303 Bean Validationのアノテーションで行っている場合「@NotBlank、@NotEmpty、@NotNullの挙動の違いをSpring Boot + Thymeleafで整理する」でも書いた通り、全角スペースの取り扱いが難しくなってきます(チェックエラーにならないため)。
対応方針
ControllerAdvice + InitBainderの組み合わせで共通処理として対応します。
※ControllerAdvice、InitBainder等の詳細はkazuki43zooさんの「Spring MVC(+Spring Boot)上でのリクエスト共通処理の実装方法を理解する」がとても分かりやすいです。
実装サンプル
※「@NotBlank、@NotEmpty、@NotNullの挙動の違いをSpring Boot + Thymeleafで整理する」で作成した簡易画面に肉付けする形で実装してみます。
Apache CommonsのStringUtilsを利用するためcommons-lang3への依存を追加します(バージョンはよしなに)。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
次にjava.beans.PropertyEditorSupportをextendsしてCustomeEditorを作成します(ここでApache CommonsのStringUtilsを利用します)。基本的にgetAsTextとsetAsTextをオーバーライドするだけでOKです。重要なのはsetAsTextで、このメソッドの引数としてFormに入力された値が渡ってくるので、それを解析し然るべき加工をしてsetValueメソッドに渡します。
package com.example.demo.support;
import java.beans.PropertyEditorSupport;
import org.apache.commons.lang3.StringUtils;
public class CustomeStringTrimmerEditor extends PropertyEditorSupport {
private final boolean emptyAsNull;
public CustomeStringTrimmerEditor(boolean emptyAsNull) {
this.emptyAsNull = emptyAsNull;
}
@Override
public String getAsText() {
Object value = this.getValue();
return value != null ? value.toString() : "";
}
@Override
public void setAsText(String text) {
if (text == null) {
this.setValue((Object) null);
} else {
String value = StringUtils.strip(text);
if (this.emptyAsNull && "".equals(value)) {
this.setValue((Object) null);
} else {
this.setValue(value);
}
}
}
}
最後にAdviceクラスを作成します。InitBinder#registerCustomEditorには上記で作成したCustomeEditorを指定します。
package com.example.demo.support;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
@ControllerAdvice
public class HelloAdvice {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new CustomeStringTrimmerEditor(true));
}
}
なお、一連の大まかな処理フローは、「(2)@RequestMappingメソッドの処理の流れ」が分かりやすいです。
Formクラスの入力フィールドに付与するアノテーション
正直@NotBlank、@NotEmpty、@NotNullどれでも引っかかるのでどれでもいいのですが、強いていうなら@NotNullが適切なのかなぁと思います。
ソースは以下です。
https://github.com/kenichi-nagaoka/spring-boot-form-validation-sample
以上です。
参考
https://howtodoinjava.com/spring-boot/custom-property-editor-example/
https://www.baeldung.com/spring-mvc-custom-property-editor