Implementing a Custom AccessLimit Annotation and Interceptor for Rate Limiting in Spring Boot
This article demonstrates how to create a Java annotation for access limiting, implement the corresponding Spring Boot interceptor that checks Redis counters, register the interceptor in the application, and apply the annotation to a controller method to enforce request rate limits.
The author, a Java architect, introduces a practical tutorial on building a custom rate‑limiting mechanism for Spring Boot applications using a user‑defined annotation and an interceptor.
Step 1 – Define the annotation:
import java.lang.annotation.Retention;<br/>import java.lang.annotation.Target;<br/><br/>import static java.lang.annotation.ElementType.METHOD;<br/>import static java.lang.annotation.RetentionPolicy.RUNTIME;<br/><br/>@Retention(RUNTIME)<br/>@Target(METHOD)<br/>public @interface AccessLimit {<br/> int seconds();<br/> int maxCount();<br/> boolean needLogin() default true;<br/>}Step 2 – Implement the interceptor that reads the annotation, checks login status, and uses Redis to count requests:
import com.alibaba.fastjson.JSON;<br/>import com.example.demo.action.AccessLimit;<br/>import com.example.demo.redis.RedisService;<br/>import com.example.demo.result.CodeMsg;<br/>import com.example.demo.result.Result;<br/>import org.springframework.beans.factory.annotation.Autowired;<br/>import org.springframework.stereotype.Component;<br/>import org.springframework.web.method.HandlerMethod;<br/>import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;<br/><br/>import javax.servlet.http.HttpServletRequest;<br/>import javax.servlet.http.HttpServletResponse;<br/>import java.io.OutputStream;<br/><br/>@Component<br/>public class FangshuaInterceptor extends HandlerInterceptorAdapter {<br/><br/> @Autowired<br/> private RedisService redisService;<br/><br/> @Override<br/> public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {<br/> if (handler instanceof HandlerMethod) {<br/> HandlerMethod hm = (HandlerMethod) handler;<br/> AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);<br/> if (accessLimit == null) {<br/> return true;<br/> }<br/> int seconds = accessLimit.seconds();<br/> int maxCount = accessLimit.maxCount();<br/> boolean login = accessLimit.needLogin();<br/> String key = request.getRequestURI();<br/> if (login) {<br/> // In a real project, obtain the user ID from the session<br/> key += "" + "1"; // placeholder user ID<br/> }<br/> AccessKey ak = AccessKey.withExpire(seconds);<br/> Integer count = redisService.get(ak, key, Integer.class);<br/> if (count == null) {<br/> redisService.set(ak, key, 1);<br/> } else if (count < maxCount) {<br/> redisService.incr(ak, key);<br/> } else {<br/> render(response, CodeMsg.ACCESS_LIMIT_REACHED);<br/> return false;<br/> }<br/> }<br/> return true;<br/> }<br/><br/> private void render(HttpServletResponse response, CodeMsg cm) throws Exception {<br/> response.setContentType("application/json;charset=UTF-8");<br/> OutputStream out = response.getOutputStream();<br/> String str = JSON.toJSONString(Result.error(cm));<br/> out.write(str.getBytes("UTF-8"));<br/> out.flush();<br/> out.close();<br/> }<br/>}Step 3 – Register the interceptor in Spring Boot configuration:
import com.example.demo.ExceptionHander.FangshuaInterceptor;<br/>import org.springframework.beans.factory.annotation.Autowired;<br/>import org.springframework.context.annotation.Configuration;<br/>import org.springframework.web.servlet.config.annotation.InterceptorRegistry;<br/>import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;<br/><br/>@Configuration<br/>public class WebConfig extends WebMvcConfigurerAdapter {<br/><br/> @Autowired<br/> private FangshuaInterceptor interceptor;<br/><br/> @Override<br/> public void addInterceptors(InterceptorRegistry registry) {<br/> registry.addInterceptor(interceptor);<br/> }<br/>}Step 4 – Apply the annotation to a controller method to enforce the limit:
import com.example.demo.result.Result;<br/>import org.springframework.stereotype.Controller;<br/>import org.springframework.web.bind.annotation.RequestMapping;<br/>import org.springframework.web.bind.annotation.ResponseBody;<br/><br/>@Controller<br/>public class FangshuaController {<br/><br/> @AccessLimit(seconds = 5, maxCount = 5, needLogin = true)<br/> @RequestMapping("/fangshua")<br/> @ResponseBody<br/> public Result<String> fangshua() {<br/> return Result.success("请求成功");<br/> }<br/>}The article concludes with a brief invitation to share the tutorial and join a community of architects for further learning.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
