Redis接口訪問優(yōu)化的方法步驟
說明:之前寫過一篇使用Redis接口訪問的博客,如下。最近有相關(guān)需求,把代碼拿出來后,做了一些優(yōu)化,挺有意思的,本文介紹在原基礎(chǔ)上
優(yōu)化
總的來說,這次使用Redis實現(xiàn)接口防抖,增加了一個時間段參數(shù),可以限制接口在某個時間段內(nèi),訪問不能超過多少次。如下:
(自定義注解,打在接口上)
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 LimitAccess {
/**
* 限制訪問的key
* @return
*/
String key();
/**
* 限制訪問次數(shù)
* @return
*/
int times();
/**
* 時間段
* @return
*/
int duration();
}
(切面,實現(xiàn)限制訪問)
import com.hezy.annotation.LimitAccess;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* AOP類(通知類)
*/
@Component
@Aspect
@Log4j2
public class LimitAspect {
@Value("${access.enable:false}")
private boolean enable;
@Autowired
private RedisTemplate redisTemplate;
@Pointcut("@annotation(com.hezy.annotation.LimitAccess)")
public void pt(){};
@Around("pt()")
public Object aopAround(ProceedingJoinPoint pjp) throws Throwable {
// 設(shè)置一個開關(guān),控制是否執(zhí)行
if (!enable) {
return pjp.proceed();
}
// 獲取切入點上面的自定義注解
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
// 獲取方法上面的注解
LimitAccess limitAccess = methodSignature.getMethod().getAnnotation(LimitAccess.class);
// 獲取注解上面的屬性值
int limit = limitAccess.times();
String key = limitAccess.key();
int duration = limitAccess.duration();
// 遞增鍵的值,如果鍵不存在則初始化為1
Long currentCount = redisTemplate.opsForValue().increment(key, 1);
// 如果鍵是新創(chuàng)建的,設(shè)置過期時間
if (currentCount != null && currentCount == 1) {
redisTemplate.expire(key, duration, TimeUnit.SECONDS);
}
// 檢查是否超過限制
if (currentCount != null && currentCount > limit) {
log.info("訪問過于頻繁: " + pjp.toLongString());
throw new RuntimeException("訪問過于頻繁");
}
return pjp.proceed();
}
}
(使用,在對應(yīng)的接口上,打上注解,填上數(shù)值,如下表示,1秒內(nèi)不能訪問超過3次)
@LimitAccess(key = "test", times = 3, duration = 1)
@GetMapping
public String test() {
return demoService.test();
}
另外,在代碼中加了一個開關(guān),可在配置文件中設(shè)置此配置,表示開啟或者關(guān)閉,默認(rèn)是關(guān)閉的
access: enable: true
啟動項目,測試一下

思考
以上代碼,有兩點需要思考:
注解能不能加在Service層的方法上,加了有沒有用?另外加了會不會讓聲明式事務(wù)失效?
這個限制,沒有到用戶的維度,也就是說所有的用戶,只要在一個時間段內(nèi)訪問超過次數(shù)就限制,這顯然是不行的。有什么辦法嗎?
第一點,我測試過,注解可以加在Service層方法上,是可以的,不會讓事務(wù)失效,如下:
@LimitAccess(key = "deleteUserById", times = 3, duration = 1)
@Transactional
@Override
public void deleteUserById(Integer id) {
// 刪除用戶
userMapper.deleteUserById(id);
int i = 1 / 0;
// 刪除用戶對應(yīng)的角色
userMapper.deleteUserRoleMapper(id);
}
接口限制,事務(wù),都生效了。
第二點,這確實是個問題,要做到針對用戶層面的接口限制是必須的,不然有一個用戶惡意刷新,其他用戶都用不了了,這怎么可以。要解決這個問題,首先要拿到當(dāng)前操作用的標(biāo)識,用戶名、用戶ID,然后再存入key的時候,拼接上這個標(biāo)識作為key。
String key = limitAccess.key() + 用戶標(biāo)識(用戶名、用戶id);
獲取當(dāng)前用戶信息,參考下面這篇文章:
如果你不是自己從0開發(fā)項目,一般成熟的項目都會有獲取當(dāng)前操作用戶信息的方式的。實在不行,你讓前端把用戶id作為參數(shù)傳給你,你在切面里獲取這個用戶id都可以。
總結(jié)
本文是對之前用Redis接口訪問的優(yōu)化,以及對兩個問題的考慮,希望能對大家有啟發(fā)。
獲取源碼:https://github.com/HeZhongYing/limit_access_demo
到此這篇關(guān)于Redis接口訪問優(yōu)化的方法步驟的文章就介紹到這了,更多相關(guān)Redis接口訪問優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis+自定義注解+AOP實現(xiàn)聲明式注解緩存查詢的示例
實際項目中,會遇到很多查詢數(shù)據(jù)的場景,這些數(shù)據(jù)更新頻率也不是很高,一般我們在業(yè)務(wù)處理時,會對這些數(shù)據(jù)進(jìn)行緩存,本文主要介紹了Redis+自定義注解+AOP實現(xiàn)聲明式注解緩存查詢的示例,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
RedisTemplate 實現(xiàn)基于Value 操作的簡易鎖機(jī)制(示例代碼)
本文將介紹如何使用 RedisTemplate 的 opsForValue().setIfAbsent() 方法來實現(xiàn)一種簡單的鎖機(jī)制,并提供一個示例代碼,展示如何在 Java 應(yīng)用中利用這一機(jī)制來保護(hù)共享資源的訪問,感興趣的朋友跟隨小編一起看看吧2024-05-05
Redis TTL命令實現(xiàn)數(shù)據(jù)生存時間
生存時間可以通過Redis中的不同命令來設(shè)置、查看和管理,TTL命令是其中之一,本文主要介紹了Redis TTL命令實現(xiàn)數(shù)據(jù)生存時間,具有一定的參考價值,感興趣的可以了解一下2024-06-06

