Springboot + redis 使用AOP实现防止重复提交问题

springboot + redis 使用AOP实现防止重复提交问题

一,定义自定义注解。

我在里面定义了一个锁住接口时间的方法,默认值为10。

package com.nci.common.annotation;

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 NoRepeatSubmit {
    /**
     * 设置请求锁定时间
     *
     * @return
     */
    int lockTime() default 10;
}

二,添加一个切面

采用Redis来缓存提交接口的唯一标识,然后设置过期时间,唯一标识我才用接口的URL和用户的token组合在一起就能达到唯一,用户每发起第一次添加请求,会经过界面,在切面获取信息后组装起来存入Redis,当用户后续发起请求时,首先判断Redis中是否缓存了这个key,如果缓存了,则证明已经提交,于是反馈给前端,如果不存在,证明没有提交,则存入Redis。

package com.nci.common.aspect;

import com.nci.common.annotation.NoRepeatSubmit;
import com.nci.common.utils.R;
import com.nci.common.utils.RequestUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 *  重复提交切面
 */
@Aspect
@Component
public class RepeatSubmitAspect {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointCut(NoRepeatSubmit noRepeatSubmit) {
    }

    @Around("pointCut(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        int lockSeconds = noRepeatSubmit.lockTime();

        HttpServletRequest request = RequestUtils.getRequest();
        Assert.notNull(request, "request can not null");

        // 此处可以用token或者JSessionId
        String token = request.getHeader("token");
        String path = request.getServletPath();
        String sign = path + "/" + token;
        Boolean key = redisTemplate.hasKey(sign);
        if(key){
            return R.error("重复请求,请稍后再试");
        }
        redisTemplate.opsForValue().set(sign,sign,lockSeconds, TimeUnit.SECONDS);
        return pjp.proceed();

    }

}

package com.nci.common.utils;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

public class RequestUtils {
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes ra= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return ra.getRequest();
    }
}

三,方法上加上注解

    @NoRepeatSubmit
    @PostMapping("/saveData")
    public R saveData(@RequestBody XgxxVo vo){
        User user = getUser();
        Integer res = XgxxService.saveData(vo,user);
        if(res == 1){
            return R.ok();
        }
        return R.error("保存数据失败");
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值