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 "登录成功!!";
    }
    }

相关推荐
Boilermaker19927 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维7 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
alonewolf_997 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子7 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
sheji34168 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
恋爱绝缘体18 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
wszy18098 小时前
新文章标签:让用户一眼发现最新内容
java·python·harmonyos
wszy18099 小时前
顶部标题栏的设计与实现:让用户知道自己在哪
java·python·react native·harmonyos
程序员小假9 小时前
我们来说一下无锁队列 Disruptor 的原理
java·后端
资生算法程序员_畅想家_剑魔10 小时前
Kotlin常见技术分享-02-相对于Java 的核心优势-协程
java·开发语言·kotlin