日韩精品一区二区三区在线视频放-无码中文字幕V?一区二区-成年片免费观看视频-国内少妇人妻丰满av-国产精品中文字幕免费观看-亚洲成人久久一区二区三区-国内少妇偷人精品视频无缓冲-一区二区国产精品日本一区二区三区在线网

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

SpringBoot+Vue實(shí)現(xiàn)個(gè)性化音樂推薦系統(tǒng):協(xié)同過濾與工程化實(shí)踐

SpringBoot+Vue實(shí)現(xiàn)個(gè)性化音樂推薦系統(tǒng):協(xié)同過濾與工程化實(shí)踐 做音樂推薦系統(tǒng)之前我以為最麻煩的部分是推薦算法。真正把SpringBoot后端和Vue前端完全打通、讓推薦結(jié)果在頁面上流暢跑起來之后我才意識(shí)到算法只占三成工作量剩下七成全在工程化——用戶行為怎么埋點(diǎn)、數(shù)據(jù)怎么清洗、冷啟動(dòng)怎么解決、前后端怎么聯(lián)調(diào)、部署環(huán)境怎么兼容。這篇博文就是把我從零搭完這套“基于SpringBoot Vue的個(gè)性化音樂推薦系統(tǒng)”的完整過程、技術(shù)選型邏輯和踩坑記錄整理出來給正準(zhǔn)備做同類項(xiàng)目或者想入門推薦系統(tǒng)實(shí)戰(zhàn)的同學(xué)一個(gè)可復(fù)現(xiàn)的參考。1. 整體設(shè)計(jì)與技術(shù)選型思路1.1 項(xiàng)目定位先想清楚是“練手項(xiàng)目”還是“可上線系統(tǒng)”開始動(dòng)工之前我反復(fù)問自己一個(gè)問題這個(gè)音樂推薦系統(tǒng)做出來是給自己交作業(yè)用的還是真的能支撐小規(guī)模用戶使用的這個(gè)定位差別非常大直接影響技術(shù)選型和代碼組織方式。如果只是一個(gè)課程設(shè)計(jì)級(jí)別的demo完全可以用內(nèi)存HashMap模擬用戶行為數(shù)據(jù)前端頁面走個(gè)過場(chǎng)算法隨便寫個(gè)相似度計(jì)算就能交差。但如果想做成一個(gè)架構(gòu)清晰、能擴(kuò)展、能部署到服務(wù)器上給別人試聽的項(xiàng)目就必須把以下問題全部考慮進(jìn)去用戶行為數(shù)據(jù)播放、收藏、下載、跳過需要持久化存儲(chǔ)并且要支持后續(xù)增量更新推薦引擎要獨(dú)立于業(yè)務(wù)代碼至少能做到每天定時(shí)算一次而不是每次請(qǐng)求都全量計(jì)算前后端要徹底分離接口要標(biāo)準(zhǔn)化前端不能依賴后端模板渲染歌曲文件、封面圖片需要靜態(tài)資源管理方案音頻流播放要解決跨域和格式兼容問題。我自己定的目標(biāo)是做一個(gè)“介于demo和商業(yè)系統(tǒng)之間”的項(xiàng)目前后端分離、具備完整的用戶體系、推薦算法可選擇離線計(jì)算或?qū)崟r(shí)計(jì)算兩條路徑、部署方案支持Docker。這樣項(xiàng)目既能拿得出手講架構(gòu)又不會(huì)因?yàn)檫^度設(shè)計(jì)把自己拖死。1.2 后端為什么選SpringBoot而不是其他框架現(xiàn)在Java后端框架基本被SpringBoot統(tǒng)治了選它不稀奇但我還是想說說它在這個(gè)項(xiàng)目里的幾個(gè)不可替代的優(yōu)勢(shì)。首先是快速構(gòu)建RESTful API的能力。音樂推薦系統(tǒng)本質(zhì)上是一個(gè)接口密集型項(xiàng)目用戶登錄注冊(cè)、歌曲搜索、歌單管理、行為上報(bào)、推薦拉取大大小小加起來有四五十個(gè)接口。SpringBoot的starter機(jī)制加上注解式開發(fā)讓我不用關(guān)心復(fù)雜的XML配置一個(gè)RestController就能搞定一個(gè)模塊。配合Lombok實(shí)體類也不用寫一堆getter/setter開發(fā)效率比傳統(tǒng)SSH高了好幾個(gè)檔次。其次是生態(tài)成熟度。推薦系統(tǒng)繞不開數(shù)據(jù)存儲(chǔ)和緩存SpringBoot對(duì)MySQL、Redis、MongoDB都有非常成熟的starter支持。我在項(xiàng)目里用Redis緩存熱門歌曲和用戶推薦結(jié)果只需要幾行配置就能接入省去了大量底層代碼。第三是部署友好。項(xiàng)目最終要跑在Linux服務(wù)器上SpringBoot內(nèi)嵌Tomcat打包成jar直接java -jar啟動(dòng)不需要單獨(dú)安裝Tomcat容器。這一點(diǎn)在做Docker鏡像時(shí)非常省事——基礎(chǔ)鏡像基于openjdk拿到j(luò)ar包就能跑體積小、啟動(dòng)快。當(dāng)然SpringBoot也有它的問題最大的就是版本兼容性。如果你的JDK版本比較新比如JDK17老版本的SpringBoot2.x會(huì)有一些潛在地雷后面我會(huì)單獨(dú)講這塊。1.3 前端選Vue 3而不是Vue 2的原因和代價(jià)前端框架我選的是Vue 3 Vite Element Plus這套組合。熱搜詞里一大堆vue安裝、vue路由、vue播放m3u8的問題說明很多人在Vue環(huán)境上卡過殼所以我額外多說幾句選型理由。Vue 3相比Vue 2最大的提升是Composition API。做音樂播放器這種狀態(tài)復(fù)雜的界面邏輯復(fù)用非常關(guān)鍵。我用Composition API把播放邏輯抽成了一個(gè)usePlayer的hook頁面組件里只需要調(diào)用這個(gè)hook就能控制播放、暫停、切歌、管理播放列表代碼復(fù)用性比Options API好了不只一個(gè)檔次。如果是Vue 2這套邏輯寫起來會(huì)非常別扭mixin的命名沖突問題也讓人頭疼。Vite替代Webpack也是一個(gè)加速選擇。項(xiàng)目開發(fā)階段Vite的冷啟動(dòng)速度幾乎秒開熱更新也快不像Webpack改動(dòng)一個(gè)文件要等好幾秒。代價(jià)是Vite默認(rèn)只支持ESM有些老庫需要額外配置遇到兼容性問題要多花點(diǎn)時(shí)間。UI組件庫選的Element Plus表格、表單、分頁、彈窗這些后臺(tái)管理界面需要的組件都有現(xiàn)成的配合Vue 3的響應(yīng)式系統(tǒng)開發(fā)效率非常高。唯一需要注意的是Element Plus按需引入的配置網(wǎng)上教程很多版本不一致照著官方文檔來最穩(wěn)妥。1.4 推薦算法選型不迷信復(fù)雜模型先跑通協(xié)同過濾推薦算法我用了經(jīng)典的協(xié)同過濾Collaborative Filtering具體來說是物品協(xié)同過濾ItemCF。為什么不上深度學(xué)習(xí)模型原因很簡(jiǎn)單數(shù)據(jù)集規(guī)模不夠。這類個(gè)人項(xiàng)目一般也就幾千首歌曲、幾百個(gè)用戶這個(gè)規(guī)模下深度模型不僅訓(xùn)練慢效果也不一定比協(xié)同過濾好。協(xié)同過濾的優(yōu)點(diǎn)是算法直觀、實(shí)現(xiàn)成本低、效果可解釋只要代碼寫得干凈性能完全夠用。ItemCF的核心邏輯就一句話根據(jù)用戶的歷史行為找到與用戶喜歡的歌相似的其他歌曲然后推薦給用戶。相似度的計(jì)算基于“喜歡歌曲A的用戶是否也喜歡歌曲B”也就是通過用戶行為構(gòu)建歌曲之間的共現(xiàn)矩陣再算余弦相似度。這種方式不需要歌曲本身的任何內(nèi)容特征純靠用戶行為驅(qū)動(dòng)非常符合“個(gè)性化”這個(gè)項(xiàng)目的核心賣點(diǎn)。除了ItemCF我還做了一個(gè)基于內(nèi)容的粗糙推薦作為補(bǔ)充給每首歌曲打標(biāo)簽風(fēng)格、語種、年代用戶聽過的歌的標(biāo)簽加權(quán)平均繼續(xù)推薦同一風(fēng)格的歌曲。這部分代碼量不大但能解決協(xié)同過濾的冷啟動(dòng)問題。1.5 數(shù)據(jù)存儲(chǔ)設(shè)計(jì)MySQL存業(yè)務(wù)數(shù)據(jù)Redis管熱數(shù)據(jù)數(shù)據(jù)存儲(chǔ)我用了雙軌方案MySQL存用戶、歌曲、歌單、行為記錄、推薦結(jié)果快照等業(yè)務(wù)數(shù)據(jù)Redis緩存熱門歌曲、在線用戶狀態(tài)、推薦接口的熱數(shù)據(jù)。MySQL表結(jié)構(gòu)設(shè)計(jì)上特別注意了行為記錄表user_behavior的數(shù)據(jù)量預(yù)期。即使只有幾千用戶每個(gè)人的播放行為累積起來也會(huì)有幾十萬條記錄所以這張表必須建索引而且查詢要限定時(shí)間范圍和用戶維度。我在user_id和song_id上都建了聯(lián)合索引查詢效率在百萬級(jí)數(shù)據(jù)下基本在毫秒級(jí)。Redis在項(xiàng)目里承擔(dān)了三個(gè)職責(zé)一是存熱門歌曲榜二是存每個(gè)用戶的推薦結(jié)果緩存三是做登錄token的會(huì)話管理。推薦結(jié)果用Redis緩存這個(gè)設(shè)計(jì)很關(guān)鍵因?yàn)镮temCF離線計(jì)算完成后會(huì)寫庫但用戶頻繁刷新推薦頁不可能每次都去數(shù)據(jù)庫重新拉全量結(jié)果直接從Redis取字符串格式的歌曲ID列表性能差出了幾個(gè)量級(jí)。2. 核心功能模塊拆解與數(shù)據(jù)庫設(shè)計(jì)2.1 從用戶視角梳理功能清單做后臺(tái)系統(tǒng)之前我習(xí)慣先站在用戶視角畫一遍使用流程。整個(gè)音樂推薦系統(tǒng)的用戶側(cè)功能我提煉為五個(gè)大模塊用戶認(rèn)證模塊注冊(cè)、登錄、退出、個(gè)人信息維護(hù)。登錄成功后簽發(fā)JWT前端把Token存localStorage每次請(qǐng)求帶著Token后端通過攔截器校驗(yàn)身份。歌曲瀏覽模塊歌曲列表、歌手列表、專輯列表支持按風(fēng)格、語種、年代篩選支持模糊搜索歌名、歌手、歌詞。行為記錄模塊用戶在頁面上播放、切換、收藏、取消收藏、下載歌曲時(shí)前端向后端上報(bào)行為事件后端寫user_behavior表。推薦模塊首頁“猜你喜歡”推薦流、每日推薦歌單、相似歌曲推薦。推薦結(jié)果既支持離線計(jì)算好的也支持用戶實(shí)時(shí)行為觸發(fā)的小規(guī)模計(jì)算。播放器模塊前端播放器支持音頻播放、進(jìn)度拖拽、音量調(diào)節(jié)、循環(huán)模式切換、播放列表管理。版權(quán)合規(guī)范圍內(nèi)提供試聽音頻文件用靜態(tài)資源服務(wù)器托管。管理端功能相對(duì)簡(jiǎn)單歌曲管理增刪改查、上下架、用戶管理、行為數(shù)據(jù)統(tǒng)計(jì)、推薦算法參數(shù)配置排行榜權(quán)重比例、推薦數(shù)量上限。2.2 數(shù)據(jù)庫表結(jié)構(gòu)設(shè)計(jì)附關(guān)鍵字段解釋數(shù)據(jù)庫我建了8張核心表這里挑幾張關(guān)鍵的說說設(shè)計(jì)思路和容易踩的坑。user表用戶表字段包括id、username、passwordBCrypt加密存儲(chǔ)、nickname、avatar、created_time。注意username要做唯一索引注冊(cè)接口要處理并發(fā)情況下的重復(fù)注冊(cè)問題。song表歌曲表字段包括id、title、singer、album、duration、style、language、publish_date、audio_url、cover_url、play_count、status。其中audio_url字段在高潮部分有坑——部分音樂源返回到M3U8格式的流媒體地址前端直接放audio標(biāo)簽是播放不了的后面排查篇會(huì)詳細(xì)講。user_behavior表用戶行為表字段包括id、user_id、song_id、behavior_typeplay、collect、download、skip、create_time。這張表是推薦算法的數(shù)據(jù)基礎(chǔ)也是數(shù)據(jù)量最大的表。必須在user_id和song_id上建聯(lián)合索引behavior_type建議用int類型枚舉而不是varchar查詢更快存儲(chǔ)更省。recommend_result表推薦結(jié)果快照表字段包括id、user_id、song_idsJSON字符串、strategy_type、update_time。離線推薦任務(wù)跑完后寫入這張表前端拉推薦接口時(shí)直接從這張表取。playlist表和playlist_song表歌單表與歌單歌曲關(guān)聯(lián)表。維護(hù)用戶自定義歌單playlist_song表用聯(lián)合主鍵(playlist_id, song_id)防止重復(fù)添加。系統(tǒng)還設(shè)計(jì)了一張behavior_config表用來配置不同行為類型的權(quán)重分?jǐn)?shù)因?yàn)橥扑]算法計(jì)算用戶偏好分?jǐn)?shù)時(shí)不是簡(jiǎn)單計(jì)數(shù)而是加權(quán)求和播放一次算1分收藏算3分下載算5分完整聽完額外加2分跳過一首歌扣1分。這個(gè)權(quán)重是可配置的能通過管理頁面調(diào)整非常實(shí)用。2.3 推薦模塊的數(shù)據(jù)流從原始行為到推薦結(jié)果推薦模塊的完整數(shù)據(jù)流我總結(jié)為四個(gè)階段階段一是原始行為數(shù)據(jù)采集。前端各類播放事件觸發(fā)后上報(bào)到后端的/behavior/report接口接口校驗(yàn)Token拿到userId將行為數(shù)據(jù)寫入user_behavior表。階段二是離線計(jì)算任務(wù)。系統(tǒng)每天凌晨跑一次定時(shí)任務(wù)掃描最近30天的用戶行為數(shù)據(jù)構(gòu)建用戶-歌曲評(píng)分矩陣計(jì)算歌曲之間的相似度矩陣然后為每個(gè)用戶生成TopN推薦列表寫入recommend_result表。階段三是推薦結(jié)果緩存。定時(shí)任務(wù)跑完后把每個(gè)用戶的推薦歌曲ID列表同步寫入Rediskey的格式是recommend:user:{userId}過期時(shí)間24小時(shí)。階段四是前端推薦展示。用戶打開推薦頁前端調(diào)用/recommend/list接口后端優(yōu)先查Redis如果Redis沒有再查MySQL返回歌曲ID列表后再通過批量查詢接口拿歌曲完整信息最后渲染時(shí)過濾掉已經(jīng)下架的歌曲。這套數(shù)據(jù)流的好處是把計(jì)算密集型的推薦任務(wù)與在線業(yè)務(wù)解耦。用戶請(qǐng)求推薦永遠(yuǎn)不會(huì)觸發(fā)重計(jì)算最壞的情況也只是查一次MySQL接口響應(yīng)時(shí)間能控制在100ms以內(nèi)。3. 推薦系統(tǒng)核心算法原理與實(shí)現(xiàn)3.1 ItemCF算法公式拆解用大白話講清楚物品協(xié)同過濾ItemCF的核心是計(jì)算物品之間的相似度。我先把公式邏輯講透再給代碼。相似度計(jì)算公式采用余弦相似度similarity(i, j) |N(i) ∩ N(j)| / sqrt(|N(i)| * |N(j)|)其中N(i)表示喜歡/點(diǎn)擊過物品i的用戶集合。這個(gè)公式的意義是如果很多用戶都同時(shí)喜歡物品i和物品j那么i和j的相似度就高。分母的sqrt是為了懲罰熱門物品——一個(gè)被所有人點(diǎn)過的歌它和任何歌的共現(xiàn)次數(shù)都可能高但不代表真的相似用分母抵消熱門度偏差。得到物品相似度矩陣后用戶u對(duì)物品j的預(yù)測(cè)興趣分p(u, j) Σ(w(u, i) * similarity(i, j))即用戶喜歡過的所有物品i的權(quán)重行為分?jǐn)?shù)就是權(quán)重乘以i和j的相似度累加求和。按得分從高到低排序去掉用戶已經(jīng)聽過的物品取topN就是推薦結(jié)果。這套算法我實(shí)現(xiàn)的時(shí)候做了兩個(gè)優(yōu)化一是只計(jì)算與用戶行為物品有相似關(guān)系的候選物品避免全物品遍歷二是設(shè)置了相似度閾值比如小于0.1的直接扔掉減少噪聲。3.2 代碼實(shí)現(xiàn)相似度矩陣計(jì)算與推薦生成算法部分我用Java實(shí)現(xiàn)核心代碼如下我加了詳細(xì)的注釋public class ItemCFRecommender { /** * 構(gòu)建用戶-歌曲行為數(shù)據(jù)集 * key: userId, value: MapsongId, 行為得分 */ private MapLong, MapLong, Double userItemPref; /** * 物品相似度矩陣 * key: songId_i, value: MapsongId_j, 相似度 */ private MapLong, MapLong, Double itemSimMatrix; public void fit(ListUserBehavior behaviors) { // 第一步統(tǒng)計(jì)數(shù)據(jù)集中不同行為類型的權(quán)重 // behaviorType: play1.0, collect3.0, download5.0, skip-1.0 MapLong, MapLong, Double pref new HashMap(); for (UserBehavior behavior : behaviors) { pref.computeIfAbsent(behavior.getUserId(), k - new HashMap()) .merge(behavior.getSongId(), behavior.getWeight(), Double::sum); } this.userItemPref pref; // 第二步計(jì)算物品共現(xiàn)矩陣 MapLong, MapLong, Integer cooccurrence new HashMap(); MapLong, Integer itemUserCount new HashMap(); for (MapLong, Double itemPrefs : pref.values()) { ListLong items new ArrayList(itemPrefs.keySet()); for (Long itemI : items) { itemUserCount.merge(itemI, 1, Integer::sum); for (Long itemJ : items) { if (!itemI.equals(itemJ)) { cooccurrence.computeIfAbsent(itemI, k - new HashMap()) .merge(itemJ, 1, Integer::sum); } } } } // 第三步計(jì)算余弦相似度 itemSimMatrix new HashMap(); for (Map.EntryLong, MapLong, Integer entry : cooccurrence.entrySet()) { Long itemI entry.getKey(); double denominator Math.sqrt(itemUserCount.getOrDefault(itemI, 1)); for (Map.EntryLong, Integer simEntry : entry.getValue().entrySet()) { Long itemJ simEntry.getKey(); double sim simEntry.getValue() / (denominator * Math.sqrt(itemUserCount.getOrDefault(itemJ, 1))); if (sim 0.1) { // 過濾低相似度噪聲 itemSimMatrix.computeIfAbsent(itemI, k - new HashMap()).put(itemJ, sim); } } } } /** * 為用戶生成TopN推薦 */ public ListLong recommend(Long userId, int topN) { MapLong, Double pref userItemPref.getOrDefault(userId, Collections.emptyMap()); MapLong, Double scores new HashMap(); // 對(duì)用戶行為過的每個(gè)物品找出相似物品累加得分 for (Map.EntryLong, Double prefEntry : pref.entrySet()) { Long itemI prefEntry.getKey(); double prefScore prefEntry.getValue(); MapLong, Double simItems itemSimMatrix.getOrDefault(itemI, Collections.emptyMap()); for (Map.EntryLong, Double simEntry : simItems.entrySet()) { Long itemJ simEntry.getKey(); if (pref.containsKey(itemJ)) { continue; // 除去用戶已經(jīng)聽過的 } scores.merge(itemJ, prefScore * simEntry.getValue(), Double::sum); } } return scores.entrySet().stream() .sorted(Map.Entry.Long, DoublecomparingByValue().reversed()) .limit(topN) .map(Map.Entry::getKey) .collect(Collectors.toList()); } }3.3 冷啟動(dòng)問題的三種應(yīng)對(duì)策略協(xié)同過濾最大的天敵是冷啟動(dòng)。新用戶沒有行為記錄算法算不出任何東西新歌曲沒有用戶行為永遠(yuǎn)不會(huì)被推薦。我做了三層防護(hù)。第一層新用戶策略。用戶注冊(cè)成功、第一次打開推薦頁時(shí)后端發(fā)現(xiàn)該用戶沒有行為記錄直接返回一個(gè)基于熱門歌曲和精選歌單的“新人推薦列表”。這個(gè)列表的數(shù)據(jù)來源是Redis緩存的全站熱門Top100加上管理員手動(dòng)置頂?shù)耐扑]位歌曲。等用戶產(chǎn)生了行為再切換到個(gè)性化推薦。第二層新歌曲策略。歌曲上傳時(shí)不進(jìn)入推薦候選池而是先通過內(nèi)容標(biāo)簽風(fēng)格、語種、年代與老歌建立弱關(guān)聯(lián)等積累到一定量的用戶行為后再參與協(xié)同過濾計(jì)算。這樣可以避免新歌完全消失的情況。第三層基于內(nèi)容的兜底推薦。用歌曲的風(fēng)格標(biāo)簽算一個(gè)粗糙的相似度風(fēng)格相同權(quán)重1.0語種相同權(quán)重0.5年代相近權(quán)重0.3。當(dāng)協(xié)同過濾結(jié)果太少或者置信度低時(shí)用內(nèi)容相似度補(bǔ)滿推薦坑位。這套兜底代碼邏輯不復(fù)雜但親自測(cè)試后發(fā)現(xiàn)對(duì)用戶的體驗(yàn)提升非常大——推薦結(jié)果再差也不至于空著。3.4 推薦效果的簡(jiǎn)單評(píng)估方法作為個(gè)人項(xiàng)目不可能像大廠一樣搞AB測(cè)試但我還是設(shè)計(jì)了一套簡(jiǎn)易評(píng)估法。從user_behavior表里把最近30天的數(shù)據(jù)按時(shí)間切分前20天當(dāng)訓(xùn)練集后10天當(dāng)測(cè)試集用訓(xùn)練集生成推薦結(jié)果看測(cè)試集里用戶實(shí)際播放的歌曲有多少出現(xiàn)在推薦列表中算一個(gè)“推薦命中率”。我本地跑完命中率大概有18%到23%比隨機(jī)推薦高了將近10倍說明算法是有效果的。另一個(gè)評(píng)估維度是覆蓋率也就是推薦池里有多少歌曲能被推薦出去。ItemCF如果過度熱門導(dǎo)向會(huì)導(dǎo)致大量長(zhǎng)尾歌曲永遠(yuǎn)沒機(jī)會(huì)出現(xiàn)所以我在生成推薦結(jié)果時(shí)從相似度Top200里隨機(jī)取一部分低熱度歌曲保證結(jié)果多樣性。這個(gè)“多樣性注入”的經(jīng)驗(yàn)值是推薦列表里保留20%到30%的長(zhǎng)尾位。4. 后端核心接口設(shè)計(jì)與關(guān)鍵實(shí)現(xiàn)4.1 接口規(guī)范與統(tǒng)一響應(yīng)結(jié)構(gòu)前后端分離項(xiàng)目接口規(guī)范定了后面聯(lián)調(diào)就能省掉一堆破事。我用了RESTful風(fēng)格所有接口返回統(tǒng)一結(jié)構(gòu){ code: 200, message: success, data: {} }Java對(duì)應(yīng)的實(shí)體類是Result code用int類型200表示成功401表示未認(rèn)證403表示無權(quán)限500表示服務(wù)器內(nèi)部錯(cuò)誤。前端Axios封裝了響應(yīng)攔截器根據(jù)code做統(tǒng)一處理比如401的時(shí)候自動(dòng)清除本地Token并跳轉(zhuǎn)登錄頁。接口路徑我按模塊劃分列舉幾個(gè)核心的POST /api/auth/register 用戶注冊(cè)POST /api/auth/login 用戶登錄GET /api/song/page 歌曲分頁列表GET /api/song/search?keywordxxx 歌曲搜索POST /api/behavior/report 上報(bào)用戶行為GET /api/recommend/list 獲取個(gè)性化推薦GET /api/playlist/my 我的歌單4.2 JWT身份認(rèn)證實(shí)現(xiàn)從依賴到攔截器登錄認(rèn)證用JWT 攔截器是常規(guī)方案這里把完整實(shí)現(xiàn)路徑寫清楚。第一步是引入依賴我用的是jjwt庫dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-impl/artifactId version0.11.5/version scoperuntime/scope /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-jackson/artifactId version0.11.5/version scoperuntime/scope /dependency第二步是JwtUtil工具類負(fù)責(zé)生成Token和解析Token。生成時(shí)把userId放進(jìn)去同時(shí)設(shè)置過期時(shí)間我設(shè)成7天音樂App打開頻率高太短容易反復(fù)登錄。第三步是攔截器實(shí)現(xiàn)。用戶請(qǐng)求除了注冊(cè)、登錄、歌曲列表這些公開接口外都帶著Token攔截器校驗(yàn)Token合法性并從Redis里查一下用戶會(huì)話狀態(tài)如果Redis里沒有說明Token被注銷過直接返回401。第四步是解決跨域問題。前后端分離部署前端跑在5173端口后端跑在8080端口跨域是必然的。我在后端配置了一個(gè)WebMvcConfigurer的CorsFilter允許前端域名或IP:端口放行所有請(qǐng)求頭。4.3 MyBatis-Plus分頁查詢與動(dòng)態(tài)SQL歌曲列表分頁用的是MyBatis-Plus內(nèi)置的分頁插件。配置分頁攔截器后直接寫一個(gè)Page 對(duì)象作為查詢參數(shù)MyBatis-Plus自動(dòng)拼接LIMIT語句。動(dòng)態(tài)條件查詢這塊MyBatis-Plus的LambdaQueryWrapper非常好用。按風(fēng)格篩選就eq(Song::getStyle, style)按年代范圍就between(Song::getPublishDate, start, end)多個(gè)條件組合起來就是鏈?zhǔn)秸{(diào)用代碼可讀性比拼接SQL高太多。唯一要提醒的是分頁插件版本兼容問題。如果你用SpringBoot 3.x就要用MyBatis-Plus 3.5.3以上版本低版本的分頁插件會(huì)直接報(bào)錯(cuò)。這個(gè)坑我在熱搜詞里看到好多人遇到了屬于版本匹配的經(jīng)典問題。4.4 Redis緩存策略熱門榜與推薦結(jié)果的雙寫一致性Redis在這個(gè)項(xiàng)目中主要用于緩存具體緩存策略如下熱門歌曲榜熱門榜基于play_count字段排序這個(gè)字段每次播放都會(huì)更新MySQL如果每次都去數(shù)據(jù)庫查Top100非常浪費(fèi)。我的方案是Redis維護(hù)一個(gè)ZSetkey為hot_song_rank每次有播放行為時(shí)ZINCRBY命令把play_count加1。前端要熱門榜數(shù)據(jù)時(shí)直接從ZSet查Top100返回效率極高。推薦結(jié)果緩存離線推薦任務(wù)跑完后把每個(gè)用戶的推薦結(jié)果序列化成JSON字符串存入Redis的String類型key。這里注意TTL設(shè)置我設(shè)置的24小時(shí)第二天凌晨定時(shí)任務(wù)跑完會(huì)覆蓋。雙寫一致性問題因?yàn)镽edis里有推薦結(jié)果管理員手動(dòng)上架新歌后緩存中的推薦可能沒有新歌。我的解決方案是不做實(shí)時(shí)更新而是接受24小時(shí)延遲。這在實(shí)際使用中可以接受還能少了很多麻煩。如果確實(shí)需要實(shí)時(shí)性可以在歌曲修改接口里通過Redis的keys pattern模糊匹配后批量刪除推薦緩存觸發(fā)下次請(qǐng)求時(shí)重建緩存。4.5 并發(fā)與性能優(yōu)化接口響應(yīng)時(shí)間實(shí)測(cè)我把項(xiàng)目部署到2核4G的服務(wù)器上用JMeter壓測(cè)了核心接口。單機(jī)環(huán)境下歌曲列表接口QPS約800推薦接口走RedisQPS約1200登錄接口因?yàn)橐鯞Crypt校驗(yàn)和JWT發(fā)放在300左右。對(duì)于個(gè)人項(xiàng)目來說完全夠用。性能優(yōu)化最大的收益來自于兩個(gè)動(dòng)作一是把推薦接口的數(shù)據(jù)庫查詢?nèi)繐Q成Redis緩存二是給MySQL慢查詢加了優(yōu)化。我開了MySQL的slow_query_log發(fā)現(xiàn)最慢的是一條連表查詢用戶播放歷史的SQL耗時(shí)1.8秒。后來改成先查Redis再查單表響應(yīng)時(shí)間降到了80ms以內(nèi)。5. 前端Vue 3核心功能實(shí)現(xiàn)與踩坑記錄5.1 Vue 3項(xiàng)目搭建與目錄結(jié)構(gòu)設(shè)計(jì)前端項(xiàng)目用Vite搭建npm create vitelatest music-frontend -- --template vue創(chuàng)建。安裝依賴后我把src目錄按模塊組織src ├── api/ # 接口請(qǐng)求封裝 │ ├── auth.js # 認(rèn)證相關(guān)接口 │ ├── song.js # 歌曲相關(guān)接口 │ ├── behavior.js # 行為上報(bào)接口 │ └── recommend.js # 推薦接口 ├── assets/ # 靜態(tài)資源 ├── components/ # 通用組件 │ ├── PlayerBar.vue # 底部播放器 │ ├── SongCard.vue # 歌曲卡片 │ └── SearchBox.vue # 搜索框 ├── router/ # 路由配置 ├── store/ # Pinia狀態(tài)管理 │ ├── user.js # 用戶狀態(tài) │ └── player.js # 播放器狀態(tài) ├── views/ # 頁面組件 │ ├── Home.vue # 首頁 │ ├── Search.vue # 搜索頁 │ ├── Recommend.vue # 推薦頁 │ ├── Playlist.vue # 歌單頁 │ └── Login.vue # 登錄頁 └── utils/ # 工具函數(shù) └── request.js # Axios封裝這個(gè)目錄結(jié)構(gòu)參考了企業(yè)級(jí)Vue項(xiàng)目的分層方式把接口、頁面、組件、狀態(tài)管理分開后面對(duì)著接口開發(fā)新頁面會(huì)非常順手。組件命名統(tǒng)一用大駝峰頁面組件放views復(fù)用組件放components這個(gè)習(xí)慣能讓你在項(xiàng)目變大后少走很多彎路。5.2 播放器核心實(shí)現(xiàn)全局狀態(tài)管理與Audio控制播放器是整個(gè)前端最復(fù)雜的模塊因?yàn)椴还苡脩羟袚Q到哪個(gè)視圖底部播放器都要保持播放狀態(tài)歌曲不能斷。這意味著播放狀態(tài)不能放在單個(gè)頁面組件里必須放在全局狀態(tài)管理器中。我用的狀態(tài)管理工具是PiniaVue 3官方推薦播放器store的核心設(shè)計(jì)如下export const usePlayerStore defineStore(player, { state: () ({ currentSong: null, playList: [], playIndex: -1, isPlaying: false, currentTime: 0, duration: 0, audio: new Audio() // 全局唯一的Audio實(shí)例 }), actions: { playSong(song) { ... }, togglePlay() { ... }, nextSong() { ... }, prevSong() { ... } } })之所以只用new Audio()單例是因?yàn)槿绻總€(gè)組件都創(chuàng)建自己的Audio標(biāo)簽切歌時(shí)效率低而且聲音會(huì)混雜。全局單例Audio對(duì)象配合Pinia響應(yīng)式狀態(tài)任何組件都能通過store控制全局播放。音頻地址加載有個(gè)核心坑歌曲URL來自后端接口有些是mp3格式有些是m3u8格式。m3u8是流媒體分片格式原生Audio是播放不了的。我引入hls.js這個(gè)庫來解析m3u8流代碼如下import Hls from hls.js function loadAudio(url) { const audio playerStore.audio if (url.endsWith(.m3u8) || url.includes(.m3u8)) { if (Hls.isSupported()) { audio.pause() if (hlsInstance) hlsInstance.destroy() hlsInstance new Hls() hlsInstance.loadSource(url) hlsInstance.attachMedia(audio) hlsInstance.on(Hls.Events.MANIFEST_PARSED, () { audio.play().catch(err console.warn(autoplay blocked:, err)) }) } else if (audio.canPlayType(application/vnd.apple.mpegurl)) { audio.src url } } else { audio.src url } }hls.js的版本更新很快網(wǎng)上有些教程還是老API直接抄容易報(bào)錯(cuò)。我這里用的API是官方最新文檔里的寫法實(shí)測(cè)可行。要注意的是m3u8流媒體存在版權(quán)和帶寬合規(guī)問題項(xiàng)目中涉及引用第三方流媒體地址時(shí)務(wù)必確認(rèn)來源合法性生產(chǎn)環(huán)境建議使用自己存儲(chǔ)的音頻文件或正規(guī)授權(quán)的CDN資源。5.3 Axios封裝與接口請(qǐng)求攔截接口請(qǐng)求統(tǒng)一走Axios我封裝了一個(gè)request.js工具核心邏輯是創(chuàng)建Axios實(shí)例配置baseURL和超時(shí)時(shí)間然后在請(qǐng)求攔截器里加Token在響應(yīng)攔截器里處理錯(cuò)誤碼。import axios from axios const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config }) request.interceptors.response.use( response { const res response.data if (res.code 401) { localStorage.removeItem(token) router.push(/login) return Promise.reject(new Error(未登錄)) } if (res.code ! 200) { ElMessage.error(res.message || 請(qǐng)求失敗) return Promise.reject(new Error(res.message)) } return res.data }, error { ElMessage.error(error.message || 網(wǎng)絡(luò)錯(cuò)誤) return Promise.reject(error) } )這里有個(gè)細(xì)節(jié)前端開發(fā)環(huán)境用Vite的devServer代理把/api轉(zhuǎn)發(fā)到后端避免開發(fā)時(shí)跨域問題。生產(chǎn)環(huán)境通過Nginx反向代理/api前綴的請(qǐng)求轉(zhuǎn)發(fā)到后端容器。5.4 推薦頁瀑布流與虛擬滾動(dòng)優(yōu)化推薦頁是用戶打開最多的頁面我設(shè)計(jì)成瀑布流卡片布局每首歌曲一張卡片顯示封面、歌名、歌手、播放次數(shù)。數(shù)據(jù)量大的時(shí)候直接渲染幾百個(gè)卡片會(huì)很卡我用虛擬滾動(dòng)方案只渲染可見區(qū)域內(nèi)的卡片滾動(dòng)時(shí)動(dòng)態(tài)更新。Vue 3沒有內(nèi)置虛擬滾動(dòng)組件我用了第三方庫vue-virtual-scroller。安裝后把推薦列表包進(jìn) 組件性能提升非常明顯。實(shí)測(cè)在1200首歌曲的列表里滾動(dòng)幀率從30fps以下提升到穩(wěn)定60fps??ㄆc(diǎn)擊播放的交互邏輯點(diǎn)擊卡片后調(diào)用playerStore.playSong(song)同時(shí)上報(bào)behavior/report接口。上報(bào)接口要做防抖處理避免用戶連續(xù)點(diǎn)擊同一首歌產(chǎn)生大量重復(fù)記錄。5.5 前端踩過的坑路由模式、跨域、樣式隔離這一節(jié)把我在前端實(shí)現(xiàn)過程中踩過的坑做個(gè)實(shí)錄很多坑搜索引擎里問的人非常多。第一個(gè)坑是Vue Router的mode。部署到Nginx后刷新二級(jí)頁面出現(xiàn)404這是因?yàn)樽吡薶istory模式需要Nginx做try_files配置把所有路由重寫到index.html。我用的配置是location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; }第二個(gè)坑是跨域CORS。前后端分離開發(fā)時(shí)Axios請(qǐng)求后端接口會(huì)被攔截。解決方案開發(fā)環(huán)境用Vite proxy代理生產(chǎn)環(huán)境用Nginx代理后端同時(shí)配置CORS白名單兜底。騰訊地圖也好、其他第三方SDK也好引入時(shí)都會(huì)有類似問題統(tǒng)一這么處理。第三個(gè)坑是樣式污染。Vue組件的
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
亚洲天堂另类| 欧美性爱日韩高清| 国产精品原创巨作?v网站| 国产 三级自拍| 亚洲另类在线观看| 男人的天堂日韩| 综合影院永久入口国产| 天天综合网站| 麻豆久久精品亚洲精品88| 中日韩欧美精品无码AⅤ一区二区| 中文字幕黑人大片| 91欧| 簧片免费看视频| 欧美视频激情久久久久久| 超碰色老头| 岛国成人av在线播放网址| 欧美色66| 国产最火爆久久国产网站网站| 亚洲综合九九| 九九av| 久操com| 97色97好| 亚洲国产成人7777| 熟女一区二区| 亚洲蜜乳av| 青青草十区九区爱夜| 襙一襙| 日韩情色视频| 国产一级舔足在线观看| 欧美日日网| 97亚洲中文| 麻豆啪啪啪视频| 欧洲精品欧洲精品| 亚洲中文字幕网| 欧美日韩国产色五月综合在线| 婷婷去俺也去六月色| 天天澡天天爽日日av| 看日韩黄片| 久久仑合| www成人啪啪18秘 免费| 无码人妻毛片丰满熟妇精品区| 18禁的网站在线| 久操大香蕉超碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰 | 伊人久久亚洲色欲综合网站| 国产精品一级片在线看| 午夜九九| 91黑丝在线播放| 91 丝袜在线播放| 午夜欧美神马久久久久| 欧美日韩国产三级黄色| 超碰97欧美日韩| 成人性爱电影网| 超碰在线一区二区三区| 久久亚洲不卡一区二区三区 | 爱啪精品一区| 精品国产www久久| 国内毛片四区| 熟妇艹鸡八| 久久久亚洲熟妇熟女| 欧洲乱码一区二区| 97色碰| 国产乱伦视频污| 欧美青青视频| 91蜜桃婷婷狠狠久久综合9色| 久久久无码视频| 中文幕97| 日韩成人午夜精品久久高潮| 91日本在线观看| 操逼A∨| 农村妇女精品一区二区| 一区二区日韩欧美久久| 亚洲本色精品一区二区久久| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 91男人天堂网| 打av高清| 久久久久成人蜜桃精品| 性爱免费视频成人| 91丝袜视频在线观看| 大香蕉色网| 国产精品一二三在线看| 91情色| 日本中文字幕一区| 很黄很污的免费网站| 婬女免费一二三区A片| 日韩欧美亚欧在线视频| 亚洲玖玖爱| 九九综合九九综合| 日韩久射综合| 金典av| 天天摸夜夜摸| 二区熟妇韩日| 91视频成人福利网站在线一区| 97最新在线播放视频| 亚洲密乳AV| 天天干人人乐| 日本精品一区二区不卡| 大香蕉伊人网WWWn0n| 国产成人在线观看综合| 午夜120视频在线观看| 韩国免费播放一级毛片| 超碰碰97资源站| 超碰到97情色| 欧美综合在线91| 热天堂一区二区| 97色碰| 国产午夜无码片在线观看影视| 亚洲无码精品AV久久久| 一级性爱网| 78精品在线| 五十路成人在线视频二区三区| 欲香欲色天天天综合和网| 男人的天堂成人的社区| www老逼91| 五月丁香在线| 久久久久久久一级黄色打同平台| 久久岛国| yiqicaoav| 国产区在线| 亚洲少妇视频| 97天天摸天天爽| 春色91| J?P?NESEHD熟女熟妇伦| 国产成人午夜视频网址| 大香蕉久久| 久久伊人大香蕉| 大香蕉手机视频| 中文字幕 国产 精品| 国产在线观看91精品一区| 国产精品com| 91骚熟女| 都市久久精品激情亚洲| 一级黄色视频网| 伊人久久综合影院| 国产精品一区二区 尿失禁| 丁香五月综合| 欧美性爱五月天| 99亚亚热| 日本一级不卡一二区| 4虎在线视频| 最新9久久久9免费视频| 美女天天干| 91宗合网| 精品国产乱码久久| www.久久最新地址| 色综合99| 色女综合| 熟妇一区,二区,三区。| 超碰97护士| 曰韩操B| 精品人妻美妇91job| 久久精品—区二区三区内射| 精品国产91av一区二区三区| 亚洲精品美女久久久久久久久| 婷婷丁香熟妇综合网| 97电影院超碰| 精人妻无码一区二区三区伊人直播 | 一卡二卡在线播放| 69精品| 91在线秘 男同| 亚洲av综合色区无码一| 六月丁香啪啪啪| 亚洲AO在线| 国产精品久久久999| 熟女露脸激情自拍视频| 欧美综合天天| 操逼片中文| www.久久| 96久久久精品| 欧美日韩在线视频网站| 国产一区在线免费播放| 自拍盗摄一区| 国产三级片在线观看| 久久欲| www.色操逼| 亚洲色性情三级| 超碰97.com| 中文字幕三四区| 国产最新小视频在线播放下载| 日本在线不卡v二区| 一个人在线看的黄色电影网站| 超碰久久综合| 欧 美 自 拍 偷 拍| 日欧操屄视频| 日韩人妻精品中文字幕| 久久精品久久久久久久久| 久久性视频| 伊人991| 亚洲综合首页| 日韩精品一二三四| www.成人无码| 国产精品久久aV| 色噜噜婷婷| 偷拍综合亚洲| 中文字幕,人妻,日韩| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 综合情欲网| 樱花蜜乳av| 超碰97男人| 日韩有码 一区二区三区| 吻戏激情性巴克| 五十路成人在线视频二区三区| 1人人看人人摸人人操| 志村玲子视频一区二区| 欧美少妇色图| 97超碰美国| 色九久| 日韩成人网址| 中文字幕国产| 欧美做爰无码A片视频| 制服丝袜第二页| 欧美一级久久久久久久大片动画| 国产精品网站免费| 热无码中文亚洲H一道本一区二区| 色婷五月天| 久久精品导航| 97五月天| 俄罗斯及免费在线看| 天天爱天天韩国日本牛牛牛牛 | 超碰在线974| 国产捆绑一区| 日韩国产精品人妻无码久久久| 情侣开房子拍 日韩无码 女的很漂亮| 亚欧美综合网| 91xingse| 国产亚洲精品久久久久小| 好舒服视频| 再深点灬舒服灬太大了好硬好爽| 亚欧高清| 夜夜做夜夜爽精品视频| av最新免费中文字幕| 天天夜夜久久| 国产AV久久久蜜爱影集| 97精品视频| 久久综合精品一区二区三区| 精品国产乱码| 极品出轨视频网站| 嗯嗯啊中文字幕| 日韩av性爱在线播放| 爱干爱射网啊啊啊| 日韩不卡在线一区二区| 91bbbbbb| 99re69| 亚洲欧美在线观看2021 | 91色情黑丝搞鸡在线观看一区二区三区三州| 99热 按摩 日韩| 久久国产热视频97电影| 日韩超碰97| 啊啊啊啊一区| 三级AV入口| 久久一二三四五六七八九区| 91老熟女逼| 家庭乱伦性爱av| 欧美日韩夜夜| 手机在线人成免费视频| 免费国产电影一区二区| 天天操福利视频综合网站| 婷婷六月天| 92性色国产午夜福利在线661| 亚av顶级裸体一区二区三区四区五区| 欧美丰满熟妇XXXX性ppX人交| 蜜臀99久久国产| 好看的91视频| 婷婷五月天av| 无码操逼网| 91精品国产综合久久久蜜臀酒店| av东京热男人的天堂| 亚洲激情网| 飘花国产午夜精品不卡| 夜夜久久久| 日本蜜桃| 婷婷五月天色色| 18禁止看精品中文字幕| 中文字幕一区二区无码成人| 久久爽爽精品| 按摩中文字幕| 激情av| 亚洲精品天堂久久A∨51成人漫| 新91视频.cmp| 精品久久9| 91九九九馒头| 五月香婷婷| 人妻人人做人人澡人人爽欧美一区| 加勒比中文av| 玖玖无码超碰| 久久精品中文| 大乔未久88一区| 日本三级小说中文字幕| www.狠狠操| 91爆操视频| 国产精品久久久久久亚洲色欲| 亚洲丝袜二区在线| 精品少妇人妻| 欧美国产操逼| 免费成人在线熟妇网| 蜜桃久久久久久| 九九Av| 国产一区二区三区精品观看啪| 国产人妖的免费的视频| 秋霞怕怕片| 老熟女网站| 99在线精品视频| 中日韩久久久免费看| 国产丸一视频| 99精品在线| 国产中午字一暮区| 91狠狠狠| 91丝袜美女视频| 蜜臀99久| 91模特在线观看| 国产成人啪一区二区| 色娱乐色呦呦夜夜夜夜av| 欧美日韩精品国产91| 人人污日韩一区二区| 婷婷啪啪| 欧美人妻精品| aaa淫乱视频| 欧美精品双插| 综合网亚洲1| 日韩综合第八区国产精品| 九9精品| 天天热精品| 91热色| 超碰在线免费一区二区三区| 久久色精品视频在线| 九九九九精品九九九九| 国产高清午夜成人在线观看| 玖玖爱在线视频免费观看| 国产精品麻豆成人av| 欧美操人视频| 五月色网| 欧美日韩情色一区二区| 色女女女导航| 中文字幕AV片| 国产熟女无套内射| 可以免费看黄片的视频| 温婉少妇玩3p| 97色在线| 色五月天AV| 嗯嗯啊啊的视频| 久久大香蕉97| 亚洲97在线观看| 韩国免费播放一级毛片| 午夜无码精品免费看性色| 日本午夜福利影院| 亚洲国产精品久久久男人的天堂| 2020中文字幕在线| 日本高清视频在线观看黄已三辽| 国产精品熟女一区二区三区| 亚欧毛片基地国产毛片基地| 精品一二三区久久AAA片| 日韩啪啪啪啪啪| 超碰 另类 欧美 | 97伊人| 久久精品一区二区一8| 国产日韩欧美亚洲精品95| 超碰人人草| 好吊色一区| 欧美成人精品一区二区男人蜜臀| 2017天天插| 中文字幕后石码三区四区| 欧美一级久久久丰满| 日韩A优精品在线观看| 五月丁香六月| 日han少妇无码| 99这里只有精品| 91丨人妻丨国产丨丝袜| 亚洲AV无线| 亚洲欧美大| 亚洲怡春院| 草草草视频| 日本欧美韩国国产在线| 激情五月综合网| 久久精品国产久精国产| 久久这里只精品免费福利| 亚洲乱码尤物193YW| 99综合网| 成年在线视频日本亚洲在线视频区精品江靖宇公司 | 黄色性爱网网| 欧美视频第二页| 国产白丝网站| 人妻精品视频一区二区| 亚洲伊人久久精品影院| 校园春色 欧美| 中文字幕一二区二三区人妻专区| 嗯啊啊啊轻点视频 | 920日本午夜免费| 日本精品一区二区三| 婷婷干黄色| 亚洲精品久| 欧美 亚洲| 韩三级a视频在线观看| 精品国产乱码久久久久久久久1| 亚洲www91| 手机在线免费看的av| 国产女人高潮视频| 一区二三区四区视频大全套| 夜夜影视四色| 久久久九九| 黑人无码一区二区| 欧美 亚洲 91| 啪啪视频亚洲第一| 试看60秒| 免费中文在线| 久久黄人人爽视频| 麻豆天美国美国产AV| 亚洲欧美综合网| 人人干人人操人人..com| 亚洲综合 欧美| 亚洲免费成人在线高清无码视频 | 国产精品久久久久中文字幕| 超碰在线97国产| 不卡av在线中文字幕| 加勒比综合九九99视频在线播放| 欧美1区二区三区公司| 蜜臀人妻少妇久久在线观看| 91亚洲色图| 欧美天堂日韩三级国产传媒| 波多野42部无码喷潮在线观看| 欧美日韩亚洲天堂网| 麻花豆传媒剧国产MV出差| 九一精品牛牛一区二区| 亚洲无码超碰免费| 玖玖爱伊人玖玖爱| 开心五月婷婷激情| 日韩无码一区二区三区| 久久成年精品| AA特级绝黄| 中文字幕av一区二区三区人妻少妇 | 久久仑合| 成人av动漫在线观看| 97超碰精品成| 天天射,天天操,天天爽-国内精品一区二区三区-成人AV | 四虎AV在线播放| 欧洲Au麻豆| 免费强奸av| 日韩三级伊人| 色欧洲97| 熟女日韩| 激情综合网五月婷婷五月天| 精品久9| 亚洲城人男人的天堂| 波多野结衣被操50分钟免费视频 | 久久天天艹| 亚洲极品| 九九热在线精品视频| 国产精品人妻无码久久久互動交流 | 久久这里只| 老熟女区| 99人人干| 天天色天天干天天爱| 婷婷久久久精品| 嗯嗯嗯啊啊啊在线免费观看| 亚洲欧洲无码bt精品合集| 久久久96精品| 91欧美偷拍| 狠狠色综合网| 亚洲精品一二牛牛| 91热| 国产精品午夜成人福利| 中亚精品极乱| 五月婷色| 超碰人人色| 在线强奷到舒服的无码视频| 少妇人妻好深太紧了vr91| BBBBB97COM| 91影视亚洲| n1038 一二三区| 99视频精品| 无码WWW免费视频网站| 99热在线播放| 国产视频97| 久久久∴| 1区2区3区中文字幕日韩| 91操人| 国产一级作爱毛片| 日韩成人精品| 99热| 欧美中文综合| 成人无码欧美一级A片狼牙直播| 熟妇精品juliaannAV| 黄色网址久久精品欧美喷水| 色青青久久影视| 日韩三A大片在线观看| 精品九九| CCYY草草影院地址入口| 妇女性内射冈站HDWWWCOM| a级免费在线观看| 精品人妻一区二区三区在| 青青草福利视频| 性91| 99精品国产户外露出| 国产成人欧美精品在线| 欧美福利视频啊啊啊啊| 日逼逼免费看| 人人操人人uiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii | 久久精品亚洲成a人天堂| 青青久久手机线视频| 国产一区二区精品久久99| 国产福利小视频高清在线观看| 亚洲欧洲精品视频发布| 99热婷婷| 99热精品青草在线| 欧美天天综合站| 国产精品69久久久久孕妇欧美 | 伊人久久亚洲色欲综合网站 | 国产精品电影推荐| 91操熟妇| 肏逼视频日本| 亚洲欧综合另类无码一区| 欧美性爱系列| 97超碰国产亚洲精品资源| 日本熟人妻中文字幕在线|...久久国产精品-国产精品_日本一区二区三区中文字幕 | 国产精品久久久久久片| www.色婷婷.com| 91扒丝袜综合在线| 精品综合久久久久久97| 精品黄色电影| 精品成人动漫一区二区| 国产无马av| 91网站18在线观看| 99热8| 久久久久白虎| 午夜乱轮操逼视频免费看| 中文字幕成人理论在线| 国产不卡片| 999九九精品| 欧美 亚洲精品首页| 日韩无码视频黄色| 大香蕉啪啪啪| 中文字幕神马久久| 亚洲在线| 亚洲av无码成人精品国产| 天天摸夜夜摸| 欧美激情内射| 国产精品一区二区校花| 超碰人人妻| 午夜综合在线| 91视频精品| 成人午夜无码视频| 欧美激情久| 国产强奸乱伦第1页| 国产精品自在线发布| 后入 亚洲 美女 射| 蜜臀在线看片| 国产极品精品美女视频| 狠狠中文字幕| 另类图片五月天| 国产亚洲性生活视频播放| 污啪啪啪视频| 亚洲成人AB| 精品一区二区在线针对华人免费观看这里只有精品免费观看 | www.色吧5.com| 亚洲AV免费在线| 日韩中文字幕宗合在线| 亚洲欧美国产中文视频| 欧美|91色综合| 偷拍亚洲视频一区二区三区四区| ..日韩av毛片精品久久久| 岛国小电影| 亚洲交性| 玖玖色综合| 91国产伊人大香蕉| 国产高清MV操逼视频| 天色综合网| 日韩无限资源| 女优免费一区二区永久| 老熟乱一区二区三区四区| 乱伦av.com| 欧美亚洲国产日本在线,久久精品国产| WWW.操逼.COM| 91美女视屏| 97干97色| 福利风月五月天影院| 好属操| 久久人妻丝袜一区二区三| 变态综合色| 天天干,夜夜爽| 综合网少妇| 色九月婷婷| 懂色Av一区二区三区| 久久香蕉网| 天堂性色| 啊啊啊啊啊啊在线看| 男人天堂网站| 九九热超碰97亚洲最新香蕉| 久艾草在线精品视频在线观看| 亚洲三区视频| 97超碰人妻| 亚洲欧美黄| 蜜桃臀av在线观看| 91老熟妇| 欧美一二在线| 天天色天天干天天射| 后入式视频国产自| 强奸乱亚洲| 中韩中文字幕在线观看| 水澄无码AV| 一级做受视频免费是看美女| 亚洲精品骚逼| 一级A片女人高潮叫床| 亚洲第一视频 欧美风情 日韩| 久热九九| 白丝被操91| 久久少妇人妻| 六月丁香五月婷婷| 国产午夜精品理论片a大结局| 青青草吊丝| 亚洲最新中文字幕免费| 91热热色| 欧美色图亚州激情| 亚洲av影音先锋| 日日骚一区二区三区| 大香蕉操久久| 亚欧免费| 久草看看看| 麻豆国产原创AV色哟哟 | 综合亚洲情色| 粉嫩av在线一区二区| 久久伊人东京热| 丰满人妻一区二区三区在线| 欧美黄片免费在线观看视频| 亚洲色婷婷综合久久久久中文| 超碰 另类 欧美| 欧美激情中文字幕另类小说| 好属操| 色www精品视频在线观看| 超碰精品在线| 熟女这里只有精品6| 欧美,日韩,中文,另类| 蜜桃中文字日产乱幕4区| 亚洲黄色网址视频| 激情小说在线视频| 久久久久极品| 蜜桃传媒一区二区亚洲| 国产精品视频精品一二| a级免费在线观看| 久久精品无码不卡| 久婷婷一区| 91大学精品激情戏| 人妻乱仑一区二区三区| 蜜乳AV免费观看| 人人妻人人爽人人精品| 好屌色综合| 毛片中心9视频99| 最新国产亚洲精品精品国产亚洲综合| 亚欧高清| 欧美97爱| 97欧美日韩精品| 久久亚洲色图中文字幕| 久久久久9久久久久| 久操大香蕉| 亚洲1区2区三区高清中文字幕| 青娱乐休闲视频在线观看| 久久熟女嫩草成人片免费| 亚洲精品欧洲精品| 天天看综合网| 色色综合网站| 欧美综合区| 久久久久亚洲?V片无码V| 狠狠婷婷亚洲中文综合久久| JuliaAnn丝袜熟女系列| 黑人精品欧美一区二区蜜桃| 秋霞鲁丝午夜无码一区二区三| 中文字幕在线观看第二页| 屌色在线97视频| 中文字幕在线观看二区三区| 午夜偷拍久久熟女| 黄片色区软件| 一起草日韩| 人人看人人爰人人操| 久久午夜鲁丝片| 深夜福利黄片| 国产在线综合福利网站| 女人综合网| 好爽视频在线观看视频| 91亚洲人| 婷婷综合伊人一区| 久久亚洲AV无码白度| 91精品老女人| 欧美天天综合网| 亚洲91网| 欧美极品美女aaaaaa级黄片| 新亚洲无码| 你懂的在线观看区国产| 乱性AV| 国产强奸91| 欧美日韩激情无码专区| 自拍偷拍 高清无码| 婷婷视频在线免费观看| 人人干人人搞人人摸| 精品区国产区一区二区三区| 97任你吞精| 九九RE视频在线精品| 色婷婷成人| 91大胆欧美| 99re3这里只有精品| 你草精品在线视频| 国产精品天干天干综合网麻豆| 丝袜狠狠草尤物 91| WWW美腿丝袜香蕉中文| 欧美天天影院| 国产熟女精品一区二区| www.亚洲黄色| 中国一区二区亚洲人妻| 久久久久9| 精品国产乱码久久久久久影片| 国精品一区二区三| 神马久久69| 暴力av在线| 碰碰97| 高清国产成人无码| 乱老女人一区二区视频| 伊人影院中文字幕| 欧美情色贴图| 蜜桃久久一区| 国产无码精品无码| 日韩午夜精品一区二区三区电影| 亚洲人妻AV| 激情文学 国产一二三aV| 欧美日韩人妻婷婷一区| 精品久久97| 国产美女裸体秘 永久无遮挡| 黄色网址在线免费观看| 深夜操逼网| 日本新免费二区三区| 91久久婷婷| 日本精品网站在线中文| 日韩av乱伦| 日本加靬比网站发布页| 欧美日韩人妻精品一区二区三区 | 四虎在线观看网站| 青青草久草| 啪啪AV导航| 啊啊啊com| 中出20p| 91看黄片| 精品区9| 欧美美女后入| 亚洲学生妹高清av| 人人透人人操| 久操在97| 极品销魂美女一区二区| 国产精品成人无码av无码免费| 97国产精品国| 96国产精品| 欧美日产国产在线成人第一区| 性爱动态120秒| 97网址97| 亚瑟国产精品久久无码| 亚洲色图久久成人| 91精品国产长腿丝袜美女| CCYY草草影院地址入口| 天天做天天爱天天爽| 欧美日韩美女精品久草一区二区三区| 国产 日韩,欧美 自拍| www.色婷婷色综合| 长久操视频| 日韩欧美操逼xxx| 激情综合97| 免费视频观看60秒| 久久AV无码网址| 熟女一区二区三区| 国产在线综合网| 天天综合网~69| 麻豆色99999| 91动漫操逼视频| 蜜桃久久久久久久久久久久| 国内亚洲高清无码| 大鸡吧尹人在线| 中日韓欧美高清| 99热伊人| 操久久久久| 久久婷婷色| 超碰在线在公开超碰在线在公开| 久久成人国产| 91丨精品丨国产丨丝袜| 黑人白女精品一区| 婷婷另类小说| 国产高清精品一区二区三区毛片| 久热久一区二区三区| 精品九九九九九| 可以免费观看的av| 久久精品国产亚洲av水密被窝| 国产超碰人人操| 日本免费二区三区| 九九热九九| 久久香蕉国产线看观看亚洲女人 | 日本日逼高清| 高清肉丝中文无码| 亚洲成a人片在线观看中文!!!| 色网在线| 国语精品内射在线观看| …中文字幕亚洲乱,97人妻无码费视…| 欧美丝袜制服久久| 加勒比无码毛片| 综合网色| 操国产高清| 日韩一区二区熟女| 草草影院最新网址| 欧美精品,四区。五区| 在线v中文字幕一区二区三区| 久9综合在线| 五月丁香| 国产1024在线播放| 欧美 日韩 婷婷 五月| 特级丰满少妇一级AAAA爱毛片| 久久久月天| 久久久一级| 99e久久国产精品| 91在线/欧洲| 色婷五月| 色视频蜜乳| 日韩av情韩国爱禁区av一区二区| 97综合在线| 欧美视频一| 欧美 亚洲 91| 超碰人人妻| 五十路六十路素人熟女| 色情婷婷久久五月天| 99激情视频| 亚洲欧洲av影音| 日韩97视频| 亚洲天堂中文字幕无码男同| 99久久久久久亚洲精品不卡| 色婷婷一区二区三区久久午夜成人不| 亚洲宅男天堂| 搞中出久久| 美女性91| 亚洲色资源| 成人五月香网在线| 三级AV入口| 97日亚洲欧美| 东京热不卡视频| 亚洲中文字幕噜噜噜久久久| 精品高清一区二区三区三州| juliaann欧美丝袜办公室| 97天天操天天干| 99热最新网址| 中文字幕乱码人妻二区三区| 97久操| 精品无码人妻一区二区免费蜜桃| 91碰碰碰| 欧亚性爱啪啪| 91在线精品一区二区三区| 日韩精品资源| 日本久久综合| 婷婷情色综合网| 欧美日韩岛国大片在线观看| a片偷拍视频| 亚洲一区二区AV| 夜色97| 加勒比AV网| 欧美少妇熟女| 欧美日韩性爱精品| 中文字幕91页| 成人AV超碰免费在线| www.91视频网| 97操综合| 9999亚洲精品| 久久少妇视频| 99少妇精品视频| av资源在线播放天堂| 日韩黄片视频试看| 五月天我淫我色av| 亚洲欧美情色| 国产精品在线免费| 视频在线97| 日本欧美m v精品网站加| 红桃视频高潮| www.四虎在线| 屌逼传媒| 青草视频在线看看看看看看看看看| 久久九九国产精品| 性色av蜜臀av色欲aV| 久久精品人人做人人看| 思思热国产高清| 成人av性爱电影在线观看| 日韩超碰97| 九久9精品| 啪啪啪综合| 亚洲午夜精品久久久中文影院| 亚洲高清男人天堂| 欧美丝袜美女电影一二三四区| 欧美久久婷婷| 操死我了嗯嗯嗯| 久久曰曰| 玖玖资源中文字幕制服丝袜| 日本A级视频| 97资源欧美| 91人妻视频| 殴洲老熟女| 91网站视频在线观看| 91天天c| 超碰夫妻97| 午夜福利在线合集| 超碰久在线天天做| 国产熟女自拍| 国产激情在线| 久久一区二区三区四区五区| 国产精品香蕉| 国产福利电影| 久操网无码在线| 在线中文字幕极品av| 中国一区二区亚洲人妻| 久久美女福利是上海美女| 久久精品性| 91狠| 日本不卡码黄色| 亚州色图欧美| 热久久无毒不卡| 加勒比aⅴ| 91这里只有精品| 日韩免费看在线黄色片| 亚洲 一区二区 自拍| 国产在线精品偷| 美女尤物福利视频| 麻豆福利视频导航| 91N综合网在线| 综合亚洲网| 26uuu久久| 日欧亚洲二三区大片不卡| 免费A V在线| 国产精品交换一区二区| 国产精品制服丝袜中文字幕日韩一区二区三区 | 亚洲精品毛片在线观看| 亚洲日韩国产欧美综合v| 亚洲AV免费在线| 99自拍B亚洲 | www.99热在线只有精品| 肉丝无码中文高清| 啊啊啊想要| 黄色片,com| 开心五月婷婷| 青青草手机在线免费观看| 97伦乱| 91春色| 无码精品啪啪啪一区二区三区三州| 亚洲加勒比| 久久久久极品| 中文字幕后石码三区四区| 在线看的av| 99在线免费视频| 国厂麻豆77q4| 97精| 亚洲成人一区二区精品| 手机av天堂久久久久| 亚洲伊人久久精品影院| 国产一级内射高清视频 | 精品国产乱码久久久影院| 日韩免费簧片| 欧美成人性爱视频大全| 91国产大片| 亚洲无码一区成人免费午夜| 国产亚洲性生活视频播放| 日本日逼视频网| 日韩午夜国产| 男人天堂欧美| 偷看洗澡一二三区美女| 99re只有精品| 国内一区二区免费| 色官网在线| 97超碰久| 99精品国产户外露出| 五月天精品| 久久精品日韩专区免费观看| 少妇高潮流水av免费| 97天天摸天天碰| 亚欧美色图| 欧美性爱日韩性爱| 蜜桃臀 后入 一区 二区 三区 在线| 日韩欧美麻豆 | 婷婷午夜| 亚洲综合草草| 99久久婷婷丁香| 国产极品久久久| 久久久新亚洲AV| 开心五月激情网| 精品少妇一区二区| 亚洲无码久久久久久久| 亚洲第91页| 手机在线免费看的av| 久久久久久久久久久97| 日逼97| 色婷婷久久| 日夜尻逼网| 国产精品岛国片在线观看| 国产亚洲精品美女| 97网址97| 很黄很色的视频在线观看| 伊人青青草久久| 国产兽交视频在线播放| 偷拍 精品 另类 四区| 欧洲人妻视频| 99久久综合网| 国产久久天堂资源| 十八禁视频网站| 91痴汉| 五月丁香综合啪啪| 日本一线产区和二线产区伦理片| 最新日韩黄片| 夜夜国自区| 色婷婷五月综合激情中文字幕| 欧洲亚洲天堂精品| 色狠狠 - 百度| 极品色电影院| 无码视频黄色网战| 青青草依人大香蕉| 五月婷丁香| 天堂无码| 一区二区三区日韩欧美| 秋霞操逼片| 人妻人人澡人人爽人人| 亚州免费啪啪视频| 亚洲色图第四色| 最新日韩黄片| 亚洲se91| 好爽,再快点啊哈嗯嗯嗯嗯| 狠狠色噜噜狠狠狠狠2018| 国产亚洲色婷婷99精品91| 懂色天天爱天天日天天射天天澡| 天天影视之亚洲综合网| 综合婷婷| 久久综合九色综合欧洲98| 国产成人AV麻豆| 亚洲97久久精品亚洲| 97中文字幕一区| 色老汉玖玖爱| 黄视频免费| 亚洲天天精品| 欧美亚洲综合色| 国产亚洲精品一区二区三区| 97在线无精品| 日韩不卡av一二三| 亚洲欧美人妻| 天天综合网入口~91| 国产日韩在线播放| 精品69网| 亚州色图欧美| 超碰精品在线| 无码不卡八戒| 综合色久欲| 午夜男人天堂| 国产精品婬乱一级毛片彝族| 蜜臀AV午夜精品久| 青青草啪啪网| 99视频自拍| 欧美日韩啪啪电影| 国产精品一区在线播放| 不卡九肏| 翔田千里av一区二区三区| 亚洲伊人成综合成人网| 97伦乱| 99国产精品在线观看| 国产伦乱91| 国产9 9在线 | 亚洲| 亚洲第一视频 欧美风情 日韩| 日韩av熟女一区二区三区成人| 中日韩欧美精品无码AⅤ一区二区| 老熟女网站| 国产精品毛片| 久久久久一本一区二区青青蜜月| 99精品久久久久久久婷婷蜜桃| 久久在线观看免费视频| 天天综合~91| 超碰97久久观看| 中亚精品极乱| 亚洲综合精品国产一区| 内射夫妻三片| 啊v在线观看视频| 黄色一区三区| 日本A级视频| 国产高清1234区| 五月天色图| 国产99999久久精品| 一个人在线看的黄色电影网站| 激情久久av一区av二区av| 中国少妇XXXX做受| 啪啪视频免费在线观看| 久久久78| 国产吹潮女在线观看| 少妇同性| 国产四虎在线| 麻豆人妻精品一区二区| 在线v中文字幕一区二区三区| 7777奇米影视久久| 国产强奸AV在线| 超碰九区| 香港久久久| 亚洲影视高清第一页| 熟女高潮合集-永久久久-成人AV| 亚洲aw毛茸茸在线 | 日韩精品免费高清视频在线| 欧美一区二区三区不卡高清视频| 激情在线青青操| 超碰人人干天天射| 91AV国产精品| q2午夜理论片夜色av| 国产视频大全| 欧美色图 人妻| 久久久久ab| 美欧老女人97| 国产丝袜美腿美女麻豆| 日韩国产十八禁| 国产性刺激| 天天综合香 ld视频| 嗯嗯啊啊用力视频免费| 久久久久精| 你操综合| 久久综合乱子伦国产免费| 九九热免费国产视频婷婷伊人五月 | 久久综合18p| 美日韩一卡二卡三卡免费人妻精品| 一本一道人妻久久一区二区三区 | 欧美黑人猛交春色影视大全| 日本三级韩三级99久久| 爽爽淫人网| 久久理论字幕视频| sss视频华人在线| 免费人人搞97| 国产美女口爆吞精| 久久宗合亚洲| 后入式999| 国产欧美另类久久久精品课程| 人妻精品一区二区| 日韩97| AV一起草在线| 自拍偷拍 高清无码| 91动漫操逼视频| 国产日比| 按摩中文字幕| 99re69| 亚洲精品久久一区二区三区蜜桃臀| 美女让帅哥通她小鸡鸡| 天天操天天干美女网址导航| 欧美九九九九九| 日韩性爱长视频免费| 美女视频尤物网在线看| 久久久精品视频免费观看| 欧美精品日韩一区二区| 麻豆精品久久久久久久| 91麻豆天美传媒HD| 射丝袜大香蕉| 国产精品96久久久久久| 亚洲成人精品在线一区| 亚洲无吗在线视频| 色综合色综合网| 91丝袜美腿网站| 老司机午夜福利视频一区二区| 女人18精品一区二区三区| 欧美精品97| 91丨九色丨国产丨人妻在线 | 国产成人+综合亚洲+天堂| 久久女人视频| 2019亚洲男人天堂| 9久精品| 91人妻做a观看视频| 嗯嗯嗯好爽| 啊啊啊啊啊啊啊在线| 夜夜躁狠狠躁日日躁av| 亚州免费啪啪视频|