使用Redis實(shí)現(xiàn)記錄訪問次數(shù)的三種方案
0. 前言
準(zhǔn)備一個(gè)Controller,用來測(cè)試。
@RestController
@RequestMapping("test")
@Tag(name = "測(cè)試",description = "測(cè)試springMVC攔截器實(shí)現(xiàn)記錄訪問次數(shù)")
public class TestController {
@GetMapping("getInfo/{id}")
public String test(@PathVariable Integer id) {
switch (id){
case 1:
return "1";
case 2:
return "2";
default:
return "3";
}
}
}
訪問次數(shù),記錄用戶訪問的次數(shù),一般有如下幾種方案:
1. 使用Filter實(shí)現(xiàn)
emm有點(diǎn)麻煩,以后再說。
2. 使用AOP實(shí)現(xiàn)
1. 導(dǎo)入依賴
<!-- AOP依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 寫一個(gè)切面類,實(shí)現(xiàn)統(tǒng)計(jì)訪問次數(shù)。
@Aspect // 表示這是一個(gè)切面
@Component // 托管到spring容器中
public class AccessRecordAspect {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
// 定義切點(diǎn) 匹配TestController中的test*方法
@Pointcut("execution(* com.huan.web.controllers.TestController.test*(..))")
public void a(){}
// 使用后置增強(qiáng),在方法正確執(zhí)行后執(zhí)行
@AfterReturning("a()")
public void record(JoinPoint joinPoint){
System.out.println("記錄訪問記錄");
// 獲取目標(biāo)方法參數(shù)
Object[] args = joinPoint.getArgs();
System.out.println(args[0]);
redisTemplate.opsForValue().increment("訪問的數(shù)據(jù):"+args[0]);
}
}
3. 開啟AOP
@Configuration
@ComponentScan
@EnableCaching // 開啟緩存功能
@EnableAspectJAutoProxy // 開啟aop功能
public class AppConfig {
}
4. 測(cè)試
訪問http://localhost:8080/test/getInfo/1 進(jìn)行測(cè)試,測(cè)試結(jié)果。



5. plus版本
使用循環(huán)增強(qiáng)實(shí)現(xiàn),并將將redis中的記錄的數(shù)據(jù)返回給前端。
(1) 新建一個(gè)bean類
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class TestBean {
private Integer id;
private Long praise;
}
(2) 新增一個(gè)controller方法
在新增的controller方法中,返回一個(gè)map,將數(shù)據(jù)返回給前端。
@GetMapping("getInfo-getPraise/{id}")
public Map<String,Object> testPraise(@PathVariable Integer id) {
Map<String,Object> map = new HashMap<>();
TestBean testBean = null;
testBean.setId(id);
map.put("code",1);
map.put("obj",testBean);
return map;
}
(3) 新增一個(gè)循環(huán)增強(qiáng)方法
在新增的循環(huán)增強(qiáng)方法中,統(tǒng)計(jì)訪問次數(shù),并將訪問次數(shù)返回給前端。
@Pointcut("execution(* com.huan.web.controllers.TestController.testPraise*(..))")
public void c(){}
@Around("c()")
public Object showPraise_test(ProceedingJoinPoint joinPoint){
System.out.println("showPraise_test顯示點(diǎn)贊數(shù)");
//運(yùn)行目標(biāo)方法返回的值
Object proceed = null;
try {
proceed = joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
Map<String,Object> map = (Map<String, Object>) proceed;
TestBean testBean = (TestBean) map.get("obj");
testBean.setPraise(redisTemplate.opsForValue().increment("PraiseNumById-test:"+testBean.getId()));
return proceed;
}
(4) 測(cè)試

3. 使用springMVC攔截器實(shí)現(xiàn)
1. 配置攔截器
@Configuration
@ComponentScan("com.huan.web")
public class InterceptorConfig implements WebMvcConfigurer {
//這里需要注入攔截器,確保 RedisTemplate 在攔截器之前被正確創(chuàng)建和注入
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//將一個(gè)新的 MyInterceptor 實(shí)例添加到攔截器注冊(cè)表中
//攔截/resfood/getById-map/*所有請(qǐng)求
registry.addInterceptor(myInterceptor).addPathPatterns(
"/resfood/getById-map/**");
}
}注意如果這里沒有注入攔截器,可能會(huì)因?yàn)橛捎?nbsp;RedisTemplate 沒有正確注入到你的攔截器中導(dǎo)致空指針異常(如下圖)。

