手把手带你搭建个人博客系统(二)
创始人
2024-01-20 16:27:33
0

在这里插入图片描述

请添加图片描述

⭐️前言⭐️

因文章篇幅较长,所以整个流程分两篇文章来完成。

🍉博客主页: 🍁【如风暖阳】🍁
🍉精品Java专栏【JavaSE】、【备战蓝桥】、【JavaEE初阶】、【MySQL】、【数据结构】
🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)、GitHub


请添加图片描述

📍内容导读📍

  • 🍅1.针对完成任务
    • 1.1博客列表页
    • 1.2博客详情页
    • 1.3登录功能
    • 1.4检验登录状态
    • 1.5正确显示用户信息
      • 1.5.1 博客列表页
      • 1.5.2 博客详情页
    • 1.6注销功能
    • 1.7发布博客
    • 1.8删除博客

请添加图片描述

🍅1.针对完成任务

在前端共涉及的四个页面,都需要分别完成“约定前后端交互接口”、“编写服务器代码”、“编写客户端代码”等任务流程。

1.1博客列表页

这个页面需要展示出数据库中的博客列表,按以下开发流程来进行操作

1)约定接口
在这里插入图片描述
2)编写服务器代码

//通过这个类来处理 /blog 路径对应的请求
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper=new ObjectMapper();//这个方法用来获取到数据库中的博客列表@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//从数据库中查询到博客列表,转成JSON格式,然后直接返回即可BlogDao blogDao=new BlogDao();List blogs=blogDao.selectAll();//把blogs对象转成JSON格式String respJson=objectMapper.writeValueAsString(blogs);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}
}

postman测试成功:
在这里插入图片描述
3)编写客户端代码
这一步需要我们在之前写好的前端代码中进行调整,加入ajax请求,使得前端页面能够与服务器交互,并从数据库中获取到博客列表



博客列表

我的博客系统
主页写博客注销

如风暖阳

gitHub地址
文章分类
21

1.2博客详情页

1)约定前后端交互接口
在这里插入图片描述
可以发现在博客详情页的请求中,与博客列表页不同的是多了?blogId=1这样的查询字符串;
该查询字符串在blog_list.htmla链接标签中就加入了
在这里插入图片描述
2)编写客户端代码
加入ajax请求,使得博客详情页的内容,可以通过请求,从服务器中根据查询字符串中的信息,找到对应的博客,展示在前端页面上。

该操作还需要注意,博客正文要用markdown格式渲染,所以要引入editor.md依赖

核心代码块:
在这里插入图片描述
完整前端代码:



博客详情页

我的博客系统
主页写博客注销

如风暖阳

gitHub地址
文章分类
21

3)编写服务器代码,在BlogServlet类中修改doGet方法,使得浏览器发来的请求中,如果有查询字符串,就返回博客详情页json数据;如果没有查询字符串,就返回博客列表页json数据。

//通过这个类来处理 /blog 路径对应的请求
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper=new ObjectMapper();//这个方法用来获取到数据库中的博客列表@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");BlogDao blogDao=new BlogDao();//先尝试获取到req中的blogId参数,如果该参数存在,说明是要求请求博客详情//如果该参数不存在,说明是要请求博客的列表String parm=req.getParameter("blogId");if(parm==null) {//不存在参数,获取博客列表List blogs=blogDao.selectAll();//把blogs对象转成JSON格式String respJson=objectMapper.writeValueAsString(blogs);resp.getWriter().write(respJson);}else {//存在参数,获取博客详情int blogId=Integer.parseInt(parm);Blog blog=blogDao.selectOne(blogId);String respJson=objectMapper.writeValueAsString(blog);resp.getWriter().write(respJson);}}
}

效果预览
在这里插入图片描述

1.3登录功能

