Redis--黑馬點評--達人探店功能實現詳解

達人探店

發布探店筆記

探店筆記類似于點評網站的評價,往往是圖文結合,對應的表有兩個:

  • tb_blog:探店筆記表,包含筆記中的標題、文字、圖片等

  • tb_blog_comments:其他用戶對探店筆記的評價

tb_blog表結構如下:

image-20250702181240618

可以從結構中看出,跟發布探店筆記相關的字段有shop_id,title,images,content,liked,comments

業務流程:

點擊首頁最下方菜單欄的+按鈕,即可發布探店圖文:

image-20250702181724959

image-20250702181739831

需要注意的是發布照片與發布筆記是兩個分離的功能,因為上傳照片的功能不僅僅是發筆記有這個需求,在其他業務中可能也會需要發布照片,因此上傳照片功能是一個獨立功能,點擊上傳照片時會先發出一個請求實現上傳,上傳成功后返回這張圖片的地址,也就是上傳之后的可訪問的地址,這個地址就會做為表單的參數,在發布筆記時一起提交到后臺,即在發布筆記時上傳的其實不是照片的本身,而是上傳成功后的圖片地址,因此發布照片和發布筆記是不同的功能,會發起兩個不同的請求。

而黑馬點評這邊已經將接口寫好了,http: //127.0.0.1:8081/upload/blog,這個接口是為了上傳圖片的,因此需要修改存放的地址,是將其存放在前端服務器中的目錄中,另一個接口http: //127.0.0.1:8081/blog,上傳博客。

測試接口:

image-20250702221715696

image-20250702222000809

可以查看數據庫表:

image-20250702222120371

而在發布完探店筆記后,發現沒有實現查看探店筆記的接口。

image-20250702222431898

因此:

案例展示:實現查看探店筆記的接口

需求:點擊首頁的探店筆記,會進入詳情頁面,實現該頁面的查詢接口:

controller層:

@GetMapping("/{id}")
public Result queryBlog(@PathVariable("id") Long id){return blogService.queryBlogById(id);
}

service層

@Override
public Result queryBlogById(Long id) {// 1.查詢blogBlog blog = getById(id);if (blog == null) {return Result.fail("筆記不存在!");}// 2.查詢blog有關的用戶queryBlogUser(blog);return Result.ok(blog);
}private void queryBlogUser(Blog blog) {Long userId = blog.getUserId();User user = userService.getById(userId);blog.setName(user.getNickName());blog.setIcon(user.getIcon());}

測試:

image-20250702230047012

點贊

在首頁的探店筆記排行榜和探店圖文詳情頁面都有點贊功能:

在Java代碼中直接利用MyBatisPlus來修改數據庫中的liked字段,每一次點贊都是進行一次接口請求,并且沒有點贊限制,沒有進行用戶判斷。而且是直接修改數據庫,影響性能。

案例:完善點贊功能

需求:

  • 同一個用戶只能點贊一次,再次點擊則為取消點贊

  • 如果當前用戶已經點贊,則點贊按鈕高亮(前端已實現,判斷字段blog類的isLike屬性)

實現思路:可以在新建一個表,記錄筆記的id,以及點贊用戶的id,這樣每次點贊只需要看表中存在不存在這個用戶的值即可,不需要去使用MySQL數據庫,可以使用輕量級的數據庫,比如redis,可以使用集合類的數據結構,key為筆記的id,value則為點贊的用戶id,并且一個用戶只能點贊一次,所以value不能重復,所以可以使用set數據結構。

實現步驟:

  1. 給blog類中添加一個isLike字段,標識是否被當前用戶點贊

  2. 修改點贊功能,利用redis的set集合判斷是否點贊過,未點贊過則點贊數+1,已點贊過則點贊數-1,并且點贊過的用戶需要添加在set集合中。

  3. 修改根據id查詢blog的業務,判斷當前登錄用戶是否點贊過,賦值給isLike字段

  4. 修改分頁查詢blog業務,判斷當前登錄用戶是否點贊過,賦值給isLike字段

代碼實現:

?/*** 用戶圖標*/@TableField(exist = false)private String icon;/*** 用戶姓名*/@TableField(exist = false)private String name;/*** 是否點贊過了*///該注解表示該成員變量不是數據庫表中的字段@TableField(exist = false)private Boolean isLike;

service層業務代碼:

?public Result likeBlog(Long id) {//1.獲取登錄用戶Long userId = UserHolder.getUser().getId();//2.判斷當前登錄用戶是否已經點贊String key = BLOG_LIKED_KEY + id;Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());if(Boolean.FALSE.equals(isMember)){//3.如果未點贊,可以點贊//3.1點贊數+1boolean success = lambdaUpdate().set(Blog::getLiked, getById(id).getLiked() + 1).eq(Blog::getId, id).update();//3.2,將用戶id存儲到redis的set集合中if (success) {stringRedisTemplate.opsForSet().add(key, userId.toString());}}else {//4.如果已點贊,取消點贊//4.1.數據庫點贊數-1,boolean success = lambdaUpdate().set(Blog::getLiked, getById(id).getLiked() - 1).eq(Blog::getId, id).update();//4.2將用戶id從Redis的set集合中刪除if (success) {stringRedisTemplate.opsForSet().remove(key, userId.toString());}}return Result.ok();}

其次,我們還需要修改查詢blog的業務代碼,在查詢用戶之后,還需要查詢該博客是否被點贊,再去修改isLiked的值。

由于查詢有兩種查詢,一種分頁查詢,一種普通查詢,因此我們將是否被點贊這個業務封裝成函數,進行簡化代碼。

代碼實現:

private void isBlogLiked(Blog blog) {Long userId = UserHolder.getUser().getId();String key = BLOG_LIKED_KEY + blog.getId();Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());//防止包裝類為空blog.setIsLike(Boolean.TRUE.equals(isMember));}

進行測試:

進行點贊:

image-20250705160213204

檢查redis數據庫:

image-20250705160227537

取消點贊:

image-20250705160325467

再次查看Redis數據庫:

發現已經不存在。

至此業務實現成功。

點贊排行榜

業務詳情:

在探店筆記的詳情頁面,應該把給該筆記點贊的人顯示出來,比如最早點贊的top5,形成點贊排行榜:

我們可以借鑒微信朋友圈點贊的機制。誰先點贊,誰在前面

接口信息:

image-20250705161123523

案例實現:實現查詢點贊排行榜的接口

需求:按照點贊時間先后排序,返回top5的用戶

思路分析:

我們需要按照點贊時間先后排序,但是點贊的用戶信息存儲在redis中的set集合里,set集合是無序集合,因此我們需要去更換集合,同時還要滿足唯一性與有序性,將Redis中的集合數據結構進行對比。

ListSetSortedSet
排序方式按添加順序排序無序可排序,根據score值
唯一性不唯一唯一唯一
查找方式按照索引查找或者首尾查找按照元素查找根據元素查找

由此看來,SortedSet更符合業務需求。

但是SortedSet和set有很多不同之處,就別去set中有sismember命令去查詢某個元素是否在集合內,但是SortedSet就沒有這樣的命令,但是我們可以使用zscore命令來查詢score值,如果元素不存在則score值就不存在,如果存在則有score值。這個命令也可以判斷元素是否存在。如果查詢排行榜可以使用zrange命令來查詢。zrange命令就是查找范圍內的元素。并且會天然的排序,可以按照時間戳來排序時,就會按照時間戳從小到大排序,最早插入的在最前面,這樣就可以完成查詢排行榜的業務。

思路實現:

改造之前的點贊業務,將set集合替換為SortedSet集合:

?private void isBlogLiked(Blog blog) {Long userId = UserHolder.getUser().getId();String key = BLOG_LIKED_KEY + blog.getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());//防止包裝類為空blog.setIsLike(score != null);}?@Overridepublic Result likeBlog(Long id) {//1.獲取登錄用戶Long userId = UserHolder.getUser().getId();//2.判斷當前登錄用戶是否已經點贊String key = BLOG_LIKED_KEY + id;Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());if(score == null){//3.如果未點贊,可以點贊//3.1點贊數+1boolean success = lambdaUpdate().set(Blog::getLiked, getById(id).getLiked() + 1).eq(Blog::getId, id).update();//3.2,將用戶id存儲到redis的set集合中if (success) {stringRedisTemplate.opsForZSet().add(key, userId.toString(),System.currentTimeMillis());}}else {//4.如果已點贊,取消點贊//4.1.數據庫點贊數-1,boolean success = lambdaUpdate().set(Blog::getLiked, getById(id).getLiked() - 1).eq(Blog::getId, id).update();//4.2將用戶id從Redis的set集合中刪除if (success) {stringRedisTemplate.opsForZSet().remove(key, userId.toString());}}return Result.ok();}

實現排行榜接口:

?@Overridepublic Result queryBlogLikes(Long id) {//1.獲取當前blog的點贊top5String key = BLOG_LIKED_KEY + id;Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);//2.解析出其中的用戶id,map映射,將long類型的字符串轉為Longif (top5 == null || top5.isEmpty()) {return Result.ok(Collections.emptyList());}List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());//3.根據用戶ID查詢用戶,這里直接返回的是user對象,但是在前端頁面應該顯示的是UserDTO,所以這里需要將user對象轉為UserDTO對象List<UserDTO> userDTOS = userService.listByIds(ids).stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());//4.返回return Result.ok(userDTOS);}

進行測試:

先嘗試一個賬號點贊:

image-20250705172826834

測試成功,在進行多個賬戶點贊:

發現bug:新開網頁時,發現下面的博客不登錄看不到,根據報錯提示發現是空指針異常,即userid為空,解決方案,在從UserHolder中取user時先進行判斷,如果為空,則直接return;

代碼演示:

private void isBlogLiked(Blog blog) {UserDTO user = UserHolder.getUser();if (user == null){return;}Long userId = user.getId();String key = BLOG_LIKED_KEY + blog.getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());//防止包裝類為空blog.setIsLike(score != null);}

解決;

繼續測試:

image-20250705173141042

發現順序不對,去IDEA中檢查:

image-20250705173222559

發現順序是對的,在進入數據庫中查詢:

image-20250705172647714

發現是使用關鍵字in的問題,

因此要使用order by ,但不能直接指定id,因為默認order by id 的話是按順序從小到大的,因此要指定順序:

image-20250705173758401

因此需要修改查詢語句,又因為MyBatisPlus沒有封裝該方法,只能去自定義SQL語句。

修改代碼如下:

?//3.根據用戶ID查詢用戶,這里直接返回的是user對象,但是在前端頁面應該顯示的是UserDTO,所以這里需要將user對象轉為UserDTO對象//where id in (ids) order by field(id,ids)List<UserDTO> userDTOS = userService.lambdaQuery().in(User::getId, ids).last("order by field(id,"+ idStr+")").list().stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());

再次進行刷新測試:

image-20250705180255556

至此,點贊排行榜業務實現成功。

希望對大家有所幫助!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87774.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87774.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87774.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一探 3D 互動展廳的神奇構造?

3D 互動展廳的神奇之處&#xff0c;離不開一系列先進技術的強力支撐 。其中&#xff0c;VR(虛擬現實)技術無疑是核心亮點之一。通過佩戴 VR 設備&#xff0c;觀眾仿佛被瞬間 “傳送” 到一個全新的世界&#xff0c;能夠全身心地沉浸其中&#xff0c;360 度無死角地觀察周圍的一…

C++ 網絡編程(15) 利用asio協程搭建異步服務器

&#x1f680; [協程與異步服務器實戰]&#xff1a;[C20協程原理與Boost.Asio異步服務器開發] &#x1f4c5; 更新時間&#xff1a;2025年07月05日 &#x1f3f7;? 標簽&#xff1a;C20 | 協程 | Boost.Asio | 異步編程 | 網絡服務器 文章目錄前言一、什么是協程&#xff1f;二…

【Java21】在spring boot中使用虛擬線程

文章目錄 0.環境說明1.原理解析2.spring boot的方案3.注意事項&#xff08;施工中&#xff0c;歡迎補充&#xff09; 前置知識 虛擬線程VT&#xff08;Virtual Thread&#xff09; 0.環境說明 用于驗證的版本&#xff1a; spring boot: 3.3.3jdk: OpenJDK 21.0.5 spring boot…

利器:NPM和YARN及其他

文章目錄**1. 安裝 Yarn&#xff08;推薦方法&#xff09;****2. 驗證安裝****3. 常見問題及解決方法****① 權限不足&#xff08;Error: EPERM&#xff09;****② 網絡問題&#xff08;連接超時或下載失敗&#xff09;****③ 環境變量未正確配置****4. 替代安裝方法&#xff0…

跨平臺直播美顏SDK集成實錄:Android/iOS如何適配貼紙功能

眾所周知&#xff0c;直播平臺與短視頻平臺的貼紙功能不僅是用戶表達個性的方式&#xff0c;更是平臺提高用戶粘性和互動轉化的法寶。 可問題來了&#xff1a;如何讓一個貼紙功能&#xff0c;在Android和iOS兩大平臺上表現一致、運行流暢、加載穩定&#xff1f;這背后&#xff…

JavaWeb(蒼穹外賣)--學習筆記04(前端:HTML,CSS,JavaScript)

前言 本片文章是學習B站黑馬程序員蒼穹外賣的學習筆記。因為最近期末周&#xff0c;一直在應付考試所以就學的很少&#xff0c;恰好視頻中在講Nginx反向代理和負載均衡&#xff08;寫著對前端的內容做一個復習&#xff09; 概述&#xff1a; 1.web前端主要由三部分組成&…

智能學號抽取系統 V5.4.3.2 —— Vue.js 實現的多功能課堂隨機抽簽工具

智能學號抽取系統 V5.4.3.2 —— Vue.js 實現的多功能課堂隨機抽簽工具 在教學或會議場景中&#xff0c;我們經常需要隨機抽取一個或多個學號/編號來決定發言者、答題者或者參與者。為了提高效率和公平性&#xff0c;我們可以使用一些智能化的小工具來實現這一過程。 今天介紹…

從0開始學習R語言--Day39--Spearman 秩相關

在非參數統計中&#xff0c;不看數據的實際數值&#xff0c;單純比較兩組變量的值的排名是通用的基本方法&#xff0c;但在客觀數據中&#xff0c;很多變量的關系都是非線性的&#xff0c;其他的方法不是對樣本數據的大小和線性有要求&#xff0c;就是只能對比數據的差異性&…

WSL - Linux 安裝 Anaconda3-2025.06-0 詳細教程 [WSL 分發版均適用]

一、檢查系統狀態 安裝前先確認 WSL - Linxu 已正常啟動&#xff08;比如 Ubuntu&#xff09;&#xff0c;網絡連接穩定&#xff0c;并且系統磁盤有足夠空間&#xff0c;一般建議預留至少 5GB 以上的可用空間&#xff0c;避免因空間不足導致安裝失敗。 二、下載安裝包 Anacond…

熱血三國建筑攻略表格

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>熱血三國建筑攻略表格</title><style>…

SpringBoot+MySQL醫院掛號系統源碼

概述 基于SpringBootMySQL開發的醫院掛號系統完整源碼&#xff0c;該系統功能完善&#xff0c;包含從患者掛號到醫生管理的全流程解決方案&#xff0c;采用主流技術棧開發&#xff0c;代碼規范易于二次開發。 主要內容 系統包含完整的前后臺功能模塊&#xff1a; ??前臺功…

Linux系統之MySQL數據庫基礎

目錄 一、概述 數據庫概念 數據庫的類型 關系型數據庫模型 關系數據庫相關概念 二、安裝 1、mariadb安裝 2、mysql安裝 3、啟動并開機自啟 4、本地連接&#xff08;本地登錄&#xff09; 三、mysqld數據庫配置與命令 yum安裝后生成的目錄 mysqld服務器的啟動腳本 …

MySQL--InnoDB存儲引擎--頁結構

目錄 一、頁的大小 二、頁的分類 三、頁頭和頁尾 3.1 頁頭--File Header 3.2 頁尾--File Trailer 3.3 LSN 四、數據行 五、頁中數據的查詢 六、事務和索引在頁中的記錄 一、頁的大小 前面介紹了每個數據頁默認大小為16KB&#xff0c;是操作系統“數據塊” 4KB 的整數倍…

卡車檢測數據集-700張圖片交通運輸管理 智能監控系統 道路安全監測

跌倒檢測數據集-4500張圖片&#x1f4e6; 已發布目標檢測數據集合集&#xff08;持續更新&#xff09;&#x1f69b; Deteccin de carpa 2 Computer Vision Project&#x1f4cc; 數據集概覽包含類別&#x1f3af; 應用場景&#x1f5bc; 數據樣本展示&#x1f527; 使用建議&a…

Python爬蟲實戰:研究pangu庫相關技術

1. 引言 1.1 研究背景與意義 在數字化信息傳播時代,中文文本排版質量直接影響信息傳達效果。規范的排版要求中文與西文、數字間保持合理空格間距,但人工處理不僅效率低,且易出現一致性問題。隨著互聯網中文內容爆發式增長,傳統人工排版已無法滿足需求。Python 作為高效的…

day48-考試系統項目集群部署

1. ?考試系統項目集群架構圖負載均衡說明7層負載通過nginx對http請求進行轉發&#xff08;uri,ua,類型&#xff09;4層負載對端口負載均衡&#xff08;后端&#xff09;2. &#x1f4dd;環境準備角色主機ip負載均衡lb01/lb02172.16.1.5/172.16.1.6前端web集群web01/web02172.1…

Redis+Caffeine雙層緩存策略對比與實踐指南

RedisCaffeine雙層緩存策略對比與實踐指南在高并發場景下&#xff0c;緩存是提升系統性能和并發處理能力的關鍵手段。常見的緩存方案包括遠程緩存&#xff08;如Redis&#xff09;和本地緩存&#xff08;如Caffeine&#xff09;。單層緩存各有優劣&#xff0c;結合兩者優勢的雙…

FastAPI+React19 ERP系統實戰 第02期

一、搭建環境 1.1 創建Python虛擬環境 切換Python版本: pyenv local 3.12創建虛擬環境: python -m venv venv激活虛擬環境: venv\Scripts\activate1.2 安裝FastAPI項目依賴 requirements.txt fastapi==0.109.1

百度AI文心大模型4.5系列開源模型評測,從安裝部署到應用體驗

2025年6月30日&#xff0c;百度突然宣布&#xff0c;將旗下最新的大語言模型文心大模型4.5&#xff08;ERNIE 4.5&#xff09;全系列開源&#xff0c;震動整個AI行業。百度在GitCode平臺上開源了文心大模型4.5系列&#xff0c;包括ERNIE-4.5-VL-424B-A47B-Base-PT等多個型號。此…

windows安裝maven環境

在maven官網下載安裝包 https://maven.apache.org/download.cgi 下載完成后安裝maven&#xff0c;一般下載編輯好的 創建個maven目錄解壓出來即可 配置環境變量 根據剛剛的安裝路徑&#xff0c;新建一個命名為MAVEN_HOME的系統變量 新建完成點開系統變量的Path項&#xff0c;…