篇章十 论坛系统——业务开发——板块和帖子

目录

1.板块

1.1 思路

1.2 实现逻辑

1.3 参数要求

1.4 实现步骤

1.Mapper.xml

2.Mapper.java

3.Service接口

4.Service实现

5.单元测试

6.Controller

7.测试API

8.前后端交互

2.帖子

1.1思路​编辑

1.2 参数要求

​编辑

1.3 实现步骤

1.Mapper.xml

2.Mapper.java

3.定义Service接口

 4.实现Service

5. 单元测试

6.Controller实现

7.测试API接口

8.前后端交互


1.板块

1.1 思路

1.2 实现逻辑

1.3 参数要求

1.4 实现步骤

1.Mapper.xml

2.Mapper.java

3.Service接口

package com.example.forum.services;import com.example.forum.model.Board;import java.util.List;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 15:45*/
public interface IBoardService {/*** 查询num条记录* @param num 要查询的条数* @return*/List<Board> selectByNum(Integer num);}

4.Service实现

package com.example.forum.services.impl;import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.dao.BoardMapper;
import com.example.forum.exception.ApplicationException;
import com.example.forum.model.Board;
import com.example.forum.services.IBoardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 15:47*/
@Slf4j
@Service
public class IBoardServiceImpl implements IBoardService {@Resourceprivate BoardMapper boardMapper;/*** 查询num条记录** @param num 要查询的条数* @return*/@Overridepublic List<Board> selectByNum(Integer num) {// 非空校验if (num <= 0) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 调用DAO查询数据库中的数据List<Board> result = boardMapper.selectByNum(num);// 返回结果return result;}
}

5.单元测试

package com.example.forum.services.impl;import com.example.forum.model.Board;
import com.example.forum.services.IBoardService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;import java.util.List;import static org.junit.jupiter.api.Assertions.*;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 16:28*/
@SpringBootTest
class IBoardServiceImplTest {@Resourceprivate IBoardService boardService;@Testvoid selectByNum() {List<Board> boards = boardService.selectByNum(1);if (boards != null) {System.out.println(boards);}}
}

6.Controller

package com.example.forum.controller;import com.example.forum.common.AppResult;
import com.example.forum.model.Board;
import com.example.forum.services.IBoardService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 16:38*/
@Api(tags="版块接口")
@Slf4j
@RestController
@RequestMapping("/board")
public class BoardContrller {// 从配置文件中读取值 如果没有配置 默认值为9@Value("${forum.index.board-num:9}")private Integer indexBoardNum;@Resourceprivate IBoardService boardService;/*** 查询首版本列表* @return*/@ApiOperation("获取首页板块列表")@GetMapping("/topList")public AppResult<List<Board>> topList() {log.info("首页板块个数为: " + indexBoardNum);// 调用Service查询结果List<Board> boards = boardService.selectByNum(indexBoardNum);// 判断是否为空if(boards == null) {boards = new ArrayList<>();}// 返回结果return AppResult.success(boards);}
}

7.测试API

8.前后端交互

// ========================= 获取版块信息 =======================// 成功后,调用buildTopBoard()方法,构建版块列表$.ajax({type: 'get',url: 'board/topList',success : function (respData) {if(respData.code == 0) {// 构建版块列表buildTopBoard(respData.data);} else {// 提示信息$.toast({heading: '警告',text: respData.message,icon: 'warning'});}},error : function () {// 提示信息$.toast({heading: '错误',text: '访问出现问题,请与管理员联系.',icon: 'error'});}});//========================= 构造首页版块=======================// 构造首页版块function buildTopBoard(data) {// 版块导航let navBoardListEl = $('#topBoardList');// 遍历版块data.forEach(board => {// 构建版块let itemHtml = '<li class="nav-item">'+ '<a class="nav-link" href="javascript:void(0);">'+ '<span class="nav-link-icon d-md-none d-lg-inline-block">'+ '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-point-filled" width="24"'+ 'height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"'+ 'stroke-linecap="round" stroke-linejoin="round">'+ '<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>'+ '<path d="M12 7a5 5 0 1 1 -4.995 5.217l-.005 -.217l.005 -.217a5 5 0 0 1 4.995 -4.783z"'+ 'stroke-width="0" fill="currentColor"></path>'+ '</svg>'+ '</span>'+ '<span class="nav-link-title">'+ board.name+ '</span>'+ '</a>'+ '</li>'// 为版块绑定当前版块数据对象以便后续获取let boardItem = $(itemHtml);// 把版块信息绑定到当前导航单元boardItem.data('board', board);console.log('data = ' + boardItem.data('board').name + ', id = ' + boardItem.data('board').id);// 处理点击事件boardItem.click(function () {// alert('data = ' + boardItem.data('board').name + ', id = ' + boardItem.data('board').id);// 激活效果changeNavActive(boardItem);});// 加入版块导航navBoardListEl.append(boardItem);});}

2.帖子

1.1思路

1.2 参数要求

1.3 实现步骤

1.Mapper.xml

2.Mapper.java

3.定义Service接口

IUserService

