目录
一、项目简介
二、技术选型
三、数据库设计
四、接口设计及思考
回复帖子部分
4.1 回复帖子
4.1.1.1 实现逻辑
4.1.1.2创建Service接⼝
4.1.1.3 实现Service接⼝
4.1.1.4 实现Controller
4.1.1.5 测试接口
4.1.1.6 实现前端页面
4.2 点赞帖子
4.2.1.1 参数要求
4.2.1.2 创建Service接⼝
4.2.1.3 实现Service接⼝
4.3 删除帖子
4.3.1.1 参数要求
4.3.1.2 创建Service接口
4.3.1.3 实现Service接⼝
4.3.1.4 实现Controller
一、项目简介
本系统实现了基于 Spring 的前后端分离版本的社群系统, 后端主要采用了SSM架构,前端采用ajax和后端进行交互,采用MySQL 数据库,实现了用户登录注册、个人信息和帖子的查看、发布帖子、帖子回复、站内信等功能。
应用技术有:SpringBoot、SpringMVC、Mybaits、MySQL、CSS等。
二、技术选型
三、数据库设计
数据库名: forum_db
公共字段:⽆特殊要求的情况下,每张表必须有⻓整型的⾃增主键,删除状态、创建时间、更新时 间,如下所⽰:
共建五张表
SQL脚本
-- ----------------------------
-- 创建数据库,并指定字符集
-- ----------------------------
drop database if exists forum_db;
create database forum_db character set utf8mb4 collate utf8mb4_general_ci;
-- 选择数据库
use forum_db;SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- 创建帖子表 t_article
-- ----------------------------
DROP TABLE IF EXISTS `t_article`;
CREATE TABLE `t_article` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '帖子编号,主键,自增',`boardId` bigint(20) NOT NULL COMMENT '关联板块编号,非空',`userId` bigint(20) NOT NULL COMMENT '发帖人,非空,关联用户编号',`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题,非空,最大长度100个字符',`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '帖子正文,非空',`visitCount` int(11) NOT NULL DEFAULT 0 COMMENT '访问量,默认0',`replyCount` int(11) NOT NULL DEFAULT 0 COMMENT '回复数据,默认0',`likeCount` int(11) NOT NULL DEFAULT 0 COMMENT '点赞数,默认0',`state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0正常 1 禁用,默认0',`deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0 否 1 是,默认0',`createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,非空',`updateTime` datetime NOT NULL COMMENT '修改时间,精确到秒,非空',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '帖子表' ROW_FORMAT = Dynamic;-- ----------------------------
-- 创建帖子回复表 t_article_reply
-- ----------------------------
DROP TABLE IF EXISTS `t_article_reply`;
CREATE TABLE `t_article_reply` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号,主键,自增',`articleId` bigint(20) NOT NULL COMMENT '关联帖子编号,非空',`postUserId` bigint(20) NOT NULL COMMENT '楼主用户,关联用户编号,非空',`replyId` bigint(20) NULL DEFAULT NULL COMMENT '关联回复编号,支持楼中楼',`replyUserId` bigint(20) NULL DEFAULT NULL COMMENT '楼主下的回复用户编号,支持楼中楼',`content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '回贴内容,长度500个字符,非空',`likeCount` int(11) NOT NULL DEFAULT 0 COMMENT '点赞数,默认0',`state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0 正常,1禁用,默认0',`deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否 1是,默认0',`createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,非空',`updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒,非空',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '帖子回复表' ROW_FORMAT = Dynamic;-- ----------------------------
-- 创建版块表 t_board
-- ----------------------------
DROP TABLE IF EXISTS `t_board`;
CREATE TABLE `t_board` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '版块编号,主键,自增',`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '版块名,非空',`articleCount` int(11) NOT NULL DEFAULT 0 COMMENT '帖子数量,默认0',`sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序优先级,升序,默认0,',`state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态,0 正常,1禁用,默认0',`deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否,1是,默认0',`createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,非空',`updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒,非空',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '版块表' ROW_FORMAT = Dynamic;-- ----------------------------
-- 创建站内信表 for t_message
-- ----------------------------
DROP TABLE IF EXISTS `t_message`;
CREATE TABLE `t_message` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '站内信编号,主键,自增',`postUserId` bigint(20) NOT NULL COMMENT '发送者,并联用户编号',`receiveUserId` bigint(20) NOT NULL COMMENT '接收者,并联用户编号',`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容,非空,长度255个字符',`state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0未读 1已读,默认0',`deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否,1是,默认0',`createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,非空',`updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒,非空',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '站内信表' ROW_FORMAT = Dynamic;-- ----------------------------
-- 创建用户表 for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户编号,主键,自增',`username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名,非空,唯一',`password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '加密后的密码',`nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '昵称,非空',`phoneNum` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱地址',`gender` tinyint(4) NOT NULL DEFAULT 2 COMMENT '0女 1男 2保密,非空,默认2',`salt` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '为密码加盐,非空',`avatarUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户头像URL,默认系统图片',`articleCount` int(11) NOT NULL DEFAULT 0 COMMENT '发帖数量,非空,默认0',`isAdmin` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否管理员,0否 1是,默认0',`remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注,自我介绍',`state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0 正常,1 禁言,默认0',`deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否 1是,默认0',`createTime` datetime NOT NULL COMMENT '创建时间,精确到秒',`updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `user_username_uindex`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;-- 写入版块信息数据INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (1, 'Java', 0, 1, 0, 0, '2023-01-14 19:02:18', '2023-01-14 19:02:18');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (2, 'C++', 0, 2, 0, 0, '2023-01-14 19:02:41', '2023-01-14 19:02:41');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (3, '前端技术', 0, 3, 0, 0, '2023-01-14 19:02:52', '2023-01-14 19:02:52');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (4, 'MySQL', 0, 4, 0, 0, '2023-01-14 19:03:02', '2023-01-14 19:03:02');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (5, '面试宝典', 0, 5, 0, 0, '2023-01-14 19:03:24', '2023-01-14 19:03:24');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (6, '经验分享', 0, 6, 0, 0, '2023-01-14 19:03:48', '2023-01-14 19:03:48');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (7, '招聘信息', 0, 7, 0, 0, '2023-01-25 21:25:33', '2023-01-25 21:25:33');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (8, '福利待遇', 0, 8, 0, 0, '2023-01-25 21:25:58', '2023-01-25 21:25:58');INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`, `deleteState`, `createTime`, `updateTime`) VALUES (9, '灌水区', 0, 9, 0, 0, '2023-01-25 21:26:12', '2023-01-25 21:26:12');-- 写入帖子表数据
insert into t_article values (null, 1, 1, '测试数据-标题1', '测试数据-内容1', 0,0,0,0,0, '2023-08-11 16:52:00','2023-08-11 16:52:00');
insert into t_article values (null, 1, 1, '测试数据-标题2', '测试数据-内容2', 0,0,0,0,0, '2023-08-11 16:53:00','2023-08-11 16:53:00');
insert into t_article values (null, 1, 1, '测试数据-标题3', '测试数据-内容3', 0,0,0,0,0, '2023-08-11 16:54:00','2023-08-11 16:54:00');
insert into t_article values (null, 2, 2, '测试数据-标题4', '测试数据-内容4', 0,0,0,0,0, '2023-08-11 16:55:00','2023-08-11 16:55:00');
insert into t_article values (null, 2, 2, '测试数据-标题5', '测试数据-内容5', 0,0,0,0,0, '2023-08-11 16:56:00','2023-08-11 16:56:00');-- 写入回复表数据
insert into t_article_reply values (NULL, 1, 1, NULL, NULL, '回复内容111', 0, 0, 0, '2023-08-14 16:52:00', '2023-08-14 16:52:00');
insert into t_article_reply values (NULL, 1, 1, NULL, NULL, '回复内容222', 0, 0, 0, '2023-08-14 16:53:00', '2023-08-14 16:53:00');
insert into t_article_reply values (NULL, 1, 1, NULL, NULL, '回复内容333', 0, 0, 0, '2023-08-14 16:54:00', '2023-08-14 16:54:00');
insert into t_article_reply values (NULL, 1, 2, NULL, NULL, '回复内容444', 0, 0, 0, '2023-08-14 16:55:00', '2023-08-14 16:55:00');
insert into t_article_reply values (NULL, 1, 2, NULL, NULL, '回复内容555', 0, 0, 0, '2023-08-14 16:56:00', '2023-08-14 16:56:00');
四、接口设计及思考
回复帖子部分
4.1 回复帖子
4.1.1 提交回复内容
• 在帖⼦详情⻚⾯⽤⼾可以发表回复
4.1.1.1 实现逻辑
1. 帖⼦在正常状态下允许⽤⼾回复 (校验1)
2. 填写回复内容,点击提交按钮后发送请求到服务器
3. 服务器校验回复内容、帖⼦与⽤⼾状态(校验二),通过后写⼊数据库 (回复表中新增一条数据)
4. 帖⼦回复数量加1 (帖子表的更新)
5. 返回结果
思考:根据3. 4.,发表回复时,需要对两张表进行更新操作,那么就需要用事务管理起来
使用事务的原则:当一个执行流程中,要进行多个更新操作(增删改),不论涉及几张表都需要用事务管理起来。
4.1.1.2创建Service接⼝
• 在IArticleReplyService定义⽅法
/*** 新增一个回复记录* @param articleReply*/@Transactionalvoid create (ArticleReply articleReply);
}
4.1.1.3 实现Service接⼝
• 在ArticleReplyServiceImpl中实现⽅法
4.1.1.4 实现Controller
• 新建ArticleReplyController并提供对外的API接⼝
4.1.1.5 测试接口
测试⽤例:
1. ⽤⼾在没有登录的情况下回复帖⼦,不成功
2. 回复已删除或已禁⽤的帖⼦,不成功 3. 回复不存在的帖⼦,不成功
4. 禁⾔⽤⼾回复帖⼦,不成功
5. ⽤⼾和帖⼦状态正常的情况下,回复帖⼦,成功
6. 回复成功,帖⼦回复数量加1
7. 在测试⼯具中编辑并在数据库中查看验证是否成功
4.1.1.6 实现前端页面
// ====================== 回复帖⼦ ======================$('#details_btn_article_reply').click(function () {let articleIdEl = $('#details_article_id');let replyContentEl = $('#details_article_reply_content');// ⾮空校验if (!replyContentEl.val()) {// 提⽰$.toast({heading: '提⽰',text: '请输⼊回复内容',icon: 'warning'});return;}// 构造帖⼦对象let articleReplyObj = {articleId: articleIdEl.val(),content: replyContentEl.val()}// 发送请求$.ajax({type: 'post',url: '/article/reply',// 发送的数据data: articleReplyObj,success: function (respData) {// ⽤状态码判断是否成功if (respData.code == 0) {// 清空输⼊区editor.setValue('');// 更新回贴数currentArticle.replyCount = currentArticle.replyCount + 1;$('#details_article_replyCount').html(currentArticle.replyCount);// 构建回贴⻚⾯loadArticleDetailsReply();$.toast({heading: '提⽰',text: respData.message,icon: 'success'});} else {// 提⽰$.toast({heading: '提⽰',text: respData.message,icon: 'info'});}},error: function () {$.toast({heading: '错误',text: '出错了,请联系管理员',icon: 'error'});}});
});
4.2 点赞帖子
• ⽤⼾在帖⼦详情⻚进⾏点赞操作
4.2.1.1 参数要求
4.2.1.2 创建Service接⼝
• 在IArticleService定义⽅法
/*** 点赞* @param id 帖子Id*/void thumbsUpById(Long id);
}
4.2.1.3 实现Service接⼝
• 在ArticleServiceImpl中实现⽅法
@Overridepublic void thumbsUpById(Long id) {//非空校验if (id == null || id <= 0) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}//查询帖子信息Article article = selectById(id);if (article == null || article.getState() == 1 || article.getDeleteState() == 1) {//打印日志log.info(ResultCode.FAILED_ARTICLE_NOT_EXISTS.toString());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));}//构造更新对象Article update = new Article();update.setId(article.getId());update.setLikeCount(article.getLikeCount() + 1);//更新数据库int row = articleMapper.updateByPrimaryKeySelective(update);if (row != 1) {log.info(ResultCode.FAILED_CREATE.toString() + "userId = " + article.getUserId());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}}
}
4.2.1.4 实现Controller
• 在ArticleController中提供对外的API接⼝
@ApiOperation("点赞")@PostMapping("/thumbsUp")public AppResult thumbsUp(HttpServletRequest request,@ApiParam(value = "帖子Id") @RequestParam(value = "id") @NonNull Long id){// 获取⽤⼾信息HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.SESSION_USER_KEY);// 判断是否被禁⾔if (user.getState() != 0) {// ⽇志log.warn(ResultCode.FAILED_USER_BANNED.toString() + ", userId = " +user.getId());// 返回错误信息return AppResult.failed(ResultCode.FAILED_USER_BANNED);}// 更新点赞数articleService.thumbsUpById(id);// 返回结果return AppResult.success();}
4.3 删除帖子
4.3.1.1 参数要求
4.3.1.2 创建Service接口
• 在IBoardService定义⽅法
/*** 版块中的帖子数量 -1* @param id 版块Id*/void subOneArticleCountById(Long id);
}
• 在IUserService定义⽅法
/*** 用户发帖数 -1* @param id*/void subOneArticleCountById(Long id);
}
• 在IArticleService定义⽅法,并加⼊事务管理
/*** 根据Id删除帖子* @param id 帖子Id*/
@Transactionalvoid deleteById(Long id);
}
4.3.1.3 实现Service接⼝
• 在BoardServiceImpl中实现⽅法
@Overridepublic void subOneArticleCountById(Long id) {//非空校验if (id == null || id < 0) {//打印日志log.warn(ResultCode.FAILED_ARTICLE_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_ARTICLE_NOT_EXISTS));}//查询板块信息Board board = selectById(id);// 校验版块是否存在if (board == null) {// 打印日志log.warn(ResultCode.FAILED_BOARD_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_BOARD_NOT_EXISTS));}// 构造要更新的对象Board updateBoard = new Board();updateBoard.setId(board.getId()); // 版块IDupdateBoard.setArticleCount(board.getArticleCount() - 1); // 帖子数量if (updateBoard.getArticleCount() < 0) {//如果小于0那么设置为0updateBoard.setArticleCount(0);}// 调用DAOint row = boardMapper.updateByPrimaryKeySelective(updateBoard);if (row != 1) {// 打印日志log.warn(ResultCode.FAILED.toString() + ",受影响的行数不等于1.");// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED));}}
}
• 在UserServiceImpl中实现⽅法
@Overridepublic void subOneArticleCountById(Long id) {//非空校验if (id == null || id < 0) {//打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}//根据用户名查询用户信息User user = userMapper.selectById(id);//校验用户是否存在if(user == null){// 打印日志log.warn(ResultCode.FAILED_ARTICLE_NOT_EXISTS.toString() + ", user id = " + id);// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_ARTICLE_NOT_EXISTS));}//构造要更新的对象User updateUser = new User();updateUser.setId(user.getId());//用户IdupdateUser.setArticleCount(user.getArticleCount() - 1);//帖子数量-1//判断-1之后,用户的发帖数是否小于0if(updateUser.getArticleCount() < 0){//如果小于0,则设置为0updateUser.setArticleCount(0);}//调用DAOint row = userMapper.updateByPrimaryKeySelective(updateUser);if (row != 1) {// 打印日志log.warn(ResultCode.FAILED.toString() + ",受影响的行数不等于1.");// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED));}
• 在ArticleServiceImpl中实现⽅法
@Overridepublic void deleteById(Long id) {//非空校验if (id == null || id <= 0) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}//根据Id查询帖子信息Article article = articleMapper.selectByPrimaryKey(id);if (article == null || article.getDeleteState() == 1) {//打印日志log.info(ResultCode.FAILED_ARTICLE_NOT_EXISTS.toString() + ",article id = " + id);//抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));}//构造更新对象Article updateArticle = new Article();updateArticle.setId(article.getId());updateArticle.setDeleteState((byte) 1);//更新数据库int row = articleMapper.updateByPrimaryKeySelective(updateArticle);if (row != 1) {log.info(ResultCode.ERROR_SERVICES.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));}//更新版块中的帖子数量boardService.subOneArticleCountById(article.getUserId());//更新用户发帖数userService.subOneArticleCountById(article.getUserId());log.info("删除帖子成功,article id = " + article.getId() + ",user id = " + article.getUserId() + ".");}
4.3.1.4 实现Controller
• 在ArticleController中提供对外的API接⼝
/*** 根据Id删除帖⼦** @param id 帖⼦Id* @return*/
@ApiOperation("删除帖⼦")
@PostMapping("/delete")
public AppResult deleteById (HttpServletRequest request,@ApiParam("帖⼦Id") @RequestParam("id") @NonNull Longid) {// 1. ⽤⼾是否禁⾔HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.SESSION_USER_KEY);if (user.getState() == 1) {// 返回错误描述return AppResult.failed(ResultCode.FAILED_USER_BANNED);}//查询帖子信息Article article = articleService.selectById(id);//2.帖子是否存在或已删除if (article == null || article.getDeleteState() == 1) {// 返回错误描述return AppResult.failed(ResultCode.FAILED_ARTICLE_NOT_EXISTS);}// 3. ⽤⼾是否是作者if (article.getUserId() != user.getId()) {// 返回错误描述return AppResult.failed(ResultCode.FAILED_FORBIDDEN);}// 调⽤Service执⾏删除articleService.deleteById(id);// 返回成功return AppResult.success();}