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

相关推荐
Lyyaoo.4 分钟前
【JAVA基础面经】线程的状态
java·开发语言
Hello小赵5 分钟前
C语言如何自定义链接库——编译与调用
android·java·c语言
希望永不加班9 分钟前
SpringBoot 配置绑定:@ConfigurationProperties
java·spring boot·后端·spring
悟空码字10 分钟前
MySQL性能优化的天花板:10条你必须掌握的顶级SQL分析技巧
java·后端·mysql
indexsunny13 分钟前
互联网大厂Java面试实战:Spring Boot、MyBatis与Kafka在电商场景中的应用
java·spring boot·面试·kafka·mybatis·电商·技术栈
殷紫川18 分钟前
CompletableFuture 异步编程全解:核心能力、编排方案、异常处理与超时控制
java
ss27322 分钟前
致Java初学者的一封信
java·开发语言
white-persist22 分钟前
【vulhub spring CVE-2018-1270】CVE-2018-1270 Spring Messaging 远程命令执行漏洞 完整复现详细分析解释
java·服务器·网络·数据库·后端·python·spring
潇洒畅想30 分钟前
1.1 从∑到∫:用循环理解求和与累积
java·数据结构·python·算法
维齐洛波奇特利(male)1 小时前
@Pointcut(“execution(* com.hdzx..*(..))“)切入点与aop 导致无限循环
java·开发语言