SpringBoot+Redis怎么实现后端接口防重复提交校验
发布时间:2023-05-16 14:37:24
1. 概述
在日常开发中,为了防止用户重复提交同一个请求,我们需要实现接口防重复提交校验。本文将给出一种使用 SpringBoot Redis 实现后端接口防重复提交校验的方法。
2. 实现思路
我们使用 SpringBoot 创建一个简单的后端项目。当用户发送请求时,我们将用户的请求参数和请求时间戳作为 Redis 的 key,存储到 Redis 中,并设置一定时间过期,这段时间内用户无法进行相同请求。具体实现如下。
3. 代码实现
3.1 添加 Redis 依赖
在 pom.xml 文件中添加 Redis 依赖,我们使用的是 jedis 版本。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
3.2 添加 Redis 配置
在 application.properties 文件中添加 Redis 配置项。
# Redis 配置 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password=123456 spring.redis.database=0
3.3 编写防重复提交校验的注解
我们定义一个 @PreventReSubmit 注解,用来标记需要进行防重复提交校验的接口。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventReSubmit {
/**
* 重复提交时间间隔(毫秒)
*/
long interval() default 5000L;
}
3.4 编写防重复提交校验的拦截器
我们编写一个拦截器 PreventReSubmitInterceptor,在用户请求进入控制器方法之前进行拦截。
@Component
public class PreventReSubmitInterceptor extends HandlerInterceptorAdapter {
@Autowired
private JedisPool jedisPool;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
Method method = ((HandlerMethod) handler).getMethod();
PreventReSubmit annotation = method.getAnnotation(PreventReSubmit.class);
if (annotation == null) {
return true;
}
String key = getKey(request);
try (Jedis jedis = jedisPool.getResource()) {
String result = jedis.setex(key, (int) (annotation.interval() / 1000), "0");
if (!"OK".equals(result)) {
response.sendError(500, "请勿重复提交同一个请求");
return false;
}
}
return true;
}
/**
* 获取 Redis key,key 由请求路径和请求参数、请求时间戳组成
*/
private String getKey(HttpServletRequest request) {
StringBuilder sb = new StringBuilder(request.getRequestURI());
Map<String, String[]> map = request.getParameterMap();
if (map != null && !map.isEmpty()) {
sb.append("?");
for (String key : map.keySet()) {
sb.append(key).append("=").append(Arrays.toString(map.get(key))).append("&");
}
sb.deleteCharAt(sb.length() - 1);
}
sb.append("_").append(System.currentTimeMillis());
return sb.toString();
}
}
3.5 注册拦截器
我们在 WebMvcConfigurerAdapter 中注册编写的拦截器。
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private PreventReSubmitInterceptor preventReSubmitInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(preventReSubmitInterceptor);
super.addInterceptors(registry);
}
}
3.6 使用注解进行防重复提交校验
我们在需要进行防重复提交校验的方法上添加 @PreventReSubmit 注解即可。
@PostMapping("/test")
@PreventReSubmit
public String test(@RequestParam String name) {
return "hello " + name;
}
4. 总结
本文通过使用 SpringBoot Redis 实现后端接口防重复提交校验的方法,给出了一种简单易行的实现方案。在实际开发中,可以根据具体业务需求对此方案进行进一步优化和拓展。
