本篇文章为你整理了Redisson多策略注解限流(redis 策略)的详细内容,包含有redis注解缓存 redis 策略 rediscache注解 redisson限流实现 Redisson多策略注解限流,希望能帮助你了解 Redisson多策略注解限流。
生成key的工具类
根据类型生成锁的对象(key)的工具类,使用map+函数式接口优化if,其中BaseContext是一个获取用户唯一标识userId的工具类
@Component
public class ProceedingJoinPointUtil {
@Autowired
private HttpServletRequest request;
private Map LimitType, Function ProceedingJoinPoint,String functionMap = new HashMap (9);
@PostConstruct
void initMap(){
//初始化策略
functionMap.put(LimitType.METHOD, this::getMethodTypeKey);
functionMap.put(LimitType.PARAMS, this::getParamsTypeKey);
functionMap.put(LimitType.USER, this::getUserTypeKey);
functionMap.put(LimitType.REQUEST_URI,proceedingJoinPoint -
request.getRequestURI());
functionMap.put(LimitType.REQUESTURI_USERID, proceedingJoinPoint -
request.getRequestURI()+BaseContext.getUserId());
functionMap.put(LimitType.REQUEST_URI_PARAMS,proceedingJoinPoint -
request.getRequestURI()+getParams(proceedingJoinPoint));
functionMap.put(LimitType.REQUEST_URI_PARAMS_USERID,proceedingJoinPoint -
request.getRequestURI()+getParams(proceedingJoinPoint)+BaseContext.getUserId());
functionMap.put(LimitType.SINGLEUSER,(proceedingJoinPoint)-
String.valueOf(BaseContext.getUserId()));
functionMap.put(LimitType.SINGLEMETHOD,(proceedingJoinPoint - {
StringBuilder sb = new StringBuilder();
appendMthodName(proceedingJoinPoint,sb);
return sb.toString();
}));
public Object getKey(ProceedingJoinPoint joinPoint, RedisLimit redisLimit) {
//根据限制类型生成key
Object generateKey = "";
//自定义
if(redisLimit.type() != LimitType.CUSTOM){
generateKey = generateKey(redisLimit.type(), joinPoint);
}else {
//非自定义
generateKey = redisLimit.key();
return generateKey;
* 根据LimitType生成key
* @param type
* @param joinPoint
* @return
private Object generateKey(LimitType type , ProceedingJoinPoint joinPoint) {
Function function = functionMap.get(type);
Object result = function.apply(joinPoint);
return result;
* 方法级别
* key = ClassName+MethodName
* @param joinPoint
* @return
private String getMethodTypeKey(ProceedingJoinPoint joinPoint){
StringBuilder sb = new StringBuilder();
appendMthodName(joinPoint, sb);
return sb.toString();
private String getParamsTypeKey(ProceedingJoinPoint joinPoint){
StringBuilder sb = new StringBuilder();
appendMthodName(joinPoint, sb);
appendParams(joinPoint, sb);
return sb.toString();
private String getUserTypeKey(ProceedingJoinPoint joinPoint){
StringBuilder sb = new StringBuilder();
appendMthodName(joinPoint, sb);
appendParams(joinPoint, sb);
//获取userId
appendUserId(sb);
return sb.toString();
private void appendMthodName(ProceedingJoinPoint joinPoint, StringBuilder sb) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
sb.append(joinPoint.getTarget().getClass().getName())//类名
.append(method.getName());//方法名
* StringBuilder添加方法参数值
* @param joinPoint
* @param sb
private void appendParams(ProceedingJoinPoint joinPoint, StringBuilder sb) {
for (Object o : joinPoint.getArgs()) {
sb.append(o.toString());
private String getParams(ProceedingJoinPoint joinPoint) {
StringBuilder sb = new StringBuilder();
for (Object o : joinPoint.getArgs()) {
if(o instanceof MultipartFile){
try {
ImageTypeCheck.getImgHeightAndWidth(((MultipartFile) o).getInputStream());
} catch (IOException e) {
throw new BusinessException("MultipartFile输入流获取失败,source:ProceedingJoinPointUtils.149",USER_PRINCIPAL_EMAIL);
}else {
sb.append(o.toString());
return sb.toString();
* StringBuilder添加UserId
* @param sb
private void appendUserId(StringBuilder sb) {
sb.append(BaseContext.getUserId());
定义aop具体逻辑
@Aspect
@Component
@Slf4j
public class RedisLimitAspect {
@Autowired
private RedissonClient redissonClient;
@Autowired
private ProceedingJoinPointUtil proceedingJoinPointUtil;
@Pointcut("@annotation(com.cat.www.aop.limit.anno.RedisLimit)")
private void pointCut() {
@Around("pointCut() @annotation(redisLimit)")
private Object around(ProceedingJoinPoint joinPoint, RedisLimit redisLimit) {
Object generateKey = proceedingJoinPointUtil.getKey(joinPoint, redisLimit);
//redis key
String key = redisLimit.prefix() +generateKey.toString();
//声明一个限流器
RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
//设置速率,time秒中产生count个令牌
rateLimiter.trySetRate(RateType.OVERALL, redisLimit.count(), redisLimit.time(), RateIntervalUnit.SECONDS);
// 试图获取一个令牌,获取到返回true
boolean tryAcquire = rateLimiter.tryAcquire();
if (!tryAcquire) {
return new ResultData ().FAILED().setResultIns("访问过于频繁");
Object obj = null;
try {
obj = joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException();
return obj;
以上就是Redisson多策略注解限流(redis 策略)的详细内容,想要了解更多 Redisson多策略注解限流的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。