使用Redis實現(xiàn)記錄訪問次數(shù)的三種方案
0. 前言
準備一個Controller,用來測試。
@RestController @RequestMapping("test") @Tag(name = "測試",description = "測試springMVC攔截器實現(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實現(xiàn)
emm有點麻煩,以后再說。
2. 使用AOP實現(xiàn)
1. 導(dǎo)入依賴
<!-- AOP依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2. 寫一個切面類,實現(xiàn)統(tǒng)計訪問次數(shù)。
@Aspect // 表示這是一個切面 @Component // 托管到spring容器中 public class AccessRecordAspect { @Autowired private RedisTemplate<String,Object> redisTemplate; // 定義切點 匹配TestController中的test*方法 @Pointcut("execution(* com.huan.web.controllers.TestController.test*(..))") public void a(){} // 使用后置增強,在方法正確執(zhí)行后執(zhí)行 @AfterReturning("a()") public void record(JoinPoint joinPoint){ System.out.println("記錄訪問記錄"); // 獲取目標方法參數(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. 測試
訪問http://localhost:8080/test/getInfo/1
進行測試,測試結(jié)果。
5. plus版本
使用循環(huán)增強實現(xiàn),并將將redis中的記錄的數(shù)據(jù)返回給前端。
(1) 新建一個bean類
@Data @AllArgsConstructor @NoArgsConstructor @ToString public class TestBean { private Integer id; private Long praise; }
(2) 新增一個controller方法
在新增的controller方法中,返回一個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) 新增一個循環(huán)增強方法
在新增的循環(huán)增強方法中,統(tǒng)計訪問次數(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顯示點贊數(shù)"); //運行目標方法返回的值 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) 測試
3. 使用springMVC攔截器實現(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) { //將一個新的 MyInterceptor 實例添加到攔截器注冊表中 //攔截/resfood/getById-map/*所有請求 registry.addInterceptor(myInterceptor).addPathPatterns( "/resfood/getById-map/**"); } }
注意如果這里沒有注入攔截器,可能會因為由于 RedisTemplate
沒有正確注入到你的攔截器中導(dǎo)致空指針異常(如下圖)。
2. 定義攔截器
在攔截器中使用RedisTemplate記錄訪問的次數(shù)。
@Component public class MyInterceptor implements HandlerInterceptor { /* Spring Data Redis 提供的一個模板類,用于簡化與 Redis 數(shù)據(jù)庫的交互 類似于map類型,可以存儲和檢索各種類型的數(shù)據(jù),包括字符串、對象、集合等。 但是,它提供了一些額外的功能,如鍵的過期時間、哈希表操作、列表操作等。 */ @Autowired private RedisTemplate<String,Object> redisTemplate; /** * 在請求處理之后,視圖渲染之前執(zhí)行,用于進行資源清理 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); //輸出接收的請求 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. 控制器類
寫一個簡單的測試的控制器類。
@RestController @RequestMapping("test") //swagger注解 @Tag(name = "測試",description = "測試springMVC攔截器實現(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. 測試
在測試前在idea中查看redis中的數(shù)據(jù),在測試前redis中沒有任何數(shù)據(jù)。
在瀏覽器地址欄(或其他工具)輸入localhost:8080/test/getInfo/1,進行測試。
控制臺輸出。
再次查看redis中的數(shù)據(jù),發(fā)現(xiàn)多了鍵值,也記錄了訪問數(shù)據(jù)。
以上就是使用Redis實現(xiàn)記錄訪問次數(shù)的三種方案的詳細內(nèi)容,更多關(guān)于Redis記錄訪問次數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis高級玩法之利用SortedSet實現(xiàn)多維度排序的方法
Redis的SortedSet是可以根據(jù)score進行排序的,以手機應(yīng)用商店的熱門榜單排序為例,根據(jù)下載量倒序排列。接下來通過本文給大家分享Redis高級玩法之利用SortedSet實現(xiàn)多維度排序的方法,一起看看吧2019-07-07redis 解決庫存并發(fā)問題實現(xiàn)數(shù)量控制
本文主要介紹了redis 解決庫存并發(fā)問題實現(xiàn)數(shù)量控制,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04基于?Spring?Aop?環(huán)繞通知實現(xiàn)?Redis?緩存雙刪功能(示例代碼)
基于 spring aop 常規(guī)應(yīng)用場景多是用于日志記錄以及實現(xiàn) redis 分布式鎖,在 github 中也有項目是把它拿來當(dāng)作緩存的異常捕捉,這篇文章主要介紹了基于?Spring?Aop?環(huán)繞通知實現(xiàn)?Redis?緩存雙刪,需要的朋友可以參考下2022-08-08