个人博客系统(前后端分离)

news2024/11/26 2:21:39

努力经营当下,直至未来明朗!

文章目录

  • 一、项目简介
  • 二、项目效果
  • 三、项目实现
    • 1. 软件开发的基本流程
    • 2. 博客系统 需求分析
    • 3. 博客系统 概要设计
    • 4. 创建maven项目
    • 5. 编写数据库操作的代码
  • 四、项目代码
  • 总结


普通小孩也要热爱生活!

一、项目简介

个人博客系统采用前后端分离的方法来实现,同时使用了数据库来存储相关的数据,同时使用tomcat进行项目的部署。前端主要有四个页面构成:登录页、列表页、详情页以及编辑页,以上模拟实现了最简单个博客列表页面。其结合后端实现了以下的主要功能:登录、编辑博客、注销、删除博客、以及强制登录等功能。
但是该项目没有设计用户注册功能,只能提前在数据库中存储用户信息后经过校验登录;并且用户头像不能自己设定,在进行前端页面的书写过程中已经将头像的图片写为静态了;而用户信息中的文章数以及分类数也没有在后端中具体实现,直接在前端页面中写为了静态的。


二、项目效果

必须在开着tomcat的情况下才能进行以下页面的操作。

  1. 登录页面
    在这里插入图片描述

  2. 列表页面 / 主页
    1

  3. 博客详情页
    2

  4. 编辑页
    3


三、项目实现

1. 软件开发的基本流程

① 可行性分析;
② 需求分析:明确程序要解决什么问题,做成啥样,都有啥功能。(实际开发中是产品经理制定的)
③ 概要设计
④ 详细设计
⑤ 编码
⑥ 测试
⑦ 发布

2. 博客系统 需求分析

① 实现博客列表页的展示功能
② 实现博客详情页的显示功能
③ 登录功能(暂时不实现注册)
④ 限制用户权限(强制要求登录)
⑤ 显示用户信息
⑥ 实现注销(退出登录)
⑦ 发布博客
⑧ 删除博客

3. 博客系统 概要设计

(写代码要“谋定而后动”)
其实这里主要是【数据库设计】

当前我们的业务比较简单,只需要两个表:

① 博客表blog(blogId,title,content,postTime,userId)
② 用户表user(userId,userName,password) (其中Gitee地址以及文章分类这样的功能先不考虑)

4. 创建maven项目

注:① auto-increment是从1开始的
② text的大小是64kb,博客内容一般不太会超过64kb,而博客中的截图不是和文本一起存储的。

5. 编写数据库操作的代码

  1. 引入依赖:servlet3.1.0、mysql5.1.49、jackson2.13.4.1
  2. 封装数据库的DataSource(单例模式+线程安全)
    除了封装DataSource,把数据库的建立连接、断开连接也都进行封装。

补:
① ctrl+alt+t:surround功能
② Connection是 java.sql.Connection,不是 java.mysql.Connection

  1. 在关闭释放资源的时候,写法一是将三个需要释放的连接分别try…catch, 写法二是三个需要释放的连接只使用 一个try…catch连接。

写法一更好。
理由:写法一里如果某个环节抛出异常,不影响继续执行后续的close操作。而写法二一旦出现异常就会进入catch,此时后续的close就执行不到了,会造成资源泄露。
(直接抛出异常throws也是同理写法二,会造成资源泄露。)

  1. 根据需求创建实体类
    一个实体类对象就对应表里的一条记录。

实体类怎么写?
——表结构怎么写,实体类就怎么写。

mysql中的datetime和timestamp类型都是在java中使用TimeStamp表示的。

  1. 针对上述实体类涉及到的 增删改查 进行进一步的封装,也就是把jdbc代码封装一下。
    Dao: Data Access Object
    访问数据库的操作就可以使用这几个Dao对象来进行。

