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

相关推荐
好家伙VCC6 分钟前
【无标题】
java
小碗羊肉1 小时前
【JavaWeb | 第十一篇】文件上传(本地&阿里云OSS)
java·阿里云·servlet
吾疾唯君医1 小时前
Java SpringBoot集成积木报表实操记录
java·spring boot·spring·导出excel·积木报表·数据文件下载
Byron Loong1 小时前
【c++】为什么有了dll和.h,还需要包含lib
java·开发语言·c++
hexu_blog2 小时前
vue+java实现图片批量压缩
java·前端·vue.js
头歌实践平台2 小时前
Hadoop开发环境搭建
java·大数据·hadoop
Seven972 小时前
一致性Hash算法:如何实现分布式系统中的高效数据分片?
java
摇滚侠2 小时前
IDEA 生成 try catch 快捷键
java·ide·intellij-idea
阿旭超级学得完3 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表