2. 定義攔截器
在攔截器中使用RedisTemplate記錄訪問的次數(shù)。
@Component
public class MyInterceptor implements HandlerInterceptor {
/*
Spring Data Redis 提供的一個(gè)模板類,用于簡(jiǎn)化與 Redis 數(shù)據(jù)庫(kù)的交互
類似于map類型,可以存儲(chǔ)和檢索各種類型的數(shù)據(jù),包括字符串、對(duì)象、集合等。
但是,它提供了一些額外的功能,如鍵的過期時(shí)間、哈希表操作、列表操作等。
*/
@Autowired
private RedisTemplate<String,Object> redisTemplate;
/**
* 在請(qǐng)求處理之后,視圖渲染之前執(zhí)行,用于進(jìn)行資源清理
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
//輸出接收的請(qǐng)求
System.out.println(request.getRequestURI());
String[] key = request.getRequestURI().split("/");
System.out.println(Arrays.toString(key));
// 操作值 自增1 鍵名為key[2]+":"+key[3]形成的新字符串
redisTemplate.opsForValue().increment(key[2]+":"+key[3]);
}
}3. 控制器類
寫一個(gè)簡(jiǎn)單的測(cè)試的控制器類。
@RestController
@RequestMapping("test")
//swagger注解
@Tag(name = "測(cè)試",description = "測(cè)試springMVC攔截器實(shí)現(xiàn)記錄訪問次數(shù)")
public class TestController {
//rest風(fēng)格url
@GetMapping("getInfo/{id}")
public String test(@PathVariable Integer id) {
switch (id){
case 1:
return "1";
case 2:
return "2";
default:
return "3";
}
}
}4. 測(cè)試
在測(cè)試前在idea中查看redis中的數(shù)據(jù),在測(cè)試前redis中沒有任何數(shù)據(jù)。

在瀏覽器地址欄(或其他工具)輸入localhost:8080/test/getInfo/1,進(jìn)行測(cè)試。

控制臺(tái)輸出。


再次查看redis中的數(shù)據(jù),發(fā)現(xiàn)多了鍵值,也記錄了訪問數(shù)據(jù)。
以上就是使用Redis實(shí)現(xiàn)記錄訪問次數(shù)的三種方案的詳細(xì)內(nèi)容,更多關(guān)于Redis記錄訪問次數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
聊一聊redis奇葩數(shù)據(jù)類型與集群知識(shí)
現(xiàn)在越來越多的項(xiàng)目都會(huì)利用到redis,多實(shí)例redis服務(wù)比單實(shí)例要復(fù)雜的多,這里面涉及到定位、容錯(cuò)、擴(kuò)容等技術(shù)問題,下面這篇文章主要給大家介紹了關(guān)于redis奇葩數(shù)據(jù)類型與集群知識(shí)的相關(guān)資料,需要的朋友可以參考下2022-01-01
Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄的示例代碼
本文主要介紹了基于Redis如何實(shí)現(xiàn)短信驗(yàn)證碼登錄功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
Redis Cluster集群數(shù)據(jù)分片機(jī)制原理
這篇文章主要介紹了Redis Cluster集群數(shù)據(jù)分片機(jī)制原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
詳解如何利用Redis實(shí)現(xiàn)生成唯一ID
隨著下單流量逐漸上升,為了降低數(shù)據(jù)庫(kù)的訪問壓力,需要通過請(qǐng)求唯一ID+redis分布式鎖來防止接口重復(fù)提交。今天我們就一起來看探討一下,如何通過服務(wù)端來完成請(qǐng)求唯一?ID?的生成2022-11-11

