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
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 = "/testChange")
public String user(@RequestParam Map param) {
return "成功调用接口";
}