springboot前后端分离项目(图书+博客+聊天室)
1、项目简介基于Vue CLI4 + SpringBoot开发的前后端分离项目。主要功能:博客、书架、聊天室。参考项目:https://github.com/Antabot/White-Jotterhttps://github.com/Tellsea/springboot-learn/-/tree/master/springboot-websocket本项目地址:码云:https://gitee.
一、项目简介
项目名称: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)前端
- Vue CLI4
- ElementUI
- axios
2)后端
- Spring Boot 2.1.3.RELEASE
- Apache Shiro
- Apache Log4j +Alibaba Druid(http://localhost:8443/druid/)
- Spring Data JPA
- Lombok
3)数据库
- MySQL 8.0.26
4)开发环境
-
IDEA 2019.1
-
JDK 1.8.0_191
-
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));
更多推荐
所有评论(0)