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

SpringBoot+React博客论坛系统 附带详细运行指导视频

文章目录

  • 一、项目演示
  • 二、项目介绍
  • 三、项目运行截图
  • 四、主要代码

一、项目演示

项目演示地址: 视频地址

二、项目介绍

项目描述:这是一个基于SpringBoot+React框架开发的博客论坛系统。首先,这是一个前后端分离的项目,文章编辑器支持Markdown语法,项目代码简洁规范,注释说明详细,易于理解和学习。其次,这项目功能丰富,具有一个博客论坛系统该有的所有功能。

项目功能:此项目分为两个角色:普通用户管理员普通用户有登录注册、浏览博客和问答信息、发表评论、问答发起者也能采纳评论、写文章、提问题、管理个人信息、关注他人等等功能。管理员除了拥有普通用户的所有功能,还有管理所有用户信息、管理所有文章信息、管理所有文章分类信息、管理所有文章标签信息、管理所有评论信息等等功能。

应用技术:SpringBoot + React + MySQL + MyBatis + Redis + Antd

运行环境:IntelliJ IDEA2019.3.5 + MySQL5.7(项目压缩包中自带) + Redis5.0.5(项目压缩包中自带) + JDK1.8 + Maven3.6.3(项目压缩包中自带)+ Node14.16.1(项目压缩包中自带)

三、项目运行截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、主要代码

1.前台编辑器页面代码:

 <div className={editorStyle.editor}><div className={editorStyle.title}><div className={editorStyle.back} onClick={() => backHome()}>返回首页</div><div style={{width: '80%', paddingTop: '0.5rem'}}><Input defaultValue={article.title} value={article.title} onChange={ e => setArticle({...article, title: e.target.value}) } ref={inputTitle} className={editorStyle.input} placeholder="请在这里输入文章标题"/></div></div><div className={editorStyle.content}><EditorContent onSave={() => saveArticle(6, 1)} ref={editor} preview={true} subfield={true}addImg={($file) => addImg($file)}value={article.contentMarkdown} onChange={handleChange}/></div><div className={editorStyle.footer}><div className={editorStyle.left}><div style={{width: '50%'}}><Select defaultValue={article.categoryId} value={article.categoryId} onChange={ e => setArticle({...article, categoryId: e}) }  style={{width: '100%'}} placeholder="请选择文章分类">{categoryList && categoryList.map((item, index) => {return (<Select.Option key={index} value={item.id}>{item.name}</Select.Option>)})}</Select></div><div style={{width: '50%', marginLeft: '1rem'}} ><ConfigProvider locale={zhCN}><Select mode="multiple" defaultValue={article.tagList} value={article.tagList} onChange={ e => {if(e.length > 3) {message.warning("最多选择3个标签哦!")} else {setArticle({...article, tagList: e});}} } style={{width: '100%'}} placeholder="请选择文章标签">{tagList && tagList.map((item, index) => {return (<Select.Option key={index} value={item.id}>{item.name}</Select.Option>)})}</Select></ConfigProvider></div></div><div className={editorStyle.center}><TextArea rows={1} defaultValue={article.summary} value={article.summary} onChange={ e => setArticle({...article, summary: e.target.value}) } placeholder="请输入文章摘要" /></div><div className={editorStyle.right}><div className={editorStyle.save} onClick={() => saveArticle(6, 1)}>保存草稿箱</div><div className={editorStyle.submit} onClick={() => saveArticle(1, 2)}>发布</div></div></div></div>

