SpringBoot微頭條實戰項目

一、項目概述

微頭條是一個基于現代技術棧構建的新聞發布和瀏覽平臺,旨在為用戶提供便捷的新聞閱讀體驗和高效的新聞管理功能。該項目通過前后端分離的架構設計,實現了用戶注冊、登錄、新聞瀏覽、搜索、發布、修改和刪除等功能,同時通過JWT技術保證了用戶認證的安全性和高效性。

二、業務功能

? 用戶功能

? 注冊功能:用戶可以通過填寫相關信息完成注冊,成為平臺的合法用戶。

? 登錄功能:用戶使用注冊的賬號和密碼登錄平臺,登錄成功后通過JWT生成并存儲token,用于后續的用戶身份驗證。

? JWT實現:利用JWT技術生成和校驗token,確保用戶在每次請求時都能被正確識別和授權。

? 頭條新聞功能

? 分頁瀏覽:新聞以分頁的形式展示,用戶可以通過翻頁查看更多的新聞內容,提高了瀏覽效率。

? 搜索功能:用戶可以通過輸入新聞標題的關鍵字進行搜索,快速找到感興趣的新聞。

? 新聞詳情:用戶點擊新聞標題可以查看新聞的詳細內容,包括新聞正文、發布時間等。

? 修改和刪除:用戶可以對自己發布的新聞進行修改和刪除操作,但無法修改或刪除其他用戶發布的新聞,體現了權限控制機制。

三、技術棧

? 前端技術棧

? ES6:作為基礎的JavaScript語法,提供更簡潔、高效的代碼編寫方式。

? Node.js:作為運行環境,支持前端項目的開發和運行。

? npm:作為項目依賴管理工具,方便管理和安裝項目所需的依賴包。

? Vite:作為項目構建工具,提供快速的開發體驗和高效的構建性能。

? Vue3:作為項目數據的渲染框架,實現數據的動態綁定和頁面的響應式更新。

? Axios:用于前后端數據的交互,通過發送HTTP請求獲取或提交數據。

? Vue Router:用于頁面的跳轉,實現單頁面應用的路由管理。

? Pinia:用于存儲用戶的數據,提供全局狀態管理。

? LocalStorage:作為用戶校驗token的存儲手段,確保用戶在瀏覽器端的安全性和持久性。

? Element-Plus:提供豐富的UI組件,提升頁面的美觀度和用戶體驗。

? 后端技術棧

? Java:作為開發語言,版本為JDK17,提供強大的編程能力和豐富的庫支持。

? Tomcat:作為服務容器,版本為10.1.7,用于部署和運行Java Web應用。

? MySQL 8:作為項目存儲數據的數據庫,提供高效的數據存儲和查詢功能。

? SpringMVC:用于控制層實現前后端數據交互,處理用戶的HTTP請求并返回響應。

? MyBatis-Plus:用于實現數據的CRUD操作,簡化數據庫訪問代碼。

? Druid:作為數據源的連接池,提供高效的數據庫連接管理和性能優化。

? Spring Boot:作為項目基礎架構,簡化Spring應用的初始搭建和開發過程。

? MD5:用于用戶密碼的加密,確保用戶密碼的安全性。

? JWT:用于token的生成和校驗,實現無狀態的用戶認證機制。

? Jackson:用于JSON數據的轉換,方便前后端數據的交互和處理。

四、項目優勢

? 用戶體驗:通過分頁瀏覽和關鍵字搜索功能,用戶可以快速找到感興趣的新聞,提升了瀏覽效率。

? 安全性:采用JWT技術進行用戶認證,結合MD5加密用戶密碼,確保了用戶數據的安全性。

? 開發效率:使用Vue3和Spring Boot等現代技術棧,提高了開發效率,降低了開發成本。

? 可擴展性:基于前后端分離的架構設計,便于后續功能的擴展和維護。

五、功能展示

? 頭條首頁信息搜索:用戶可以在首頁通過關鍵字搜索新聞,快速定位到感興趣的新聞內容。

? 登錄功能:用戶通過輸入賬號和密碼進行登錄,登錄成功后獲取token并存儲在LocalStorage中。

在這里插入圖片描述

? 注冊功能:新用戶可以填寫相關信息完成注冊,注冊成功后即可登錄使用平臺。
在這里插入圖片描述

? 新聞發布功能:用戶可以發布新的新聞,輸入標題和內容后提交至后端服務器。
在這里插入圖片描述

? 新聞修改功能:用戶可以對自己發布的新聞進行修改,包括標題和內容的更新。

? 新聞刪除功能:用戶可以刪除自己發布的新聞,但無法刪除其他用戶發布的新聞,體現了權限控制機制。

微頭條項目通過合理的技術選型和功能設計,為用戶提供了一個安全、高效、易用的新聞發布和瀏覽平臺。

項目準備工作

前端項目創建:

通過網盤分享的文件:qianduan.zip
鏈接: https://pan.baidu.com/s/1synlG5QjepKxT_D-GioeEw?pwd=u4jn 提取碼: u4jn

1.將項目導入到vscode
在這里插入圖片描述

2.運行代碼 下載所需要的依賴 下載完之后會出現這個文件夾

npm install

在這里插入圖片描述
3.運行項目

npm run dev

在這里插入圖片描述

