@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyValidatorAnnotation.MyValidator.class)
public @interface MyValidatorAnnotation {
String message() default "not a valid DTO";
Class<? extends Payload>[] payload() default {};
Class<?>[] groups() default {};
// I have created this validator as interface's inner class to
// to keep code simpler but it can be "outer" class also.
@Component // this is not necessarily needed
class MyValidator
implements ConstraintValidator<MyValidatorAnnotation, MyDto> {
@Resource
private MyRepository myRepository;
@Override
public boolean isValid(MyDto myDto, ConstraintValidatorContext context) {
boolean valid = true;
// If you need some custom messages, try something like:
context.disableDefaultConstraintViolation();
if (StringUtils.isBlank(myDto.getName())) {
context.buildConstraintViolationWithTemplate("NAME WAS BLANK")
.addPropertyNode("name")
.addConstraintViolation();
valid = false;
}
// Any checks you need to do with myRepository
// or with any other resources
return valid;
}
}
}
那么使用/触发这个验证依赖于几件事。请参见下面的服务示例:
@Service
@Validated
public class MyService {
// In this method validation will not work if called from MyService itself.
// Works only when called from "outside" so from any other managed bean
public void handleMyDtoExt(@Valid MyDto myDto) {
// furious handling
}
// Works when called anywhere even from service itself.
// The drawback is that you need more code & injection & testing which you of
// course want to avoid.
// In this case you also might not want add @Validated to your service.
@Resource
private Validator validator;
private void handleMyDto(MyDto myDto) {
Set<ConstraintViolation<MyDto>> cvs = validator.validate(myDto);
if(!cvs.isEmpty()) {
throw new ConstraintViolationException(cvs);
}
// furious handling
}
}
1条答案
按热度按时间t3psigkw1#
我会坚持使用验证注解和constraintviolationexception来保持代码和验证尽可能简单。
有许多选项取决于您计划如何进行验证,但在类似的情况下,我使用的方法是创建一个注解和一个验证器,就像controller中的任何验证注解一样使用。
验证内容如下所示:
那么使用/触发这个验证依赖于几件事。请参见下面的服务示例: