Implementing Request Rate Limiting in Spring Boot with Custom Annotations

This article demonstrates how to create a Spring Boot request‑rate‑limiting solution using a custom @RequestLimit annotation, a Redis‑backed interceptor, and configuration classes, providing step‑by‑step code examples and usage instructions for both class‑level and method‑level protection.

Top Architect
Top Architect
Top Architect
Implementing Request Rate Limiting in Spring Boot with Custom Annotations

The article explains how to implement a request rate‑limiting mechanism in a Spring Boot application by defining a custom @RequestLimit annotation and an interceptor that checks request counts stored in Redis.

When a request arrives, the interceptor retrieves a key composed of the request path and session ID from Redis; if the count exceeds the configured maxCount within the defined second window, the request is rejected with a JSON error response.

Key code snippets include the definition of the @RequestLimit annotation, the RequestLimitIntercept interceptor, the WebMvcConfig class that registers the interceptor, and example controller methods demonstrating usage at class and method levels.

Annotation definition:

import java.lang.annotation.*;

/**
 * Request limit custom annotation
 */
@Documented
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {
    // maximum requests within the time window (seconds)
    int second() default 1;
    // maximum allowed request count
    int maxCount() default 1;
}

Interceptor implementation (simplified):

@Slf4j
@Component
public class RequestLimitIntercept extends HandlerInterceptorAdapter {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            Method method = hm.getMethod();
            RequestLimit rl = method.getAnnotation(RequestLimit.class);
            if (rl == null) {
                rl = method.getDeclaringClass().getAnnotation(RequestLimit.class);
            }
            if (rl != null && isLimit(request, rl)) {
                responseOut(response, Result.error(ApiResultEnum.REQUST_LIMIT));
                return false;
            }
        }
        return super.preHandle(request, response, handler);
    }

    private boolean isLimit(HttpServletRequest request, RequestLimit rl) {
        String limitKey = request.getServletPath() + request.getSession().getId();
        Integer count = (Integer) redisTemplate.opsForValue().get(limitKey);
        if (count == null) {
            redisTemplate.opsForValue().set(limitKey, 1, rl.second(), TimeUnit.SECONDS);
        } else {
            if (count >= rl.maxCount()) {
                return true;
            }
            redisTemplate.opsForValue().increment(limitKey);
        }
        return false;
    }

    private void responseOut(HttpServletResponse response, Result result) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = response.getWriter();
        out.append(JSONObject.toJSON(result).toString());
    }
}

To use the feature, annotate a controller class or method with @RequestLimit(maxCount = 5, second = 1), and the interceptor will enforce the limit automatically.

Full source code is available on Gitee (https://gitee.com/rstyro/spring-boot/tree/master/SpringBoot-limit) and GitHub (https://github.com/rstyro/Springboot/tree/master/SpringBoot-limit).

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaSpring BootInterceptor
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.