91名师指路-头部
91名师指路

redisson防止表单重复提交

由于某些原因,现在不支持支付宝支付,如需要购买源码请加博主微信进行购买,微信号:13248254750

一:引入pom

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.0</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二:编写yml

server:
port: 8002

spring:
application:
name: mszl-blog

redis:
database: 0
port: 6379
host: 127.0.0.1
password:
jedis:
pool:
max-active: 200 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
timeout: 3000 # 连接超时时间(毫秒)

三:配置RedissonConfig

package com.mszl.blog.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

@Value("${spring.redis.host}")
private String host;

@Value("${spring.redis.port}")
private String port;


/**
* 单Redis节点模式
*/
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":" + port); // redis://127.0.0.1:6379
RedissonClient redisson = Redisson.create(config);
return redisson;
}

/**
* 集群模式
* 备注:可以用"rediss://"来启用SSL连接
*/
/*@Bean
public RedissonClient redissonClusterClient() {
Config config = new Config();
config.useClusterServers().setScanInterval(2000) // 集群状态扫描间隔时间,单位是毫秒
.addNodeAddress("redis://127.0.0.1:7000")
.addNodeAddress("redis://127.0.0.1:7002");
RedissonClient redisson = Redisson.create(config);
return redisson;
}*/

}

四:自定义注解

package com.mszl.blog.repeatsubmit;

import java.lang.annotation.*;

/**
* 功能:自定义注解[重复提交]
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatSubmit {

long lockTime() default 5;

}

五:切面类

package com.mszl.blog.repeatsubmit;

import com.mszl.blog.config.RedissonConfig;
import com.mszl.blog.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@Slf4j
@Aspect
@Component
public class RepeatSubmitAspect {

@Autowired
private RedissonConfig redissonClient;


@Pointcut("@annotation(repeatSubmit)")
public void pointcutNoRepeatSubmit(RepeatSubmit repeatSubmit){

}

@Around("pointcutNoRepeatSubmit(noRepeatSubmit)")
public Object around(ProceedingJoinPoint joinPoint, RepeatSubmit noRepeatSubmit) throws Throwable {
HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token=request.getHeader("token");
String path=request.getServletPath();
long lockTime=noRepeatSubmit.lockTime();
String key="REPEAT_SUBMIT_" + path + token;

// 分布式锁
RLock lock = redissonClient.redissonClient().getLock(key);
boolean res = lock.tryLock(0, lockTime, TimeUnit.SECONDS); // 尝试加锁,最多等待0秒,上锁以后5秒自动解锁[lockTime默认为5s, 用户可以自定义]
if(!res){
throw new BusinessException(206, "请勿重复提交");
}

Object object=joinPoint.proceed();
return object;
}

}

六:在controller类上加上@RepeatSubmit

@RepeatSubmit(lockTime = 10)
@PostMapping("/blog/adduser")
public ReturnMsgUtils insertUser(@RequestBody Userbak uu){
ReturnMsgUtils result=userService.insertUser(uu);
return result;
}

注意:@RepeatSubmit可以不指定lockTime,默认为5s,也可以根据自己的实际情况改成对应的时间。


七:测试

请求接口:http://localhost:8002/blog/adduser,注意我这里没有把 /blog/adduser 接口对应的代码贴出来,这个接口只是单纯的往用户表;里面新增一条记录。注意:需要在请求头添加token,因为我们在切面类里面有获取token并作为redis中的key

第一次请求,截图如下。

接口返回信息如下:

{
    "code"200,
    "msg""恭喜您, 操作成功",
    "data"null

}


token截图,我这里写死,大家根据自己的实际请求来赋值token即可。


在10秒内第二次请求接口,截图如下:

接口返回信息如下:

{
    "code": 206,
    "msg": "请勿重复提交",
    "data": null


项目结构


参考资料:

https://blog.csdn.net/CoreyXuu/article/details/86646183



2021-09-06 10:51:57     阅读(1579)

名师出品,必属精品    https://www.91mszl.com

联系博主    
用户登录遮罩层
x

账号登录

91名师指路-底部