statement.executeUpdate(); 返回的数据表示影响到几行

  1. 进行前后端交互
    让页面发起http请求,服务器返回http响应。(需要约定好http请求是啥样的,响应是啥样的)
    1)博客列表页:
    ① 不要写死数据,而是让页面从数据库中获取到当前的博客列表。

(先将前端的所有相关文件粘贴到webapp目录下)

② 页面在加载的时候,通过ajax发起http请求,从服务器获取到博客列表数据。
在这里插入图片描述

③ 当web出现问题的时候,首先想到的就是“抓包”,看是前端原因还是后端原因。(如果有的没有抓取到就进行强制刷新ctrl+f5

注:fiddler中出现的favicon是浏览器发送的请求,是获取页面图标的,如果该网站没有图标就会出现404
10

① 在前后端分离的程序中,获取页面和获取页面中的数据是分开的请求。
② 如果是只有页面没有数据,且抓包也抓不到获取数据的请求,那就说明是前端代码出问题了,前端没有正确发送ajax请求。

注:方法只有被调用之后才会生效!!
一定要仔细!!保证不会出现空指针异常!!

问题以及解决
① 我们想要呈现的是格式化的时间,但是会发现此时出现的是时间戳!
11
原因

通过抓包查看发现服务器返回的响应数据就是一个时间戳
12
服务器代码中,是将从mysql数据库中查询到的时间放到了postTime这个属性中,然后又通过jackson将其转为json字符串返回;即:在转json的过程中,将其变为了时间戳。
13

解决方法

那么jackson是如何获取到Blog对象中的时间戳的? 通过getter方法来获取的。
15

所以就魔改getter方法,让该方法返回一个String,而不是TimeStamp。String就是一个格式化好了的时间日期!
16

① 这个SimpleDateFormat类可以将时间戳转为格式化的时间!
(使用示例可以参考:SimpleDateFormat类使用)
17
② 需要把时间戳转成格式化时间,具体啥格式需要在构造方法中进行指定!
③ (参数格式可以自己指定,但是具体字母时不能改变的,每个都有自己的含义,如MM表示月份,mm表示分钟,具体的参数含义在使用的时候自己上网确认!)

18
(格式化时间日期)


② 另外,又发现问题:列表中的文章顺序应该是最近发布的在最上面,但是目前是按先发布排上面的顺序来排列的。
20

所以,解决方法:在查询的时候加上个排序。
21


③ 此时,如果插入的博客内容比较长的话就会占据很大篇幅的列表页,因为把整个正文篇幅都显示出来了;但是按理来说,博客列表页要显示的是正文的 “摘要”信息

22
(长文)

解决方法
针对博客的列表页中的内容进行截断,长度达到一定数值就取出一部分子串。(长度自己规定就ok)
23

25
(效果)

【注】当我们的程序出现了问题,该如何动手解决?

① 一定要梳理清楚出现问题的代码的流程
② 能够找到相关代码 (调试,不是对照着找!!)


2)实现博客详情页
① 点击查看全文就会跳转到详情页,并且看到详情页中对应的博客正文。

② 处理方式:
点击查看全文,此时就会发起一个get请求,该请求是在请求blog_detail.html这个页面;此时还需要告诉服务器我们请求的是哪个博客!
约定:在请求页url中加上query string来进行具体哪个博客的标识。(在生成“查看全文”按钮的时候就已经添加了query string进行标识了)
28

③ 进入博客详情页之后,需要让博客详情页再次发起ajax请求,向服务器获取到当前blogId对应的博客内容;再由博客详情页将拿到的数据添加到浏览器页面上。

④ 操作步骤:
1)约定前后端交互接口
在博客详情页中发起ajax请求,获取到具体的博客内容。
29
2)实现服务器代码
按照上述约定来返回数据

3)实现客户端代码
让页面发起的ajax请求来获取到博客数据

location.search 用来获取query string
30

(每次修改代码都要重启服务器)

但是会发现当点击“查看全文”后,所跳转的页面还是之前的结果,这是触发了浏览器的缓存

① 理由:
浏览器需要通过网络从远程服务器获取到当前的页面数据,可能比较耗时;此时为了提高效率,做法就是让浏览器把必要的数据进行缓存;下次访问就不必访问网络了,而是直接读取缓存。
② 做法:
所以,为了保证数据从网络上获取就需要进行强制刷新ctrl+f5.

如果发现前端页面有问题,就fn+f12调出控制台查看异常情况。

补充:
① VS里的编译器是cl.exe, IDEA的编译器是javac… 编译器一般都是命令行的。
②IDE是集成开发环境, IDE != IDEA


问题

① 博客正文期待是markdown格式的(毕竟博客编辑页是一个markdown编辑器,提交的数据是markdown格式的,数据库中存储的也是markdown格式的,所以最终显示也应该是markdown格式的结果)
31
② 显示结果是纯文本(不符合预期,预期是渲染过的markdown)
32

解决方法
使用editor.md这个库来完成渲染。
在blog_detail.html中引入editor.md依赖
33
35

36
(渲染之后)

如果想要内容的背景显示半透明效果,修改设置一下就ok。

37
(这个效果不好)

39
(transparent的意思就是让当前元素完全应用父元素的背景)


3)博客登录
登录逻辑

① 用户访问login.html,输入用户名和密码
② 点击登录按钮后发起一个请求,将用户名和密码提交给服务器
③ 服务器对身份进行验证,验证成功就跳转到博客详情页

① 约定前后端接口
40
(注:请求再前端,响应在后端)

② 编写前端代码

41
一定要指定name属性,为了与键值对中的键对应!
43

③ 编写后端代码
LoginServlet


4)实现在博客列表页、详情页和编辑页中强制登录后才能访问。(常见)

业务逻辑

在博客列表页、详情页和编辑页中,都在页面加载时发起一个ajax请求,这个ajax请求就是从服务器获取当前的登录状态。如果当前是未登录就直接重定向到登录页面,如果是已经登录则不做任何处理。

① 前后端交互接口:
50
② 前端代码:判定状态码是200还是403,如果是200就无事发生,403就强行跳转
51

③ 后端代码:
只是单纯的查看当前用户是否为登录状态,即:获取会话以及里面的user对象,如果能拿到就已经登录过返回200,否则返回403.
52

因为 登录限制及跳转 在很多页面中都使用,但是我们没必要进行重复性的工作,所以直接在前端代码中新建一个文件夹js,并新建文件 app.js 来存储这些重复的代码,以此来实现代码的复用。


5)在列表页和详情页中动态显示用户信息

逻辑设定

① 博客列表页:在页面进行加载的同时从服务器获取当前登录的用户信息,并把该信息显示到页面上。
② 博客详情页:在页面进行加载的同时从服务器获取博客作者用户信息,并把该信息显示到页面上。

① 前后端交互接口:
55
② 编写后端代码

56
(使用了两次sql查询,其实是可以使用一条sql搞定的:联合查询 or 子查询)

③ 编写前端代码
57

小结】写web程序套路
其实以上实现的功能所做的事情都差不多:

① 业务逻辑梳理
② 设计前后端交互
③ 编写前端代码:基本上是ajax(发请求)+ dom(根据请求显示到页面上)操作
④ 写后端代码:基本上就是servlet + jdbc + jackson操作
(前后端编写代码顺序不定)

补充:
① 图片存入数据库其实存的是图片的路径,而图片是以文件的形式存到硬盘上。
② 不太建议将图片直接存入数据库,图片是二进制数据,对于关系型数据库是不太友好的。


6)注销(退出登录状态)
Windows的注销其实也就是退出登录状态sign out。

业务逻辑

