目录
一、项目简介
二、技术选型
三、数据库设计
四、接口设计及思考
回复帖子部分
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
     */
    @Transactional
    void 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中实现⽅法 
    
 
        @Override
    public 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
     */
@Transactional
    void deleteById(Long id);
}
4.3.1.3 实现Service接⼝
 
          •  
          在BoardServiceImpl中实现⽅法  
         
 
             @Override
    public 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()); // 版块ID
        updateBoard.setArticleCount(board.getArticleCount() - 1); // 帖子数量
        if (updateBoard.getArticleCount() < 0) {
            //如果小于0那么设置为0
            updateBoard.setArticleCount(0);
        }
        // 调用DAO
        int row = boardMapper.updateByPrimaryKeySelective(updateBoard);
        if (row != 1) {
            // 打印日志
            log.warn(ResultCode.FAILED.toString() + ",受影响的行数不等于1.");
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
    }
}
 
           •  
           在UserServiceImpl中实现⽅法  
          
 
              @Override
    public 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());//用户Id
        updateUser.setArticleCount(user.getArticleCount() - 1);//帖子数量-1
        //判断-1之后,用户的发帖数是否小于0
        if(updateUser.getArticleCount() < 0){
            //如果小于0,则设置为0
            updateUser.setArticleCount(0);
        }
        //调用DAO
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            // 打印日志
            log.warn(ResultCode.FAILED.toString() + ",受影响的行数不等于1.");
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        } 
            •  
            在ArticleServiceImpl中实现⽅法  
           
 
               @Override
    public 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 Long
                                     id) {
        // 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();
         }
         



















