java 使用redis校验 防止网络延迟表单重复提交

一、引入redis依赖

<!-- 引入redis配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

二、配置redis连接信息

spring:
  redis: #以下redis部分自行修改
    host: localhost
    port: 6379
    password: 密码
    database: 1   #选择一号库

三、创建一个注解类

使用注解配置你要切哪个方法需要校验(一般是增删改方法,查询一般不需要校验)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 网络抖动校验注解
 */
@Target(ElementType.METHOD)//只能在方法上使用
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface AntiExplosion {

}

四、创建一个切面类

使用环绕切面,切添加注解的方法

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 校验网络抖动配置
 */
@Configuration
@Aspect  //定义这是切面类
public class AntiExplosionAspect {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 切方法上添加此注解的接口信息
     */
    @Around("@annotation(com.test.zsq.annotaion.AntiExplosion)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //获取redis操作
        ValueOperations<String, String> stringRedis = stringRedisTemplate.opsForValue();
        //获取当前方法所有的参数信息
        List<Object> args = Arrays.asList(proceedingJoinPoint.getArgs());
        Object proceed = null;
        //判断是否存在参数
        if (args.size() != 0) {
            //获取方法名
            String name = proceedingJoinPoint.getSignature().getName();
            //将参数转成json字符串
            String jsonString = JSON.toJSONString(args);
            //进行MD5加密(为了减少key存储长度,你自己随便找一个方式)
            String build = MD5Util.build(jsonString);
            String key = "test-server:prevent:" + name + ":" + build;
            //获取redis中的数据
            String antiShake = stringRedis.get(key);
            if (name.equals(antiShake)) {
                throw new CommonException("正在执行中,请勿重复操作");
            }

//            //判断当前执行的方法是否执行过,让线程进行等待
//            while (name.equals(antiShake)) {
//                Thread.sleep(1000);
//                antiShake = stringRedis.get("test-server:prevent:" + build);
//            }

            //执行后续的代码时添加一个缓存
            stringRedis.set(key, name, 5, TimeUnit.MINUTES);
            try {
                //向下执行接口
                proceed = proceedingJoinPoint.proceed();
            } finally {
                //清除redis中的缓存
                stringRedisTemplate.delete(key);
            }
        }
        return proceed;
    }
}

使用方式,只需要在要校验的方法上添加注解

@RestController
@RequestMapping("/test")
public class TestController{

    @Resource
    private TestCertService testService;

	//将需要校验的方法上添加校验注解即可
    @AntiExplosion
    @RequestMapping("add")
    public Long add(User user) {
        return testService.add(user);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值