 /*** 更新当前用户的发帖数* @param id 用户 id*/void addOneArticleCountById(Long id);

IBoardService 

 /*** 根据板块数据查询板块信息* @param id 板块 id* @return*/Board selectById(Long id);/*** 更新当前板块的发帖数* @param id 板块 id*/void addOneArticleCountById(Long id);

IArticleService

package com.example.forum.services;import com.example.forum.model.Article;
import org.springframework.transaction.annotation.Transactional;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 19:20*/
public interface IArticleService {/*** 发布帖子* @param article 要发布的帖子*/@Transactional // 当前方法中的执行过程会被事务管理起来void create(Article article);
}

 4.实现Service

 UserServiceImpl

/*** 更新当前用户的发帖数** @param id 用户 id*/@Overridepublic void addOneArticleCountById(Long id) {if(id == null || id <= 0) {// 打印日志log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_ARTICLE_COUNT));}// 查询对应的板块User user = userMapper.selectByPrimaryKey(id);if(user == null) {// 打印日志log.warn(ResultCode.ERROR_IS_NULL.toString() + ", user id = " + id);// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}// 更新帖子数量User updateUser = new User();updateUser.setId(user.getId());updateUser.setArticleCount(user.getArticleCount() + 1);int row = userMapper.updateByPrimaryKeySelective(updateUser);if (row != 1) {log.warn(ResultCode.FAILED.toString() + ", 受影响的行数不等于 1");throw new ApplicationException(AppResult.failed(ResultCode.FAILED));}}

IBoardServiceImpl 

/*** 根据板块ID查询板块信息** @param id 板块 id* @return*/@Overridepublic Board selectById(Long id) {if(id == null || id <= 0) {// 打印日志log.warn(ResultCode.FAILED_BOARD_ARTICLE_COUNT.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_ARTICLE_COUNT));}// 调用DAO查询数据Board board = boardMapper.selectByPrimaryKey(id);// 返回结果return board;}/*** 更新当前板块的发帖数** @param id 板块 id*/@Overridepublic void addOneArticleCountById(Long id) {if(id == null || id <= 0) {// 打印日志log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_ARTICLE_COUNT));}// 查询对应的板块Board board = boardMapper.selectByPrimaryKey(id);if(board == null) {// 打印日志log.warn(ResultCode.ERROR_IS_NULL.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}// 更新帖子数量Board updateBoard = new Board();updateBoard.setId(board.getId());updateBoard.setArticleCount(board.getArticleCount() + 1);// 调用DAO, 执行更新int row = boardMapper.updateByPrimaryKeySelective(updateBoard);if (row != 1) {log.warn(ResultCode.FAILED.toString() + ", 受影响的行数不等于 1");throw new ApplicationException(AppResult.failed(ResultCode.FAILED));}}

ArticleServiceImpl

package com.example.forum.services.impl;import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.dao.ArticleMapper;
import com.example.forum.exception.ApplicationException;
import com.example.forum.model.Article;
import com.example.forum.model.Board;
import com.example.forum.model.User;
import com.example.forum.services.IArticleService;
import com.example.forum.services.IBoardService;
import com.example.forum.services.IUserService;
import com.example.forum.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.Date;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 19:20*/
@Slf4j
@Service
public class ArticleServiceImpl implements IArticleService {@Resourceprivate ArticleMapper articleMapper;// 用户和板块的操作@Resourceprivate IUserService userService;@Resourceprivate IBoardService boardService;/*** 发布帖子** @param article 要发布的帖子*/@Overridepublic void create(Article article) {// 非空校验if (article == null || article.getUserId() == null || article.getBoardId() == null|| StringUtils.isEmpty(article.getTitle())|| StringUtils.isEmpty(article.getContent())) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 设置默认值article.setVisitCount(0); // 访问数article.setReplyCount(0); // 回复数article.setLikeCount(0);  // 点赞数article.setDeleteState((byte)0);article.setState((byte) 0);Date date = new Date();article.setCreateTime(date);article.setUpdateTime(date);// 写入数据库int articleRow = articleMapper.insertSelective(article);if(articleRow <= 0) {log.warn(ResultCode.FAILED_CREATE.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}// 获取用户信息User user = userService.selectById(article.getUserId());// 没有找到指定的用户信息if(user == null) {log.warn(ResultCode.FAILED_CREATE.toString() + ", 发帖失败 user id = " + article.getUserId());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}// 更新用户的发帖数userService.addOneArticleCountById(user.getId());// 获取板块信息Board board = boardService.selectById(article.getBoardId());// 是否在数据库中有对应的版块if (board == null) {log.warn(ResultCode.FAILED_CREATE.toString() + ", 发帖失败 board id = " + article.getBoardId());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}// 更新版块中的数量boardService.addOneArticleCountById(board.getId());// 打印日志log.info(ResultCode.SUCCESS.toString() + ", user id = " + article.getUserId()+ ", board id = " + article.getBoardId() + ", article id = " + article.getId() + "发帖成功");
//        throw new ApplicationException(AppResult.failed("测试事务回滚"));}
}

5. 单元测试

6.Controller实现

package com.example.forum.controller;import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.config.AppConfig;
import com.example.forum.model.Article;
import com.example.forum.model.Board;
import com.example.forum.model.User;
import com.example.forum.services.IArticleService;
import com.example.forum.services.IBoardService;
import com.sun.istack.internal.NotNull;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;/*** Created with IntelliJ IDEA* Description* User: 王杰* Date: 2025-06-15* Time: 21:42*/
@Api(tags = "文章接口")
@Slf4j
@RestController
@RequestMapping("/article")
public class ArticleController {@Resourceprivate IBoardService boardService;@Resourceprivate IArticleService articleService;/*** 发布新贴* @param boardId 版块Id* @param title 文章标题* @param content 文章内容* @return*/@ApiOperation("发布新帖")@PostMapping("/create")public AppResult create(HttpServletRequest request,@ApiParam("版块Id") @RequestParam("boardId") @NotNull Long boardId,@ApiParam("文章标题") @RequestParam("title") @NotNull String title,@ApiParam("文章内容") @RequestParam("content") @NotNull String content) {// 校验用户是否禁言HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);if (user.getState() == 1) {// 用户已禁言return AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE);}// 版块的校验Board board = boardService.selectById(boardId.longValue());if(board == null || board.getDeleteState() == 1 || board.getState() == 1) {// 打印日志log.info(ResultCode.FAILED_BOARD_BANNED.toString());return AppResult.failed(ResultCode.FAILED_BOARD_BANNED);}// 封装文章对象Article article = new Article();article.setTitle(title); // 标题article.setContent(content); // 正文article.setBoardId(boardId); // 版块 idarticle.setUserId(user.getId()); // 作者 idarticleService.create(article);return AppResult.success();}
}

7.测试API接口

8.前后端交互

Editor.md - 开源在线 Markdown 编辑器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/85087.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/85087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React Native 上线前的准备与企业实战经验总结

上线前的准备与企业实战经验总结 关键要点 热更新简化部署&#xff1a;CodePush 和 Expo OTA 允许快速推送 JavaScript 和资源更新&#xff0c;绕过应用商店审核&#xff0c;适合修复 Bug 或小规模功能迭代。监控与分析提升质量&#xff1a;Sentry 提供实时错误跟踪&#xff…

【AI时代速通QT】第一节:C++ Qt 简介与环境安装

目录 前言 一、为什么是 Qt&#xff1f;—— C 开发者的必备技能 二、Qt 的核心魅力&#xff1a;不止于跨平台 2.1 优雅之一&#xff1a;代码隔离&#xff0c;清晰明了 2.2 优雅之二&#xff1a;信号与槽&#xff08;Signal & Slot&#xff09;机制 2.3 优雅之三&…

pandas学习笔记

前言 总结才是知识&#xff0c;作者习惯不好&#xff0c;不会总结&#xff0c;导致函数一旦不使用就会忘记怎么使用&#xff0c;特此写了本文&#xff0c;用于给自己一个复习的资料. 提示&#xff1a;如果你是小白&#xff0c;每个代码请自己敲打。 一 pandas的介绍 Pandas is…

算法题(力扣每日一题)—改变一个整数能得到的最大差值

给你一个整数 num 。你可以对它进行以下步骤共计 两次&#xff1a; 选择一个数字 x (0 < x < 9). 选择另一个数字 y (0 < y < 9) 。 数字 y 可以等于 x 。 将 num中所有出现 x 的数位都用 y 替换。 令两次对 num 的操作得到的结果分别为 a 和 b 。 请你返回 a 和 b…

Kubernetes笔记

1.简介 Kubernetes的本质是一组服务器集群&#xff0c;它可以在集群的每个节点上运行特定的程序&#xff0c;来对节点中的容器进行管理。目的是实现资源管理的自动化&#xff0c;主要提供了如下的主要功能&#xff1a; 自我修复&#xff1a;一旦某一个容器崩溃&#xff0c;能够…

Flutter——数据库Drift开发详细教程(八)

目录 自定义 SQL 类型定义类型使用自定义类型在 Dart 中在 SQL 中 方言意识支持的 SQLite 扩展json1fts5地缘垄断 自定义 SQL 类型 Drift 的核心库主要以 SQLite3 为目标平台编写。这体现在Drift 开箱即用的SQL 类型上——这些类型由 SQLite3 支持&#xff0c;并新增了一些由 …

安卓远控工具 CRaxsRat v7.6 安装与使用教程(仅供合法测试学习)

在当今的信息安全领域&#xff0c;移动设备已成为重点关注对象。本文将介绍一款用于远程管理与教学研究的工具 —— CRaxsRat v7.6&#xff0c;并详细讲解其安装与使用流程。本教程仅供网络安全爱好者在合法授权环境下学习使用&#xff0c;严禁任何非法用途。 &#x1f50d; 一…

容器的本质是进程

前言 Linux 容器的本质&#xff0c;是一个被隔离和限制的进程。 与虚拟机不同&#xff0c;容器无需虚拟化一个完整的操作系统&#xff0c;所以它比虚拟机更轻量级&#xff0c;效率也更高。 Linux 容器通过 namespaces 技术来隔离容器的视图&#xff0c;使得容器进程只能看到…

LeetCode 第75题:颜色分类

给定一个包含红色、白色和蓝色、共n个元素的数组nums&#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排序。 使用整数0、1和2分布表示红色、白色和蓝色。 必须在不使用库内置sort函数的情况下解决这个问题。 示例1&a…

PHP基础-函数

函数是一段可重复使用的代码块&#xff0c;可以将一系列操作封装起来&#xff0c;使代码更加模块化、可维护和可重用&#xff0c;来大大节省我们的开发时间和代码量&#xff0c;提高编程效率。在PHP中你可以使用&#xff1a; 内置函数&#xff08;如 strlen()、array_merge()&a…

【FastAPI高级实战】结合查询参数与SQLModel Joins实现高效多表查询(分页、过滤、计数)

想象一下&#xff0c;你正在开发一个超酷的Web应用&#xff0c;比如一个博客平台或者一个在线商店。你的API不仅要能把数据&#xff08;比如文章列表、商品信息&#xff09;展示给用户&#xff0c;更要聪明到能理解用户的各种“小心思”&#xff1a;用户可能想看最新的文章、搜…

华为OD-2024年E卷-通过软盘拷贝文件[200分] -- python

问题描述&#xff1a; 有一名科学家想要从一台古董电脑中拷贝文件到自己的电脑中加以研究。但此电脑除了有一个3.5寸软盘驱动器以外&#xff0c;没有任何手段可以将文件持贝出来&#xff0c;而且只有一张软盘可以使用。因此这一张软盘是唯一可以用来拷贝文件的载体。科学家想要…

Keepalived 高可用,nginx + keepalived , lvs + keepalived、 数据库+keepalived

keepalived 官网 Keepalived 可以用来防止服务器单点故障的发生 # 原理 是基于VRRP协议实现的&#xff0c;当backup收不到vrrp包时&#xff0c;就认为master宕机了&#xff0c;这时就需要根据VRRP的优先级来选举一个backup 当master&#xff0c;就实现服务的HA&#xff08;高…

开疆智能Devicenet转ModbusTCP网关连接台达从站通讯模块配置案例

本案例是通过开疆智能Devicenet转ModbusTCP网关连接台达Devicenet从站通讯模块DVPDT02-H2的配置案例&#xff0c;网关作为ModbusTCP服务器和Devicenet主站&#xff0c;连接台达Devicenet从站&#xff0c; 配置过程&#xff1a; 首先配置Devicenet从站&#xff0c;先设置从站De…

网络NAT是什么

网络NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;是一种用于计算机网络中的技术&#xff0c;主要目的是在私有网络与公有网络&#xff08;比如互联网&#xff09;之间转换IP地址&#xff0c;实现私有网络中的多台设备通过一个公网IP访问外…

React状态管理——react-redux

目录 一、redux介绍 二、安装 三、基本实现步骤 3.1 创建Action Types 3.2 创建counterAction 3.3 创建counterReducer 3.4 结合所有Reducer 3.5 创建store 3.6 入口文件中提供store 3.7 在组件中的使用 3.8 使用thunk实现异步支持 3.8.1 安装 3.8.2 在counterAct…

Java 零工市场小程序 | 灵活就业平台 | 智能匹配 | 日结薪系统 | 用工一站式解决方案

在就业形势如此严峻的情况下&#xff0c;很多小伙伴都会选择零工的工作方式来赚取外快&#xff0c;很多用人单位也会因为职为短暂空缺或是暂时人手不够而选择招用兼职人员。 而Java 作为企业级开发的主流语言&#xff0c;以其卓越的性能和稳定性著称。把零工的需求&#xff08…

数据可视化——一图胜千言

第04篇&#xff1a;数据可视化——一图胜千言 写在前面&#xff1a;大家好&#xff0c;我是蓝皮怪&#xff01;前面几篇我们聊了统计学的基本概念、数据类型和描述性统计&#xff0c;这一篇我们要聊聊数据分析中最直观、最有趣的部分——数据可视化。你有没有发现&#xff0c;很…

1.1 Linux 编译FFmpeg 4.4.1

一、安装编译工具 sudo apt install -y autoconf automake build-essential cmake git pkg-config nasm yasm libtool zlib1g-dev说明&#xff1a; autoconf&#xff1a;生成 configure 脚本&#xff0c;用于自动配置源码。automake&#xff1a;与 autoconf 配合&#xff0c;…

【图片识别改名】如何批量识别大量图片的文字并重命名图片,基于WPF和京东OCR识别接口的实现方案

应用场景 在企业文档管理、数字图书馆、电商商品管理等场景中&#xff0c;经常需要处理大量图片中的文字信息。例如&#xff1a; 电商平台需要将商品图片中的型号、规格等信息提取出来作为文件名图书馆需要将扫描的图书页面识别为文字并整理归档企业需要将纸质文档电子化并按…