将自定义参数传递给 ConstraintValidator
Pass custom parameter to ConstraintValidator
我正在开发这个 springboot 应用程序,我需要对从 http 调用传递的值进行一些验证,我正在使用 class 级别验证 as explained here.
我正在使用这样的想法:
@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> {
在 class ValidRequestValidator 中,我实现了 ConstraintValidator 接口,我需要检查数据库中是否有另一个 Event 实体在字段日期上满足某些条件。当我想创建一个新实体时很简单,我执行一个查询,但是当我需要更新时我需要排除我当前正在尝试更新的实体。
有没有办法将 entityId 参数传递给@ValidRequest 自定义验证器?
我知道一种方法是将字段 entityId 添加到 class EventRequest,但我想保持这种分离,因为 entityId 来自查询参数。
感谢您的帮助!
除了 field-specific(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,以使方法验证器自动工作。
用法示例:
- 混合使用,
@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();
}
}
对于create
方法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
。
可能只有一个 method-level 验证就足以解决您的问题。我描述了所有变体,仅供参考可能会有用。
我正在开发这个 springboot 应用程序,我需要对从 http 调用传递的值进行一些验证,我正在使用 class 级别验证 as explained here.
我正在使用这样的想法:
@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> {
在 class ValidRequestValidator 中,我实现了 ConstraintValidator 接口,我需要检查数据库中是否有另一个 Event 实体在字段日期上满足某些条件。当我想创建一个新实体时很简单,我执行一个查询,但是当我需要更新时我需要排除我当前正在尝试更新的实体。
有没有办法将 entityId 参数传递给@ValidRequest 自定义验证器? 我知道一种方法是将字段 entityId 添加到 class EventRequest,但我想保持这种分离,因为 entityId 来自查询参数。
感谢您的帮助!
除了 field-specific(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,以使方法验证器自动工作。
用法示例:
- 混合使用,
@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();
}
}
对于create
方法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
。
可能只有一个 method-level 验证就足以解决您的问题。我描述了所有变体,仅供参考可能会有用。