① 在博客列表页/详情页/编辑页的导航栏里都有 注销 按钮,并且我们的实现方式是一个a标签,点击的时候就会给服务器发送一个http请求(不是ajax,但是如果想要使用ajax做也是OK的)
② 发送的http请求就是告诉服务器咱们要退出登录了,服务器就会把对话中的user对象给删除,同时重定向到登录页。
③ 注:删除的是会话中的user对象而不是HttpSession对象,因为HttpSession没有一个直接用于删除的方法(Servlet没有提供),虽然可以通过设置过期时间的方式来删除会话,但是并不是一个好的选择;另外,我们在实现判定登录状态的条件是HttpSession存在&&user存在,所以这里可以直接删除user对象

① 前后端交互接口
60

② 前端代码
只需要给a标签的href属性设置个值就行,不需要写任何的js代码。

后端代码:
LogoutServlet


7)发布博客

业务逻辑

在博客编辑页中获取到用户提交的数据并保存到数据库中。用户在博客编辑页中会填写标题和正文,在点击“发布文章”后发起一个http请求,然后服务器收到这些数据后构造一个Blog对象并插入数据库。

Blog对象:
61

① blogId自动生成
②title和content是用户提交的内容
③ postTime直接就是插入数据库的时间,不用手动指定,即:now()
④ userId:发布文章的时候登陆的用户就是作者,登陆的用户的信息是在HttpSession中的。

① 前后端交互接口:
62
② 实现服务器代码(响应)

补充
正常情况下,能够发起POST /blog请求应该是在已经登录状态下了,那为何还要再次检验是否是已经登录状态呢?
理由

① 万一有手动构造呢?如使用postman直接构造请求,此时就绕开了登录直接插入博客数据了。
② 构造博客对象是需要知道userId的,此时只有知道了谁在登录才能够知道文章作者(userId)。而该userId就来自与HttpSession对象getAttribute。

③ 前端代码(客户端代码)的实现:
(也不涉及js的编码)

63
① 当写上< textarea name=”content” style=”display:none”> < /textarea>的时候,用户在页面上输入的markdow内容就能够被textarea自动获取到;但是需要给初始化editor.md时加上一个新的属性:saveHTMLtoTextarea: true
65

② 此时发现一个问题:Markdown编辑器页面大小缩水了
66
这显然是前端样式的问题,所以去查看前端样式(fn+f12)
67
(发现blog-edit-container正常,但是form那儿就缩水了)
③ 也就是说:form标签没有指定高度,此时自身就缩水,导致内部的子元素也就缩水了。
解决方法:给form指定高度,和父元素一样高就行。
68
69


8)删除博客

业务逻辑

① 作者只能能删除自己的文章,不能删除别人的文章。
② 暂时没有管理员这个角色
③ 在博客详情页导航栏加上 删除按钮,当点击该按钮的时候就会触发删除操作。是通过a标签href属性发起的一个HTTP GET请求。
④ 删除的时候会进行校验:如果当前登录的用户就是文章作者才能够真正删除,否则就提示没有删除权限。

① 前后端交互接口:
70

② 实现服务器(后端代码):
大部分代码都是在判定非法情况,这是一个很好的意识。

③ 实现浏览器(前端)代码:

① 直接加个a标签
71

② 但是会发现:点击删除的时候url中是没有带上blogId的,这就导致无法删除。
③ 所以:可以在页面加载的时候通过js代码稍微修改一下href属性中的内容,使url中带上blogId。
75
72

③ 注意区分:location.href(完整路径) 和 location.seach(query string)
73

location是dom api中自带的全局对象(js中的全局对象)


四、项目代码

  1. 环境:
    IDEA + MySQL + smart tomcat + VSCode

  2. 项目布局
    00

  3. 项目代码:
    Gitee链接:个人博客系统


总结

  1. 在实现简单个人博客系统的过程中遇到了很多问题,其中的 前后端交互接口的约定 极其重要!!
  2. 只有不断重复、多练习才能更好地理解项目以及其实现。
    yyy

有任何建议以及问题可以 直接私信 或 直接评论 嗷!
欢迎小窗踢踢! or 评论区见!

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

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

相关文章

Mac 音频转换器推荐 DRmare Audio Converter、Audi Free Auditor

