使用SpringBoot+SpringMVC+Mybatis+Redis实现个人博客管理平台

news2025/1/21 15:36:59

文章目录

  • 前言
    • 1. 项目概述
    • 2. 项目需求
      • 2.1功能需求
      • 2.2 其他需求
      • 2.3 系统功能模块图
    • 3. 开发环境
    • 4. 项目结构
    • 5. 部分功能介绍
      • 5.1 数据库密码密文存储
      • 5.2 统一数据格式返回
      • 5.3 登录拦截器
    • 6. 项目展示

前言

在几个月前实现了一个servlet版本的博客系统,本项目则是在原有基础上进行升级。使用SSM框架、数据库密码使用加盐算法加密、使用Redis对session进行持久化存储从而支持分部式部署、通过拦截器实现用户登录校验、对于数据格式返回以及异常处理进行统一功能处理、增加分页以及点击量统计等功能。

1. 项目概述

用户进入主页可以看到他人发布的博客,同时也可以注册账号通过本平台编写发布博客,平台支持markdown编辑;用户也可以在个人中心修改个人信息,同时对博客可以随写随存以草稿形式,之后也可以发布修改草稿。用户可以通过博客的点击量,判断博客质量等等。

2. 项目需求

2.1功能需求

  • 登录与注册功能
  • 个人中心(查看、修改个人信息)
  • 查看博客详情
  • 编写个人博客
  • 修改个人博客
  • 删除个人博客
  • 草稿箱(保存博客为草稿,修改博客为草稿,发布草稿为博客,草稿增删改查)
  • 博客列表分页查询功能
  • 博客阅读量统计
  • 注销功能

2.2 其他需求

  • 系统界面有良好的视觉体验,营造美观舒适的界面;
  • 操作简单流畅,无可视卡顿;
  • 有良好的引导提示,增强用户体验;

2.3 系统功能模块图

在这里插入图片描述

3. 开发环境

1.前端开发:
技术:HTML、CSS、JavaScript
工具:IntelliJ IDEA 2021.3.1
2.后端开发:
服务器:tomcat-8.5.50
数据库:MySQL5.7
开发语言:Java
技术框架:SpringBoot、SpringMVC、Mybatis、Redis
管理工具:Maven
开发工具:Intellij IDEA 2020.1.4
操作系统:Windows10

4. 项目结构

Java源代码位于com.example.blog_system中;

  1. common包:设置统一数据格式返回代码(AjaxResult)、全局变量用于session存储(AppVariable)、密码加盐已经密码验证(PasswordUtils)、获取当前用户(UserSessionUtils)。
  2. config包:系统配置文件(Appconfig)用于设置登录拦截器规则、登录拦截器的实现(LoginIntercept)、数据返回增强,校验是否是统一格式返回不是则封装为统一格式(ResponseAdvice)
  3. controller包:控制层;连接页面请求和服务层,获取页面请求的参数,通过自动装配,映射不同的URL到相应的处理函数,并获取参数,对参数进行处理,之后传给服务层。关于博客文章的控制器(ArticleController),实现博客以及草稿的增删改查以及列表分页点击量统计等功能、关于用户的控制器(UserController)实现增删改查功能。
  4. entity包:实体类,定义文章以及用户属性,同时定义视图UserVo的属性。
  5. service包:服务层;为控制层提供服务,接受控制层的参数,完成相应的功能,并返回给控制层;
  6. mapper包:持久层;根据service相关功能定义与数据库相关的增删改查方法。

在这里插入图片描述

在resources包中保存着系统资源,其中:

  1. mapper:根据 com.example.blog_system.mapper中的方法实现sql语句的增删改查。
  2. static:存储系统的前端页面HTML,CSS样式,markdown编辑器,jquery等相关资源。

5. 部分功能介绍

5.1 数据库密码密文存储

基于spring框架提供的md5加密的基础上通过UUID生成随机盐值,对用户密码进行加密;

加密过程如下:

//1.加盐并生成密码
    public static String encrypt(String password){
        //1.生成盐值
        String salt = UUID.randomUUID().toString().replace("-","");
        //2.生成加盐之后的密码
        String saltpassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
        //3。生成最终密码,32位盐值+"$"+加盐密码
        String finalpassword = salt+"$"+saltpassword;
        retur

在进行用户登录密码校验中,密码解密过程,从数据库取出密码,得到盐值,根据盐值以及用户输入密码进行加密,校验与数据库存储密码是否相同。

具体实现如下:

//2.生成最终密码(数据库中的,便于密码验证)
    public static String encrypt(String password,String salt){
          //2.通过盐值和原始密码生成加盐之后的密码
        String saltpassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
//        最终密码
        String finalPassword = salt+"$"+saltpassword;
        return finalPassword;
    }

    //3.验证密码

    /**
     *
     * @param inputPassword 用户输入密码
     * @param finalPassword 数据库存储密码
     * @return
     */
    public static boolean check(String inputPassword,String finalPassword){
        //先进性非空校验和长度校验
        if (StringUtils.hasLength(inputPassword)&&StringUtils.hasLength(finalPassword)
        &&finalPassword.length()==65){
            //1.得到盐值,从finalPassword,对$加上\\进行转义,它是关键字
            String salt = finalPassword.split("\\$")[0];
            //2.使用之前加密步骤将明文加密并生成最终密码
           String confinmrPassword =  PasswordUtils.encrypt(inputPassword,salt);
           //3,进行比较
            return confinmrPassword.equals(finalPassword);
        }
        return false;
    }

5.2 统一数据格式返回

定义数据格式为状态码+状态码描述信息+返回数据,实现成功以及失败的返回。

具体实现如下:

package com.example.blog_system.common;

import lombok.Data;

import java.io.Serializable;

/**
 * 统一数据格式返回
 */
@Data
public class AjaxResult implements Serializable {
    // 状态码
    private Integer code;
    // 状态码描述信息
    private String msg;
    // 返回的数据
    private Object data;

    /**
     * 操作成功返回的结果
     */
    public static AjaxResult succecc(Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(200);
        result.setMsg("");
        result.setData(data);
        return result;
    }

    public static AjaxResult succecc(int code, Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg("");
        result.setData(data);
        return result;
    }

    public static AjaxResult succecc(int code, String msg, Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    /**
     * 返回失败结果
     */
    public static AjaxResult fail(int code, String msg) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(null);
        return result;
    }

    public static AjaxResult fail(int code, String msg, Object data) {
        AjaxResult result = new AjaxResult();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

}

5.3 登录拦截器

继承HandlerInterceptor实现一个登录拦截器,判断在用户进入主页、登录页、注册页、以外的页面进行相关操作时判断是否登录,未登录则自动跳转到登录页面。

具体实现如下:

/**登录拦截器
 * @author zq
 * @date 2023-07-22 22:33
 */

public class LoginIntercept implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession(false);
        if(session!=null&&session.getAttribute(AppVariable.USER_SESSION_KEY)!=null){
            //用户已登录
            return true;
        }
        //跳转到登录页面
        response.sendRedirect("/login.html");
        return false;
    }
}

6. 项目展示

主页:
在这里插入图片描述

我的博客列表页:
在这里插入图片描述

博客编辑页:
在这里插入图片描述

草稿列表页:
在这里插入图片描述

草稿编辑页:
在这里插入图片描述

个人中心:
在这里插入图片描述

修改个人信息:
在这里插入图片描述

登录页面:
在这里插入图片描述
注册页面:
在这里插入图片描述

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

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

相关文章

JWT无状态理解

JSON Web Tokens (JWT) 被称为无状态,因为授权服务器不需要维护任何状态;令牌本身就是验证令牌持有者授权所需的全部内容。 JWTs都签订使用数字签名算法(例如RSA)不能被伪造。因此,任何信任签名者证书的人都可以放心地…

二维深度卷积网络模型下的轴承故障诊断

1.数据集 使用凯斯西储大学轴承数据集,一共有4种负载下采集的数据,每种负载下有10种 故障状态:三种不同尺寸下的内圈故障、三种不同尺寸下的外圈故障、三种不同尺寸下的滚动体故障和一种正常状态 2.模型(二维CNN) 使…

基于传统检测算法hog+svm实现图像多分类

直接上效果图: 代码仓库和视频演示b站视频005期: 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 代码展示: 数据集在datasets文件夹下 运行01train.py即可训练 训练结束后会保存模型在本地 运行02pyqt.py会有一个可视化…

iOS开发-自定义TabbarController与Tabbar按钮Badge角标

iOS开发-自定义Tabbar按钮Badge角标 Tabbar是放在APP底部的控件。UITabbarController是一个非常常见的一种展示模式了。比如微信、QQ都是使用tabbar来进行功能分类的管理。 一、实现自定义Tabbar 我这里Tabbar继承于系统的UITabBar,定义背景图、线条的颜色、tab…

Redis系列 2- Redis 的持久化

Redis系列 2- Redis 的持久化 1、关于 Redis 持久化2、RDB 持久化2.1、RDB 文件的创建与载入2.2、RDB 自动间隔性保存的配置2.3、Redis 快照2.4、RDB 重点总结 3、AOF 持久化3.1、命令追加(append)3.2、AOF 文件的写入与同步3.3、AOF 工作原理3.4、AOF 的文件载入与数据还原3.5…

QGIS3.28的二次开发一:编译工程

环境:VS2019OSGeo4WCMake_3.26Cygwin64QGIS_3.28 注意:一定要按照步骤顺序来! 一、配置环境 (一)VS2019 VS2019下载链接https://my.visualstudio.com/Downloads?qvisual%20studio%202019&wt.mc_ido~msft~vsco…

day50-Insect Catch Game(捉虫游戏)

50 天学习 50 个项目 - HTMLCSS and JavaScript day50-Insect Catch Game&#xff08;捉虫游戏&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport"…

基于SpringBoot+Vue的大学生租房系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

第 356 场力扣周赛题解

A 满足目标工作时长的员工数目 签到题 class Solution { public:int numberOfEmployeesWhoMetTarget(vector<int> &hours, int target) {int res 0;for (auto x: hours)if (x > target)res;return res;} };B 统计完全子数组的数目 枚举子数组&#xff1a;枚举子数…

小研究 - 主动式微服务细粒度弹性缩放算法研究(四)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放&#xff0c;忽略了能够充分利用单台服务器资源的细粒度垂直缩放&#xff0c;从而导致资源浪费。为此&#xff0c;本文设计了主动式微服务细粒度弹性缩放算法…

溟㠭篆刻艺术……“瀚1”

每个人生犹如一颗颗繁星&#xff0c;在时空交错中汇聚成一条星汉灿烂的银河&#xff0c;在静谧深邃的宇宙中清澈回响&#xff0c;熠熠生辉。妻晓蕾题注溟㠭刊…… 溟㠭 篆刻作品“瀚1” 溟㠭 篆刻作品“瀚1” 溟㠭 篆刻作品“瀚1” 文/晓蕾

质效卓越,科技前沿—QECon北京站线下盛会成功落幕

7月28日-29日&#xff0c;第八届QECon质量效能大会在北京成功召开&#xff0c;这是质量效能领域备受期待的一场盛会&#xff0c;从2020年第一届QECon开启以来&#xff0c;历经四年QECon北京站终于首次线下落地。本次大会的核心主旨为“数生智慧&#xff0c;高质量发展新引擎”&…

虚拟局域网VLAN

概述 广播域 使用一个或多个以太网交换机互连接起来的交互式以太网&#xff0c;其所有站点都属于同一个广播域&#xff0c;随着交换式以太网规模的扩大&#xff0c;广播域响应扩大&#xff0c;从而形成一个巨大的广播域。 但是巨大的广播域会带来很多的弊端&#xff1a; 广…

JUC中其他常用类

1.CopyOnWriteArrayList ArrayList是线程不安全的&#xff0c;Vector是线程安全的(方法被Synchronized修饰)&#xff0c;CopyOnWriterArrayList是在Vector的基础上再做优化&#xff0c;因为当读取操作较多时&#xff0c;Vector的效率不高。CopyOnWriterArrayList中读操作并没有…

C++ 类和对象篇(一) 类的引入

目录 一、类的概念 二、类的引入 三、类的定义 1.定义一个类 2.struct 和 class 的区别 3.类中成员函数的声明、实现分离 四、封装及类的访问限定符 1.封装 2.类的访问限定符 五、类的作用域和生命周期 六、类的实例化 七、类存储方法 八、计算类的大小 一、类的概念 1…

Gazebo打不开

问题&#xff1a;启动Gazebo半天打不开&#xff0c;无反应 原因&#xff1a;启动Gazebo&#xff0c;会优先从网络上下载模型 解决方案&#xff1a; 1.断网&#xff0c;然后再启动Gazebo 2.把模型下载下来 模型下载链接&#xff1a;GitHub - osrf/gazebo_models: Gazebo da…

简要理清计算机的发展(从硬件和软件)

1.计算机硬件和其他板块的关系 2.什么是计算机系统 可以简单理解计算机系统 硬件 软件。 3.硬件、软件的发展 3.1.硬件发展 逻辑元件的发展&#xff1a; 发展时间逻辑原件速度&#xff08;次/秒&#xff09;内存外存其他第一代1946-1957电子管几千-几万汞延迟线、磁鼓穿…

从源程序到可执行文件的四个过程

从源程序到可执行文件的四个过程 预处理编译汇编链接 程序要运行起来&#xff0c;必须要经过四个步骤&#xff1a;预处理、编译、汇编和链接&#xff0c;如下图所示&#xff1a; -E选项&#xff1a;提示编译器执行完预处理就停下来&#xff0c;后边的编译、汇编、链接就先不执…

Flowable基础

简介 Flowable 是 BPMN 的一个基于 java 的软件实现&#xff0c;不过 Flowable 不仅仅包括 BPMN &#xff0c;还有 DMN 决策表和 CMMN Case 管理引擎&#xff0c;并且有自己的用户管理、微服务 API 等一系列功能&#xff0c; 是一个服务平台。 官方手册&#xff1a; https://…

百万数据快速导入导出

百万数据快速导入 pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>Resourceprivate SalariesListener salariesListener;private ExecutorService…