基于Spring Boot + Vue 前后端分离个人博客网站设计

项目源码

后端
前端
JDK8

摘要

一、绪论

1.1 课题背景、目的、意义

  • “博客”(Blog或Weblog)一词源于“Web Log(网络日志)”的缩写,就是一种十分简易的傻瓜化个人信息发布方式。任何人都可以像使用免费电子邮件一样,完成个人网页的创建、发布与更新。博客就就是开放的私人空间,可以充分利用超文本链接、网络互动、动态更新等特点,在网络中,精选并链接全球互联网中最有价值的信息、知识与资源;也可以将个人工作过程、生活故事、思想历程、闪现的灵感等及时记录与发布,发挥个人无限的表达力;更可以以文会友,结识与汇聚朋友,进行深度交流沟通。 
    在没有自己的博客之前,人们会经常进出于论坛发表贴子或者通过即时通信软件聊天,来表达自已的想法,可就是这些都就是零散的与杂乱的。博客的出现,让人们可以不断的把自己以前的与每天激发的一些想法或者感受整理放在自己的博客上,每次在写文章的时候,可能又会产生新的想法。虽然一些想法一些思考只就是皮毛,没有什么深度,但就是当下笔去写的时候每次都会对某个小小的问题有了更多的一点点思考,再写博客的时候就感觉到了一种满足感,一种想法得以释放思考得以延伸的满足感。生活中每天的一个小小的事情都会引起人们的思考,甚至就是与朋友的聊天中一个小小的火花迸发。督促自己努力、把一时的想法变成观点,争取在生命中的每天里留下点什么,这也就是人们写博客的目的之一。这样就能督促自己每一天不要浑浑噩噩,时光流逝无痕无声无息,写博客也就是在自己的每一天上留下了一道浅浅的思考与划痕。

1.2 国内外研究现状

  • 以博客的命名起源于1999年,2001年9.11事件,博客正式步入主流社会的视野。博客为人们提供了最具影响力交流互动平台,是继Email、BBS、QQ之后新兴的第四种网络交流方式,已经成为最强劲的互联网新兴媒体的代表。由于具有丰富的娱乐形式和自由的个人表达方式,博客成为新人群竞相追逐的一种时尚。2006年4月21日,数据显示:2005中国的网民数已超过1亿人,网民数位居世界第二。其中,到去年底,中国博客规模已经达到1600万,全球博客总规模突破1亿。第一批中文博客是在2002年出现的,早些时候博客只是一个新的网络名词并无特殊之处,就在不经意间,博客竟如雨后春笋般冒出来,博得越来越多网民的欢心,并在互联网上引发了一股博客热潮。目前国内知名的博客有:新浪博客,搜狐博客,CSDN博客等等。当今时代是计算机时代,人们的工作大部分都依赖计算机。数字化的世界里,人与人的交流也慢慢的数字化,而博客网站正适应这种人际交流方式的改变,迎合个人信息共享的需求它就是个人信息发布的场所,是人与人沟通的一个聚集地。

1.3 技术介绍

1.3.1 Spring Boot

  • 该次系统的Java后台用到的技术主要是 Spring Boot框架技术,Spring Boot 可以 说是现在一种成熟的Java框架了,对于使用过Spring MVC的人来讲最让人头疼的事情莫过于就是大量的配置文件,稍有不慎便会导致配置错误。Spring Boot的出现就大大的简化这一个过程。该项技术通过在.properties或者.yaml全局配置文件中直接配置经由框架简化过的配置信息就可以完成配置,这一过程的原理则是自动配置,自动装配则是根据Spring Boot框架自带的注解类得以实现,将这一过程凝缩成一句话那便是约定大于配置。在使用Spring Boot的过程中要对其框架中的注解有明确的认识,对Spring Boot 框架是如何运行的有一个大概的认识。而且此框架整合了Spring MVC和Tomcat等三方包,无需开发者特殊配置就可以拿来直接使用,而且也省去了Tomcat的单独配置,如需还引入其他非内置的三方包可以通过maven仓库直接下载,并且在其他项目中也可以将下载过的三方包通过两行配置直接拿来使用。除此之外,Spring 官方旗下还有很多其他的框架可以拿来和 Spring Boot 进行整合,如Spring cloud 微服务框架等,这些 Spring 全家桶的各种框架只需要使用 maven 简单的引入,按照官方步骤就可以实现其专用的功能.

1.3.2 MyBatisPlus

  • MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。开发平台服务,由于原来操作都是使用模拟实现,但是真实项目肯定要访问数据操作,并且每个domain都有crud,需多次写重复代码。我们使用MybatisPlus,就不用写重复代码,并且还有模板的功能,可以一键生成daomin,query,mapper接口,mapper.xml,service,controller,非常好用。MyBatis-Plus具有无侵入、损耗小、强大的CRUD操作、支持Lambda形式调用、支持主键自动生成、支持ActiveRecord模式、支持自定义全局通用操作、内置代码生成器、内置分页插件、内置性能分析插件、内置全局拦截插件等特性。

1.3.3 Shiro

  • Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。Shiro具有三个核心组件:Subject, SecurityManager 和 Realms.
    Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
      SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
      Realm:Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

1.3.4 Redis

  • Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
    Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
    Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

1.3.5 Jwt

  • Json Web Token简称JWT,在HTTP通信过程中,进行身份认证。HTTP通信是无状态的,因此客户端的请求到了服务端处理完之后是无法返回给原来的客户端。因此需要对访问的客户端进行识别,常用的做法是通过session机制:客户端在服务端登陆成功之后,服务端会生成一个sessionID,返回给客户端,客户端将sessionID保存到cookie中,再次发起请求的时候,携带cookie中的sessionID到服务端,服务端会缓存该session(会话),当客户端请求到来的时候,服务端就知道是哪个用户的请求,并将处理的结果返回给客户端,完成通信。
    session存在的问题:session保存在服务端,当客户访问量增加时,服务端就需要存储大量的session会话,对服务器有很大的考验;当服务端为集群时,用户登陆其中一台服务器,会将session保存到该服务器的内存中,但是当用户的访问到其他服务器时,会无法访问,通常采用缓存一致性技术来保证可以共享,或者采用第三方缓存来保存session,不方便。
    Json Web Token实现过程:客户端通过用户名和密码登录服务器;服务端对客户端身份进行验证;服务端对该用户生成Token,返回给客户端;客户端将Token保存到本地浏览器,一般保存到cookie中;客户端发起请求,需要携带该Token;服务端收到请求后,首先验证Token,之后返回数据。服务端不需要保存Token,只需要对Token中携带的信息进行验证即可,无论客户端访问后台的那台服务器,只要可以通过用户信息的验证即可。
    链接: Jwt

1.3.6 Vue

  • Vue,一套由我们国人开发的前端框架,它的前身可以说是Angular,但在此基础上弥补了很多它的不足之处。它是一套基于JavaScript的渐进式的框架,这里的渐进式个人理解来说就是并不强制你使用它所有的东西,你可以按需所取。它用来构建用户界面以及处理界面数据,此框架关注的是视图层,系统的业务逻辑会交由后端来处理。Vue框架的核心是Model-View-ViewModel,Model指的是后台所接收的数据,View则是展现给用户的界面,ViewModel则是将Model与View联系起来,使两者之间能有着动态的联系。Vue还有一个特别方便的地方是双向数据绑定,我们可以简单的操作DOM,不用像使用jQuery那样为了改变某一个标签的内容而进行一长串的字符串拼接操作。Vue还是一个单页面应用的框架,它的页面布局采用的是组件的概念,它可以将所有的页面都定义在一个html页面之中,尽管听起来会这个页面会很复杂,但其实使用之后就会发现它的组织方式并没有想象中的那么混乱,因为它相当于是把很多的页面分别作为组件而放到了一个页面中。而且它切换页面的速度用肉眼来讲也是极快的,用户在页面跳转时无需等待,使得整个页面更加的流畅,究其原因是因为前端的项目在用户第一次加载的时候就已经将所有的组件都已经事先加载了一遍,所以在之后的页面跳转过程中可以很顺畅,因此我们可以想到当前端页面较大时,第一次加载所耗费的时间是不少的,因此Vue框架一般是适用于中小型项目的搭建。

1.3.7 Element-ui

  • Element-Ul是饿了么前端团队推出的一款基于Vue的桌面端UI框架,它不依赖于vue,但是却是当前和vue配合做项目开发的一个比较好的ui框架。它提供了丰富的PC端组件,减少用户对常用组件的封装,降低了开发的难易程度。

1.3.8 Axios

  • axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有如下特征:从浏览器中创建 XMLHttpRequest;从 node.js 发出 http 请求;支持 Promise API;拦截请求和响应;转换请求和响应数据;取消请求;自动转换JSON数据;客户端支持防止 CSRF/XSRF。

1.3.9 前后端分离

  • 前后端分离技术,其目的是解耦,在过去的 web 开发中,jsp 技术给人的印象并不是很好,某一个模块出了问题或者需要维护更新,可能要从数据库一直修改到jsp页面,jsp页面是一种侵入式的,最令人头疼的是servlet层和jsp页面的修改,要寻找到对应的变量然后在两个文件中不停的修改,这就造成了web页面的内容和servlet层内容的耦合,是不利于后期维护的。前后端分离技术,某种程度上来讲就是前端页面负责与用户交互、接收数据和发送请求,后台进行业务逻辑处理,进行相关的数据库 操作,在后期的维护过程中,不会出现jsp页面那样两种语言穿插在一个页面中的现象。对于开发人员来说分工也更加的明确。

二、可行性分析

2.1 技术可行性分析

  • 本课题从系统的前后端来看,前端使用的是流行的Vue框架 + element-ui组件, Vue 和当前流行的其他两大框架(Angular 和 React)相比更加容易上手和学习,入门门槛相对较低一些,这也是Vue框架设计的初衷之一。element-ui组件是一套类似于 layUI 的前端样式组件库,它支持Vue的语法,可以在Vue的框架内引入后直接使用;后端的 Spring Boot框架是近年来备受Java开发者好评的框架,通过使用 IDEA 这样的开发工具,只需要几步操作就可以完成框架的搭建。

2.2 时间和资源可行性

  • 该系统从时间上来讲,除去准备工作和学习前端语法的事件,一般2-4天可以完成一个模块(前端+后端)的开发。资源方面来看,只需要在Windows环境下进行开发和测试就可以完成;开发和测试的工具选用Intellij IDEA、Navicat for MySQL、Postman、PowerDesigner和Chrome浏览器,这些工具的安装使用较为简单,上手很轻松。

三、需求分析

3.1 用户分析

  • 该系统初始创建了本组6个成员用户于数据库中,每个成员有对应的ID,统一使用指定ID和密码进行博客登录,且用户昵称、邮箱不为空,另外对用户做了权限认证,陌生用户需要进行后台审核添加,否则提示用户不存在,用户登录之后可以对博客进行查看、添加、编辑、删除等操作。

3.2 功能需求分析

  • 用户向后端提交用户名与密码,后端进行校检,错误则抛出异常,成功则生成jwt,并返回给用户作为身份凭证,用户访问接口,jwtFilter进行过滤,及登录处理,检测到无jwt则交给controller执行,有jwt,通过shiro处理,异常则抛出异常,进行GlobalExceptionHandler全局异常捕获,正常则交给controller执行,注解过滤时,无权限则抛出异常,并进行GlobalExceptionHandler全局异常捕获,有权限则交给controller执行,登录成功后,用户可以执行发表、编辑等操作,router进行路由处理,内容可以完成回显,未登录的用户进行相关操作则会回退到登陆界面指定登录后才能进行权限执行,编辑博客时运用了md编辑渲染,使得整体展示效果更为完美。

3.3 流程分析

1
2

四、结构设计

4.1 实体e-r图

3

4.2 数据库设计

  • 根据数据库逻辑模型设计,该系统需要2张表,分别是用户表(m_user)和博客表(m_blog),具体内容分别如下:
  1. 用户表(m_user)
    4
  2. 博客表(m_blog)
    5

