1.个人博客系统项目

一、项目介绍

  个人博客系统

  • 相关技术:  SpringBoot+SpringMvc+Mybatis+Mysql+Redis
  • 项目简介:本项目为一个功能完善的个人博客系统,支持文章的编辑、修改、删除和发布,以及作者个人信息的展示等功能。
  • 项目描述:
  1. 采用前后端分离架构,基于SpringBoot和Mybatis等框架构建。
  2. 设计统一的前后端数据返回格式,提高系统可读性和可维护性。
  3. 使用拦截器实现用户登录校验,并采用MD5算法对密码进行加密存储。
  4. 利用Redis对内容数据进行缓存,减轻数据库压力,提高系统性能。
  5. 使用ThreadPoolExecutor线程池技术,并发执行查询文章详情和修改文章阅读量等任务,提升系统响应速度。

二、项目实现效果

  项目包含7个前端页面(注册,登录,个人博客,总博客,修改已有博客,增加新博客,显示博客详情),每个页面顶端有一个导航栏。其中编辑文章使用markdown编辑器,不过其中个人信息没有实现修改功能,其头像和博客地址固定了(显示为奶龙和我的gitee地址)。

注册页面:

登录页面:

个人博客页面:

总博客页面:

修改已有博客页面:

增加新博客页面:

显示博客详情页面(左边有作者个人信息):


三、项目具体实现

1.软件生命周期

  一个软件的生命周期可以划分为

  • 可行性研究
  • 需求分析
  • 概要设计
  • 详细设计
  • 编码实现
  • 测试
  • 使用及维护
  • 退役

2.项目需求分析

  1. 用户 注册、登录、退出登录 的功能。
  2. 显示个人博客列表:按发布时间倒序排列,各博客显示 标题、发布时间、简介。博客下方有 查看全文、修改、删除等功能。
  3. 显示总博客列表:分页显示(首页、末页、上一页、下一页功能),按发布时间倒序排列,各博客显示 标题、发布时间、简介。博客下方有 查看全文 功能。
  4. 查看全文:显示作者信息(头像,账号名,博客地址,所发布文章总数),博客信息(标题,发布时间,文章详情,文章阅读量)。
  5. 增加新文章功能。
  6. 修改已有文章功能(在修改界面,导入文章之前已有的内容)。
  7. 删除文章功能。
  8. 用户权限限制:进入总博客页面,查看全文,无需登录。进入个人博客页面(修改,删除博客),增加新博客,都需要登录(如果用户没有登录,则强制登录)。

3.设计

  主要是设计数据库存储用户和文章信息。

用户信息表结构:

表中的 昵称 未作具体使用,博客地址,头像 固定了不可修改。

文章信息表结构:

文章发布和修改时间自动为当前时间。

4.编码实现

4.1项目构建及相关配置

  基于SpringBoot和Mybatis等框架构建项目,及mysql,Mybatis,Redis等相关配置...

4.2创建实体类(依据数据库中表结构)

例如:

@Data
public class Userinfo implements Serializable {private int id;private String username;private String password;private String nickname;private String blogSite;private String photo;private boolean state;}

4.3数据库持久层(涉及到的增删查改)

例如:

public interface ArticleMapper {//添加文章@Insert("insert into articleinfo(title,content,author_id,intro) values(#{title},#{content},#{author_id},#{intro})")public int addArticle(Articleinfo articleinfo);//以用户id获取用户文章列表@Select("select * from articleinfo where author_id=#{author_id} order by id desc")public List<Articleinfo> getUserArticleList(@Param("author_id") int author_id);//以用户id和文章id删除文章@Delete("delete from  articleinfo where author_id=#{author_id} and id=#{id}")public int deleteArticle(@Param("author_id")int author_id,@Param("id") int id);//根据用户id和文章id得到文章@Select("select * from articleinfo where author_id=#{author_id} and id=#{id}")public Articleinfo getArticleByUidAid(@Param("author_id")int author_id,@Param("id") int id);//修改文章@Update("update articleinfo set title=#{title},content=#{content},intro=#{intro} where id=#{id}")public int updateArticle(Articleinfo articleinfo);//根据文章id查询到文章@Select("select * from articleinfo where id=#{id}")public  Articleinfo getArticleByAid(@Param("id") int id);//统计用户发布文章数量@Select("select count(*) from articleinfo where author_id=#{author_id}")public int getArticleCountByUid(@Param("author_id")int author_id );//修改文章阅读量,+1.@Update("update articleinfo set read_count=read_count+1 where id=#{id}")public int updateArticleReadCount(@Param("id") int id);//查询所有文章,分页.@Select("select * from articleinfo order by id desc limit #{perPage} offset #{offsetPage}")public List<Articleinfo> getAllArticles(@Param("perPage") int perPage,@Param("offsetPage") int offsetPage);//计算一下总文章数@Select("select count(*) from articleinfo ")public int getAllArticleCount();

4.4统一前后端数据交互对象

public class ResultAjax {private int code;private String msg;private Object data;public static ResultAjax successful1(Object data){ResultAjax result=new ResultAjax();result.setCode(200);result.setData(data);result.setMsg("");return result;}public static ResultAjax successful2(int code,String msg,Object data){ResultAjax result=new ResultAjax();result.setCode(code);result.setData(data);result.setMsg(msg);return result;}public static ResultAjax fail1(int code,String msg){ResultAjax result=new ResultAjax();result.setCode(code);result.setMsg(msg);return result;}public static ResultAjax fail2(int code,String msg,Object data){ResultAjax result=new ResultAjax();result.setCode(code);result.setData(data);result.setMsg(msg);return result;}
}

4.5注册、登录、退出登录

  采用MD5算法对密码进行加密存储:

存储密码:利用uuid生成唯一的字符串作为盐值,与用户注册时输入的密码拼接后MD5加密生成最终密码,在数据库中存储盐值+最终密码。

验证密码:将数据库中盐值与最终密码分开,  将用户登录时输入的待验证密码与盐值进行MD5加密后,再与最终密码比较.

public class PasswordUtils {//加密public static String encrypt(String password){//1.用uuid作为盐值String salt= UUID.randomUUID().toString().replace("-","");//2.盐值加密码用md5加密String finalPassword= DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));//3.存储盐值和最终密码return salt+'$'+finalPassword;}//验证public static boolean verifyPassword(String password,String databasePassword){//1.将盐值与最终密码分开String[] saltPassword=databasePassword.split("\\$");//2.将待验证密码与盐值进行md5加密,再与最终密码比较.String salt=saltPassword[0];String finalPassword =saltPassword[1];String verifyPassword= DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));if(verifyPassword.equals(finalPassword)){return true;}else {return false;}}}

  登录后利用Session(会话)存储登录信息:

//得到当前登录用户对象
public class SessionUtils {public static Userinfo getLoginUser(HttpServletRequest request){HttpSession session=request.getSession(false);if(session!=null && session.getAttribute(SESSION_KEY)!=null){return (Userinfo) session.getAttribute(SESSION_KEY);}return null;}
}

4.6显示个人博客列表

  根据用户id查询该作者所有文章,按时间倒序(也可以按文章id倒序排列)显示。

4.7显示总博客列表

 要根据文章总数来计算总页数,和分页查询显示当前页面:利用ThreadPoolTaskExecutor线程池,并发执行分页查询数据库中文章和统计所有文章数(两个都是查询操作可以并发执行)每页显示文章数,由前端传入(默认每页显示两条文章)。

