簡體   English   中英

為 @Valid 注釋提供一些值,並在 isValid() 方法中使用該值更改驗證

[英]Provide some value to @Valid annotation and using that value change validation in isValid() method

我在我的項目中使用兩個數據庫,並在驗證請求正文中提供的過濾器時,對於某些請求,我需要來自 db1 的驗證,而對於某些請求,我需要來自 db2 的驗證。 我在一個枚舉中映射了值及其對應的類型。 但是我如何確定必須為請求正文中提供的特定過濾器使用哪個映射。

下面是我的 controller 演示:

@PostMapping(path = "/v1/abc")
public PageableDto getAll{Something}(
            @RequestAttribute UserClaim userClaim,
            @Valid SearchParametersDto searchParametersDto,
            @RequestBody @Valid List<FilterDto> filters)  

這需要使用 DB1 進行驗證。

@PostMapping(path = "/v1/xyz")
    public PageableDto getAll{Something}(
            @RequestAttribute UserClaim userClaim,
            @Valid SearchParametersDto searchParametersDto,
            @RequestBody @Valid List<FilterDto> filters) 

這需要使用 DB2 進行驗證。

在 FilterDto class 中,我創建了注釋。

@Getter
@Setter
@FilterValidatorBehaviour
public class FilterDto {
    String name;
    String operation;
    String value;

    @JsonIgnore
    public DataBaseTypeObject getObjectWithFieldName(MappingEnum mapping) {
        //return get map with enum name map
        return mapping.getMappingMap().get(name);
    }
}

在注釋實現 class。 我已經覆蓋了 isValid 方法,如下所示。

@Override
    public boolean isValid(FilterDto filterDto, ConstraintValidatorContext ctx) {
       return filterDto.getValue().getClass().equals(
filterDto.getObjectWithFieldName(MappingEnum.DB1_MAPPING).getType()); 
   
 }

下面是 MappingEnum class:

@RequiredArgsConstructor
@Getter
public enum MappingEnum {

        DB1_MAPPING(Map.ofEntries(
                Map.entry("field1",new DB1Object("field1", String.class)),
                Map.entry("field2",new DB1Object("field2", String.class)),
                Map.entry("field3",new DB1Object("field3", String.class)),
                )),

        DB2_MAPPING(Map.ofEntries(
                Map.entry("field1",new DB2Object("field1", String.class)),
                Map.entry("field2",new DB2Object("field2", String.class)),
                Map.entry("field3",new DB2Object("field3", String.class)),
                )),


        private final Map<String, ? extends DataBaseTypeObject> mappingMap;

這里 DB1Object 和 DB2Object 是 DataBaseTypeObject 的子類。

在解決方案方向上的任何幫助都會有很大幫助?

一種可能的解決方案是將@FilterValidatorBehaviour注釋從FilterDto移動到 controller 本身。 缺點是因為您傳遞了一個列表,所以您必須重構驗證器以接受List<FilterDto>而不僅僅是一個FilterDto

好處是您可以將自定義屬性添加到@FilterValidatorBehaviour注釋。 例如,您可以創建一個包含MappingEnum的屬性:

@Documented
@Retention(RUNTIME)
@Target({PARAMETER}) // Make sure to set PARAMETER
@Constraint(validatedBy = FilterValidatorBehaviourValidator.class)
public @interface FilterValidatorBehaviour {
    MappingEnum value(); // Add this
    String message() default "{filterValidatorBehaviour}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}

要讀取此value屬性,您可以在ConstraintValidator中實現initialize()方法並將其設置為字段:

@Override
public void initialize(FilterValidatorBehaviour constraintAnnotation) {
    this.mappingEnum = constraintAnnotation.value(); // Read mappingEnum from annotation
}

現在您可以在isValid()方法中使用this.mappingEnum 確保不要忘記您必須將驗證器從ConstraintValidator<FilterValidatorBehaviour, FilterDto>重構為ConstraintValidator<FilterValidatorBehaviour, List<FilterDto>>

之后,您可以在 controller 中使用@FilterValidatorBehaviour(MappingEnum.DB1_MAPPING)@FilterValidatorBehaviour(MappingEnum.DB2_MAPPING) 例如:

@PostMapping(path = "/v1/abc")
public PageableDto getAll{Something}(
            @RequestAttribute UserClaim userClaim,
            @Valid SearchParametersDto searchParametersDto,
            // Add the @FilterValidatorBehaviour annotation
            @RequestBody @Valid @FilterValidatorBehaviour(MappingEnum.DB1_MAPPING) List<FilterDto> filters) {
    // TODO: implement
    return null;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM