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

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

  • 项目源码
  • 摘要
  • 一、绪论
    • 1.1 课题背景、目的、意义
    • 1.2 国内外研究现状
    • 1.3 技术介绍
      • 1.3.1 Spring Boot
      • 1.3.2 MyBatisPlus
      • 1.3.3 Shiro
      • 1.3.4 Redis
      • 1.3.5 Jwt
      • 1.3.6 Vue
      • 1.3.7 Element-ui
      • 1.3.8 Axios
      • 1.3.9 前后端分离
  • 二、可行性分析
    • 2.1 技术可行性分析
    • 2.2 时间和资源可行性
  • 三、需求分析
    • 3.1 用户分析
    • 3.2 功能需求分析
    • 3.3 流程分析
  • 四、结构设计
    • 4.1 实体e-r图
    • 4.2 数据库设计
  • 五、详细设计
    • 5.1 首页布局介绍
      • 5.1.1 Header
      • 5.1.2 blogs
    • 5.2 主要功能介绍
      • 5.2.1 登录
      • 5.2.2 编辑
      • 5.2.3 详情内容
      • 5.2.4 路由权限拦截
      • 5.2.5 Controller
  • 六、系统测试
    • 6.1 登录模块测试
    • 6.2 编辑模块测试
    • 6.3 详情模块测试
    • 6.4 路由模块测试
  • 七、结论

项目源码

后端
前端

摘要

一、绪论

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中携带的信息进行验证即可,无论客户端访问后台的那台服务器,只要可以通过用户信息的验证即可。

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 流程分析

基于Spring Boot + Vue 前后端分离个人博客网站设计_第1张图片
基于Spring Boot + Vue 前后端分离个人博客网站设计_第2张图片

四、结构设计

4.1 实体e-r图

基于Spring Boot + Vue 前后端分离个人博客网站设计_第3张图片

4.2 数据库设计

  • 根据数据库逻辑模型设计,该系统需要2张表,分别是用户表(m_user)和博客表(m_blog),具体内容分别如下:
  1. 用户表(m_user)
    基于Spring Boot + Vue 前后端分离个人博客网站设计_第4张图片
  2. 博客表(m_blog)
    基于Spring Boot + Vue 前后端分离个人博客网站设计_第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时间线组件。
    基于Spring Boot + Vue 前后端分离个人博客网站设计_第6张图片
    基于Spring Boot + Vue 前后端分离个人博客网站设计_第7张图片

5.1.1 Header






5.1.2 blogs






5.2 主要功能介绍

5.2.1 登录

  • 登录模块使用了element-ui中的container布局容器(上下结构)和Form表单,初始账号和密码为吕泽江、55110,并完成表单的校验、登录按钮的点击登录事件(从返回的结果请求头中获取到令牌信息,然后使用存储提交令牌和用户信息的状态)、token的状态同步、axios拦截的任务
  • Login.vue





  • store.index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  //全局参数属性
  state: {
    token: '',
    userInfo: JSON.parse(sessionStorage.getItem("userInfo"))
  },
  //方法
  mutations: {
    // set方法
    SET_TOKEN: (state, token) => {
      state.token = token
      //本地存储
      localStorage.setItem("token", token)
    },
    SET_USERINFO: (state, userInfo) => {
      state.userInfo = userInfo
      //会话存储
      sessionStorage.setItem("userInfo", JSON.stringify(userInfo))
    },
    REMOVE_INFO: (state) => {
      state.token = ''
      state.userInfo = {}
      localStorage.setItem("token", '')
      sessionStorage.setItem("userInfo", JSON.stringify(''))
    }
  },
  getters: {
    // get方法
    getUser: state => {
      return state.userInfo
    }

  },
  actions: {
  },
  modules: {
  }
})

  • Axios.js
import axios from 'axios'
import Element from 'element-ui'
import router from './router'
import store from './store'

//全局前缀url
axios.defaults.baseURL = "http://localhost:8081"

//前置拦截(请求访问)
axios.interceptors.request.use(config => {
    return config
})

