посоветуйте метод контроллера * перед обработкой * @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.