SoFunction
Updated on 2025-03-08

Three solutions for SpringBoot interface to prevent duplicate submissions

Preface

In web development, preventing users from submitting forms repeatedly is a common requirement. Users may click the submit button multiple times due to network delays, misoperation, etc., causing the background to receive multiple identical requests. This will not only waste server resources, but may also lead to problems such as data inconsistency. This article will introduce several methods to implement interface anti-repeated submission in Spring Boot.

Use the Token mechanism

The Token mechanism is a common anti-repetition method. The specific steps are as follows:
Generate token: Each time the user requests a form page, the server generates a unique token and stores it in the Session.
Pass token: Embed the token into the form and submit it with the form.
Verify token: After the server receives the request, it first verifyes whether the token is valid. If it is valid, continue to process the request and remove the token from the Session; if it is invalid, an error message is returned.

Implementation steps

1. Generate tokens

Generate tokens in Controller and store them in Session:

/**
 * form
 * @param session
 * @author senfel
 * @date 2024/11/12 11:29
 * @return 
 */
@GetMapping("/form")
public ModelAndView showForm(HttpSession session) {
    ModelAndView form = new ModelAndView("form");
    String token = ().toString();
    ("token", token);
    ("token", token);
    return form;
}

2. Pass token

Add hidden fields to the form to pass the token:

<form action="/base/submit" method="post">
    <input type="hidden" name="token" th:value="${token}">
    <!-- Other form fields -->
    <button type="submit">Submit</button>
</form>

3. Verify Token

Verify the token in Controller:

/**
 * handleForm
 * @param token
 * @param session
 * @author senfel
 * @date 2024/11/12 11:34
 * @return 
 */
@PostMapping("/submit")
public String handleForm(@RequestParam String token, HttpSession session) {
    String sessionToken = (String) ("token");
    if (sessionToken == null || !(token)) {
        throw new RuntimeException("Duplicate submit detected");
    }
    // Remove Token    ("token");
    // Process form data    return "success";
}

Using Redis

Redis is a high-performance key-value storage system that can be used to store and verify tokens. The specific steps are as follows:
Generate token: Each time the user requests a form page, the server generates a unique token and stores it in Redis.
Pass token: Embed the token into the form and submit it with the form.
Verify token: After the server receives the request, it first verifies whether the token exists in Redis. If it exists, continue to process the request and delete the token from Redis; if it does not exist, an error message is returned.

Implementation steps

1. Introduce Redis dependencies

Add Redis dependencies in :

<dependency>
   <groupId></groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. Generate tokens

Generate tokens in Controller and store them in Redis:

@Autowired
private StringRedisTemplate redisTemplate;

/**
 * formByRedis
 * @author senfel
 * @date 2024/11/12 11:50
 * @return 
 */
@GetMapping("/formByRedis")
public ModelAndView showFormByRedis() {
    ModelAndView form = new ModelAndView("form");
    String token = ().toString();
    // Set expiration time    ().set(token, token, 5, );
    ("token", token);
    return form;
}

3. Pass token

Add hidden fields to the form to pass the token:

&lt;form action="/base/submitByRedis" method="post"&gt;
    &lt;input type="hidden" name="token" th:value="${token}"&gt;
    &lt;!-- Other form fields --&gt;
    &lt;button type="submit"&gt;Submit&lt;/button&gt;
&lt;/form&gt;

4. Verify Token

Verify the token in Controller:

/**
 * submitByRedis
 * @param token
 * @author senfel
 * @date 2024/11/12 11:50
 * @return 
 */
@PostMapping("/submitByRedis")
public String handleFormByRedis(@RequestParam String token) {
    String redisToken = ().get(token);
    if (redisToken == null) {
        throw new RuntimeException("Duplicate submit detected");
    }
    // Delete Token    (token);
    // Process form data    return "success";
}

Using Spring AOP

Spring AOP (Aspect-Oriented Programming) can be used to implement aspect programming, thereby reusing the logic against repeated commits in multiple methods.

Implementation steps

1. Definition annotation

Create a custom annotation @PreventDuplicateSubmit:

import ;
import ;
import ;
import ;

/**
 * PreventDuplicateSubmit
 * @author senfel
 * @date 2024/11/12 11:56
 */
@Target()
@Retention()
public @interface PreventDuplicateSubmit {
    /**Repeat request time*/
    int expireSeconds() default 10;
}

2. Create a facet

Create a section class DuplicateSubmitAspect:

import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import org.;
import org.;
import ;
import ;
import ;
import ;
import ;

/**
 * DuplicateSubmitAspect
 * @author senfel
 * @version 1.0
 * @date 2024/11/12 11:57
 */
@Slf4j
@Aspect
@Component
public class DuplicateSubmitAspect {

    protected static final Logger logger = ();
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * around
     * @param joinPoint
     * @author senfel
     * @date 2024/11/12 15:45
     * @return 
     */
    @Around("@annotation()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        StringBuilder key = new StringBuilder();
        //Get class        String simpleName = ().getClass().getSimpleName();
        (simpleName);
        // Get the request method        MethodSignature signature=(MethodSignature)();
        Method method = ();
        String methodName = ();
        (":").append(methodName);
        //Get request parameters        Object[] args=();
        for (Object arg : args) {
            (":").append(());
        }
        //TODO Get client IP
        // Get annotation information        PreventDuplicateSubmit annotation = ();
        // Determine whether the request has been requested        if((())){
            throw new RuntimeException("Do not repeat submission");
        }
        //The mark request has been processed        ().set((),"1",(), );
        return ();
    }
}

3. Use annotations

Use @PreventDuplicateSubmit annotation on the Controller method:

/**
 * handleFormByAnnotation
 * @param param
 * @author senfel
 * @date 2024/11/12 11:59
 * @return 
 */
@PostMapping("/submitByAnnotation")
@PreventDuplicateSubmit
public String handleFormByAnnotation(@RequestParam String param) {
    // Process form data    return "success";
}

Summarize

This article introduces three ways to implement interface anti-repeated submission in Spring Boot: using the Token mechanism, using Redis, and using Spring AOP. Each method has its applicable scenarios and advantages and disadvantages, and you can choose the appropriate method according to actual needs. Through these methods, users can effectively prevent repeated submission of forms and improve system stability and user experience.

The above is the detailed content of the three solutions for SpringBoot interface anti-repeated submission. For more information about SpringBoot interface anti-repeated submission, please pay attention to my other related articles!