創建數據庫
CREATE DATABASE sm_db;USE sm_db;SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for news_headline
-- ----------------------------
DROP TABLE IF EXISTS `news_headline`;
CREATE TABLE `news_headline`  (`hid` INT NOT NULL AUTO_INCREMENT COMMENT '頭條id',`title` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '頭條標題',`article` VARCHAR(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '頭條新聞內容',`type` INT NOT NULL COMMENT '頭條類型id',`publisher` INT NOT NULL COMMENT '頭條發布用戶id',`page_views` INT NOT NULL COMMENT '頭條瀏覽量',`create_time` DATETIME(0) NULL DEFAULT NULL COMMENT '頭條發布時間',`update_time` DATETIME(0) NULL DEFAULT NULL COMMENT '頭條最后的修改時間',`version` INT DEFAULT 1 COMMENT '樂觀鎖',`is_deleted` INT DEFAULT 0 COMMENT '頭條是否被刪除 1 刪除  0 未刪除',PRIMARY KEY (`hid`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;-- ----------------------------
-- Records of news_headline
-- ----------------------------INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (5, '江南水鄉 龍舟競渡', '江南水鄉 龍舟競渡---6月18日,浙江省湖州市“我們的節日·端午”暨第七屆江南·民當端午民俗文化旅游節在南潯區和孚鎮民當村開幕,來自南潯區各個鄉鎮的農民選手在河道中賽龍舟、劃菱桶,體驗傳統端午民俗。', 1, 1, 0, '2023-06-25 09:32:13', '2023-06-25 09:32:13', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (6, '螃蟹粽、印花蛋、艾草涼粉……你知道端午有哪些創意美食嗎?', '端午有旅行路上的見聞,有詩畫里的藝術,也少不了舌尖上的風韻。聽風入夏粽香佐茶,您還知道端午有哪些創意美食嗎?端午至味,總少不了粽子這一味。甜的、咸的,肉餡的、蛋黃的、紅棗的、豆沙的……一起來尋味端午!\n\n  古人其實早就喜歡把各種果干放進粽子里,美食家蘇軾還發明了楊梅粽。《玉臺新詠》中說,“酒中喜桃子,粽里覓楊梅。”后來蘇軾曾借用過這個典故,在元祐三年所寫的端午帖子中說,“不獨盤中見盧橘,時于粽里得楊梅”。', 1, 1, 0, '2023-06-25 09:32:40', '2023-06-25 09:32:40', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (7, '尼克斯拒絕執行羅斯球隊選項 羅斯成自由球員', '北京時間6月25日,據多方消息源報道,尼克斯拒絕執行德里克-羅斯下賽季的球隊選項,羅斯成為完全自由球員。\n\n  34歲的羅斯在剛剛結束的賽季隊內角色嚴重下滑,他僅出戰27場比賽,場均登場12.5分鐘,得到5.6分1.5籃板1.7助攻。\n\n  2021年,羅斯與尼克斯簽下3年4300萬美元的續約合同,其中最后一年為1560萬美元球隊選項。', 2, 2, 0, '2023-06-25 09:34:26', '2023-06-25 09:34:26', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (8, '班凱羅承諾代表美國男籃打世界杯 名單僅差1人', '北京時間6月25日,據著名NBA記者沙姆斯-查拉尼亞報道,魔術前鋒保羅-班凱羅承諾將代表美國男籃參加2023年男籃世界杯。\n\n  班凱羅在剛剛結束的賽季場均能夠砍下20.0分6.9籃板3.7助攻,獲得了NBA2022-23賽季年度最佳新秀。', 2, 2, 0, '2023-06-25 09:34:59', '2023-06-25 09:34:59', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (9, 'F1加拿大大獎賽正賽:維斯塔潘冠軍 阿隆索亞軍', '2023年F1加拿大大獎賽正式比賽結束。紅牛車隊維斯塔潘桿位發車一路輕松領跑,再次完成了Pole-to-Win!這是紅牛車隊歷史上的第100座分站冠軍!同時也是維斯塔潘F1生涯的第41座分站冠軍,追平了“車神”埃爾頓·塞納的冠軍數!阿斯頓馬丁車隊阿隆索亞軍,梅賽德斯車隊漢密爾頓季軍。', 2, 2, 0, '2023-06-25 09:35:43', '2023-06-25 09:35:43', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (10, 'CTCC紹興柯橋站圓滿落幕 張志強曹宏煒各取一冠', '6月24日,2023賽季CTCC中國汽車場地職業聯賽紹興柯橋站在雨中的浙江國際賽車場上演了兩回合決賽的巔峰角逐。在線上線下觀眾的共同見證下,超級杯-TCR中國系列賽、運動杯-長三角賽車節聯袂獻上高水平對決,以精彩的比賽獻禮這個端午節假期!TCR 中國系列賽第三回合于今天上午率先開戰。來自殼牌捷凱領克車隊的張志強穿云破霧奪得冠軍;奪得該回合亞軍的是駕駛新賽車出戰的東風本田車手高度,季軍則由Z.SPEED N車隊的張臻東斬獲。這也是超級杯四冠王本賽季首次登臺。', 2, 2, 0, '2023-06-25 09:36:18', '2023-06-25 09:36:18', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (11, '國象聯賽常規賽收兵:杭州銀行第一 山東成功上岸', '6月17日,“武陵山大裂谷杯”中國國際象棋甲級聯賽常規賽在武陵云海國際酒店進行了最后一輪的爭奪,杭州銀行弈和山東隊,搶到常規賽的冠軍;山東隊也是憑借這場平局,成功脫離保級區。本輪最大的懸念是第八名的爭奪——在年底進行的甲級聯賽總決賽中,前八名為上半區爭冠組,保級無憂;而第九至十二名為保級區,不僅奪冠無望,還要為保級而苦戰。', 2, 2, 0, '2023-06-25 09:36:51', '2023-06-25 09:36:51', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (12, '圍棋名宿解讀高考作文:人生如棋 要先學會下“本手”', '今年高考開考了,在語文考試后,體育借勢沖上了社交媒體的熱搜榜。奧運相關話題進入高考,是意料之中。不過當記者看到關于圍棋術語“本手、妙手和俗手”的作文命題時,著實覺得有些難。在被迅速刷屏的朋友圈里,記者感受到了很多從業者的激動、興奮乃至油然而生的自豪感。但也有人則為那些沒學過棋的孩子感到擔心,這么難的題目,究竟該如何解題?\n\n  “圍棋正在深入人心。題目有些難,‘俗手’如何定義?但確實應該先下好‘本手’。”翻到中國圍棋協會副主席、國家圍棋隊領隊華學明的這條朋友圈動態時,記者瞬間覺得這道公認的難題有了解題的思路。正如高考作文材料中所說,本手是基礎。只有持之以恒地打好基礎,補強短板,守住不發生系統性風險的底線,才有可能在本手的基礎上,下出妙手,避免俗手。而如果脫離了基礎,所謂的妙手很可能就是花拳繡腿,經不起推敲,更經不起對手的沖擊。世界冠軍柯潔表示:“很多人在對局中經常會拘泥于局部,下出假妙手。想下出真正的妙手,必須在平日里有一定的經驗積累和訓練,才可能完成真正卓越的妙手。”人生如棋,棋如人生。“其實人生中大部分時間都是在下本手”,圍棋名宿曹大元九段說。', 2, 2, 0, '2023-06-25 09:37:43', '2023-06-25 09:37:43', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (13, '不甘人后:被生成式AI彌漫的亞馬遜', '今年早些時候,隨著ChatGPT席卷全球,亞馬遜的經理們要求員工開動腦筋,想想如何使用人工智能(AI)聊天機器人技術來改進自家產品和工作流程。\n\n  其中一些想法被分享在一份名為《生成式AI——ChatGPT的影響和機會分析》的內部文件中。這份文件共列了ChatGPT和類似應用程序在亞馬遜多個團隊中的67個潛在應用案例。\n\n  早在20世紀90年代,亞馬遜就靠在網上賣書創造了互聯網界首個真正的商業奇跡。\n\n  隨后,Kindle閱讀器帶來革命性體驗,Alexa和Echo智能音箱又帶來了語音計算,而AWS則創造了云計算行業,ChatGPT就運行在這個行業之上。\n\n  但這次熱潮中拿到先發優勢的是同為科技大廠的微軟。微軟現在是OpenAI背后的金主,且還在忙著把ChatGPT的底層技術融進微軟產品和服務中。', 4, 5, 0, '2023-06-25 09:40:20', '2023-06-25 09:40:20', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (14, '微創新超實用:米家旅行箱居然想到了這一點', '旅行說走就走,除非老板沒安排。名義上是旅游,實則執行任務,對內講“為公司負重前行”,對外稱“帶薪游山玩水”,一介打工人,兩副撲克臉,個中苦樂誰人知!\n\n“差旅人”精明如我,隨身攜帶更偏向實用。\n\n必備日用之外,能路上買的盡量不帶,華而不實的東西,往包里多塞一個都算我輸。行李箱尺寸自然也要濃縮到小巧但夠裝的20英寸,拉著輕松又順手,常用小物件轉移到背包,“輕裝上戰場”。', 4, 5, 0, '2023-06-25 09:41:04', '2023-06-25 09:41:04', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (15, '小鵬G6動態試駕:輔助駕駛很驚喜', '這次我們開著小鵬G6上了賽道,又體驗了最新版本的高速NGP和城市NGP,小鵬,還順便測了下充電速度,那么小鵬G6駕駛感受如何?輔助駕駛表現怎么樣?', 4, 5, 0, '2023-06-25 09:42:07', '2023-06-25 09:42:07', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (16, '養車市場陷入低價內卷,“虎貓狗”還沒等到春天', '今年“618”期間,汽車后市場的玩家們都打出了“低價牌”。比如途虎養車宣布推出“6.18全民養車季”活動,在此期間北京車主可享受“輪胎買一送一”以及多品牌輪胎降價促銷的活動。\n\n  與此同時,京東養車和天貓養車兩大大廠玩家,在本次618期間也喊出了各自的營銷口號。\n\n  前者不僅喊出了“養車愛車立省不止30%”的口號,還推出了輪胎、保養買貴賠兩倍、“輪胎免費裝、三年無憂質保”、5公里無服務門店賠雙倍安裝費等舉措;天貓養車的618活動,則覆蓋了更大的零部件范圍,比如推出了空調清洗、機油和輪胎更換等低價服務。\n\n  這樣看,在本次618期間,途虎養車、京東養車和天貓養車均貫徹著“以價換量”的戰略,以至于讓行業價格戰一觸即發。這些玩家會這樣做,主要是為了與傳統4S店、以及與彼此競爭,以便保證自身獲得更多的市場份額。', 4, 5, 0, '2023-06-25 09:42:51', '2023-06-25 09:42:51', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (17, '微軟股價歷史新高 聊天機器人技術潛力顯現', '周四,微軟股價創下歷史新高,成為今年繼英偉達和蘋果之后,又一家市值達到新高點的大型科技公司。這家軟件巨頭正致力于在其產品和服務中添加生成式人工智能功能,旨在全面改造其Office產品陣容,其中包括Excel、PowerPoint、Outlook和Word等。股價上漲3.2%,收于每股348.1美元,為2021年11月19日以來的最高收盤價。自今年初起,微軟股價累計上漲了45%,市值增加約8006億美元。微軟持有OpenAI的大部分股份,這家初創公司憑借聊天機器人ChatGPT引發生成式人工智能的熱潮。近幾個月來,該工具廣受歡迎,展示了聊天機器人技術所具有的巨大潛力。微軟于今年1月宣布將再向OpenAI投資100億美元。然而有報道稱,微軟與OpenAI之間既有合作,亦存競爭,這種特殊的雙重關系導致了雙方關系的緊張和潛在沖突。科技股如英偉達等同樣受益于生成式人工智能技術的應用,各公司將此技術融入各自產品,進而推動相關芯片需求。英偉達股價今年已飆升192%,被視為最大贏家。', 4, 5, 0, '2023-06-25 09:43:48', '2023-06-25 09:43:48', 0);
INSERT INTO `news_headline` (hid,title,article,TYPE,publisher,page_views,create_time,update_time,is_deleted) VALUES (18, '再獲11億美元投資:蔚來“長期主義”的底氣', '如果說全系降價3萬是李斌的“陽謀”,那么蔚來ET5T的發布,則是李斌的又一次誠意之作。\n\n  ET5T是蔚來首款售價下探到30萬元以下的新車,作為ET5的姐妹車型,ET5T和ET5的雙車合璧,得以在30萬以下快速開疆辟土。\n\n  這樣的做法有跡可循:特斯拉曾經在Model Y上實踐過,并大獲成功。\n\n  Model Y和Model 3共用平臺,零部件復用率高達75%,研發成本驟降。盡管Model Y最初被用戶吐槽是Model 3的放大版,但不置可否的是Model Y確實解決了用戶對Model 3空間不足的槽點。\n\n  不過,最為關鍵的還是Model Y的價格足夠低,直接降低了特斯拉的購買門檻,給那些對價格敏感,本猶豫要不要多花四五萬的消費者一個充足的理由。\n\n  蔚來ET5T正在用一種經受了市場驗證過的方式,直面與特斯拉的競爭。但同時,蔚來ET5T在智能化、空間表現、設計以及產品力上,都正在接近、超越特斯拉Model Y。\n\n  蔚來ET5T,平替特斯拉Model Y?\n\n  小家庭,預算30萬左右,消費者到底會選哪款純電動車?\n\n  全球市場的反饋是,特斯拉Model Y ——一款緊湊型SUV。2022年,Model Y的全球銷量為74.7萬輛,其在中國的銷量為31.5萬臺,約占其全球份額的42.2%。\n\n  按照車型大小,SUV可以分為大型、中型、小型、緊湊型四大類。按照價位,SUV又可以分為實用型、經濟型、中高檔型、豪華型、超豪華型等。\n\n  Model Y 在中高端SUV的細分市場中一騎絕塵,可以說是沒有對手。因為無論是奔馳EQC、寶馬iX3,還是國產的比亞迪唐EV等,和Model Y相比,都不能對其構成威脅。奔馳EQC、寶馬iX3這兩款車型都是“油改電”,算不上真正的電動車。而比亞迪的智能化能力,遠及不特斯拉,座艙、智駕上的核心模塊還來自于供應商方案,并非自研。\n\n  雷峰網認為,此前,國內的自主品牌中只有蔚來的ES6能和Model Y一較高下。不過ES6的均價比Model Y高出一大截,二者入門版之間的價差大約在10萬左右。但在蔚來推出ET5T后,局勢必然會發生逆轉。', 4, 5, 0, '2023-06-25 09:44:20', '2023-06-25 09:44:20', 0);-- ----------------------------
-- Table structure for news_type
-- ----------------------------
DROP TABLE IF EXISTS `news_type`;
CREATE TABLE `news_type`  (`tid` INT NOT NULL AUTO_INCREMENT COMMENT '新聞類型id',`tname` VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '新聞類型描述',`version` INT DEFAULT 1 COMMENT '樂觀鎖',`is_deleted` INT DEFAULT 0 COMMENT '頭條是否被刪除 1 刪除  0 未刪除',PRIMARY KEY (`tid`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;-- ----------------------------
-- Records of news_type
-- ----------------------------
INSERT INTO `news_type` (tid,tname) VALUES (1, '新聞');
INSERT INTO `news_type` (tid,tname) VALUES (2, '體育');
INSERT INTO `news_type` (tid,tname) VALUES (3, '娛樂');
INSERT INTO `news_type` (tid,tname) VALUES (4, '科技');
INSERT INTO `news_type` (tid,tname) VALUES (5, '其他');-- ----------------------------
-- Table structure for news_user
-- ----------------------------
DROP TABLE IF EXISTS `news_user`;
CREATE TABLE `news_user`  (`uid` INT NOT NULL AUTO_INCREMENT COMMENT '用戶id',`username` VARCHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶登錄名',`user_pwd` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶登錄密碼密文',`nick_name` VARCHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶昵稱',`version` INT DEFAULT 1 COMMENT '樂觀鎖',`is_deleted` INT DEFAULT 0 COMMENT '頭條是否被刪除 1 刪除  0 未刪除',PRIMARY KEY (`uid`) USING BTREE,UNIQUE INDEX `username_unique`(`username`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;-- ----------------------------
-- Records of news_user
-- ----------------------------
INSERT INTO `news_user` (uid,username,user_pwd,nick_name) VALUES (1, 'zhangsan', 'e10adc3949ba59abbe56e057f20f883e', '張三');
INSERT INTO `news_user` (uid,username,user_pwd,nick_name) VALUES (2, 'lisi', 'e10adc3949ba59abbe56e057f20f883e', '李四');
INSERT INTO `news_user` (uid,username,user_pwd,nick_name) VALUES (5, 'zhangxiaoming', 'e10adc3949ba59abbe56e057f20f883e', '張小明');
INSERT INTO `news_user` (uid,username,user_pwd,nick_name)VALUES (6, 'xiaohei', 'e10adc3949ba59abbe56e057f20f883e', '李小黑');SET FOREIGN_KEY_CHECKS = 1;
搭建SpringBoot項目
1.創建Springboot工程
2.導入pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.nie</groupId><artifactId>spring-weitoutiao</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.5</version></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mybatis-plus  --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><!-- 數據庫相關配置啟動器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- druid啟動器的依賴  --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.18</version></dependency><!-- 驅動類--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version></dependency></dependencies><!--    SpringBoot應用打包插件--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
3.寫入配置 application.yml
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:url: jdbc:mysql:///sm_dbusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverserver:port: 8080servlet:context-path: /mybatis-plus:type-aliases-package: com.nie.pojoglobal-config:db-config:logic-delete-field: isDeletedid-type: autotable-prefix: news_#jwt配置
jwt:token:tokenExpiration: 120 #有效時間,單位分鐘tokenSignKey: headline123456  #當前程序簽名秘鑰 自定義
4.druid兼容springboot3文件
文件名:org.springframework.boot.autoconfigure.AutoConfiguration.imports
內容:com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure

在這里插入圖片描述

5.啟動類和mybatiesPlus配置
package com.nie;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
@MapperScan("com.nie.pojo")
public class Main {public static void main(String[] args) {SpringApplication.run(Main.class, args);}@Beanpublic MybatisPlusInterceptor getMybatisConfiguration() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//配置分頁插件mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//配置樂觀鎖mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//配置防止權標刪除mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return  mybatisPlusInterceptor;}}
6.工具類準備

6.1 封裝結果類

package com.nie.utils;/*** 全局統一返回結果類*/
public class Result<T> {// 返回碼private Integer code;// 返回消息private String message;// 返回數據private T data;public Result(){}// 返回數據protected static <T> Result<T> build(T data) {Result<T> result = new Result<T>();if (data != null)result.setData(data);return result;}public static <T> Result<T> build(T body, Integer code, String message) {Result<T> result = build(body);result.setCode(code);result.setMessage(message);return result;}public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {Result<T> result = build(body);result.setCode(resultCodeEnum.getCode());result.setMessage(resultCodeEnum.getMessage());return result;}/*** 操作成功* @param data  baseCategory1List* @param <T>* @return*/public static<T> Result<T> ok(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.SUCCESS);}public Result<T> message(String msg){this.setMessage(msg);return this;}public Result<T> code(Integer code){this.setCode(code);return this;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}

6.2 枚舉類

package com.nie.utils;/*** 統一返回結果狀態信息類**/
public enum ResultCodeEnum {SUCCESS(200,"success"),USERNAME_ERROR(501,"usernameError"),PASSWORD_ERROR(503,"passwordError"),NOTLOGIN(504,"notLogin"),USERNAME_USED(505,"userNameUsed");private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}public Integer getCode() {return code;}public String getMessage() {return message;}
}

6.3 MD5加密工具類

package com.nie.utils;import org.springframework.stereotype.Component;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;@Component
public final class MD5Util {public static String encrypt(String strSrc) {try {char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f' };byte[] bytes = strSrc.getBytes();MessageDigest md = MessageDigest.getInstance("MD5");md.update(bytes);bytes = md.digest();int j = bytes.length;char[] chars = new char[j * 2];int k = 0;for (int i = 0; i < bytes.length; i++) {byte b = bytes[i];chars[k++] = hexChars[b >>> 4 & 0xf];chars[k++] = hexChars[b & 0xf];}return new String(chars);} catch (NoSuchAlgorithmException e) {e.printStackTrace();throw new RuntimeException("MD5加密出錯!!+" + e);}}
}
MybatiesX插件生成service接口 service實現類 mapper.xml mapper接口

選中三個數據庫表 點擊第一個
在這里插入圖片描述
配置路徑
在這里插入圖片描述
選擇配置 點擊finish
在這里插入圖片描述

添加主鍵,樂觀鎖,邏輯刪除注解!!!

用戶表:

package com.nie.pojo;import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;import java.io.Serializable;/*** @TableName news_user*/
@Data
public class User implements Serializable {@TableIdprivate Integer uid;private String username;private String userPwd;private String nickName;@Versionprivate Integer version;private Integer isDeleted;
}

類型表:

package com.nie.pojo;import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;import java.io.Serializable;/*** @TableName news_type*/@Data
public class Type implements Serializable {@TableIdprivate Integer tid;private String tname;@Versionprivate Integer version;private Integer isDeleted;
}

新聞表:

package com.nie.pojo;import com.baomidou.mybatisplus.annotation.*;import java.io.Serializable;
import java.util.Date;
import lombok.Data;/*** @TableName news_headline*/
@Data
public class Headline implements Serializable {@TableIdprivate Integer hid;private String title;private String article;private Integer type;private Integer publisher;private Integer pageViews;private Date createTime;private Date updateTime;@Versionprivate Integer version;private Integer isDeleted;
}

后臺功能開發

封裝JWT工具類

package com.nie.utils;import com.alibaba.druid.util.StringUtils;
import io.jsonwebtoken.*;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;import java.util.Date;@Data
@Component
@ConfigurationProperties(prefix = "jwt.token")
public class JwtHelper {// JWT 令牌的有效時間,單位為毫秒(1000毫秒 = 1秒)private long tokenExpiration;// JWT 簽名密鑰,用于生成和驗證 JWT 令牌private String tokenSignKey;/*** 生成 JWT 令牌字符串。* <p>* 這個方法根據用戶 ID 創建一個 JWT 令牌,并設置其有效時間和簽名。** @param userId 用戶的唯一標識* @return 生成的 JWT 令牌字符串*/public String createToken(Long userId) {System.out.println("tokenExpiration = " + tokenExpiration);System.out.println("tokenSignKey = " + tokenSignKey);String token = Jwts.builder().setSubject("YYGH-USER") // 設置主題(可以是任意字符串,用于標識令牌的用途).setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * 1000 * 60)) // 設置令牌的有效時間(單位為分鐘).claim("userId", userId) // 添加用戶 ID 到 JWT 的自定義聲明中.signWith(SignatureAlgorithm.HS512, tokenSignKey) // 使用 HS512 算法和簽名密鑰對令牌進行簽名.compressWith(CompressionCodecs.GZIP) // 對 JWT 令牌進行壓縮.compact(); // 將 JWT 令牌轉換為緊湊的字符串形式return token;}/*** 從 JWT 令牌字符串中獲取用戶 ID。* <p>* 這個方法解析 JWT 令牌,并從其自定義聲明中提取用戶 ID。** @param token JWT 令牌字符串* @return 用戶 ID,如果令牌無效或為空,則返回 null*/public Long getUserId(String token) {if (StringUtils.isEmpty(token)) return null; // 如果令牌為空,直接返回 nullJws<Claims> claimsJws = Jwts.parser() // 解析 JWT 令牌.setSigningKey(tokenSignKey) // 設置簽名密鑰.parseClaimsJws(token); // 解析并驗證 JWT 令牌Claims claims = claimsJws.getBody(); // 獲取 JWT 的聲明部分Integer userId = (Integer) claims.get("userId"); // 從聲明中提取用戶 IDreturn userId.longValue(); // 返回用戶 ID 的長整型值}/*** 判斷 JWT 令牌是否過期。* <p>* 這個方法解析 JWT 令牌,并檢查其有效時間是否已經過期。** @param token JWT 令牌字符串* @return 如果令牌過期或無效,返回 true;否則返回 false*/public boolean isExpiration(String token) {try {boolean isExpire = Jwts.parser() // 解析 JWT 令牌.setSigningKey(tokenSignKey) // 設置簽名密鑰.parseClaimsJws(token) // 解析并驗證 JWT 令牌.getBody() // 獲取 JWT 的聲明部分.getExpiration() // 獲取令牌的有效時間.before(new Date()); // 檢查有效時間是否在當前時間之前// 如果沒有過期,返回 falsereturn isExpire;} catch (Exception e) {// 如果解析失敗或令牌過期,返回 truereturn true;}}
}

用戶模塊
controller

package com.nie.controller;import com.nie.pojo.User;
import com.nie.service.UserService;
import com.nie.utils.JwtHelper;
import com.nie.utils.Result;
import com.nie.utils.ResultCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("user")
@CrossOrigin
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate JwtHelper jwtHelper;@PostMapping("login")public Result login(@RequestBody User user) {Result result=userService.login(user);return  result;}@GetMapping("getUserInfo")public Result getUserInfo(@RequestHeader String token){Result result=userService.getUserInfo(token);return result;}@PostMapping("checkUserName")public Result checkUserName(String username){Result result=userService.checkUserName(username);return  result;}//注冊@PostMapping("regist")public Result regist(@RequestBody User user){Result result=userService.regist(user);return  result;}//登陸檢查@GetMapping("checkLogin")public Result checkLogin(@RequestHeader String token){boolean expiration = jwtHelper.isExpiration(token);if (expiration) {return  Result.build(null, ResultCodeEnum.NOTLOGIN);}return Result.ok(null);}
}

service接口

package com.nie.service;import com.nie.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nie.utils.Result;/**
* @author Administrator
* @description 針對表【news_user】的數據庫操作Service
* @createDate 2025-04-15 12:01:47
*/
public interface UserService extends IService<User> {Result login(User user);Result getUserInfo(String token);Result checkUserName(String username);Result regist(User user);
}

service實現類

package com.nie.service.impl;import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nie.pojo.User;
import com.nie.service.UserService;
import com.nie.mapper.UserMapper;
import com.nie.utils.JwtHelper;
import com.nie.utils.MD5Util;
import com.nie.utils.Result;
import com.nie.utils.ResultCodeEnum;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;/**
* @author Administrator
* @description 針對表【news_user】的數據庫操作Service實現
* @createDate 2025-04-15 12:01:47
*/
@Service
@MapperScan("com.nie.mapper")
public class UserServiceImpl extends ServiceImpl<UserMapper, User>implements UserService{@Autowiredprivate UserMapper userMapper;@Autowiredprivate JwtHelper jwtHelper;@Overridepublic Result login(User user) {LambdaQueryWrapper<User> lambdaQueryWrappen=new LambdaQueryWrapper<>();lambdaQueryWrappen.eq(User::getUsername,user.getUsername());User loginUser = userMapper.selectOne(lambdaQueryWrappen);if (loginUser == null) {return Result.build(null, ResultCodeEnum.USERNAME_ERROR);}if (!StringUtils.isEmpty(user.getUserPwd()) && MD5Util.encrypt(user.getUserPwd()).equals(loginUser.getUserPwd())){String token = jwtHelper.createToken(Long.valueOf(loginUser.getUid()));Map data=new HashMap();data.put("token",token);return Result.ok(data);}return Result.build(null,ResultCodeEnum.PASSWORD_ERROR);}@Overridepublic Result getUserInfo(String token) {//判斷傳過來的token是否過期 true就是過期了boolean expiration = jwtHelper.isExpiration(token);if (expiration) {return Result.build(null,ResultCodeEnum.NOTLOGIN);}int userid = jwtHelper.getUserId(token).intValue();User user = userMapper.selectById(userid);user.setUserPwd("");Map data=new HashMap();data.put("loginUser",user);return Result.ok(data);}//是否可以注冊@Overridepublic Result checkUserName(String username) {LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(User::getUsername,username);Long count = userMapper.selectCount(lambdaQueryWrapper);if (count==0) {return Result.ok(null);}else{return Result.build(null,ResultCodeEnum.USERNAME_USED);}}//注冊業務@Overridepublic Result regist(User user) {LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(User::getUsername, user.getUsername());Long count = userMapper.selectCount(lambdaQueryWrapper);if (count > 0) {return Result.build(null, ResultCodeEnum.USERNAME_USED);}//密碼加密user.setUserPwd(MD5Util.encrypt(user.getUserPwd()));userMapper.insert(user);return  Result.ok(null);}
}

mapper接口

package com.nie.mapper;import com.nie.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/**
* @author Administrator
* @description 針對表【news_user】的數據庫操作Mapper
* @createDate 2025-04-15 12:01:47
* @Entity com.nie.pojo.User
*/
public interface UserMapper extends BaseMapper<User> {}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nie.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.nie.pojo.User"><id property="uid" column="uid" /><result property="username" column="username" /><result property="userPwd" column="user_pwd" /><result property="nickName" column="nick_name" /><result property="version" column="version" /><result property="isDeleted" column="is_deleted" /></resultMap><sql id="Base_Column_List">uid,username,user_pwd,nick_name,version,is_deleted</sql>
</mapper>

首頁模塊
配置分頁查詢實體類

package com.nie.pojo.vo;import lombok.Data;@Data
public class PortalVo {private String keyWords;private int type=0;private int pageNum=1;private int pageSize=10;}

controller

package com.nie.controller;import com.nie.pojo.vo.PortalVo;
import com.nie.service.HeadlineService;
import com.nie.service.TypeService;
import com.nie.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("portal")
@CrossOrigin
public class PortalController {@Autowiredprivate TypeService typeService;@Autowiredprivate HeadlineService headlineService;@GetMapping("findAllTypes")public Result findAllTypes(){Result result=typeService.findAllTypes();return result;}@PostMapping("findNewsPage")public Result findNewsPage(@RequestBody PortalVo portalVo){Result result=headlineService.findNewsPage(portalVo);return result;}@PostMapping("showHeadlineDetail")public Result showHeadlineDetail(Integer hid){Result result=headlineService.showHeadlineDetail(hid);return  result;}
}

service接口

package com.nie.service;import com.nie.pojo.Type;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nie.utils.Result;/**
* @author Administrator
* @description 針對表【news_type】的數據庫操作Service
* @createDate 2025-04-15 12:01:47
*/
public interface TypeService extends IService<Type> {Result findAllTypes();
}

service實現類

package com.nie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nie.pojo.Type;
import com.nie.service.TypeService;
import com.nie.mapper.TypeMapper;
import com.nie.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/**
* @author Administrator
* @description 針對表【news_type】的數據庫操作Service實現
* @createDate 2025-04-15 12:01:47
*/
@Service
public class TypeServiceImpl extends ServiceImpl<TypeMapper, Type>implements TypeService{@Autowiredprivate TypeMapper typeMapper;@Overridepublic Result findAllTypes() {List<Type> types=typeMapper.selectList(null);return Result.ok(types);}
}

mapper接口

package com.nie.mapper;import com.nie.pojo.Type;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/**
* @author Administrator
* @description 針對表【news_type】的數據庫操作Mapper
* @createDate 2025-04-15 12:01:47
* @Entity com.nie.pojo.Type
*/
public interface TypeMapper extends BaseMapper<Type> {}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nie.mapper.TypeMapper"><resultMap id="BaseResultMap" type="com.nie.pojo.Type"><id property="tid" column="tid" /><result property="tname" column="tname" /><result property="version" column="version" /><result property="isDeleted" column="is_deleted" /></resultMap><sql id="Base_Column_List">tid,tname,version,is_deleted</sql>
</mapper>

頭條模塊

登陸驗證和保護

  • 客戶端在進入發布頁前、發布新聞前、進入修改頁前、修改前、刪除新聞前先向服務端發送請求攜帶token請求頭
  • 后端接收token請求頭后,校驗用戶登錄是否過期并做響應
  • 前端根據響應信息提示用戶進入登錄頁還是進入正常業務頁面
    controller
@GetMapping("checkLogin")
public Result checkLogin(@RequestHeader String token){if (StringUtils.isEmpty(token) || jwtHelper.isExpiration(token)){//沒有傳或者過期 未登錄return Result.build(null, ResultCodeEnum.NOTLOGIN);}return Result.ok(null);
}

攔截器

package com.nie.interceptors;import com.fasterxml.jackson.databind.ObjectMapper;
import com.nie.utils.JwtHelper;
import com.nie.utils.Result;
import com.nie.utils.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;@Component
public class LoginProtectedInterceptor implements HandlerInterceptor {// 自動注入 JwtHelper 工具類,用于處理 JWT 相關的邏輯@Autowiredprivate JwtHelper jwtHelper;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 從請求頭中獲取名為 "token" 的值String token = request.getHeader("token");// 調用 JwtHelper 的 isExpiration 方法,檢查 token 是否過期boolean expiration = jwtHelper.isExpiration(token);// 如果 token 未過期,允許請求繼續執行if (!expiration) {return true;}// 如果 token 過期或無效,創建一個未登錄的提示結果Result result = Result.build(null, ResultCodeEnum.NOTLOGIN);// 創建 ObjectMapper 對象,用于將 Result 對象轉換為 JSON 格式的字符串ObjectMapper objectMapper = new ObjectMapper();// 將 Result 對象轉換為 JSON 格式的字符串String json = objectMapper.writeValueAsString(result);// 將 JSON 字符串寫入響應體,返回給客戶端response.getWriter().print(json);// 返回 false,表示攔截請求,阻止請求繼續執行return false;}
}

配置攔截器 所有以headline開頭的路徑

package com.nie.config;import com.nie.interceptors.LoginProtectedInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate LoginProtectedInterceptor loginProtectedInterceptor;@Override/****添加攔截器*/public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginProtectedInterceptor).addPathPatterns("/headline/**");}
}

controller

package com.nie.controller;import com.nie.pojo.Headline;
import com.nie.service.HeadlineService;
import com.nie.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("headline")
@CrossOrigin
public class HeadlineController {@Autowiredprivate HeadlineService headlineService;@PostMapping("publish")public Result publish(@RequestBody Headline headline,@RequestHeader String token){Result result=headlineService.publish(headline,token);return result;}@PostMapping("findHeadlineByHid")public Result findHeadlineByHid(Integer hid){Headline headline = headlineService.getById(hid);Map map=new HashMap();map.put("headline",headline);return  Result.ok(map);}@PostMapping("updata")public Result updata(@RequestBody Headline headline){Result result=headlineService.updateData(headline);return result;}@PostMapping("removeByHid")public Result removeByHid(Integer hid){Result result=headlineService.removeByHid(hid);return result;}
}

service接口

package com.nie.service;import com.nie.pojo.Headline;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nie.pojo.vo.PortalVo;
import com.nie.utils.Result;/**
* @author Administrator
* @description 針對表【news_headline】的數據庫操作Service
* @createDate 2025-04-15 12:01:47
*/
public interface HeadlineService extends IService<Headline> {Result findNewsPage(PortalVo portalVo);Result showHeadlineDetail(Integer hid);Result publish(Headline headline,String token);Result updateData(Headline headline);Result removeByHid(Integer hid);
}

service實現類

package com.nie.service.impl;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nie.pojo.Headline;
import com.nie.pojo.vo.PortalVo;
import com.nie.service.HeadlineService;
import com.nie.mapper.HeadlineMapper;
import com.nie.utils.JwtHelper;
import com.nie.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/**
* @author Administrator
* @description 針對表【news_headline】的數據庫操作Service實現
* @createDate 2025-04-15 12:01:47
*/
@Service
public class HeadlineServiceImpl extends ServiceImpl<HeadlineMapper, Headline>implements HeadlineService{@Autowiredprivate HeadlineMapper headlineMapper;@Autowiredprivate JwtHelper jwtHelper;@Overridepublic Result findNewsPage(PortalVo portalVo) {IPage<Map> Page=new Page<>(portalVo.getPageNum(),portalVo.getPageSize());headlineMapper.selectMyPage(Page,portalVo);//獲取他里面的集合數據List<Map> records = Page.getRecords();Map data=new HashMap();data.put("pageData",records);data.put("pageNum",Page.getCurrent());data.put("pageSize",Page.getSize());data.put("totalPage",Page.getPages());data.put("totalSize",Page.getTotal());Map pageInfo=new HashMap();pageInfo.put("pageInfo",data);return Result.ok(pageInfo);}//根據ID查詢頭條詳情@Overridepublic Result showHeadlineDetail(Integer hid) {Map data=headlineMapper.queryDetailMap(hid);Map headline=new HashMap();headline.put("headline",data);//修改閱讀量加1Headline headline1=new Headline();headline1.setHid((Integer) data.get("hid"));headline1.setVersion((Integer) data.get("version"));//閱讀量+1headline1.setPageViews((Integer) data.get("pageViews")+1);headlineMapper.updateById(headline1);return Result.ok(headline);}@Overridepublic Result publish(Headline headline,String token) {//token查詢用戶idint userId = jwtHelper.getUserId(token).intValue();headline.setPublisher(userId);headline.setPageViews(0);headline.setCreateTime(new Date());headline.setUpdateTime(new Date());headlineMapper.insert(headline);return Result.ok(null);}@Overridepublic Result updateData(Headline headline) {Integer version = headlineMapper.selectById(headline.getHid()).getVersion();headline.setVersion(version);headline.setUpdateTime(new Date());headlineMapper.updateById(headline);return Result.ok(null);}@Overridepublic Result removeByHid(Integer hid) {headlineMapper.deleteById(hid);return Result.ok(null);}
}

mapper接口

package com.nie.mapper;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.nie.pojo.Headline;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nie.pojo.vo.PortalVo;
import org.apache.ibatis.annotations.Param;import java.util.Map;/**
* @author Administrator
* @description 針對表【news_headline】的數據庫操作Mapper
* @createDate 2025-04-15 12:01:47
* @Entity com.nie.pojo.Headline
*/
public interface HeadlineMapper extends BaseMapper<Headline> {IPage<Map> selectMyPage(IPage page,@Param("portalVo") PortalVo portalVo);Map queryDetailMap(Integer hid);
}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nie.mapper.HeadlineMapper"><resultMap id="BaseResultMap" type="com.nie.pojo.Headline"><id property="hid" column="hid" /><result property="title" column="title" /><result property="article" column="article" /><result property="type" column="type" /><result property="publisher" column="publisher" /><result property="pageViews" column="page_views" /><result property="createTime" column="create_time" /><result property="updateTime" column="update_time" /><result property="version" column="version" /><result property="isDeleted" column="is_deleted" /></resultMap><sql id="Base_Column_List">hid,title,article,type,publisher,page_views,create_time,update_time,version,is_deleted</sql><select id="selectMyPage" resultType="map">select hid,title,type,page_views pageViews,TIMESTAMPDIFF(HOUR,create_time,NOW()) pastHours,publisher from news_headline where is_deleted=0<if test="portalVo.keyWords !=null and portalVo.keyWords.length()>0 ">and title like concat('%',#{portalVo.keyWords},'%')</if><if test="portalVo.type != null and portalVo.type != 0">and type = #{portalVo.type}</if></select><select id="queryDetailMap" resultType="java.util.Map">select hid,title,article,type, h.version ,tname typeName ,page_views pageViews,TIMESTAMPDIFF(HOUR,create_time,NOW()) pastHours,publisher,nick_name author from news_headline hleft join news_type t on h.type = t.tidleft join news_user u  on h.publisher = u.uidwhere hid = #{hid}</select></mapper>

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

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

相關文章

如何給電腦換個ip地址?電腦換ip幾種方法

更換電腦的IP地址的方法取決于你的具體需求和網絡環境&#xff08;是換本地局域網IP還是換對外公網IP&#xff09;。以下是幾種常見的方法&#xff1a; 一、更換本地局域網IP地址&#xff08;在同一個網絡內&#xff09; 這個IP地址通常由你的路由器&#xff08;或公司的網絡管…

Pytest項目_day04(Python做接口請求)

Requests包 在python中&#xff0c;可以使用requests包&#xff0c;用于做接口請求和接口測試request支持http和https簡單的get函數調用如下&#xff1a;r.jsonr.status_coder.textget函數的帶params用法post函數的帶params用法 post也可以和get一樣在url中傳入參數在requests包…

Flink與Kafka核心源碼詳解-目錄

Flink是Apache軟件基金會下開源的分布式流批一體計算框架&#xff0c;具備實時流計算和高吞吐批處理計算的大數據計算能力。本專欄內容為Flink源碼解析的記錄與分享。 本文解析的Flink源碼版本為&#xff1a;flink-1.19.0 以下為Flink-1.19.0-完整源碼詳解的目錄導航。 Flink-…

【VLLM篇】:原理-實現

1、VLLM vLLM是一個建立在【PagedAttention】之上的高吞吐的【分布式服務引擎】&#xff0c;目標是【提高吞吐量】、【提高內存利用率】&#xff08;kv-cache內存利用率高達96%&#xff09;&#xff0c;它的內存管理分配方式從【固定分配】改進為【分頁管理】&#xff0c;類似操…

什么是 TcpCommunicationSpi

&#x1f9e9; 一、核心定位&#xff1a;什么是 TcpCommunicationSpi&#xff1f; /*** <tt>TcpCommunicationSpi</tt> is default communication SPI which uses* TCP/IP protocol and Java NIO to communicate with other nodes.*/翻譯&#xff1a;TcpCommunicat…

【NLP輿情分析】基于python微博輿情分析可視化系統(flask+pandas+echarts) 視頻教程 - 詞云圖-微博評論用戶詞云圖實現

大家好&#xff0c;我是java1234_小鋒老師&#xff0c;最近寫了一套【NLP輿情分析】基于python微博輿情分析可視化系統(flaskpandasecharts)視頻教程&#xff0c;持續更新中&#xff0c;計劃月底更新完&#xff0c;感謝支持。今天講解詞云圖-微博評論用戶詞云圖實現 視頻在線地…

數據結構----棧和隊列認識

目錄 棧&#xff08;后進先出&#xff09; 棧的實現 頭文件 初始化 入棧 注意&#xff1a; bool 判空 出棧----棧頂 注意 出棧頂元素&#xff0c;元素不會刪除 注意&#xff1a; 獲取棧中有效個數 銷毀棧 源文件操作 用棧實現遞歸* 隊列&#xff08;先進先出&a…

【Kafka系列】第二篇| Kafka 的核心概念、架構設計、底層原理

在大數據和分布式系統飛速發展的今天&#xff0c;消息隊列作為高效的通信工具&#xff0c;在系統解耦、異步通信、流量削峰等方面作用顯著。 而 Kafka 這款高性能、高吞吐量的分布式消息隊列&#xff0c;在日志收集、數據傳輸、實時計算等場景中應用廣泛。 接下來&#xff0c;我…

Kafka-exporter采集參數調整方案

#作者&#xff1a;張桐瑞 文章目錄1 問題概述2 修改方案2.1修改參數2.2配置示例3 消費者組均分腳本3.1使用說明3.2腳本內容3.3實現原理說明4 KAFKA-EXPORTER流程代碼4.1KAFKA-EXPORTER拉取數據流程1 問題概述 由于kafka-exporter獲取kafka指標時間過長&#xff0c;無法通過cur…

AT32的freertos下modbus TCP移植

1.準備模板 打開雅特力官網&#xff0c;也就是帶有LwIP的示例。 下載官方源碼&#xff1a;modbus 2.移植 我這里是在這里新建兩個文件夾&#xff0c;分別是modbus與port&#xff0c;這個任意&#xff0c;只需要將必要的文件加入項目即可。 將源碼中的modbus這些都移植過來&a…

Redis面試精講 Day 16:Redis性能監控與分析工具

【Redis面試精講 Day 16】Redis性能監控與分析工具 開篇 歡迎來到"Redis面試精講"系列第16天&#xff0c;今天我們將深入探討Redis性能監控與分析工具。在大型分布式系統中&#xff0c;Redis作為關鍵的數據存儲和緩存組件&#xff0c;其性能指標直接影響整個系統的…

vue3+vue-flow制作簡單可拖拽可增刪改流程圖

實現效果實現代碼 準備工作 安裝依賴 npm install vue-flow/core npm install vue-flow/minimap //小地圖 npm install vue-flow/controls //自帶的縮放、居中、加鎖功能我這里只用到上述三個&#xff0c;還有其余的可根據實際情況配合官方文檔使用。 npm install vue-flow/bac…

itextPdf獲取pdf文件寬高不準確

正常情況下我們通過下面方式獲取寬高PdfReader reader new PdfReader(file.getPath()); float width reader.getPageSize(1).getWidth(); float height reader.getPageSize(1).getHeight();但是這樣獲取的寬高是不準確的&#xff0c;永遠都是 寬 > 高&#xff0c;也就是橫…

NodeJs學習日志(2):windows安裝使用node.js 安裝express,suquelize,mysql,nodemon

windows安裝使用node.js 安裝express&#xff0c;suquelize&#xff0c;mysql&#xff0c;nodemon 系統是win10&#xff0c;默認已經安裝好nodejs與npm包名作用expressWeb應用框架suquelize數據庫ORMmysql數據庫nodemon代碼熱重載安裝express 添加express生成器 npm add expres…

VueCropper 圖片裁剪組件在Vue項目中的實踐應用

VueCropper 圖片裁剪組件在Vue項目中的實踐應用 1. 組件介紹 VueCropper 是一個基于 Vue.js 的圖片裁剪組件&#xff0c;它提供了豐富的圖片裁剪功能&#xff0c;包括&#xff1a; 圖片縮放、旋轉、移動固定比例裁剪高質量圖片輸出多種裁剪模式選擇 2. 安裝與引入 首先需要安裝…

給同一個wordpress網站綁定多個域名的實現方法

在WordPress網站上綁定多個域名&#xff0c;可以通過以下幾種方法實現&#xff1a; 1. 修改wp-config.php文件 在wp-config.php文件中&#xff0c;找到define(‘WP_DEBUG’, false);&#xff0c;在其下方添加以下代碼&#xff1a; define(WP_SITEURL, http:// . $_SERVER[HT…

HarmonyOS分布式開發實戰:打造跨設備協同應用

&#x1f4d6; 文章目錄 第一章&#xff1a;HarmonyOS分布式架構揭秘第二章&#xff1a;跨設備協同的核心技術第三章&#xff1a;開發環境搭建與配置第四章&#xff1a;實戰項目&#xff1a;智能家居控制系統第五章&#xff1a;數據同步與狀態管理第六章&#xff1a;性能優化與…

用 Enigma Virtual Box 把 Qt 程序壓成單文件 EXE——從編譯、收集依賴到一鍵封包

關鍵詞&#xff1a;Qt、windeployqt、Enigma Virtual Box、單文件、綠色軟件 為什么要打成單文件&#xff1f; 傳統做法&#xff1a;用 windeployqt 把依賴拷進 release 目錄&#xff0c;發給用戶一個文件夾&#xff0c;文件又多又亂。理想做法&#xff1a;把整個目錄壓成一個…

unity中實現選中人物腳下顯示圓形標識且完美貼合復雜地形(如彈坑) 的效果

要實現人物腳下圓形 完美貼合復雜地形&#xff08;如彈坑&#xff09; 的效果&#xff0c;核心思路是 「動態生成貼合地面的 Mesh」 —— 即根據地面的高度場實時計算環形頂點的 Y 坐標&#xff0c;讓每個頂點都 “貼” 在地面上。核心邏輯&#xff1a;確定環形范圍&#xff1a…

引領GameFi 2.0新范式:D.Plan攜手頂級財經媒體啟動“龍珠創意秀”

在GameFi賽道尋求新突破的今天&#xff0c;一個名為Dragonverse Plan&#xff08;D.Plan&#xff09;的項目正以其獨特的經濟模型和宏大愿景&#xff0c;吸引著整個Web3社區的目光。據悉&#xff0c;D.Plan即將聯合中文區頂級加密媒體金色財經與非小號&#xff08;Feixiaohao&a…