Mac 音频转换器推荐 DRmare Audio Converter、Audi Free Auditor 给大家推荐两款 Mac 上的音频转换器&#xff0c;这两款转换器都可以转换苹果音乐&#xff0c;iTunes歌曲或者一些常规的音轨到MP3, FLAC, WAV, M4A, AAC格式等等&#xff0c;转换后我们就可以在所有的设备和播放…

stm32f407VET6 系统学习 day06 窗口看门狗, IIC 通信协议

1.独立看门狗&#xff0c;与窗口看门狗的差别 1. 差别1 &#xff1a; 窗口看门狗&#xff0c; 有上限 0x7F&#xff0c; 有下限 0x40 &#xff0c;&#xff0c; 独立看门狗只有下限 0 2. 差别2&#xff1a; 时钟源不同&#xff0c; 独立看门狗&#xff1a;LSI 窗口…

【iMessage苹果推群发】苹果相册推它由pushchatkey.pem和pushchatcert.pem作为单独的文件使用

推荐内容IMESSGAE相关 作者推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者推荐内容3.日历推 *** 点击即可查看作者要求内容信息作者推荐…

cut与分层抽样

个人觉得&#xff0c; 把分层抽样称为“分类采样”会更贴切一些。通常最基本的采样手段是&#xff1a;随机抽样&#xff0c;但是在很多场景下&#xff0c;随机抽样是有问题的&#xff0c;举一个简单的例子&#xff1a;如果现在要发起一个啤酒品牌知名度的调查问卷&#xff0c;我…

Improved Unsupervised Lexical Simplification with Pretrained Encoders 论文精读

Improved Unsupervised Lexical Simplification with Pretrained Encoders 论文精读InformationAbstract1 Introduction2 System Description2.1 Simplification Candidate Generation2.2 Substitution Ranking2.3 Obtaining Equivalence Scores3 End-to-end System Performanc…

好书推荐《C++17 in Detail》

无意中发现作者的博客&#xff08;https://www.cppstories.com/&#xff09;和这本书。这本书算是对C17新增特性较为全面的介绍&#xff0c;而且从实战出发&#xff0c;不流于语法细枝末节&#xff0c;简洁清晰&#xff0c;可以作为Scott Meyers那本非著名的《Effective Modern…

2022环境电器年度行业分析报告:洗地机同比增长357%,扫地机器人销量197万+

在当前的大环境下&#xff0c;人们的消费观念不断变化&#xff0c;健康因素在购买决策中的比重逐渐增大&#xff0c;因此&#xff0c;与此挂钩的环境电器行业也迎来发展变化。 在这里&#xff0c;鲸参谋也综合了京东平台环境电器中一些重点类目的销售数据&#xff0c;主要包括吸…

Krita像素画教程

Krita Windows 上一款自由开源的绘画软件 Krita 是一款自由开源的免费绘画软件&#xff0c;使用 GPL 许可证发布。它的功能齐全&#xff0c;能胜任从起草、勾线、上色到最终调整的所有绘画流程&#xff0c;可以绘制概念草图、插画、漫画、动画、接景和 3D 贴图&#xff0c;支持…

云服务器部署内网穿透映射本地服务

项目开发时需要和前端联调&#xff0c;考虑使用内网穿透避免每次上传服务部署的过程 下载frp &#xff08;开源内网穿透、反向代理工具&#xff09; https://github.com/fatedier/frp/releases/上传云服务器并解压&#xff08;使用xftp等工具上传&#xff09; tar -zxvf frp_0…

尚硅谷JavaWeb教程

1、Servlet Server Applet 全称为&#xff1a;Java Servlet是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据&#xff0c;生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口&#xff0c;广义的Servlet是指任何实现了这个Servlet接口的类。 1.1、Ser…

李沐精读论文:DETR End to End Object Detection with Transformers

