How does Spring Boot prevent duplicate submissions
How does Spring Boot prevent duplicate submissions
Scenario: The submission of the same URL by the same user within 2 seconds is considered as a duplicate submission.
Think logic:
1. From the perspective of the database
2. Considering from the application level, first judge whether it is a stand-alone service or a distributed service, then you need to consider some caches at this time, and use the caches to ensure the repeated submission of data.
Assuming it is a distributed application, you can assemble user information, such as token and requested url, and store it in a cache, such as redis, and set the timeout to 2 seconds to ensure the uniqueness of the data.
The following is the code implementation:
http ://
Application.java
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author spring.tsh
* @function description anti-duplicate submission
* @date 2018-08-26
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.yml
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
RedisConfig.java
package com.common;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConfigrLvbzTRuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfig {
@Bean
@ConfigurationProperties(prefix = "spring.redis")
public JedisConnectionFactory getConnectionFactory() {
return new JedisConnectionFactory(new RedisStandaloneConfiguration(), JedisClientConfiguration.builder().build());
}
@Bean
RedisTemplate
redisTemplate.setConnectionFactory(getConnectionFactory());
return redisTemplate;
}
}
Custom annotation NoRepeatSubmit.java
package com.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // apply to the method
@Retention(RetentionPolicy.RUNTIME) // valid at runtime
/**
* @function description to prevent duplicate submission mark annotation
* @author srping.tsh
* @date 2018-08-26
*/
public @interface NoRepeatSubmit {
}
aop parsing annotation NoRepeatSubmitAop.java
package com.common;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect
@Component
/**
* @function description aop parsing annotation
* @author gaozz.club
* @date 2018-11-02rLvbzTR
*/
public class NoRepeatSubmitAop {
private Log logger = LogFactory. getLog(getClass());
@Autowired
private RedisTemplate
@Around("execution(* com.example..*Controller.*(..)) && @annotation(nrs)")
public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) {
Value Operations
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder. getRequestAttributes();
String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
HttpServletRequest request = attributes. getRequest();
String key = sessionId + "-" + request. getServletPath();
if (opsForValue.get(key) == null) {// If there is this url in the cache, it will be considered as a duplicate submission
Object o = pjp. proceed();
opsForValue.set(key, 0, 2, TimeUnit.SECONDS);
return o;
} else {
logger.error("Duplicate submission");
return null;
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("An unknown exception occurred when verifying repeated submission!");
return "{\"code\":-889,\"message\":\"An unknown exception occurred when verifying repeated submissions!\"}";
}
}
}
Test class:
package com.example;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.common.NoRepeatSubmit;
/**
* @function description test Controller
* @author spring.tsh
* @date 2018-08-26
*/
@RestController
public class TestController {
@RequestMapping("/test")
@NoRepeatSubmit
public String test() {
return ("program logic return");
}
}
0 Comments