当前位置: 首页 > 面试题库 >

建议控制器方法*之前*处理@Valid注释

印辉
2023-03-14
问题内容

我正在使用Spring MVC 4.1向宁静的Web服务添加速率限制。

我创建了@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,该会向客户端返回错误响应,从不触发my
@Before,因此绕过了速率限制。

如何以优先于参数验证的方式拦截这样的Web请求?

我曾经考虑过使用Spring Interceptor或普通的Servlet过滤器,但是它们是通过简单的url模式映射的,我需要通过GET / POST /
PUT / etc进行区分。


问题答案:

我最终放弃了尝试寻找AOP解决方案的方法,而是创建了一个Spring
Interceptor。拦截器将处理preHandle所有请求,并监视其处理程序为的请求@RateLimited

@Component
public class RateLimitingInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private final RateLimitService rateLimitService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (HandlerMethod.class.isAssignableFrom(handler.getClass())) {
            rateLimit(request, (HandlerMethod)handler);
        }
        return super.preHandle(request, response, handler);
    }

    private void rateLimit(HttpServletRequest request, HandlerMethod handlerMethod) throws TooManyRequestsException {

        if (handlerMethod.getMethodAnnotation(RateLimited.class) != null) {
            String ip = request.getRemoteAddr();
            int secondsToWait = rateLimitService.secondsUntilNextAllowedInvocation(ip);
            if (secondsToWait > 0) {
                throw new TooManyRequestsException(secondsToWait);
            } else {
                rateLimitService.recordInvocation(ip);
            }
        }
    }
}


 类似资料:
  • 我正在使用Spring MVC 4.1为restful Web服务添加速率限制。 我创建了一个注释,可以应用于控制器方法。Spring AOP方面会拦截对这些方法的调用,并在请求过多时引发异常: 这一切都非常有效,除非控制器方法的参数标记为,例如: 问题:如果验证失败,验证器会抛出由@ExceptionHandler处理的,它会向客户端返回错误响应,永远不会触发我的,因此绕过速率限制。 如何以优先

  • 我的rest控制器包含以下post映射: ServiceExceptionn是特定于我的应用程序的自定义异常。 控制器建议如下所示: 应用yml包含以下属性: 如果我使用大小大于2MB的文件调用rest api,则会出现以下异常: 我在这里面临的问题是:控制器的建议没有按照预期工作。handleFileTooLargeException-必须执行此方法,因为它使用特定异常类型中提到的Excepti

  • 问题内容: 我试图在带注释的控制器之后使用AOP进行一些处理。一切都在正常运行,但没有执行建议。 这是控制器代码: 以及在application-config中的设置 和实际的建议 甚至可以对带注释的控制器提出建议吗?我正在使用Spring 2.5。 问题答案: 我假设你想在用注释的类中执行所有方法后提出建议@Controller。 这是一个例子: 如果你想将Spring AOP与AspectJ语

  • 我正在开发一个Spring应用程序,并在HandlerInterceptorAdapter的预处理()方法中对用户进行身份验证,如果用户进行了身份验证,我将如下设置请求属性: 如果用户未通过身份验证,我是这样设置的 然后在稍后的控制器方法中,我用HttpServletRequest检索用户,如下所示: 问题是我需要在每个控制器方法中接收HttpServletRequest,以检查用户是否经过身份验

  • 我的Spring Boot应用程序中有一系列Rest API控制器,其请求映射与某些URL匹配。我需要更改我的实现,以始终确保为所有请求设置特定的自定义标头。如果标头不在那里,我想使请求失败。如果是这样,我想转发到适当的控制器,这将与我当前的实现相同。 有没有办法在Spring Boot做到这一点,而无需修改我现有的控制器呢?我可以尝试使用类似Spring Security的东西吗,即使我的头与安

  • 根据请求主体中的session_type,我必须将请求映射到特定的POJO(JSON->JAVA POJO)。 例如,如果请求正文中的'session_type'是'typeX',那么请求应该映射到ClassX POJO。如果请求正文中的“session_type”是“type y”,那么请求应该映射到ClassY POJO。 如果有一种方法可以使用某种requestbody注释来完成它呢?

  • 我在spring boot 1.5.3中有rest api应用程序,我使用安全性登录并通过令牌对我的api验证每个请求。我想添加我的自定义异常与未经授权的异常时,用户没有找到由令牌。类添加了异常,但每个响应都有500个代码,但我想要401个响应代码。Belowe是我的密码。 StateLessAuthenticationFilter StateLessLoginFilter MyOwnExcept

  • 在我添加了一个Spring Security过滤器后,这就停止工作了。 部署应用程序时,映射按预期配置 提交GET请求。 请求参数是由ExtJS添加的,这不是一个问题,因为它在没有安全性的情况下工作。