1)约定接口
在这里插入图片描述
登录成功后,跳转到博客列表页。
在前端登录实现部分中,我们使用的是input标签,所以通过form表单的方式来构造登录请求更方便。
2)编写前端代码
主要是加入form表单,并把提交按钮类型改为submit,还需要改提交按钮对应的css样式

blog_login.html:



Document

我的博客系统
主页写博客

登录

用户名
密码

blog_login.css:

.login-container {width: 100%;/* 注意减号两边有空格 */height: calc(100% - 50px);/* 需要让里面的子元素, 垂直水平居中, 需要用到 flex 布局 */display: flex;align-items: center;justify-content: center;
}.login-dialog {width: 400px;height: 350px;background-color: rgba(255,255,255,0.8);border-radius: 10px;
}.login-dialog h3 {text-align: center;padding: 50px 0;
}.login-dialog .row {height: 50px;width: 100%;display: flex;align-items: center;justify-content: center;
}.login-dialog .row span {/* 把span设置为块级元素方便后续设置尺寸 */display: block;width: 100px;font-weight: 700;
}#username,#password {width: 200px;height: 40px;font-size: 22px;line-height: 40px;padding-left: 10px;border-radius: 10px;
}.row #submit {width: 300px;height: 50px;border-radius: 10px;color: white;background-color: rgb(0,128,0);border: none;outline: none;margin-top:50px ;
}.row #submit:active {background-color: #666;
}

3)编写服务器代码
约定的路径是/login,需要新建一个Servlet类来处理这里的登录请求

@WebServlet("/login")
public class LoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");resp.setCharacterEncoding("utf8");//1.获取到请求中的参数String username=req.getParameter("username");String password=req.getParameter("password");System.out.println("username="+username+",password="+password);if(username==null||"".equals(username)||password==null||"".equals(password)) {// 请求的内容缺失, 肯定是登录失败!!resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前的用户名或密码为空!");return;}//2.和数据库中的内容进行比较UserDao userDao=new UserDao();User user=userDao.selectByName(username);if(user==null||!user.getPassword().equals(password)) {//用户没有查到或者密码不匹配,登录失败!resp.setContentType("text/html; charset=utf8");resp.getWriter().write("用户名或密码错误!");return;}//3.如果比较通过,就创建会话HttpSession session=req.getSession(true);//把刚才的用户信息,存储到会话中session.setAttribute("user",user);//4.返回一个重定向报文,跳转到博客列表页resp.sendRedirect("blog_list.html");}
}

效果预览
请添加图片描述

1.4检验登录状态

在我们完成了登录功能后,需要对前边两个页面(博客列表页和博客详情页)进行调整,使得这两个页面必须登录后才能访问。

要想实现上述的功能,就需要在博客列表页/详情页加载的时候,通过ajax访问一下服务器,获取当前的登录状态,看看能不能获取到,如果获取到了,就说明当前确实是已经登录了,此时就可以留在这个页面了;如果没有获取到,说明未登录,就需要跳转到登录页面。

1)约定接口
在这里插入图片描述
如果登录了就返回当前登录的用户信息,未登录,就直接返回一个userId=0的对象。
在这里插入图片描述
2)编写服务器代码

LoginServlet类中加上doGET方法

//这个方法用来让前端检测当前的登录状态@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");HttpSession session=req.getSession(false);if(session==null) {//检测下会话是否存在,不存在说明未登录User user=new User();resp.getWriter().write(objectMapper.writeValueAsString(user));return;}User user=(User) session.getAttribute("user");if(user==null) {//虽然会话存在,但是会话里没有user对象,也视为未登录user=new User();resp.getWriter().write(objectMapper.writeValueAsString(user));return;}//代码执行到这里说明已经登录//不把密码返回给前端user.setPassword("");resp.getWriter().write(objectMapper.writeValueAsString(user));}

3)编写前端代码
在博客详情页和博客列表页中加入ajax请求,在页面一加载出来的时候就向服务器发送请求来判定登录状态。

因为两个页面都需要进行判断,所以把判断逻辑单独出一个js文件中,让这两个前端代码引入即可。

//这个文件放一些页面公共的代码function getUserInfo(pageName) {$.ajax({type:'get',url:'login',success:function(body) {//判定此处的body是不是一个有效的user对象(userId是否为0)if(body.userId&&body.userId>0) {//登录成功,不做处理console.log("当前用户登录成功! 用户名: " + body.username);}else {//登录失败!//让前端页面跳转到login.htmlalert("当前您尚未登录!请登录后再访问博客列表!");location.assign('blog_login.html');}},error: function() {alert("当前您尚未登录! 请登录后再访问博客列表!");location.assign('blog_login.html');}});
}

在这里插入图片描述

1.5正确显示用户信息

该步骤需要注意两点:

  • 在博客列表页的用户名,要根据登录的用户来进行确定
  • 在博客详情页的用户名,要根据博客的作者来确定

1.5.1 博客列表页

因为在数据库中并没有存储个人的头像和文章数量等信息,所以只能对用户名做出变动,因为之前在1.4中完成了登录状态检测的步骤后,也就完成了后端代码,这一步只需要在前端进行微调,在页面是博客列表页时,能够将用户名做出修改即可。

//这个文件放一些页面公共的代码function getUserInfo(pageName) {$.ajax({type:'get',url:'login',success:function(body) {//判定此处的body是不是一个有效的user对象(userId是否为0)if(body.userId&&body.userId>0) {//登录成功,不做处理console.log("当前用户登录成功! 用户名: " + body.username);if(pageName=='blog_list.html') {changeUserName(body.username);}}else {//登录失败!//让前端页面跳转到login.htmlalert("当前您尚未登录!请登录后再访问博客列表!");location.assign('blog_login.html');}},error: function() {alert("当前您尚未登录! 请登录后再访问博客列表!");location.assign('blog_login.html');}});
}function changeUserName(username) {let h3=document.querySelector('.card>h3');h3.innerHTML=username;
}

效果预览:在这里插入图片描述

1.5.2 博客详情页

要想完成博客详情页中用户名的更改,还需要重新约定接口编写前后端代码

1)约定接口
在这里插入图片描述
2)编写前端代码

关键代码
前端代码中的两个ajax请求,是异步并发执行的,并不能确定先后顺序,所以在一个函数的回调函数中,调用另一个函数,让其变为串行执行,才能控制顺序。
在这里插入图片描述

在这里插入图片描述

3)编写服务器代码

@WebServlet("/authorInfo")
public class AuthorServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json; charset=utf8");// 通过这个方法, 来获取到指定的博客的作者信息.String param = req.getParameter("blogId");if (param == null || "".equals(param)) {// 参数缺少了.resp.getWriter().write("{ \"ok\": false, \"reason\": \"参数缺失!\" }");return;}// 根据当前 blogId 在数据库中进行查找, 找到对应的 Blog 对象, 再进一步的根据 blog 对象, 找到作者信息.BlogDao blogDao = new BlogDao();Blog blog = blogDao.selectOne(Integer.parseInt(param));if (blog == null) {resp.getWriter().write("{ \"ok\": false, \"reason\": \"要查询的博客不存在!\" }");return;}// 根据 blog 对象, 查询到用户对象UserDao userDao = new UserDao();User author = userDao.selectById(blog.getUserId());if (author == null) {resp.getWriter().write("{ \"ok\": false, \"reason\": \"要查询的用户不存在!\" }");return;}// 把 author 返回到浏览器这边// 注意要把密码给干掉!author.setPassword("");resp.getWriter().write(objectMapper.writeValueAsString(author));}
}

1.6注销功能

在导航栏中有一个“注销”按钮,当用户点击注销以后,就会在服务器上取消登录状态,并且能够跳转到登录页面。

1)约定前后端交互接口