    //查询所有文章,分页.@RequestMapping("/getAllArticles")public ResultAjax getAllArticles(Integer currentPage,Integer perPage) throws ExecutionException, InterruptedException {//无需验证登录也可访问总博客页.//1.校验参数if(currentPage==null||currentPage<=0||perPage==null ||perPage<=0){return ResultAjax.fail1(-1,"参数错误");}//2.查询数据库.分页查询limit perPage offset (currentPage-1)*perPage,task1.int offsetPage=(currentPage-1)*perPage;//计算一下总文章数,再来计算总页数,task2.int  allArticleCount=0;//这两个都是查询,可以并发执行.FutureTask<List<Articleinfo>> task1 = new FutureTask(() -> {return articleService.getAllArticles(perPage,offsetPage);});taskExecutor.submit(task1);FutureTask<Integer> task2 = new FutureTask(() -> {return articleService.getAllArticleCount();});taskExecutor.submit(task2);List<Articleinfo> list=task1.get();allArticleCount= task2.get();int pageSzie=1;if(allArticleCount!=0){pageSzie=allArticleCount/perPage;if(allArticleCount%perPage!=0){pageSzie+=1;}}HashMap<String,Object> hashMap=new HashMap<>();hashMap.put("articleList",list);hashMap.put("pageSize",pageSzie);return ResultAjax.successful1(hashMap);}
}

4.8查看全文

  显示文章和用户信息:根据文章id查询到文章,再拿到用户id,从而查询到用户信息。其中(查询用户对象和统计该用户发布文章数量 并且修改当前文章阅读量+1,以上三个操作利用ThreadPoolTaskExecutor线程池并发执行):

//查看全文//返回文章和用户对象.@RequestMapping("/fullText")public ResultAjax fullText(Integer id) throws ExecutionException, InterruptedException {//1.校验参数if(id==null || id<=0){return ResultAjax.fail1(-1,"参数错误");}//2.根据文章id查询到文章,再从中拿到用户id.Articleinfo articleinfo=articleService.getArticleByAid(id);if(articleinfo==null){return ResultAjax.fail1(-2,"查看全文失败");}int uid=articleinfo.getAuthor_id();if(uid<=0){return ResultAjax.fail1(-2,"查看全文失败");}// 得到相应用户对象和统计发布文章数量// 并且修改文章阅读量,+1.//3.以上三个操作并发执行,利用线程池.//根据uid查询用户对象FutureTask<UserinfoVO> userTask = new FutureTask(() -> {return userService.getUserByUserId(uid);});taskExecutor.submit(userTask);//统计用户发布文章数量FutureTask<Integer> articleCountTask = new FutureTask(() -> {return articleService.getArticleCountByUid(uid);});taskExecutor.submit(articleCountTask);//修改文章阅读量,+1.FutureTask <Integer> articleReadCountTask = new FutureTask(() -> {return articleService.updateArticleReadCount(id);});taskExecutor.submit(articleReadCountTask );UserinfoVO userinfovo=userTask.get();int articleCount=articleCountTask.get();int articleReadCount=articleReadCountTask.get();//返回更新操作影响的行数//校验一下参数if(userinfovo==null || articleCount<=0 || articleReadCount !=1){return ResultAjax.fail1(-2,"查看全文失败");}//4.组装好数据userinfovo.setArticleCount(articleCount);//设好文章发布数量articleinfo.setRead_count(articleinfo.getRead_count()+1);//文章阅读量+1.//5.用一个哈希表返回HashMap<String,Object> hashMap=new HashMap<>();hashMap.put("user",userinfovo);hashMap.put("article",articleinfo);return ResultAjax.successful1(hashMap);}

4.9增加新文章

增加文章操作...

4.10修改文章

修改文章操作:先查询导入原有文章内容,还要验证该文章是否为当前作者的文章后才能修改(通过比较当前登录用户id与文章用户id)。

4.12删除文章

此处删除文章操作是真的删除数据库中文章...

4.13用户权限限制

  使用拦截器实现用户登录校验:

  进入总博客页面,查看全文,无需登录。进入个人博客页面(修改,删除博客),增加新博客,需要登录(如果用户没有登录,则强制登录)

/*** 登录拦截器*/
public class LoginIntercept implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session=request.getSession(false);if(session!=null && session.getAttribute(SESSION_KEY)!=null){return true;}//没登录就跳转到登录页面response.sendRedirect("/login.html");return false;}
}/*** 系统配置*/
@Configuration
public class MyConfig implements WebMvcConfigurer {// 添加拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginIntercept()).addPathPatterns("/**") // 拦截所有接⼝.excludePathPatterns("/editor.md/*")//放行.excludePathPatterns("/img/*").excludePathPatterns("/js/*").excludePathPatterns("/css/*").excludePathPatterns("/blog_list.html").excludePathPatterns("/article/getAllArticles").excludePathPatterns("/blog_content.html").excludePathPatterns("/article//fullText").excludePathPatterns("/reg.html").excludePathPatterns("/user/reg").excludePathPatterns("/login.html").excludePathPatterns("/user/login");}
}

