英文:
Implementatio of mutliple ConstraintValidator and their priority (enable/disable by requests endpoint)
问题
以下是翻译好的部分:
让我们假设我有一个具有两个需要验证的字段的对象:
public class AnyRQ {
@MerchantAccountValidation
@JsonProperty(value = "merchant-account")
private MerchantAccount merchantAccount;
@RequestIdValidation
@JsonProperty(value = "request-id")
private String requestId;
}
两个注解@MerchantAccountValidation和@RequestIdValidation都实现了ConstraintValidator,并包括要验证的规则(只显示一个类):
public class RequestIdValidator
implements ConstraintValidator<RequestIdValidation, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && value.length() > 10;
}
}
现在我有一个具有两个端点的控制器。端点1应验证两个字段,但端点2应仅验证requestId。
@RestController
@RequestMapping("/validate")
public class ValidController {
@PostMapping("/endpoint1")
public ResponseEntity<?> register(@Valid @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
@PostMapping("/endpoint2")
public ResponseEntity<?> authorization(@Valid @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
}
有没有办法实现一种优先级或继承来使其工作?我考虑在端点的方法级别上添加验证注解。但不幸的是,这并不起作用。
英文:
Lets say I have an Object with two fields which should be validated:
public class AnyRQ {
@MerchantAccountValidation
@JsonProperty(value = "merchant-account")
private MerchantAccount merchantAccount;
@RequestIdValidation
@JsonProperty(value = "request-id")
private String requestId;
}
Both of the Annotations @MerchantAccountValidation
and @RequestIdValidation
implements a ConstraintValidator
and including the rules to be valid or not. (Just show one class)
public class RequestIdValidator
implements ConstraintValidator<RequestIdValidation, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && value.length() > 10;
}
}
Now I have a Controller with two endpoints. Endpoint 1 should validate both Fields but Request 2 should just validate requestId
.
@RestController
@RequestMapping("/validate")
public class ValidController {
@PostMapping("/endpoint1")
public ResponseEntity<?> register(@Valid @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
@PostMapping("/endpoint2")
public ResponseEntity<?> authorization(@Valid @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
}
Is there any way to achive a kind of priority or inheritance to get this working? I was thinking about to have the Validation Annotation on the method level of the endpoints. But unfortunately this is not working.
答案1
得分: 1
Patrick!
要实现所需的结果,您可以使用@GroupSequence。它主要用于排序验证(如果id为null,无需检查实体是否存在于数据库中,例如),但对于您的任务也可以工作。
假设您有2个验证组(最好取一个更合适的名称):
public interface InitialValidation {
}
@GroupSequence(InitialValidation.class)
public interface InitialValidationGroup {
}
public interface FullValidation {
}
@GroupSequence(FullValidation.class)
public interface FullValidationGroup {
}
在DTO中指定它们:
public class AnyRQ {
@MerchantAccountValidation(groups = FullValidation.class)
@JsonProperty(value = "merchant-account")
private MerchantAccount merchantAccount;
@RequestIdValidation(groups = {InitialValidation.class, FullValidation.class})
@JsonProperty(value = "request-id")
private String requestId;
}
在控制器中使用@Validated而不是@Valid来提供相应的组:
@RestController
@RequestMapping("/validate")
public class ValidController {
@PostMapping("/endpoint1")
public ResponseEntity<?> register(@Validated(FullValidationGroup.class) @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
@PostMapping("/endpoint2")
public ResponseEntity<?> authorization(@Validated(InitialValidationGroup.class) @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
}
另一种选项是在DTO中保留一个组,但在控制器中为@Validated指定两个组。
英文:
Patrick!
To achieve the desired outcome you can use @GroupSequence. It mostly meant for ordering validations (no need to check that entity exists in database, if id is null f.e.), but would work for your task.
Let's say you have 2 validation groups (better names are required ):
public interface InitialValidation {
}
@GroupSequence(InitialValidation.class)
public interface InitialValidationGroup {
}
public interface FullValidation {
}
@GroupSequence(FullValidation.class)
public interface FullValidationGroup {
}
Specify them in the DTO:
public class AnyRQ {
@MerchantAccountValidation(groups = FullValidation.class)
@JsonProperty(value = "merchant-account")
private MerchantAccount merchantAccount;
@RequestIdValidation(groups = {InitialValidation.class, FullValidation.class})
@JsonProperty(value = "request-id")
private String requestId;
}
And in the controller use @Validated instead of @Valid to provide corresponding group:
@RestController
@RequestMapping("/validate")
public class ValidController {
@PostMapping("/endpoint1")
public ResponseEntity<?> register(@Validated(FullValidationGroup.class) @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
@PostMapping("/endpoint2")
public ResponseEntity<?> authorization(@Validated(InitialValidationGroup.class) @RequestBody AnyRQ req, Errors errors) {
if (errors.hasErrors()) {
}
return null;
}
}
The other option is to keep one group in DTO, but specify two groups in controller for @Validated.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论