2.后端查询文章列表代码:

    /*** 分页获取文章数据* @param pageDTO* @return*/@Overridepublic ResponseDTO<PageDTO<ArticleDTO>> getArticleList(PageDTO<ArticleDTO> pageDTO) {ArticleExample articleExample = new ArticleExample();// 不知道当前页多少,默认为第一页if(pageDTO.getPage() == null){pageDTO.setPage(1);}// 不知道每页多少条记录,默认为每页5条记录if(pageDTO.getSize() == null){pageDTO.setSize(5);}ArticleExample.Criteria c1 = articleExample.createCriteria();if(pageDTO.getParam() != null) {ArticleDTO articleDTO = pageDTO.getParam();if(!CommonUtil.isEmpty(articleDTO.getCategoryId()) && !"0".equals(articleDTO.getCategoryId())) {c1.andCategoryIdEqualTo(articleDTO.getCategoryId());}if(!CommonUtil.isEmpty(articleDTO.getTitle())) {c1.andTitleLike("%" + articleDTO.getTitle() + "%");}if(articleDTO.getType() != null && articleDTO.getType() != 0) {c1.andTypeEqualTo(articleDTO.getType());}if(articleDTO.getState() != null && articleDTO.getState() != 0) {c1.andStateEqualTo(articleDTO.getState());}if(articleDTO.getState() == null) {List<Integer> stateList = new ArrayList<>();stateList.add(ArticleStateEnum.WAIT.getCode());stateList.add(ArticleStateEnum.DRAFT.getCode());stateList.add(ArticleStateEnum.FAIL.getCode());c1.andStateNotIn(stateList);}if(!CommonUtil.isEmpty(articleDTO.getUserId())&& !ArticleQueryTypeEnum.LIKE.getCode().equals(articleDTO.getQueryType())&& !ArticleQueryTypeEnum.COLLECT.getCode().equals(articleDTO.getQueryType())) {c1.andUserIdEqualTo(articleDTO.getUserId());}if(ArticleQueryTypeEnum.BLOG.getCode().equals(articleDTO.getQueryType())) {c1.andTypeEqualTo(ArticleTypeEnum.BLOG.getCode());}if(ArticleQueryTypeEnum.FORUM.getCode().equals(articleDTO.getQueryType())) {c1.andTypeEqualTo(ArticleTypeEnum.FORUM.getCode());}if(ArticleQueryTypeEnum.LIKE.getCode().equals(articleDTO.getQueryType())) {LikeExample likeExample = new LikeExample();likeExample.createCriteria().andUserIdEqualTo(articleDTO.getUserId());List<Like> likeList = likeMapper.selectByExample(likeExample);List<String> articleIdList = likeList.stream().map(Like::getArticleId).collect(Collectors.toList());if(articleIdList.size() == 0) {articleIdList.add("-1");}c1.andIdIn(articleIdList);}if(ArticleQueryTypeEnum.COLLECT.getCode().equals(articleDTO.getQueryType())) {CollectExample collectExample = new CollectExample();collectExample.createCriteria().andUserIdEqualTo(articleDTO.getUserId());List<Collect> collectList = collectMapper.selectByExample(collectExample);List<String> articleIdList = collectList.stream().map(Collect::getArticleId).collect(Collectors.toList());if(articleIdList.size() == 0) {articleIdList.add("-1");}c1.andIdIn(articleIdList);}}articleExample.setOrderByClause("top desc, essence desc, official desc, create_time desc");PageHelper.startPage(pageDTO.getPage(), pageDTO.getSize());// 分页查出文章数据List<Article> articleList = articleMapper.selectByExample(articleExample);PageInfo<Article> pageInfo = new PageInfo<>(articleList);// 获取数据的总数pageDTO.setTotal(pageInfo.getTotal());// 讲domain类型数据  转成 DTO类型数据List<ArticleDTO> articleDTOList = CopyUtil.copyList(articleList, ArticleDTO.class);for(ArticleDTO articleDTO : articleDTOList) {// 获取文章所属用户信息User user = userMapper.selectByPrimaryKey(articleDTO.getUserId());articleDTO.setUserDTO(CopyUtil.copy(user, UserDTO.class));// 获取文章所属标签信息TagItemExample tagItemExample = new TagItemExample();tagItemExample.createCriteria().andArticleIdEqualTo(articleDTO.getId());List<TagItem> tagItemList = tagItemMapper.selectByExample(tagItemExample);List<String> tagIdList = tagItemList.stream().map(TagItem::getTagId).collect(Collectors.toList());List<Tag> tagList;if(tagIdList.size() == 0) {tagList = new ArrayList<>();} else {TagExample tagExample = new TagExample();tagExample.createCriteria().andIdIn(tagIdList);tagList = tagMapper.selectByExample(tagExample);}articleDTO.setTagDTOList(CopyUtil.copyList(tagList, TagDTO.class));// 获取文章所属分类信息Category category = categoryMapper.selectByPrimaryKey(articleDTO.getCategoryId());if(category == null) {articleDTO.setCategoryDTO(CopyUtil.copy(new Category(), CategoryDTO.class));} else {articleDTO.setCategoryDTO(CopyUtil.copy(category, CategoryDTO.class));}}pageDTO.setList(articleDTOList);return ResponseDTO.success(pageDTO);}

相关文章:

SpringBoot+React博客论坛系统 附带详细运行指导视频

文章目录一、项目演示二、项目介绍三、项目运行截图四、主要代码一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootReact框架开发的博客论坛系统。首先&#xff0c;这是一个前后端分离的项目&#xff0c;文章编辑器…...

C++ primer 之 extern

C primer 之 extern什么是声明什么是定义两者有什么区别ertern的作用什么是声明 就是使得名字为程序所知&#xff0c;一个文件如果想使用别处定义的名字就必须包含对那个名字的声明。 什么是定义 负责创建与名字关联的实体。 两者有什么区别 变量声明和声明都规定了变量的…...

Linux 练习二 (VIM编辑器 + GCC编译器 + GDB调试)

文章目录VIM命令思维导图GCC编译器1、GCC编译文件练习2、静态库动态库制作练习将此函数编译成动态库将此函数编译成静态库GCC优化选项 -OnGDB调试命令练习练习一&#xff1a;编写一个程序&#xff0c;通过gdb调试&#xff0c;使用到gdb的b&#xff0c;n&#xff0c;s&#xff0…...

python3 连接数据库 mysql PyMysql

python3PyMysql PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库 &#xff0c; 遵循 Python 数据库 API v2.0 规范 。 PyMySQL 安装 pip install PyMySQLPyMySQL 连接数据库 import pymysql pymysql.Connect(hostlocalhost,port 3306,user root,password **…...

昇腾AI新技能,还能预防猪生病?

国药集团动物保健股份有限公司&#xff08;简称“国药动保”&#xff09;是专业从事动物保健产品研发、生产和销售的国家高新技术企业&#xff0c;是国内少数几家具备新产品原创能力的动物保健企业。其中&#xff0c;猪圆环病毒灭活疫苗等市场份额位居行业前列。 “猪圆环病毒…...

模板方法模式(Template Method)

模式结构图 说明 基本方法是模板方法的组成部分。基本方法分为一下三种&#xff1a; 抽象方法 由抽象类声明&#xff0c;由其具体子类实现。C中就是纯虚函数。 具体方法 由抽象类或具体类声明并实现&#xff0c;子类可以进行覆盖也可以继承。C中是虚函数。 钩子方法 由抽象类…...

C C++ typedef的使用

一、为基本数据类型起别名 typedef int myint; myint x 5; "myint"是"int"的别名&#xff0c;可以使用"myint"来代替"int"声明变量&#xff0c;这个很好理解&#xff0c;但是也很少有人这么用吧。 二、为结构体起别名 …...

Laravel框架03:DB类操作数据库

Laravel框架03&#xff1a;DB类操作数据库一、概述二、数据表的创建与配置三、增删改操作1. 增加信息2. 修改数据3. 删除数据四、查询操作1. 取出基本数据2. 取出单行数据3. 获取一个字段的值4. 获取多个字段的值5. 排序6. 分页五、执行任意的SQL语句一、概述 按照MVC的架构&a…...

数据结构期末复习总结(前章)

作者的话 作为一名计算机类的学生&#xff0c;我深知数据结构的重要性。在期末复习前&#xff0c;我希望通过这篇博客给大家一些复习建议。希望能帮助大家夯实数据结构的基础知识&#xff0c;并能够更好地掌握数据结构和算法的应用。 一、绪论 数据&#xff1a;信息的载体&am…...

设计环形队列

文章目录1.思路分析1.1队列空满分析1.2出队分析2.循环队列设计1.思路分析 1.1队列空满分析 首先我们假设一个长度为4的环形队列 队头front 队尾rear 当队列为空时 frontrear 当队列满时 frontrear 所以我们无法判断队列是满的或者空的 因此我们多加入一个空间使队列长度为5&am…...

面向对象之-接口鉴权

1 需求 1.1 需求背景 为了保证接口调用的安全性&#xff0c;我们希望设计实现一个接口调用鉴权功能&#xff0c;只有经过认证之后的系统才能调用我们的接口&#xff0c;没有认证过的系统调用我们的接口会被拒绝。 2 需求分析 2.1 基础分析 对于如何做鉴权这样一个问题&…...

Python 多进程多线程线程池进程池协程

目录 一、线程与进程很简单的介绍 1.1 线程与进程的区别 二、多进程Process 2.1 多进程与多线程的区别 2.2 多进程为啥要使用队列 2.3 控制进程运行顺序 2.3.1 join &#xff0c; 2.3.1 daemon 守护进程 2.4 进程id 2.5 进程 存活状态is_alive() 2.5 实现自定义多…...

【自然语言处理】基于句子嵌入的文本摘要算法实现

基于句子嵌入的文本摘要算法实现人们在理解了文本的含义后&#xff0c;很容易用自己的话对文本进行总结。但在数据过多、缺乏人力和时间的情况下&#xff0c;自动文本摘要则显得至关重要。一般使用自动文本摘要的原因包括&#xff1a; 减少阅读时间根据摘要&#xff0c;选择自…...

fiddler抓包

一、工具介绍Fiddler是一个通过代理的方式来进行抓包工具&#xff0c;运行时会在本地建立一个代理服务&#xff0c;默认地址&#xff1a;127.0.0.1:8888。Fiddler开启之后&#xff0c;配置本机代理&#xff0c;再打开IE浏览器&#xff0c;IE的PROXY会自动变成127.0.0.1:8888&am…...

【Linux】网络套接字编程

前言 在掌握一定的网络基础&#xff0c;我们便可以先从代码入手&#xff0c;利用UDP协议/TCP协议进行编写套接字程序&#xff0c;明白网络中服务器端与客户端之间如何进行连接并且通信的。 目录 一、了解源目的IP、端口、网络字节序、套接字 端口号&#xff1a; 套接字&…...

break与continue关键字

1.概述 不知道大家有没有这样一种感受哈&#xff0c;有的时候容易混淆break语句和continue语句的用法&#xff0c;总是模棱两可&#xff0c;不敢确定自己是否使用正确了。正好&#xff0c;我们本篇的重点就是break和continue关键字的用法。 2.使用场景 Java中为啥会诞生break…...

kafka使用入门案例与踩坑记录

每次用到kafka时都会出现各种奇怪的问题&#xff0c;综合实践&#xff0c;下面汇总下主要操作步骤&#xff1a; Docker镜像形式启动 zookeeper启动 docker run -d --name zookeeper -p 2181:2181 -t wurstmeister/zookeeperkafka启动 docker run --name kafka01 -p 9092:909…...

系统启动太慢,调优后我直呼Nice

问题背景最近在负责一个订单系统的业务研发&#xff0c;本来不是件困难的事。但是服务的启动时间很慢&#xff0c;慢的令人发指。单次启动的时间约在10多分钟左右&#xff0c;基本一次迭代、开发&#xff0c;大部分的时间都花在了启动项目上。忍无可忍的我&#xff0c;终于决定…...

java知识点

文章目录异常写法JVM加载反射访问private调用方法动态代理注解元数据&#xff1a;TargetRetention元注解泛型编写泛型擦拭法局限通配符无限定通配符(<?>)集合重写方法和实现类IO流字节与字符转换同步和异步可以设置编码的类Print*类Files时间与日期时区一种二种三种异常…...

文件的打开关闭和顺序读写

目录 一、文件的打开与关闭 &#xff08;一&#xff09;文件指针 &#xff08;二&#xff09; 文件的打开和关闭 二、文件的顺序读写 &#xff08;一&#xff09;fputc 1. 介绍 2. 举例 &#xff08;二&#xff09;fgetc 1. 介绍 2. 举例1 3. 举例2 &#xff08;三&…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...