我正在使用Spring MVC 4.1为restful 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) {
...
}
问题:如果验证失败,验证器会抛出由@ExceptionHandler处理的MultiodArgumentNotValidExc0019
,它会向客户端返回错误响应,永远不会触发我的@之前
,因此绕过速率限制。
如何以优先于参数校验的方式拦截这样的Web请求?
我曾想过使用Spring拦截器或普通servlet过滤器,但它们是通过简单的url模式映射的,我需要通过GET/POST/PUT/etc进行区分。
看看是否可以为@posthrowing建议实现类似的逻辑,这些建议将具有类似的切入点。
我最终放弃了寻找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);
}
}
}
}
我的rest控制器包含以下post映射: ServiceExceptionn是特定于我的应用程序的自定义异常。 控制器建议如下所示: 应用yml包含以下属性: 如果我使用大小大于2MB的文件调用rest api,则会出现以下异常: 我在这里面临的问题是:控制器的建议没有按照预期工作。handleFileTooLargeException-必须执行此方法,因为它使用特定异常类型中提到的Excepti
问题内容: 我试图在带注释的控制器之后使用AOP进行一些处理。一切都在正常运行,但没有执行建议。 这是控制器代码: 以及在application-config中的设置 和实际的建议 甚至可以对带注释的控制器提出建议吗?我正在使用Spring 2.5。 问题答案: 我假设你想在用注释的类中执行所有方法后提出建议@Controller。 这是一个例子: 如果你想将Spring AOP与AspectJ语
我的Spring Boot应用程序中有一系列Rest API控制器,其请求映射与某些URL匹配。我需要更改我的实现,以始终确保为所有请求设置特定的自定义标头。如果标头不在那里,我想使请求失败。如果是这样,我想转发到适当的控制器,这将与我当前的实现相同。 有没有办法在Spring Boot做到这一点,而无需修改我现有的控制器呢?我可以尝试使用类似Spring Security的东西吗,即使我的头与安
需要注释处理器的帮助。我创建了一个简单的注释处理器,它使用@autoservice注释来检查注释的字段是否为最终字段。但它没有显示任何编译时错误。这是我的配置 注释: 注释处理器: pom文件: 测试文件:
在我尝试构建我的项目后,我得到以下错误: 我尝试在每个之后添加,但没有成功消除错误。 这是在将Android Studio升级到最新版本 ( 3.0 ) 之后发生的。 编辑: 在中添加 无济于事: 有什么解决方案吗?
我有以下问题: 我已经为安全性创建了注释: 在我具有类之间的继承性的情况下,是否也有可能所有类都具有@Security注释来获得最具体的定义? 约西