2015-12-01 16 views
5
私が持っている

春の検証

アンエンティティ:エンティティの

package org.ibp.soq; 

public class MyEntity { 

    private String field1; 
    private String field2; 

    //..getters and setters 

} 

バリ:

package org.ibp.soq; 

import org.springframework.stereotype.Component; 
import org.springframework.validation.Errors; 
import org.springframework.validation.Validator; 

@Component 
public class MyEntityValidator implements Validator { 

    @Override 
    public boolean supports(Class<?> clazz) { 
     return MyEntity.class.equals(clazz); 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     MyEntity myEntity = (MyEntity) target; 
     // Logic to validate my entity 
     System.out.print(myEntity); 
    } 

} 

バルクPUTメソッドでRESTコントローラ:私は、次のリクエストボディと、このリソースに対してPUT要求を行う

package org.ibp.soq; 

import java.util.List; 

import javax.validation.Valid; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.WebDataBinder; 
import org.springframework.web.bind.annotation.InitBinder; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RestController; 

@RestController 
@RequestMapping("/myEntity") 
public class MyEntityRestResource { 

    @Autowired 
    private MyEntityValidator myEntityValidator; 

    @InitBinder 
    protected void initBinder(final WebDataBinder binder) { 
     binder.addValidators(this.myEntityValidator); 
    } 

    @RequestMapping(method = RequestMethod.PUT) 
    public void bulkCreate(@RequestBody @Valid List<MyEntity> myEntities) { 
     // Logic to bulk create entities here. 
     System.out.print(myEntities); 
    } 
} 

[ 
    { 
    "field1": "AA", 
    "field2": "11" 
    }, 

    { 
    "field1": "BB", 
    "field2": "22" 
    } 
] 

私が手にエラーがある:

"Invalid target for Validator [[email protected]]: [[email protected], [email protected]]" 

これは、MyEntityValidatorが「」を有効としているため、有効ではありません。 ArrayList<MyEntity>の場合

MyEntityValidatorは、@RequestBody @Valid MyEntity myEntityというパラメータを持つリクエストボディにMyEntityオブジェクトと対応するコントローラメソッドがあると完全に機能します。

私が使用したバリデーターの設定は、MyEntityのコレクションの検証をサポートするためにどのように拡張できますか?

答えて

1

あなたが推測したように、これはSpring検証を使用して達成することはできません。 Spring検証では、オブジェクト検証とは対照的に、Bean検証(JSR 303/349)が実装されています。残念ながら、コレクションはJava Beanではありません。あなたは、Java Beanが内部に二つのオプション

  • あなたのリストをラップ
  • 方法myEntityValidator. validate(targetObject, errors)を作成一括で手動でバリデータを呼び出しています。
10

ソリューションはWebDataBindersValidatorことを登録するCollectionのカスタムValidator@ControllerAdviceを作成することです。

バリ:

import java.util.Collection; 

import org.springframework.validation.Errors; 
import org.springframework.validation.ValidationUtils; 
import org.springframework.validation.Validator; 
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 

/** 
* Spring {@link Validator} that iterates over the elements of a 
* {@link Collection} and run the validation process for each of them 
* individually. 
* 
* @author DISID CORPORATION S.L. (www.disid.com) 
*/ 
public class CollectionValidator implements Validator { 

    private final Validator validator; 

    public CollectionValidator(LocalValidatorFactoryBean validatorFactory) { 
    this.validator = validatorFactory; 
    } 

    @Override 
    public boolean supports(Class<?> clazz) { 
    return Collection.class.isAssignableFrom(clazz); 
    } 

    /** 
    * Validate each element inside the supplied {@link Collection}. 
    * 
    * The supplied errors instance is used to report the validation errors. 
    * 
    * @param target the collection that is to be validated 
    * @param errors contextual state about the validation process 
    */ 
    @Override 
    @SuppressWarnings("rawtypes") 
    public void validate(Object target, Errors errors) { 
    Collection collection = (Collection) target; 
    for (Object object : collection) { 
     ValidationUtils.invokeValidator(validator, object, errors); 
    } 
    } 
} 

ControllerAdvice:

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 
import org.springframework.web.bind.WebDataBinder; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.InitBinder; 

/** 
* Controller advice that adds the {@link CollectionValidator} to the 
* {@link WebDataBinder}. 
* 
* @author DISID CORPORATION S.L. (www.disid.com) 
*/ 
@ControllerAdvice 
public class ValidatorAdvice { 

    @Autowired 
    protected LocalValidatorFactoryBean validator; 


    /** 
    * Adds the {@link CollectionValidator} to the supplied 
    * {@link WebDataBinder} 
    * 
    * @param binder web data binder. 
    */ 
    @InitBinder 
    public void initBinder(WebDataBinder binder) { 
    binder.addValidators(new CollectionValidator(validator)); 
    } 
} 
+0

ありがとうございました!私は確かにこのアプローチを試してみます。 –

+2

\ @ControllerAdviceを使用すると、すべてのコントローラにCollectionValidatorが適用されます。非コレクションオブジェクトに別の\ @Validアノテーションがある場合、 "java.lang.IllegalStateException:Validator for Validator for target"例外が発生します。 –

+0

代わりに\ @InitBinder( "attrName")を使用するか、特定のコントローラでinitBinderを実行してください。 –

0

実際、これは春検証とJSR303を使用して達成することができます。

  • MethodValidationPostProcessor Beanを公開します。
  • コントローラクラスに@Validated(org.springframework.validation.annotation。検証済み)
  • MyEntityフィールド/メソッドでJSR303検証アノテーションを使用します。
  • @ValidでRequestBody引数に注釈を付けます(これはすでにあなたの例で行っています)。
  • MethodArgumentNotValidExceptionを処理するための@ExceptionHandlerメソッドを追加します。これはコントローラまたは@ControllerAdviceクラスで行うことができます。
関連する問題