Implementing Idempotent API with Custom @RepeatSubmit Annotation in Spring
This article explains how to achieve API idempotency in high‑concurrency scenarios by creating a custom @RepeatSubmit annotation, using AOP interception, Redis setNx for locking, and a request‑wrapper to allow repeated reading of request parameters in Spring applications.
Idempotency ensures that multiple identical API calls produce the same result as a single call, preventing inconsistent states especially when users repeatedly click a button due to network latency. The article focuses on guaranteeing idempotency for low‑traffic endpoints (e.g., adding a patient) within a configurable time window, typically five seconds.
The solution introduces a custom annotation @RepeatSubmit that can be placed on create, update, or delete endpoints. When the annotation is present, an AOP aspect intercepts the request, extracts the URL, client IP, and request parameters, and builds a unique key.
The key is stored in Redis using the SETNX command with an expiration time. If the key is successfully set, the request proceeds; otherwise, an exception is thrown and handled by a global exception handler, returning a clear error message to the client.
AOP intercepts methods annotated with @RepeatSubmit.
Request URL, IP address, and parameters are collected.
The collected data is transformed into a unique Redis key.
Redis SETNX stores the key with a TTL (default 5 seconds).
If storage succeeds, the request is allowed; if it fails, an exception is raised.
A global exception handler returns a friendly response.
Reading request parameters poses a challenge because @RequestBody streams can be consumed only once. To solve this, the article wraps HttpServletRequest in a custom RepeatedlyRequestWrapper that caches the request body in a byte array, allowing multiple reads via overridden getReader and getInputStream methods.
A filter detects JSON requests, replaces the original HttpServletRequest with the wrapper, and passes the modified request down the filter chain, enabling the AOP aspect to access the body safely.
The final annotation implementation consists of defining com.code.ape.codeape.common.security.annotation.RepeatSubmit and an aspect class
com.code.ape.codeape.common.security.component.CodeapeRepeatSubmitAspect. The aspect contains the logic described above and checks whether the incoming request has been wrapped, ensuring correct handling of both form‑data and JSON payloads.
In summary, by adding @RepeatSubmit to non‑query endpoints, developers can prevent duplicate submissions within a short time window without altering business logic, leveraging AOP, Redis locking, and a request‑wrapper for reliable parameter access.
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.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
