Aop实现后端数据重复提交

一、思路

用户每次发送请求都有一个标记,这个标记设置成5s有效存到redis中。每次请求检查该标记是否有效,还有效就说明请求太频繁了。无效就说明请求之间时间间隔够了,可以继续请求了。

gitee地址:添加链接描述

二、实现

  1. 自定义注解

    import java.lang.annotation.*;
    @Documented
    @Target({ElementType.TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NoRepeatSubmit {
    int lockTime() default 5;
    }

  2. 注解+aop前置通知检查redis。将请求路径和当前用户token拼接存到redis中,并设置过期时间

    import com.qcby.aop_cftj.myannotation.NoRepeatSubmit;
    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.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Objects;
    import java.util.concurrent.TimeUnit;

    @Component
    @Aspect
    public class NoRepeatSubmitAspect {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Pointcut("@annotation(repeatSubmit)")
    public void pointcutNoRepeat(NoRepeatSubmit repeatSubmit){};
    @Around("pointcutNoRepeat(noRepeatSubmit)")
    public Object doNoRepeat(ProceedingJoinPoint point, NoRepeatSubmit noRepeatSubmit) throws Throwable {
    int i=noRepeatSubmit.lockTime();
    HttpServletRequest httpServletRequest = HttpServletRequest();
    Cookie[] cookies = httpServletRequest.getCookies();
    String token="";
    if(cookies!=null){
    for (Cookie cookie : cookies) {
    if(cookie.getName().equals("token")){
    token=cookie.getValue().toString();
    }
    }
    }
    String url = httpServletRequest.getRequestURL().toString();
    String sign = url+"/"+token;
    Boolean key=redisTemplate.hasKey(sign);
    if (key){
    System.out.println("请勿重复提交!!");
    return null;
    // throw new Exception("请勿重复提交");

    复制代码
         }
         redisTemplate.opsForValue().set(sign,sign,i, TimeUnit.SECONDS);
         return  point.proceed();
     }
     public static HttpServletRequest HttpServletRequest(){
         return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
     }
  3. 请求时根据用户信息生成token并存到cookie中

    import io.jsonwebtoken.JwtBuilder;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    import javax.annotation.Resource;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Date;
    import java.util.UUID;
    @Service
    public class LoginService {
    @Resource
    RedisTemplate<String, String> redisTemplate;
    public String login(String phone, String password, HttpServletResponse response){
    //签名密钥
    String signature = "hello";
    JwtBuilder builder = Jwts.builder();
    //使用JWT生成器创建一个JWT
    String jwtToken = builder
    //Header
    .setHeaderParam("typ", "JWT")
    //类型
    .setHeaderParam("alg", "HS256")
    //使用的算法
    //Payload
    .claim("phone", phone)
    .setSubject("admin-test")
    .setExpiration(new Date(System.currentTimeMillis() + 10006060*24))
    //失效日期:当前时间+24小时
    .setId(UUID.randomUUID().toString())
    //signature
    .signWith(SignatureAlgorithm.HS256, signature)
    //使用的算法+签名密钥
    //调用compact()方法将三部分拼接起来并用'.'分隔
    .compact();
    Cookie cookie=new Cookie("token",jwtToken.substring(0,5));
    response.addCookie(cookie);
    return "登录成功!!";
    }
    }

相关推荐
留不住丨晚霞19 分钟前
说说SpringBoot常用的注解?
java·开发语言
华科云商xiao徐25 分钟前
Java多线程爬虫动态线程管理实现
java·爬虫·数据挖掘
柒七爱吃麻辣烫34 分钟前
八股文系列-----SpringBoot自动配置的流程
java·spring boot·rpc
M1A138 分钟前
Java 面试系列第一弹:基础问题大盘点
java·后端·mysql
发仔12339 分钟前
Dubbo介绍及示例用法
java·dubbo
goxingman1 小时前
关于使用idea打包的时候报错,Maven提示乱码java: �Ҳ�������
java·maven·intellij-idea
邓不利东2 小时前
Spring中过滤器和拦截器的区别及具体实现
java·后端·spring
草履虫建模3 小时前
Redis:高性能内存数据库与缓存利器
java·数据库·spring boot·redis·分布式·mysql·缓存
苹果醋33 小时前
Vue3组合式API应用:状态共享与逻辑复用最佳实践
java·运维·spring boot·mysql·nginx
Micro麦可乐3 小时前
Java常用加密算法详解与实战代码 - 附可直接运行的测试示例
java·开发语言·加密算法·aes加解密·rsa加解密·hash算法