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

相关推荐
Yyyyyy~2 小时前
【Java】Day4Web基础知识
java·spring boot
灿飞屋3 小时前
Kotlin与Java虚拟机三:控制流
android·java·开发语言·后端·python·kotlin·安卓
NE_STOP4 小时前
Spring AI Alibaba - MCP入门
java
nice_lcj5204 小时前
【从零理解 Spring AI · 07】对话记忆:让模型记住上一句说了什么
java·spring ai·ai应用开发·chatmemory·对话记忆
SL_staff5 小时前
制造业交付崩盘?用跨部门节点协同计划打通销售、生产与质量链路
java·开源·产品
文丑颜不良啊5 小时前
LeetCode2261~2280题目解析
java·leetcode
SL_staff6 小时前
告别规则黑盒:JVS-Rules 在金融风控中的可视化决策编排实践
java·产品·全栈
逃逸线LOF6 小时前
服务网关Gateway
java·运维·gateway
灿飞屋7 小时前
Kotlin与Java虚拟机四:函数
java·python·kotlin·安卓·android jetpack
阡陌数智8 小时前
Claude API新版本重大变更与安全升级指南
java·linux·安全