redis实现禁止重复请求的切面小功能

场景:3秒时间内禁止重复提交!

Controller:   伪代码

package com..aopCommit;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CommitController {

    @RequestMapping("/Commit")
    @CommitAop
    public String Commit() {
        System.out.println("进入方法,执行业务!");
        return "返回结果!";
    }
}

自定义注解类:

package com..aopCommit;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CommitAop {

}

切面类:

package com..aopCommit;

import com..redis.RedisPoolUtils;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

@Aspect
@Component
public class CommitImpl {

    RedisPoolUtils redisPoolUtils =new RedisPoolUtils();

    @Around("@annotation(com.wondersgroup.aopCommit.CommitAop)")
    public Object doubleCommit(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = servletRequestAttributes.getRequest();
        String ip = request.getRemoteAddr();
        String className = proceedingJoinPoint.getSignature().getDeclaringTypeName();
        String Mathod = proceedingJoinPoint.getSignature().getName();
        System.out.println("请求的IP :"+ip);
        System.out.println("类方法 :"+className+ "." + Mathod);

        String ipKey = String.format("%s#%s",className,Mathod);
        int hashCode = Math.abs(ipKey.hashCode());
        String key = String.format("%s_%d",ip,hashCode+2);
        String value =  redisPoolUtils.get(key);
        if(StringUtils.isNotBlank(value)){
            System.out.println("请勿重新提交!");
            return "请勿重新提交!";
        }
        redisPoolUtils.setex(key, UUID.randomUUID().toString(),3);

        Object object = proceedingJoinPoint.proceed();

        return object;
    }

}

redis工具类:

package com..redis;

import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class RedisPoolUtils {

    public RedisPoolUtils() {
        
    }
    
    private static JedisPool pool;
    private static String host;//地址
    private static String port;//端口
    private static String password;//授权密码
    private static String timeout;//超时时间:单位MS
    private static String maxIdle;//最大空闲数:空闲链接数大于maxIdle时,将进行回收
    private static String maxActive;//最大连接数:能够同时建立的"最大链接个数"
    private static String maxWait;//最大等待时间:单位ms
    private static String testOnBorrow;//在获取连接时,是否验证有效性
    
    static{
        //加载properties配置文件
        Properties properties = new Properties();
        JedisPoolConfig config = new JedisPoolConfig();
        InputStream is = RedisUtil.class.getClassLoader().getResourceAsStream("redis_config.properties");
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        host = properties.getProperty("redis.single.host");
        port = properties.getProperty("redis.single.port");
        password = properties.getProperty("redis.password");
        timeout = properties.getProperty("redis.timeout");
        maxIdle = properties.getProperty("redis.maxIdle");
        maxActive = properties.getProperty("redis.maxActive");
        maxWait = properties.getProperty("redis.maxWait");
        testOnBorrow = properties.getProperty("redis.testOnBorrow");
        // 得到Jedis/JedisPool实例并且设置配置
        pool = new JedisPool(config,host,Integer.parseInt(port),Integer.parseInt(timeout));
        
    }

    /**
     * 设置key value并制定这个键值的有效期
     * 
     * @param key
     * @param value
     * @param seconds
     *            单位:秒
     * @return 成功返回OK 失败和异常返回null
     */
    public String setex(String key, String value, int seconds) {
        Jedis jedis = null;
        String res = null;
        try {
            jedis = pool.getResource();
            res = jedis.setex(key, seconds, value);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            returnResource(pool, jedis);
        }
        return res;
    }
}

redis_config.properties :

redis.single.host=127.0.0.1
redis.single.port=6379
redis.password=
redis.timeout=100000
redis.maxIdle=100
redis.maxActive=300
redis.maxWait=1000
redis.testOnBorrow=true

切面jar包:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

测试结果  (第一次访问成功,3秒后再次成功,中间直接返回):

原文地址:https://www.cnblogs.com/lifan12589/p/14283435.html