//后置拦截(弹窗提示)
axios.interceptors.response.use(response => {
        let res = response.data;
        //前
        console.log("=================")
        //内容
        console.log(res)
        //后
        console.log("=================")

        if (res.code === 200) {
            //正常则返回并跳转至login登录
            return response
        } else {
            //错误弹窗(element组件message消息提示),设置超时时间自动消失
            Element.Message.error('错了哦,这是一条错误消息', {duration: 3 * 1000})
            //阻止请求继续,结束login登录逻辑
            return Promise.reject(response.data.msg)
        }
    },
    //报错进入error逻辑
    error => {
        console.log(error)
        if(error.response.data) {
            //根据返回的信息赋值
            error.message = error.response.data.msg
        }

        if(error.response.status === 401) {
            store.commit("REMOVE_INFO")
            router.push("/login")
        }
        //获取message信息,并阻止请求
        Element.Message.error(error.message, {duration: 3 * 1000})
        return Promise.reject(error)
    }
)

5.2.2 编辑

  • 编辑模块使用了基于Vue的markdown编辑器mavon-editor,整合了element-ui中的Form表单组件和messagebox弹窗组件,展示了标题、摘要、内容
  • BlogEdit.vue





5.2.3 详情内容

  • 详情模块整合了element-ui中的border组件、divider分割线组件和link文字链接,回显博客信息,将md格式的内容渲染后显示出来,于是使用markdown-it插件,用于解析md文档,然后引入github-markdown-c,另外添加了编辑按钮,并通过ownBlog判断是否时本人编辑,否则不显示编辑按钮
  • BlogDetail.vue





5.2.4 路由权限拦截

  • 路由权限模块控制某些页面(添加、编辑)需要登录之后才能更改,如果未登录访问就直接跳转到登录界面,完成登录后才能进行后续工作
  • permission.js
import router from "./router";

//路由判断登录,根据路由配置文件的参数
router.beforeEach((to, from, next) => {

    if (to.matched.some(record => record.meta.requireAuth)) { // 判断该路由是否需要登录权限

        const token = localStorage.getItem("token")
        console.log("------------" + token)

        if (token) { // 判断当前的token是否存在;登录存入的token
            if (to.path === '/login') {
            } else {
                next()
            }
        } else {
            next({
                path: '/login'
            })
        }
    } else {
        next()
    }
})

5.2.5 Controller

  • 后端controller控制用户身份、权限、博客属性
  • AccountController
package com.lvzejiang.controller;

import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lvzejiang.common.dto.LoginDto;
import com.lvzejiang.common.lang.Result;
import com.lvzejiang.entity.User;
import com.lvzejiang.service.UserService;
import com.lvzejiang.util.JwtUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

//登录接口设置
@RestController
public class AccountController {

    @Autowired
    UserService userService;

    @Autowired
    JwtUtils jwtUtils;

    /**
     * 默认账号:吕泽江
     * 默认密码:55110
     *
     */
    @PostMapping("/login")
    //body中获取loginDto
    public Result login(@Validated @RequestBody LoginDto loginDto, HttpServletResponse response) {
        //查询用户
        User user = userService.getOne(new QueryWrapper().eq("username", loginDto.getUsername()));
        //Assert断言异常处理
        Assert.notNull(user, "用户不存在");
        //判断密码是否正确
        if(!user.getPassword().equals(SecureUtil.md5(loginDto.getPassword()))){
            return Result.fail("密码不正确");
        }
        //密码正确则生成jwt(利用jwtUtils工具)
        String jwt = jwtUtils.generateToken(user.getId());
        //将jwt返回给Header
        response.setHeader("Authorization", jwt);
        response.setHeader("Access-control-Expose-Headers", "Authorization");
        //封装结果
        return Result.succ(MapUtil.builder()
                .put("id", user.getId())
                .put("username", user.getUsername())
                .put("avatar", user.getAvatar())
                .put("email", user.getEmail())
                .map()
        );
    }

    //退出接口设置
    //认证权限
    @RequiresAuthentication
    @GetMapping("/logout")
    public Result logout() {
        SecurityUtils.getSubject().logout();
        return Result.succ(null);
    }

}
  • BlogController
package com.lvzejiang.controller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lvzejiang.common.lang.Result;

import com.lvzejiang.entity.Blog;
import com.lvzejiang.service.BlogService;
import com.lvzejiang.util.ShiroUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

