サーチ…


前書き

SpringにはJSR303 Bean検証サポートがあります。これを使用して入力Beanの検証を行うことができます。 JSR303を使用したビジネスロジックからの個別の検証ロジック。

JSR303 Springのアノテーションベースのバリデーション例

JSR 303実装をクラスパスに追加します。人気のあるものは、HibernateのHibernateバリデータです。

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>

システムにユーザーを作成するための残りのAPIがあるとします

@RequestMapping(value="/registeruser", method=RequestMethod.POST)
public String registerUser(User user);

入力jsonサンプルは以下のようになります

{"username" : "[email protected]", "password" : "password1", "password2":"password1"}

User.java

public class User {

    private String username;
    private String password;
    private String password2;

    getXXX and setXXX

}

JSR 303の検証は、以下のようにユーザークラスに定義できます。

public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String username;
    
    @NotEmpty
    private String password;
    
    @NotEmpty
    private String password2;

}

また、パスワードとパスワード2(パスワードの確認)のようなビジネスバリデーターを同じにする必要があるかもしれません。これは以下のようにカスタムバリデーターを追加することができます。データフィールドに注釈を付けるためのカスタムアノテーションを作成します。

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
public @interface GoodPassword {
    String message() default "Passwords wont match.";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

検証ロジックを適用するためのValidatorクラスを記述します。

public class PastValidator implements ConstraintValidator<GoodPassword, User> {
    @Override
    public void initialize(GoodPassword annotation) {}
    
    @Override
    public boolean isValid(User user, ConstraintValidatorContext context) {
        return user.getPassword().equals(user.getPassword2());
    }
}

この検証をユーザークラスに追加する

@GoodPassword
public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String username;
    
    @NotEmpty
    private String password;
    
    @NotEmpty
    private String password2;
}

@ValidはSpringの検証をトリガします。 BindingResultは、検証後にエラーのリストを持つSpringによって挿入されたオブジェクトです。

public String registerUser(@Valid User user, BindingResult result);

JSR 303アノテーションには、カスタムメッセージを提供するために使用できるメッセージ属性があります。

@GoodPassword
public class User {

    @NotEmpty(message="Username Cant be empty")
    @Size(min=5, message="Username cant be les than 5 chars")
    @Email(message="Should be in email format")
    private String username;
    
    @NotEmpty(message="Password cant be empty")
    private String password;
    
    @NotEmpty(message="Password2 cant be empty")
    private String password2;

}

Spring JSR 303 Validation - エラーメッセージのカスタマイズ

検証アノテーションを持つシンプルなクラスがあるとします

public class UserDTO {
    @NotEmpty
    private String name;

    @Min(18)
    private int age;

//getters/setters
}

UserDTOの有効性をチェックするコントローラ。

@RestController
public class ValidationController {

    @RequestMapping(value = "/validate", method = RequestMethod.POST)
    public ResponseEntity<String> check(@Valid @RequestBody UserDTO userDTO,
           BindingResult bindingResult) {
        return new ResponseEntity<>("ok" , HttpStatus.OK);
    }
}

そして、テスト。

@Test
public void testValid() throws Exception {
    TestRestTemplate template = new TestRestTemplate();
    String url = base + contextPath + "/validate";
    Map<String, Object> params = new HashMap<>();
    params.put("name", "");
    params.put("age", "10");

    MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
    headers.add("Content-Type", "application/json");

    HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);
    String res = template.postForObject(url, request, String.class);

    assertThat(res, equalTo("ok"));
}

名前と年齢の両方が無効なので、BindingResultには2つの検証エラーがあります。それぞれにはコードの配列があります。

最小チェックのコード

0 = "Min.userDTO.age"
1 = "Min.age"
2 = "Min.int"
3 = "Min"

NotEmptyチェック

0 = "NotEmpty.userDTO.name"
1 = "NotEmpty.name"
2 = "NotEmpty.java.lang.String"
3 = "NotEmpty"

デフォルトのメッセージを置き換えるcustom.propertiesファイルを追加しましょう。

@SpringBootApplication
@Configuration
public class DemoApplication {

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
        bean.setBasename("classpath:custom");
        bean.setDefaultEncoding("UTF-8");
        return bean;
    }

    @Bean(name = "validator")
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

custom.propertiesファイルに行を追加すると

NotEmpty=The field must not be empty!

エラーの新しい値が表示されます。メッセージバリデーターを解決するには、最初からコードを探し、適切なメッセージを探します。

したがって、 @NotEmptyアノテーションが使用されているすべてのケースで.propertiesファイルにNotEmptyキーを定義すると、メッセージが適用されます。

メッセージを定義すると

Min.int=Some custom message here.

整数値にminチェックを適用するすべての注釈は、新しく定義されたメッセージを使用します。

検証エラーメッセージをローカライズする必要がある場合は、同じロジックを適用できます。

ネストされたPOJOを検証するための@有効な使用法

検証する必要があるPOJOクラスのユーザーがいるとします。

public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String email;
}

ユーザーインスタンスを検証するコントローラメソッド

public String registerUser(@Valid User user, BindingResult result);

検証する必要のあるPOJOネストされたPOJOアドレスをユーザーに拡張しましょう。

public class Address {

    @NotEmpty
    @Size(min=2, max=3)
    private String countryCode;
}

ネストされたPOJOの検証を実行するために、アドレスフィールドに@Validアノテーションを追加するだけです。

public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String email;

    @Valid
    private Address address;
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow