java防止前端重复提交

JAVA利用自定义本地锁解决重复提交的问题

  1. 引入jar包
		<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.1-jre</version>
        </dependency>
  1. 自定义本地锁
package com.hzt.listener;

import java.lang.annotation.*;

/**
 * 自定义-控制重复提交锁
 */
@Target(ElementType.METHOD)     //作用于方法
@Retention(RetentionPolicy.RUNTIME)     //运行时有效
@Documented
@Inherited
public @interface LocalLock {
    
    

    String key() default "";

}
  1. 自定义注解切面 (aop拦截器实现)
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

/**
 * @Desc: 自定义注解拦截器
 * @Author: zmk
 * @Date: 2022/4/2
 */
@Aspect
@Configuration
public class LockMethodInterceptor {
    
    
    private final Logger log = LoggerFactory.getLogger(LockMethodInterceptor.class);


    private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder()
            //最大缓存数
            .maximumSize(1000)
            //设置过期时间
            .expireAfterWrite(3, TimeUnit.SECONDS)
            .build();



    @Around(value = "@annotation(localLock)")
    public Object interceptor (ProceedingJoinPoint point, LocalLock localLock) {
    
    

        //localLock.key() 这个是获取controller的key属性, point.getArgs()获取key的值
        String key = getKey(localLock.key(), point.getArgs());
        if (StringUtils.isNotBlank(key)) {
    
    
            if (CACHES.getIfPresent(key) != null) {
    
    
                throw new RuntimeException("请勿重复提交");
            }
            //如果是第一次请求, 将key放入缓存
            CACHES.put(key, key);
        }

        try {
    
    
            return point.proceed();
        } catch (Throwable throwable) {
    
    
            throw new RuntimeException("服务器异常");
        } finally {
    
    
            //标记为无效
//            CACHES.invalidate(key);
        }

    }
    
    /**
     *
     * key 生成策略
     * @param key   key表达式
     * @param args  参数
     * @return  生成的key
     */
    private String getKey(String key, Object[] args) {
    
    
        for (int i = 0; i < args.length; i++) {
    
    
            key = key.replace("arg[" + i + "]", args[i].toString());
        }
        return key;
    }
  1. 定义controller接口
	@GetMapping("/query")
    @LocalLock(key = "param:arg[0]")
    public String query (@RequestParam("abc") String abc) {
    
    
        return "ok";
    }


第一次调用结果:
在这里插入图片描述

第二次调用结果:
在这里插入图片描述

来自: https://blog.csdn.net/weixin_33737261/article/details/114425394

猜你喜欢

转载自blog.csdn.net/weixin_42915457/article/details/124018633
今日推荐