посоветуйте метод контроллера * перед обработкой * @Valid аннотации

Я добавляю ограничение скорости в спокойный веб-сервис, используя Spring MVC 4.1.

Я создал@RateLimited аннотация, которую я могу применить к методам контроллера. Аспект Spring AOP перехватывает вызовы этих методов и выдает исключение, если было слишком много запросов:

@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RateLimitingAspect {

    @Autowired
    private RateLimitService rateLimitService;

    @Before("execution(* com.example..*.*(.., javax.servlet.ServletRequest+, ..)) " +
            "&& @annotation(com.example.RateLimited)")
    public void wait(JoinPoint jp) throws Throwable {

        ServletRequest request =
            Arrays
                .stream(jp.getArgs())
                .filter(Objects::nonNull)
                .filter(arg -> ServletRequest.class.isAssignableFrom(arg.getClass()))
                .map(ServletRequest.class::cast)
                .findFirst()
                .get();
        String ip = request.getRemoteAddr();
        int secondsToWait = rateLimitService.secondsUntilNextAllowedAttempt(ip);
        if (secondsToWait > 0) {
          throw new TooManyRequestsException(secondsToWait);
        }
    }

Это все работает отлично, кроме случаев, когда@RateLimited Метод контроллера имеет параметры, помеченные как@ValidНапример:

@RateLimited
@RequestMapping(method = RequestMethod.POST)
public HttpEntity<?> createAccount(
                           HttpServletRequest request,
                           @Valid @RequestBody CreateAccountRequestDto dto) {

...
}

Проблема: если проверка не удалась, валидатор выбрасываетMethodArgumentNotValidException, который обрабатывается@ExceptionHandler, который возвращает сообщение об ошибке клиенту, никогда не вызывая мой@Before и, следовательно, в обход ограничения скорости.

Как я могу перехватить такой веб-запрос таким образом, чтобы он имел приоритет над проверкой параметров?

Я думал об использовании Spring Interceptors или простых фильтров сервлетов, но они отображаются с помощью простых шаблонов url, и мне нужно различать их по GET / POST / PUT / etc.

Ответы на вопрос(2)

Ваш ответ на вопрос