在这里插入图片描述
2)注销逻辑的服务器代码

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//先找到当前用户的会话HttpSession session=req.getSession(false);if(session==null) {//用户没有登录,不用注销resp.getWriter().write("当前用户尚未登录!无法注销!");return;}//把这个用户的会话中的信息给删掉即可session.removeAttribute("user");resp.sendRedirect("blog_login.html");}
}

用户有一个session,同时session中有一个user属性,两者同时兼备时,就是登陆状态,注销只要把其中一个条件破坏掉即可。
在这里插入图片描述
3)客户端代码修改
把博客列表页、博客详情页、博客编辑页中的导航栏中的注销按钮中的herf属性,都做出修改,改成“logout”这个路径。

1.7发布博客

在博客编辑页中,当用户输入了博客标题和正文之后,点击发布,此时就会把博客数据提交到服务器,由服务器存储到数据库中。

1)约定前后端交互接口
在这里插入图片描述
2)实现服务器代码

BlogServlet里面添加一个doPost方法,来处理上述的post请求;
核心操作,就是读取请求中的标题和正文,构造blog,构造Blog对象,并插入数据库

 @Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session=req.getSession(false);if(session==null) {//当前用户未登录,不能提交博客resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前用户未登录,不能提交博客!");return;}User user=(User) session.getAttribute("user");if(user==null) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前用户未登录,不能提交博客!");return;}//一定要先指定好请求,按照哪种编码来解析req.setCharacterEncoding("utf8");//先从请求中取出参数(博客的标题和正文)String title=req.getParameter("title");String content=req.getParameter("content");if(title==null||"".equals(title)||content==null||"".equals(content)) {//直接告诉客户端,请求参数不对resp.setContentType("text/html;charset=utf8");resp.getWriter().write("提交博客失败!缺少必要的参数!");return;}//构造Blog对象,把当前的信息填进去,并插入数据库中//此处要给Blog设置的属性,主要是title,content,userId(作者信息)//postTime和blogId都不需要手动指定,都是插入数据库的时候自动生成的Blog blog=new Blog();blog.setTitle(title);blog.setContent(content);//作者id就是当前提交这个博客的用户的身份信息blog.setUserId(user.getUserId());BlogDao blogDao=new BlogDao();blogDao.insert(blog);//重定向到博客列表页resp.sendRedirect("blog_list.html");}

3)调整客户端代码
将整个文章内容用form表单套住,提交form表单



Document

我的博客系统
主页写博客注销

注意对css样式的选择器进行调整,保证提交按钮的样式不丢。
在这里插入图片描述

1.8删除博客

只有自己能够删除自己的博客,不能够删除别人的博客。

1)约定接口
在这里插入图片描述
2)调整前端代码

我们需要在博客详情页中进行判定,当前博客的作者,是否就是登录的用户;

如果是,就在导航栏里显示一个删除按钮,如果不是,就不显示删除按钮
在这里插入图片描述
3)编写服务器代码

@WebServlet("/blogDelete")
public class BlogDeleteServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.检查当前用户是否登录HttpSession session=req.getSession(false);if(session==null) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前尚未登录,不能删除!");return;}User user=(User) session.getAttribute("user");if(user==null) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前尚未登录,不能删除!");return;}//2.获取到参数中的blogIdString blogId=req.getParameter("blogId");if(blogId==null||"".equals(blogId)) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前blogId参数不对!");return;}//3.获取要删除的博客信息BlogDao blogDao=new BlogDao();Blog blog=blogDao.selectOne(Integer.parseInt(blogId));if(blog==null) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前要删除的博客不存在!");return;}//4.再次校验,当前的用户是否是博客的作者if(user.getUserId()!=blog.getUserId()) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前登录的用户不是作者,没有删除权限");return;}//5.确认无误,开始删除blogDao.delete(Integer.parseInt(blogId));//6.重定向到博客列表resp.sendRedirect("blog_list.html");}
}

⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...