当前位置: 首页 > news >正文

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.dtcms.com/a/318909.html

相关文章:

  • OpenCV入门:图像处理基础教程
  • 【题解】洛谷P3768 简单的数学题[杜教筛]+两种欧反公式解析
  • UDP网络编程chat
  • CompletableFuture的基础用法介绍
  • 技术优势铸就行业标杆:物联网边缘计算网关凭何引领智能变革?
  • 施耐德 Easy Altivar ATV310 变频器:高效电机控制的理想选择(含快速调试步骤及常见故障代码)
  • Flutter 局部刷新方案对比:ValueListenableBuilder vs. GetBuilder vs. Obx
  • 齐护机器人小智AI_MCP图形化编程控制Arduino_ESP32
  • 亚远景-ISO 42001:汽车AI安全的行业标准新趋势
  • 网站 博客遭遇DDoS,CC攻击应该怎样应对?
  • crew AI笔记[2] - 如何选型
  • MCU-TC397的UCB初识
  • 初识 MQ:从同步到异步,聊聊消息队列那些事
  • OpenCv对图片视频的简单操作
  • 深度学习(2):自动微分
  • 学深度学习,有什么好的建议或推荐的书籍?
  • MobileNetV3: 高效移动端深度学习的前沿实现
  • 从“炼金术”到“工程学”:深度学习十年范式变迁与未来十年路线图
  • 深度学习之opencv篇
  • HashMap寻址算法
  • QT项目 -仿QQ音乐的音乐播放器(第五节)
  • 《算法导论》第 10 章 - 基本数据结构
  • 深入剖析Java线程:从基础到实战(上)
  • ubuntu cloud init 20.04LTS升级到22.04LTS
  • vue3接收SSE流数据进行实时渲染日志
  • Web开发模式 前端渲染 后端渲染 身份认证
  • 第三章:【springboot】框架介绍MyBatis
  • Spring AOP动态代理核心原理深度解析 - 图解+实战揭秘Java代理设计模式
  • 前端百分比展示导致后端 BigDecimal 转换异常的排查与解决
  • 多账号管理方案:解析一款免Root的App分身工具