如何验证 Pageable 的大小?

Jin*_*won 6 spring pagination spring-mvc

我正在使用org.springframework.data.domain.Pageable和我的@RestController.

如何验证或限制页面大小?

没有任何验证,当客户使用sizeof调用时10000。实际pageSize2000

我认为,这可能会导致最后一页出现错误信号。

我如何验证它并通知客户?说400?

小智 6

您可以编写自定义注释来验证Pageable对象

@Constraint(validatedBy = PageableValidator.class)
@Target( { ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface PageableConstraint {
    String message() default "Invalid pagination";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    int maxPerPage() default 100;;
}
Run Code Online (Sandbox Code Playgroud)

及其实施

public class PageableValidator implements
        ConstraintValidator<PageableConstraint, Pageable> {

    private int maxPerPage;

    @Override
    public void initialize(PageableConstraint constraintAnnotation) {
        maxPerPage=constraintAnnotation.maxPerPage();
    }

    @Override
    public boolean isValid(Pageable value, ConstraintValidatorContext context) {
        return value.getPageSize()<=maxPerPage;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像任何其他 javax 验证注释一样在控制器上使用它。

@RestController
@RequestMapping("/api")
@Validated
public class EmployeeRestController {

    @Autowired
    private EmployeeService employeeService;

    @GetMapping("/employees")
    public List<Employee> getAllEmployees(@PageableConstraint(message = "Invalid page size",maxPerPage = 400) Pageable pageable) {
        return employeeService.getAllEmployees();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 当您有 1000 个端点实现分页时,这并不好,我们需要全局解决方案。 (2认同)

Sun*_*uri 1

尝试使用自定义注释来验证 Pageable 对象。如果它不起作用,请尝试如下所示的参数解析器。

您可以在扩展 WebMvcConfigurerAdapter 的 Spring 配置中创建参数解析器

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver() {

        @Override
        public Pageable resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer,
                NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
            Pageable p = super.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);
            if (webRequest.getParameter("per_page") != null) {
                int pageSize = Integer.parseInt(webRequest.getParameter("per_page"));
                if (pageSize < 1 || pageSize > 2000) {
                    message = "Invalid page size";
                }
            }
            if (message != null) {
                Set<CustomConstraintViolation> constraintViolations = new HashSet<>();
                constraintViolations.add(new CustomConstraintViolationImpl(message));
                throw new ConstraintViolationException(constraintViolations);
            }
            return new PageRequest(p.getPageNumber(), p.getPageSize());
        }
    };
    resolver.setMaxPageSize(2000);
    argumentResolvers.add(resolver);
    super.addArgumentResolvers(argumentResolvers);
}
Run Code Online (Sandbox Code Playgroud)

该解析器将确保控制器的每个请求的最大页面大小为 2000。

当大小超过 2000 时,您需要抛出 ConstraintViolationException。为此,您需要创建一个自定义 ConstraintViolation 接口并实现它

public CustomConstraintViolation implements ConstraintViolation<CustomConstraintViolation> {}

public CustomConstraintViolationImpl implements CustomConstraintViolation {

...

}
Run Code Online (Sandbox Code Playgroud)

  • 问题是如果用户请求超出最大页面大小:2000,如何验证 Pageable 对象并发送错误请求(400 http 状态代码)。 (2认同)