四、项目代码(gitee地址)

blog_system · new林/项目 - 码云 - 开源中国 (gitee.com)

(服务器过期了,没部署...,redis没用到...)


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

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

相关文章

利用钉钉机器人和PHP开发一款免费的网站可用性检测工具,单节点版

前言 手里有几套系统正在运维&#xff0c;需要保障正常运行&#xff0c;所以可用性检测就必不可少啦&#xff0c; 以前本来是用的阿里官方的云监控&#xff0c;但现在价格感觉太贵了&#xff0c;不划算 那就自己手搓一个简易版的监控吧。 成品效果展示 代码展示 <?php …

微信小程序毕业设计-实验室管理系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

centos环境上:k8s 简单安装教程

本次演示安装3节点k8s环境&#xff0c;无需多言&#xff0c;直接上操作步骤&#xff1a; 1、环境准备 k8s部署前&#xff0c;首先需要准备好环境&#xff0c;除了1.4 步骤&#xff0c;其他步骤在所有&#xff08;3个&#xff09;节点上都要执行&#xff1a; 1.1 关闭防火墙 s…

【工具】新手如何正确使用Pycharm?

1. 什么是JetBrains Toolbox JetBrains Toolbox是一个管理工具&#xff0c;用于安装、更新和管理JetBrains开发工具的所有版本。它可以简化多个IDE的管理&#xff0c;并确保你总是使用最新版本的软件。 2. 安装JetBrains Toolbox 步骤1&#xff1a;下载Toolbox 访问JetBrai…

非关系型数据库NoSQL数据层解决方案 之 redis springboot整合与读写操作 2024详解以及window版redis5.0.14下载百度网盘

redis下载安装以及基本使用 下载地址 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;0410 一个名对应一个数值 内存级 在内存里进行操作 准备启动 我们现在就有一个redis客户端的服务器了 我们再启动一个cmd 操作redis数据库 redis里面的基本数据类型有五种 …

HTML5的未来:掌握最新技术,打造炫酷网页体验

引言 随着互联网技术的飞速发展&#xff0c;HTML5已经成为构建现代网页和应用的核心技术之一。HTML5不仅提供了丰富的语义化标签&#xff0c;还引入了多项前沿技术&#xff0c;使得网页体验更加丰富多彩。本文将探讨HTML5的最新技术&#xff0c;并结合行业实践&#xff0c;提供…

Linux操作系统学习:day02

内容来自&#xff1a;Linux介绍 视频推荐&#xff1a;[Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试]( 目录 day025、Linux目录结构6、相对路径7、绝对路径8、命令提示行9、命令解析器10、命令行快捷键11、cd 命令—目录切换12、ls 命令13、文件…

Agilent 安捷伦 N9342C 手持式频谱分析仪

Agilent 安捷伦 N9342C 手持式频谱分析仪 N9342C 手持式7GHz频谱分析仪专为现场测试而设计&#xff0c;无论是安装和维护射频系统&#xff0c;现场进行故障诊断&#xff0c;监测射频环境还是分析干扰&#xff0c;都可以为您提供快速、精确的测量。它具有同类最佳的显示平均噪声…

Vscode中使用make命令

前言 需要注意&#xff0c;如下操作需要进行网络代理&#xff0c;否则会出现安装失败的情况 安装 第一步 — 安装MingGW &#xff08;1&#xff09;进入官网下载 &#xff08;2&#xff09;下载完成之后&#xff0c;双击exe文件 &#xff08;3&#xff09;点击Install &#x…

iOS18新增通话录音和应用锁!附升级教程及内置壁纸

一觉睡醒&#xff0c;iOS18终于是揭开面纱了&#xff0c;而且已经有测试版给开发者使用了。 不过还是建议咱们普通用户不要轻易尝试&#xff0c;而且在升级之前一定要用iMazing做个备份&#xff0c;以免测试系统出现问题&#xff0c;丢失数据。 这次WWDC2024与之前爆料完全一样…

