一、项目简介

项目名称:blc management system(blc MS)
基于Vue CLI4 + SpringBoot开发的前后端分离项目。
基本功能:对博客和书籍进行增删改查,在聊天室点对点聊天或者群发消息,支持发送文本消息以及图片消息,查看用户个人信息,在线预览聊天图片和用户头像。
特色功能:用户密码加密,页面访问控制,用户权限管理,Druid后台监控。

参考项目:
https://github.com/Antabot/White-Jotter
https://github.com/Tellsea/springboot-learn/-/tree/master/springboot-websocket

本项目地址:

码云: https://gitee.com/jiyuzz/blc-ms
CSDN: https://blog.csdn.net/jiyuzzz/article/details/122242514

二、主要技术栈

1)前端

  1. Vue CLI4
  2. ElementUI
  3. axios

2)后端

  1. Spring Boot 2.1.3.RELEASE
  2. Apache Shiro
  3. Apache Log4j +Alibaba Druid(http://localhost:8443/druid/)
  4. Spring Data JPA
  5. Lombok

3)数据库

  1. MySQL 8.0.26

4)开发环境

  1. IDEA 2019.1

  2. JDK 1.8.0_191

  3. apache-maven-3.6.0

三、需求分析

1、功能分析

主要功能:博客、书架、聊天室。

聊天室是独立项目,无论在主页是否登录,都可以打开(但是打开后必须登录在聊天室中注册的新用户)。

未登录时,只能访问主页或者打开聊天室,对其他页面的访问会被拦截,然后跳转到登录页;

登录时,会进行角色认证:

  • 普通用户只能浏览博客和书架;
  • 管理员具有普通用户的一切权限,并且可以进行博客和书籍的管理(增删改查)。

登录后,默认记住用户登录状态30天(通过前端localstorage结合vuex+后端shiro实现);点击注销则会从前后端同时删除用户信息然后跳转到登录页。

注册会通过shiro对密码进行加盐加密,盐的值随机生成,加密算法使用md5,盐和加密后的密码都会保存在数据库中。

登录则是通过同样的加密方法对用户输入的密码加密,然后和数据库中加密后的密码进行对比,如果相同则允许用户登录。

聊天室使用了websocket允许用户互相发送消息以及群发消息,支持文本消息以及图片消息。

2、数据库设计

1)blc.sql

为什么mysql的varchar字符长度会被经常性的设置成255—— 不明其理的约定俗成

在这里插入图片描述

在这里插入图片描述

2)chatroom.sql

在这里插入图片描述

在这里插入图片描述

四、系统设计

项目结构

在这里插入图片描述

主页

前端项目运行后,会在浏览器自动打开http://localhost:8080/index
进入项目主页,此时为游客登录,点击博客、书架都会被拦截然后跳转到登录页
在这里插入图片描述

点击右上角的管理中心,可以选择注销和进入聊天室。
点击聊天室会打开新的界面并让我们登录(因为聊天室属于独立的项目,必须使用在聊天室中注册的账号进行登录)
在这里插入图片描述

登录

点击 博客 或者 书架,都会跳转到登录页,登录成功后,会跳转到我们之前点击但是被拦截的页面
在这里插入图片描述

在数据库的user表中的用户密码都是加密的
admin的密码:123456
张三的密码:zspwd
在这里插入图片描述

不同角色登录后,可以看到的导航栏选项不同,简单地说就是admin拥有更多权限。
admin:
在这里插入图片描述

normal:
在这里插入图片描述
点击注销,前端就会删除localstorage中的用户名,后端删除shiro中的session,然后跳转到登录页

注册

注册成功会跳转到登录页

同时对密码使用了加盐加密(盐值随机生成,加密算法使用md5,随机盐和加密后的密码都保存在数据库)

在这里插入图片描述

博客

点击具体的博客可以查看但是不可以编辑

在这里插入图片描述

书架

点击左侧的分类可以分类查看,也可以通过书名或者作者名搜索书籍,也实现了分页
在这里插入图片描述

鼠标悬停在图书封面,可以预览详细信息
在这里插入图片描述

博客管理

点击右上角的管理中心下的博客管理,可以对博客进行增删改查
在这里插入图片描述

博客编辑页面,支持快捷键(基本和大多数md编辑器一致)
在这里插入图片描述

这些工具中主要是这两个,分别是保存博客以及编辑摘要和封面
点击保存就会直接同步到数据库
在这里插入图片描述

点击编辑摘要就可以编辑摘要以及封面
在这里插入图片描述

图书管理

点击右上角的管理中心下的图书管理,可以对图书进行增删改查
在这里插入图片描述

聊天室

点击右上角的管理中心下的聊天室,可以打开聊天室的登录页

1) 登录

默认就会访问登录页,点击右上角“去注册”,会跳转带注册页,注册成功会跳转到登录页。登录成功会跳转到聊天页
在这里插入图片描述
2)注册
点击头像可以实现上传头像,之后所有头像会统一保存在D:\test\chatroom这个文件夹下,并且都会以用户的账号进行重命名。注册成功会跳转到登录页。
在这里插入图片描述
3)聊天
在输入框输入想要发送的文字信息,点击右下角的发送按钮即可发送。
点击按钮旁的向下箭头即可选择发送图片,点击图片可以在线预览全图。
左侧列表代表所有在线用户,点击就会跳转到对应的聊天窗口。
选择“所有人”,就会群发消息。
在这里插入图片描述
4)个人信息
点击导航栏的接收者昵称或者发送者昵称,都可以看到个人信息(从数据库获取),点击头像可以在线预览全图。
在这里插入图片描述

