我有一个Spring启动应用程序服务一些REST端点。我正在尝试围绕过滤器,分页,排序等创建一些可重用的逻辑。
对于PagingInfoDto对象,我正在包装限制和偏移请求参数。
我正在做一些bean验证,以确保限制和偏移满足一些cusomt规则。
当我像这样实现它时,一切正常:
控制器:
@RequestMapping(value = "/somevalue", method = RequestMethod.GET)
public ResponseEntity<Object> list (
@Valid PagingInfoDto pagingInfoDto){
PagingInfoDto:
@Paging(limitDefault = 2)
public class PagingInfoDto
{
private boolean hasMore;
private Integer offset;
private Integer limit;
public Integer getOffset() {
return offset;
}
public void setOffset(Integer offset) {
this.offset = offset;
}
public Integer getLimit() {
return limit;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
public boolean isHasMore()
{
return hasMore;
}
public void setHasMore(boolean hasMore)
{
this.hasMore = hasMore;
}
}
PagingRequestFiltervalidator:
public class PagingRequestFilterValidator implements ConstraintValidator<Paging, PagingRequestFilterDto> {
private static final String MISSING_OFFSET = "offset cannot appear without limit";
private static final String ZERO_LIMIT = "limit cannot be 0";
private static final String MISSING_LIMIT = "limit cannot appear without offset";
private int limit = 0;
@Override
public void initialize(Paging paging) {
this.limit = paging.limitDefault();
}
@Override
public boolean isValid(PagingRequestFilterDto pagingRequestFilterDto, ConstraintValidatorContext constraintValidatorContext) {
boolean validity = true;
constraintValidatorContext.disableDefaultConstraintViolation();
/**
* Offset has to be greater than or equal to Zero
*/
if(pagingRequestFilterDto.getOffset() == null) {
pagingRequestFilterDto.setOffset(0);
}
/**
* Set undefined or invalid limit to default to value from the annotation
*/
if(pagingRequestFilterDto.getLimit() == null
|| pagingRequestFilterDto.getLimit() > limit) {
pagingRequestFilterDto.setLimit(limit);
}
分页注释:
@Constraint(validatedBy = {PagingRequestFilterValidator.class})
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Paging {
String message() default "Invalid Paging Details";
int limitDefault() default 20;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
我希望能够做的是使用@Paging Custom Constraint注释参数PagingInfoDto参数,以便每个端点都可以设置它自己的limitDefault。
像这样:
@RequestMapping(value = "/somevalue", method = RequestMethod.GET)
public ResponseEntity<Object> list (
**@Paging(limitDefault = 2)** PagingInfoDto pagingInfoDto){ ...
@RequestMapping(value = "/someothervalue", method = RequestMethod.GET)
public ResponseEntity<Object> otherlist (
**@Paging(limitDefault = 5)** PagingInfoDto pagingInfoDto){...
以上内容不会激活对象的验证。我觉得这很简单,因为我错过了一些非常明显的东西......
我发现了一篇博文,似乎表明您需要实现自定义Bean验证器:
http://blog.trifork.com/2009/08/04/bean-validation-integrating-jsr-303-with-spring/
我的实施
@Component
public class BeanValidator implements org.springframework.validation.Validator, InitializingBean {
private Validator validator;
public void afterPropertiesSet() throws Exception {
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
validator = validatorFactory.usingContext().getValidator();
}
public boolean supports(Class clazz) {
return true;
}
public void validate(Object target, Errors errors) {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(target);
for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
String propertyPath = constraintViolation.getPropertyPath().toString();
String message = constraintViolation.getMessage();
errors.rejectValue(propertyPath, "", message);
}
}
}
仍然没有运气。