【云岚到家】-day04-2-索引同步-搜索接口

【云岚到家】-day04-2-索引同步-搜索接口 1 索引同步1.1 编写同步程序1.1.1 创建索引结构1.1.2 编写同步程序1.1.2.1 添加依赖1.1.2.2 配置连接ES1.1.2.3 编写同步程序 1.1.3 测试1.1.4 小结1.1.4.1 如何保证CanalMQ同步消息的顺序性&#xff1f;1.1.4.2 如何保证只有一个消费者…

java课设

项目简介:射击生存类小游戏 项目采用技术: 游戏引擎: Unity编程语言: Java图形处理: NVIDIA PhysX (物理引擎), HDRP (High Definition Render Pipeline)音效与音乐: FMOD, Wwise版本控制: Git 功能需求分析: 角色控制&#xff1a;玩家能够使用键盘和鼠标控制角色移动、瞄准…

基于RandLA-Net深度学习模型的激光点云语义分割

一、场景要素语义分割部分的文献阅读笔记 RandLA-Net是一种高效、轻量级的神经网络&#xff0c;其可直接逐点推理大规模点云的语义标签。RandLA-Net基于随机点采样获得了显著的计算和内存效率&#xff0c;并采用新的局部特征聚合模块有效地保留了几何细节&#xff0c;弥补了随机…

最新下载:Folx【软件附加安装教程】

​Folx Pro是一款适合Mac的专业下载工具也是一款BT下载器&#xff0c;Folx中文版有一个支持Retina显示的现代界面&#xff0c;提供独特的系统排序、存储下载内容与预览下载文件&#xff0c;Folx中文官网提供Folx教程、激活码、下载。 Folx友好兼容浏览器&#xff1a;如果你在网…

浅谈网络通信(3)

文章目录 一、TCP[!]1.1、TCP协议报文格式1.2、TCP十大机制1.2.1、确认应答机制1.2.2、超时重传机制1.2.3、连接管理机制1.2.3.1、三次握手[其流程至关重要&#xff0c;面试必考]1.2.3.2.1、那为啥要建立连接&#xff1f;&#xff1f;建立连接的意义是啥&#xff1f;&#xff1…

Jetson Linux 上安装ZMQ

1. 安装ZMQ 框架 apt-get install libzmq3-dev 2. 或者自己build ZMQ https://github.com/zeromq/libzmq.git 参考官网教程 3. 安装CPPZMQ CPPZMQ 是ZMQ 的友好的C封装&#xff0c;只需要一个zmq.hpp 头文件即可 git clone https://github.com/zeromq/cppzmq.git cd cppz…

Ubuntu安装部署

Ubuntu安装部署 一、Ubuntu概述1、Ubuntu介绍2、Ubuntu特点 二、Ubuntu和Centos的区别1、Centos2、Ubuntu3、Centos和Ubuntu区别 三、安装Ubuntu-Server1、Ubuntu官网2、创建新的机子3、创建名称以及虚拟机在磁盘上的位置4、Ubuntu初始化和安装 四、安装Ubuntu1、开始安装2、安…

SAP RFC 输入一张表(C# 使用 SapNwRfc 二)

SapNwRfc中的配置参数&#xff0c;记录日志关闭 Trace0&#xff0c;可以得到很好的性能。 有网友在问&#xff0c;SAP RFC返回多张表&#xff08;C# 使用 SapNwRfc 一&#xff09;中如何输入一张表的数据&#xff0c;正好博主也遇到了这个场景&#xff0c;今天做了一个DEMO&…

4D毫米波雷达技术及发展

文章目录 前言一、4D毫米波雷达是什么&#xff1f;二、毫米波雷达是什么&#xff1f;毫米波雷达的基本原理多普勒效应 三、4D毫米波雷达的基本结构3D毫米波4D毫米波对比 前言 现阶段自动驾驶技术中&#xff0c;主要用到的传感器有摄像头、激光雷达和毫米波雷达。 摄像头的光谱…