springboot|springboot集成redis防止页面重复提交

1:配置pom文件

org.springframework.boot spring-boot-starter-data-redis redis.clients jedis 3.0.1

2:配置redis链接,application.yml
redis: host: 192.168.0.70 port: 6379 password: database: 13 timeout: 6000

【springboot|springboot集成redis防止页面重复提交】3:添加JedisPool配置类
package com.sword.storageproduce.redis; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * @ClassName RedisCacheConfiguration * @Description TODO * @Author wangcc * @Date 2022/5/20 10:37 * @Version 1.0 **/ @Configuration @EnableCaching public class RedisCacheConfiguration extends CachingConfigurerSupport { public static final Logger logger = LoggerFactory.getLogger(RedisCacheConfiguration.class); @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.database}") private int database; @Bean public JedisPool redisPoolFactory() { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, null,database); return jedisPool; } }

4:添加redis处理类
package com.sword.storageproduce.redis; public interface JedisClient {String set(String key, String value); String get(String key); Boolean exists(String key); Long expire(String key, int seconds); Long ttl(String key); Long incr(String key); Long hset(String key, String field, String value); String hget(String key, String field); Long hdel(String key, String... field); }

package com.sword.storageproduce.redis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; /** * @ClassName JedisClientPool * @Description TODO * @Author wangcc * @Date 2022/3/18 10:44 * @Version 1.0 **/ @Component public class JedisClientPool implements JedisClient {@Autowired private RedisCacheConfiguration configuration; @Override public String set(String key, String value) { Jedis jedis = configuration.redisPoolFactory().getResource(); String result = jedis.set(key, value); jedis.close(); return result; }@Override public String get(String key) { Jedis jedis = configuration.redisPoolFactory().getResource(); String result = jedis.get(key); jedis.close(); return result; }@Override public Boolean exists(String key) { Jedis jedis = configuration.redisPoolFactory().getResource(); Boolean result = jedis.exists(key); jedis.close(); return result; }@Override public Long expire(String key, int seconds) { Jedis jedis = configuration.redisPoolFactory().getResource(); Long result = jedis.expire(key, seconds); jedis.close(); return result; }@Override public Long ttl(String key) { Jedis jedis = configuration.redisPoolFactory().getResource(); Long result = jedis.ttl(key); jedis.close(); return result; }@Override public Long incr(String key) { Jedis jedis = configuration.redisPoolFactory().getResource(); Long result = jedis.incr(key); jedis.close(); return result; }@Override public Long hset(String key, String field, String value) { Jedis jedis = configuration.redisPoolFactory().getResource(); Long result = jedis.hset(key, field, value); jedis.close(); return result; }@Override public String hget(String key, String field) { Jedis jedis = configuration.redisPoolFactory().getResource(); String result = jedis.hget(key, field); jedis.close(); return result; }@Override public Long hdel(String key, String... field) { Jedis jedis = configuration.redisPoolFactory().getResource(); Long result = jedis.hdel(key, field); jedis.close(); return result; } }

5:添加注解类,并且定义默认访问次数,有效时间,在这里直接修改时间就可以。
package com.sword.storageproduce.common.interfices; import java.lang.annotation.*; /** * @ClassName LimitUserRequest * @Description 限制某个用户在某个时间段内请求某个方法的次数 * @Author wangcc * @Date 2022/3/18 10:23 * @Version 1.0 **/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface LimitUserRequest {/** * 限制某时间段内可以访问的次数,默认设置1 * @return */ int limitCounts() default 1; /** * 限制访问的某一个时间段,单位为秒,默认值1分钟即可 * @return */ int timeSecond() default 60; }

6:添加切点
package com.sword.storageproduce.common.aop; import com.sword.storageproduce.common.exceptions.LimitUserRequestException; import com.sword.storageproduce.common.interfices.LimitUserRequest; import com.sword.storageproduce.redis.JedisClient; import com.sword.storageproduce.util.UserHelper; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.net.InetAddress; import java.util.concurrent.TimeUnit; /** * @ClassName LimitUserRequestDisplay * @Description 限制用户重复调用方法的aop * @Author wangcc * @Date 2022/3/18 10:25 * @Version 1.0 **/ @Aspect @Component public class LimitUserRequestDisplay {public static final Logger logger = LoggerFactory.getLogger(LimitUserRequestDisplay.class); @Autowired private JedisClient jedis; @Autowired private RedisTemplate redisTemplate; @Pointcut("@annotation(com.sword.storageproduce.common.interfices.LimitUserRequest)") public void before(){ logger.info("进入切面工程"); }@Before("before()") public void requestLimit(JoinPoint joinPoint) throws LimitUserRequestException { logger.info("开始切面操作"); try { // 获取HttpRequest ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); logger.info("url={}", request.getRequestURI()); HttpServletResponse response = attributes.getResponse(); // 判断request不能为空 if (request == null) { throw new LimitUserRequestException("HttpServletRequest有误..."); }LimitUserRequest limit = this.getAnnotation(joinPoint); if(limit == null) { return; }String userId = UserHelper.getLoginUserId(); String uri = request.getRequestURI().toString(); String redisKey = "limit-user-request:" + uri + ":" + userId; // 设置在redis中的缓存,累加1 long count = jedis.incr(redisKey); // 如果该key不存在,则从0开始计算,并且当count为1的时候,设置过期时间 if (count == 1) { jedis.expire(redisKey, limit.timeSecond()); redisTemplate.expire(redisKey, limit.timeSecond(), TimeUnit.MILLISECONDS); }// 如果redis中的count大于限制的次数,则报错 if (count > limit.limitCounts()) { InetAddress address = InetAddress.getLocalHost(); logger.info("用户IP[" + address.getHostAddress() + "]访问地址[" + uri + "]超过了限定的次数[" + limit.limitCounts() + "]"); throw new LimitUserRequestException("当前用户重复访问"); } } catch (LimitUserRequestException e) { throw e; } catch (Exception e) { e.printStackTrace(); } }/** * * @Description: 获得注解 * @param joinPoint * @return * @throws Exception * * @author wangcc * @date 2022年3月18日 上午9:55:32 */ private LimitUserRequest getAnnotation(JoinPoint joinPoint) throws Exception { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method != null) { return method.getAnnotation(LimitUserRequest.class); } return null; }}

7:测试
@LimitUserRequest @GetMapping(value = "https://www.it610.com/testChange") public String user(@RequestParam Map param) { return "成功调用接口"; }


    推荐阅读