/**
 * 

* 前端控制器 *

* 博客接口 * @author 172055110吕泽江 * @since 2020-06-13 */ @RestController public class BlogController { @Autowired BlogService blogService; //列表页(分页) @GetMapping("/blogs") public Result list(@RequestParam(defaultValue = "1") Integer currentPage){ //每页3条内容 Page page = new Page(currentPage, 3); IPage pageData = blogService.page(page, new QueryWrapper().orderByDesc("created")); return Result.succ(pageData); } //详情页(通过查询id) @GetMapping("/blog/{id}") public Result detail(@PathVariable(name = "id") Long id){ Blog blog = blogService.getById(id); Assert.notNull(blog, "该文章已被删除"); return Result.succ(blog); } //编辑文章 //设置权限,登录之后才能编辑 @RequiresAuthentication @PostMapping("/blog/edit") public Result edit(@Validated @RequestBody Blog blog){ Blog temp = null; //查询Id,有则为编辑状态,无则为添加状态 if(blog.getId() != null) { temp = blogService.getById(blog.getId()); // 只能编辑自己的文章 System.out.println(ShiroUtil.getProfile().getId()); //调用ShiroUtil方法,返回Assert断言异常 Assert.isTrue(temp.getUserId().longValue() == ShiroUtil.getProfile().getId().longValue(), "没有权限编辑"); } else { temp = new Blog(); temp.setUserId(ShiroUtil.getProfile().getId()); temp.setCreated(LocalDateTime.now()); temp.setStatus(0); } //编辑保存更新 BeanUtil.copyProperties(blog, temp, "id", "userId", "created", "status"); blogService.saveOrUpdate(temp); return Result.succ(null); } }
  • UserController
package com.lvzejiang.controller;


import com.lvzejiang.common.lang.Result;
import com.lvzejiang.entity.User;
import com.lvzejiang.service.UserService;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 

* 前端控制器 *

* * @author 172055110吕泽江 * @since 2020-06-13 */ @RestController @RequestMapping("/user") public class UserController { @Autowired UserService userService; //认证登录 @RequiresAuthentication @GetMapping("/index") public Result index() { User user = userService.getById(1L); //查询id为1的用户 return Result.succ(user); //Result结果封装 } @PostMapping("/save") //Validated校验 public Result save(@Validated @RequestBody User user) { return Result.succ(user); } }

六、系统测试

6.1 登录模块测试

基于Spring Boot + Vue 前后端分离个人博客网站设计_第8张图片
基于Spring Boot + Vue 前后端分离个人博客网站设计_第9张图片

6.2 编辑模块测试

基于Spring Boot + Vue 前后端分离个人博客网站设计_第10张图片

6.3 详情模块测试

基于Spring Boot + Vue 前后端分离个人博客网站设计_第11张图片

6.4 路由模块测试

基于Spring Boot + Vue 前后端分离个人博客网站设计_第12张图片
基于Spring Boot + Vue 前后端分离个人博客网站设计_第13张图片

七、结论

  • 该系统前端是基于Vue框架的交互页面,其组件使用了Element组件,有着很好的视觉感,而且凭借其单页面应用的优势,当用户在浏览时几乎无需等待就可以 跳转到其它页面。后台使用SpringBoot和MyBaitsPlus框架来开发,能够极大的减少前台后台和后台数据库的耦合性,减轻了后期维护的负担。课题从开始到结束,一路上遇到了不少的困难和坑,因为以前所开发过的项目 基本都是后台管理系统,并且前端会使用现成的模板,但这次要同时开发前端和后端,不仅仅是 Java 语言和数据库语言就足够,还要去深入学习前端框架的语法并且考虑前端页面如何布局,组件如何使用,怎样使得前端页面能够简单的与用户进行交互,要尽可能的去减少前端和业务逻辑相关联的代码,一定程度上考虑系统的安全性。
    当然本次课设只是一个起点,后续工作还有很多,这次对于数据的开发实现并没有做很多深入工作,只是建立本人用户与密码,另外创建了小组6个成员实体,以及一个博客端数据库,单看数据库的话,你会觉得不是很“庞大”,但我有自己的看法,我认为此次的开发主要在于前后端的建设,数据库只是一个简单的套用,前端的vue、element-ui、axios,以及后端springboot、mybatisplus、shiro、redis、jwt等的运用才是本次课程设计的主攻方向与学习方向,所以本次课程设计对数据库的开发耗时很短,大部分时间用来完成前后端的学习。
    通过此次课程设计,也很好的加强了自己的学习能力,充分发挥自己的思维,对相关技术进行深入了解,以便于快速适应不断的BUG,当然,对自己的不足也有了全面的认识,在遇到困难时也能够快速的定位到问题出错的位置并且能够独立的解决这些问题,这对于今后的工作都有着极其重要的意义。
    另外,项目只是单纯的在本地运行(Windows),后续还会进行Linux服务器集群的测试开发,当然这次课程设计尽管不做类似要求,但整个项目要有始有终,后续的学习不会停下脚步,未完待续……

你可能感兴趣的:(个人博客网站设计)