Druid

访问http://localhost:8443/druid,即可进入druid监控页面
输入用户名admin,密码123456进行登录

sql监控
在这里插入图片描述

URI监控
在这里插入图片描述

日志(保存在log/blc.log),相比于sql监控更加具体,包括参数及结果等(由于使用了jpa,所以自动生成的sql语句看起来都比较怪)
在这里插入图片描述

五、主要功能实现

1)注册

  • 流程:前端访问地址/register 进入注册页面,点击注册,后端先验证用户名是否存在,如果用户名可用则对密码进行加密后存入数据库。前端收到成功信息后跳转到/login,进入登录页面。

  • 加盐加密:在密码后面加一段随机的字符串(就是盐,由后端随机生成并且保存在数据库),然后再使用md5算法进行加密,生成的加密密码保存在数据库
    在这里插入图片描述

2)登录

  • 流程:点击登录,进入后端/login。Shiro 通过 Realm 里我们重写的 doGetAuthenticationInfo 方法获取到了验证信息,再根据我们在配置类里定义的 CredentialsMatcher(HashedCredentialsMatcher),执行doCredentialsMatch,判断两个加密后的密码是否相等(数据库中取到的以及根据前端密码进行同样加密方法后生成的)。成功后会产生 session,并自动把 sessionId 设置到 cookie。前端收到后端返回的成功代码时,触发 store 中的 login() 方法,把 loginForm 对象中的username传递给 store 中的 user 对象(改变User对象时,会存进localstorage),再看用户是否在未登录时进行了路径的请求,有的话就进行跳转。
    点击右上角的按钮可以注销,会从前后端同时删除用户信息然后跳转到登录页。

在这里插入图片描述

3)页面访问拦截

  • 流程:为防止用户通过控制台输入代码绕过前端的 “全局前置守卫”,前端要带上 sesisonId 发送请求交由后端认证。
  • sessionId 生成方法:通过在后端的方法subject.login()产生 session,并自动把 sessionId 设置到 cookie。
  • 后端拦截器,如果检测不到用户登录的信息,就会拦截所有未过滤的路径请求:
    在这里插入图片描述
  • 前端:

在main.js配置路由前置守卫,如果用户未登录则跳转到登录页
在这里插入图片描述

store/index.js(vuex):储存前端的全局变量(用户名)以及修改变量时执行的方法

在这里插入图片描述

4)角色认证

未登录时,只能访问主页;

登录时,进行角色认证:

  • 普通用户只能浏览博客和书架;
  • 管理员具有普通用户的一切权限,并且可以进行博客和书籍的管理(增删改查)。

登录后,默认记住用户登录状态30天(通过前端localstorage、vuex+后端shiro实现)。

原理是控制导航栏各选项的显示(v-if)
在这里插入图片描述

5)图片上传

  • 前端:ImgUpload组件

  • 后端:对前端传来的图片重命名为六位随机数+当前日期,然后把路径存在数据库,图片保存在D:\test文件夹(使用了虚拟路径)
    在这里插入图片描述

  • 虚拟路径:访问/api/file/实际上就是访问d:/test/
    在这里插入图片描述

  • 为什么不直接存储绝对路径? 1、绝对路径不适合移植;2、目前大多数的主流浏览器禁止直接访问本地文件。

6)聊天室

WebSocket

在这里插入图片描述

建立了WebSocket之后服务器不必在浏览器发送request请求之后才能发送信息到浏览器。这时的服务器已有主动权想什么时候发就可以发送信息到服务器。而且信息当中不必在带有head的部分信息了与http的长链接通信来说,这种方式,不仅能降低服务器的压力。而且信息当中也减少了部分多余的信息。

springboot2.0集成webSocket - 简书 (jianshu.com)

SpringBoot集成WebSocket - 仅此而已-远方 - 博客园 (cnblogs.com)

为什么不使用HTTP 协议? 因为HTTP是单工通信,通信只能由客户端发起,客户端请求一下,服务器处理一下,太麻烦了。

TCP

在这里插入图片描述
来源:百度百科

实现方法

  • 后端:由WebSocket类来实现主要功能

引入依赖spring-boot-starter-websocket,即可使用几个固定的注解。在这里插入图片描述
使用了多线程来保存每个用户的连接:(ConcurrentHashMap线程安全;避免了多个线程竞争同一把锁的情况,大大提高了性能。)

    private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();

发送消息:

item.session.getAsyncRemote().sendText(message);
  • 前端chatroom.html

html5规范中为websocket定义了一系列的API,可以直接使用。
建立连接:

this.webSocket = new WebSocket("ws://localhost:8888/websocket/" + this.sendUser);

发送消息:

 this.webSocket.send(JSON.stringify(message));
Logo

前往低代码交流专区

更多推荐