论文&#xff1a; End-to-End Object Detection with Transformers 代码&#xff1a;官方代码 Deformable DETR&#xff1a;论文 代码 视频&#xff1a;DETR 论文精读【论文精读】_哔哩哔哩_bilibili 本文参考&#xff1a; 山上的小酒馆的博客-CSDN博客 端到端目标检测DETR…

【javaSE】类和对象

希望各位老铁三连支持&#xff01; 文章目录 # 关于面向对象# 类的定义和使用# 构造方法的创建和初始化# 封装## 封装的概念## 访问限定符## 封装包的各种用法# 关键字static# 代码块一、关于面向对象 1.1面向对象的定义 简单来说&#xff0c;面向对象就是一种编程的思想&…

Compose 为什么可以跨平台?

这是我在 2022 Kotlin 中文开发者大会 中带来的一个分享&#xff0c;会后有网友反馈希望将 PPT 内容整理成文字方便阅读&#xff0c;所以就有了本篇文章。大家如果要了解本次大会更多精彩内容&#xff0c;也可以去 JetBrains 官方视频号查看大会的直播回放。 前言 Compose 不止…

Bean的生命周期流程-上

Bean的生命周期流程-上引言getBeangetSingletoncreateBean后置处理器类型区分doCreateBeancreateBeanInstance 是如何创建bean的实例的引言 Spring拥有一套完善的Bean生命周期体系,而使得这套生命周期体系具有高扩展性的关键在于Bean生命周期回调接口&#xff0c;通过这些接口…

层次分析法(AHP)

主要来解决评价类问题 什么是评价类问题&#xff1a;选择哪种方案最好&#xff0c;哪位运动员表现的更优秀。 评价类问题可以用打分解决 同一颜色的单元格权重之和为1 解决评价类问题&#xff0c;大家首先要想到以下三个问题&#xff1a; 1.我们评价的目标是什么&#xff1…

FineReport数据可视化图表-配置MySQL8外接数据库(1)

1. 概述 1.1 版本 报表服务器版本 功能变更 11.0 - 11.0.3 1&#xff09;首次配置外接数据库时&#xff0c;支持自行选择是否「迁移数据至要启用的数据库」 2&#xff09;迁移外接数据库的过程提示细化&#xff0c;方便用户了解迁移进度 1.2 功能简介 报表系统配置外接数…

USB TYPE C为什么能实现正反插

USB TYPE C接口在手机&#xff0c;电脑等移动终端中使用的非常多&#xff0c;它可以分为插头和插座&#xff0c;放在PCB板上一般是插座。 USB TYPE C的插座和插头引脚信号定义大家可以看下。引脚分为两排&#xff0c;上面一排是A&#xff0c;下面一排是B。标准的USB TYPE C总共…

YOLOV5融合SE注意力机制和SwinTransformer模块开发实践的中国象棋检测识别分析系统

本文紧接前文&#xff1a; 《基于yolov5s实践国际象棋目标检测模型开发》 《yolov5s融合SPD-Conv用于提升小目标和低分辨率图像检测性能实践五子棋检测识别》 首先来看下最终效果&#xff1a; 在我棋类检测系统开发之——五子棋检测那篇博文写完之后就萌生了想做一下基于目标…

WebDAV之葫芦儿·派盘+BubbleUPnP

BubbleUPnP 支持WebDAV方式连接葫芦儿派盘。 推荐一款投屏神器,它将手机内容分享到电视大屏上与家人好友一起共享,软件还提供了丰富的音乐及影视资源,喜欢的内容在线搜索就能播放。支持连接葫芦儿派盘WebDAV服务站,可以直接播放派盘内的影视资源。 BubbleUPnP是一款支持U…

水文监测系统-水文监测站构成 设备 功能 特点介绍以及案例分享

平升电子水文监测系统实现对江河流域水位、降水量、流量、流速、水质、闸门开启度、墒情等数据的实时采集、报送和处理。为防汛抗旱减灾提供科学依据和有效信息共享&#xff0c;保障人民群众生命财产安全&#xff0c;满足水利和经济社会发展对水文服务的需求。 2022年1月&#…