传递自定义参数给ConstraintValidator



我正在研究这个springboot应用程序,其中我需要对从http调用传递的值进行一些验证,并且我使用这里解释的类级验证。

我用的是这样的:

@ValidRequest
public class EventRequest {
String date;
}
Response create(@Valid EventRequest request) {
..
}
Response update(Long entityId, @Valid EventRequest request) {
...
}
public class ValidRequestValidator 
implements ConstraintValidator<ValidRequest, EventRequest> {

在类ValidRequestValidator中,我实现了ConstraintValidator接口,我需要检查数据库中是否有另一个Event实体满足字段日期的某些条件。当我想创建一个新的实体很简单,我执行一个查询,但当我需要更新,我需要排除我目前试图更新的实体。

是否有一种方法传递entityId参数到@ValidRequest自定义验证器?我知道一种方法是添加字段entityId类EventRequest,但我想保持这种分离,因为entityId来自查询参数。

谢谢你的帮助!

除了特定字段(Single Parameter Constraint)之外,您还可以为整个方法(Cross-Parameter Constraint)实现约束。这将提供将某些方法的所有参数传递给验证器的能力。
注释定义:
注释使用两个验证器,可以应用于方法或类型。

@Constraint(validatedBy = {ValidRequestMethodValidator.class, ValidRequestTypeValidator.class})
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidRequest {
String message() default "Request is invalid!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;
}

约束验证器,将处理单个参数:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class ValidRequestTypeValidator implements ConstraintValidator<ValidRequest, EventRequest> {
@Override
public boolean isValid(EventRequest request, ConstraintValidatorContext constraintValidatorContext) {
// logic here
return false;
}
}

约束验证器,将处理特定方法的所有参数:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.constraintvalidation.SupportedValidationTarget;
import javax.validation.constraintvalidation.ValidationTarget;
@SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class ValidRequestMethodValidator implements ConstraintValidator<ValidRequest, Object[]> {
@Override
public boolean isValid(Object[] objects, ConstraintValidatorContext constraintValidatorContext) {
Long entityId = null;
EventRequest eventRequest = null;
if (objects[0] instanceof Long) {
entityId = (Long) objects[0];
}
if (objects[0] instanceof EventRequest) {
eventRequest = (EventRequest) objects[0];
}
if (objects[1] instanceof EventRequest) {
eventRequest = (EventRequest) objects[1];
}
//logic here
return false;
}
}

请注意,我们必须用@org.springframework.validation.annotation.Validated注释来注释要验证的bean,以使方法验证器自动工作。

用法示例:

  1. 混合使用,@ValidRequest注释在方法和单参数级别定义。
@ValidRequest
public class EventRequest {
public String value;
}
@RestController
@Validated
public class Controller {
Response create(@Valid EventRequest request) {
return new Response();
}
@ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response update(Long entityId, EventRequest request) {
return new Response();
}
}

Forcreate方法ValidRequestTypeValidator将被执行。
对于update方法,ValidRequestMethodValidator将被执行。


2。仅为方法

定义注释
@RestController
@Validated
public class Controller {
@ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response create(EventRequest request) {
return new Response();
}
@ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response update(Long entityId, EventRequest request) {
return new Response();
}
}

对于create方法,ValidRequestMethodValidator将使用一个元素对象数组执行
对于update方法ValidRequestMethodValidator将执行两个元素对象数组


3。同时为单个参数和方法定义注释

@ValidRequest
public class EventRequest {
public String value;
}
@RestController
@Validated
public class Controller {
@ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response update(Long entityId, @Valid EventRequest request) {
return new Response();
}
}

首先将执行单参数验证器ValidRequestTypeValidator
如果通过验证,则执行第二个方法验证器ValidRequestMethodValidator

可能只有一个方法级验证就足以处理您的问题。我描述了所有的变体,仅供参考,也许会有用。

最新更新