五、详细设计

  • 后端
    后端以SpringBoot为基础,整合了MybatisPlus作为数据层框架,并且使用mybatisplus codegenerator根据数据库表生成相应的类,另外整合了shiro(shiroconfig)并使用jwt作为前后端分离的身份凭证,所以使用JwtFilter将jwt封装成JwtToken,再将JwtToken传到自定义的AccountRealm中进行数据库的匹配,完成之后将信息返回给shiro,则可以登录成功,之后进入到相应的接口controllor,并给接口controllor设置相应的权限,没有定义权限则可以公开访问,定义权限@RequiresAuthentication则需要认证才能访问。另外在JwtFilter和CorsConfig设置跨域问题的处理,在GlobalExceptionHandler进行全局异常的处理,根据每一种不同的异常返回相应的数据。最后进行统一结果的封装Result
  1. springboot整合mybatisplus
  2. 利用mybatis代码生成
  3. 整合shiro+redis,会话共享
  4. 整合jwt,身份校检
  5. 统一结果封装
  6. 解决跨域问题
  7. 登录、博客接口开发
  • 前端
    前端以Vue为基础,整合了element-ui组件、axios HTTP库,完成前端页面渲染以及路由功能
  1. vue整合element-ui、axios
  2. 登录页面
  3. 博客页面
  4. 编辑、展示内容

5.1 首页布局介绍

  • 首页采用element-ui中的container布局容器的上下结构来布局,主要展示了Header(存在于所有页面)和blogs,其中Header包含标题、头像、用户名,使用了element中的avatar头像组件、divider分割线组件和link文字链接;blogs包含用户ID、标题、摘要、创建时间,运用了element-ui中的pagination分页组件和timeline时间线组件。

5.1.1 Header

<template>
    <div class="m-content">
        <h3>欢迎来到172055110吕泽江的博客</h3>
        <div class="block">
            <el-avatar :size="50" :src="user.avatar"></el-avatar>
            <div>{
   {
    user.username }}</div>
        </div>

        <div class="maction">
            <span><el-link href="/blogs">主页</el-link></span>
            <el-divider direction="vertical"></el-divider>
            <span><el-link type="success" href="/blog/add">发表博客</el-link></span>
            <el-divider direction="vertical"></el-divider>
            <span v-show="!hasLogin"><el-link type="primary" href="/login">登录</el-link></span>
            <span v-show="hasLogin"><el-link type="danger" @click="logout">退出</el-link></span>
        </div>
    </div>
</template>

<script>
    export default {
   
        name: "Header",
        data() {
   
            return {
   
                user: {
   
                    username: '请先登录',
                    avatar: 'https://profile.csdnimg.cn/E/6/0/2_lvjzzz\n'
                },
                //默认未登录
                hasLogin: false
            }
        },
        methods: {
   
            //退出方法
            logout() {
   
                const _this = this
                //发起请求
                _this.$axios.get("/logout", {
   
                    headers: {
   
                        "Authorization": localStorage.getItem("token")
                    }
                }).then(res => {
   
                    //移除信息
                    _this.$store.commit("REMOVE_INFO")
                    //跳转至登录页面
                    _this.$router.push("/login")
                })
            }
        },
        //回写,获取store信息
        created() {
   
            if(this.$store.getters.getUser.username) {
   
                //用户信息不为空则回写内容
                this.user.username = this.$store.getters.getUser.username
                this.user.avatar = this.$store.getters.getUser.avatar
                this.hasLogin = true
            }

        }
    }
</script>

<style scoped>
    .m-content {
   
        max-width: 960px;
        margin: 0 auto;
        text-align: center;
    }
    .maction {
   
        margin: 10px 0;
    }
</style>

5.1.2 blogs

<template>
    <div class="mcontaner">
        <Header></Header>
        <div class="block">
            <el-timeline>
                <el-timeline-item :timestamp="blog.created" placement="top" v-for="blog in blogs">
                    <el-card>
                        <h4>
                            <router-link :to="{name: 'BlogDetail', params: {blogId: blog.id}}">
                                {
   {
   blog.title}}
                            </router-link>
                        </h4>
                        <p>{
   {
   blog.description}}</p>
                    </el-card>
                </el-timeline-item>
            </el-timeline>
            <el-pagination class
  • 18
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jayco-J

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值