博客系统后端设计(三) - 实现获取博客列表页功能

news2024/11/20 23:30:56

文章目录

  • 实现获取博客列表页功能
    • 1. 约定前后端交互接口
    • 2. 实现后端代码
    • 3. 实现前端代码
    • 4. 测试代码
    • 5. 涉及到的两个 Bug

实现获取博客列表页功能




当前的博客列表上的数据都是写死的,符合逻辑的做法是,通过数据库读取数据后显示到页面上。

此处就需要打通前后端交互的操作。
让博客列表页在加载的时候,通过 Ajax 给服务器发一个请求,服务器查数据库获取到博客列表页数据,再返还给服务器,浏览器再根据数据构造页面的内容。

这样的交互过程也称为 前后端分离
意思是前端只向后端请求数据,而不请求具体的页面,后端也仅仅是返回数据。

这样设计的目的就是为了前端和后端更加的解耦,由浏览器进行具体的页面渲染,
减少了服务器的工作量。

1. 约定前后端交互接口


我们约定前端发起的 请求GET,路径是 /blog
后端返回的 响应 使用的是 json 格式的数据来组织



以上就是一个 json 格式的数组。

2. 实现后端代码


此时创建一个新的 BlogServlet 类。

@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.先查询数据库
        BlogDao blogDao = new BlogDao();
        // 使用 List 来表示
        List<Blog> blogs = blogDao.selectAll(); // 调用方法直接查询出全部的博客列表
        // 2.使用 ObjectMapper 将 blogs 转成符合要求的 json 格式的字符串
        String respJson = objectMapper.writeValueAsString(blogs);
        // 写回去
        resp.setContentType("application/json; charset=utf8");
        resp.getWriter().write(respJson);
    }
}

3. 实现前端代码


按照以下步骤用 vscode 打开这个博客列表页的文件。



在博客列表页加载过程中,触发 ajax ,访问服务器中的数据,再把拿到的数据构造到页面中。

将原来博客列表页的文章摘抄只留下一篇作为一个样例,这个样例在代码写完的时候也可以删除。





可以看到此时的博客就只有一篇了。


(1) 引入 jQuery

在前端代码下使用一个 script 标签,在这个标签里引入 jQuery。




(2) 在页面加载的时候,向服务器发起请求,获取博客列表的数据

 <script>
     // 在页面加载的时候,向服务器发起请求,获取博客列表的数据
     function getBlogs() {
         $.ajax({
             type: 'get',
             url: 'blog',
             success: function(body) {
                 // 响应的正文是一个 json 格式的字符串,此时已经被 jQuery 自动解析成一个 js 的对象数组了
                 // 此时直接 for 循环遍历即可
                 for (let blog of body) {
                     // 按照之前的写好的 html 代码构造页面内容
                        
                 }
             }
         })
     }
     
     // 记得调用方法
     getBlogs();
 </script>


上面的 type 和 url 分别是 get 和 blog ,这是因为这些都是在之前前后端交互接口中就约定好了。


(3) 构造页面内容

这里所构造的页面内容要参考之前写好的 html 代码。



根据上面的图片可以看到,有 5 个需要构造的内容。

① 构造整个博客

let blogDiv = document.createElement('div');
blogDiv.className = 'blog';


因为整个博客是一个 div 标签,因此这里的 createElement 里是一个 div。
而它的 类名 是 blog,因此这里的 clasName 为 blog。


② 构造标题

let titleDiv = document.createElement('div');
titleDiv.className = 'title';
// 把标题获取到并且设置进去
titleDiv.innerHTML = blog.title;
// 将构造好的标题添加进整个博客页面
blogDiv.appendChild(titleDiv);


因为 标题 是一个 div 标签,因此这里的 createElement 里是一个 div。
而它的 类名 是 title,因此这里的 clasName 为 title。


③ 构造发布时间

let dateDiv = document.createElement('div');
dateDiv.className = 'date';
dateDiv.innerHTML = blog.postTime;
blogDiv.appendChild(dateDiv);


这里的代码和上面的含义是一致的,只不过在第三条语句中的 blog.postTime
因为在前后端交互接口中约定好了,发布时间是 postTime




④ 构造博客摘要

let descDiv = document.createElement('div');
descDiv.className = 'desc';
descDiv.innerHTML = blog.content;
blogDiv.appendChild(descDiv);


这里的 blog.content 是由于前后端交互接口约定好了。




⑤ 构造查看全文按钮

let button = document.createElement('a');
button.innerHTML = '查看全文 &gt;&gt;';
// 期望点击按钮后会跳转到博客详情页
// 为了让博客详情页知道点了哪篇博客,把 blogId传过去
button.href = 'blog.detail.html?blogId=' + blog.blogId;
blogDiv.appendChild(button);


blog.detail.html 这是 博客详情页 的文件名,通过 blogId 来获取具体哪一篇博客。



此时的 blogDiv 只是创建出来了,还没有把它放到下图圈出的 div 里面。




此时需要先找到 父元素,上述图片中的 container-right 就是父元素。

首先在 for 循环的前面加上下面的代码。

 let containerRight = document.querySelector('.container-right');


接着在 for 的里面加上下面的代码

 // 把 blogDiv 加到父元素中
 containerRight.appendChild(blogDiv);



整体代码

<script>
    // 在页面加载的时候,向服务器发起请求,获取博客列表的数据
    function getBlogs() {
        $.ajax({
            type: 'get',
            url: 'blog',
            success: function(body) {
                // 响应的正文是一个 json 格式的字符串,此时已经被 jQuery 自动解析成一个 js 的对象数组了
                // 此时直接 for 循环遍历即可
                for (let blog of body) {
                    // 按照之前的写好的 html 代码构造页面内容
                    let containerRight = document.querySelector('.container-right');
                    // 构造整个博客
                    let blogDiv = document.createElement('div');
                    blogDiv.className = 'blog';

                    // 构造标题
                    let titleDiv = document.createElement('div');
                    titleDiv.className = 'title';
                    // 把标题获取到并且设置进去
                    titleDiv.innerHTML = blog.title;
                    // 将构造好的标题添加进整个博客页面中
                    blogDiv.appendChild(titleDiv);
                    
                    // 构造发布时间
                    let dateDiv = document.createElement('div');
                    dateDiv.className = 'date';
                    dateDiv.innerHTML = blog.postTime;
                    blogDiv.appendChild(dateDiv);

                    // 构造博客摘要
                    let descDiv = document.createElement('div');
                    descDiv.className = 'desc';
                    descDiv.innerHTML = blog.content;
                    blogDiv.appendChild(descDiv);

                    // 构造查看全文按钮
                    let button = document.createElement('a');
                    button.innerHTML = '查看全文 &gt;&gt;';
                    // 期望点击按钮后会跳转到博客详情页
                    // 为了让博客详情页知道点了哪篇博客,把 blogId传过去
                    button.href = 'blog.detail.html?blogId=' + blog.blogId;
                    blogDiv.appendChild(button);

                    // 把 blogDiv 加到父元素中
                    containerRight.appendChild(blogDiv);
                }
            }
        })
    }

    // 记得调用方法
    getBlogs();    
</script>


此时 博客列表页 就实现完成了。

4. 测试代码


首先要在数据库中插入测试数据。



在地址栏中输入 http://127.0.0.1:8080/blog-system/blog.list.html

blog.list.html 是博客列表页的文件名,blog-system 是项目名称。



可以看到此时在数据库插入的数据就显示到了博客列表页中。

此时点击 “查看全文” 按钮,就会自动跳转到 博客详情页。



此时显示的就是博客详情页界面了。





代码中实现的和跳转到博客详情页之后得地址栏是相同的。

5. 涉及到的两个 Bug


1、时间戳



可以看到此时显示的是一个时间戳,而不是一个格式化时间。


2、顺序

按照书写博客的逻辑,应该是先完成的博客在下面,后完成的在上面。
但是此时的顺序是相反的



根据上面在数据库中插入的结果可以看出,博客列表页展示出来的效果的顺序的确是不符合逻辑的。


(1) 顺序问题的解决办法

BlogDao 类(在封装数据库的操作中) 中找到 selectAll 方法,将这个方法中的 sql 语句更改为以下语句:

String sql = "select * from blog order by postTime desc";


也就是在 blog 后面添加上 order by postTime desc
order by postTime 表示的是 按照发布时间排序,desc 表示的是 排的是 降序


(2) 时间戳问题的解决办法

搜索 SimpleFormatter,查一下它的格式。



接下来在 Blog 类中,添加上下面的这段代码。

 public String getPostTime() {
     // 把时间戳转成 格式化 时间
     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     return simpleDateFormat.format(postTime);
 }


重启服务器后在地址栏输入路径。



可以看到此时的发布时间和顺序就已经正确了,此时博客列表页就已经全部完成了。

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

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

相关文章

【Linux】2.2 环境基础开发工具使用——vim

文章目录 什么是 vimvim 的基本操作vim 指令集Normal mode 指令集插入模式复制粘贴撤销剪切光标移动删除 last line mode 指令集列出行号跳到文件中的某一行查找字符保存文件 vim 的配置 什么是 vim Linux editor —— vim ——多模式的编辑器每种模式有差异&#xff0c;模式之…

人工智能洗稿-免费自媒体洗稿工具

文字洗稿 文字洗稿是指通过修改、重组、删除、替换等手段对文本进行优化、清理和调整&#xff0c;以达到改善文章质量、增加独特性和提高可读性的目的。文字洗稿是自媒体行业的一个重要需求&#xff0c;尤其是在批量撰写文章或需要大量修改文本的情况下。文字洗稿分为自动洗稿…

记一次springboot项目漏洞挖掘

前言 前段时间的比赛将该cms作为了题目考察&#xff0c;这个cms的洞也被大佬们吃的差不多了&#xff0c;自己也就借此机会来浅浅测试下这个cms残余漏洞&#xff0c;并记录下这一整个流程&#xff0c;谨以此记给小白师傅们分享下思路&#xff0c;有错误的地方还望大佬们请以指正…

云办公时代,企业如何保护数据资产安全?

云办公是一种基于云计算技术的办公方式&#xff0c;它将传统的办公软件和数据存储方式转移到了云端服务器上。用户可以通过互联网访问各种办公应用程序和数据&#xff0c;实现远程协作、移动化办公和信息共享等功能。 常见的云办公应用包括文档处理、电子邮件、日历、在线会议、…

ABAP 锁对象

需求场景 最近收到用户反馈&#xff0c;发现同一个托运单生成了两个不同的服务订单以及根据同一个送货单生成了两个托运单&#xff0c;经过排查&#xff0c;发现原因都是由同样的问题导致的&#xff0c;多窗口或者多用户同时对一条数据操作&#xff0c;就会出现这种现象。这个…

Learning C++ No.19【搜索二叉树实战】

引言&#xff1a; 北京时间&#xff1a;2023/5/2/9:18&#xff0c;五一放假第四天&#xff0c;昨天本来想要发奋图强将该篇博客写完&#xff0c;但是摆烂了一天&#xff0c;导致已经好几天没有码字&#xff0c;敲代码了&#xff0c;此时难受的感觉涌上心头&#xff0c;但是摆烂…

DNF类游戏动作实现(C语言)

没有接触制作小游戏前&#xff0c;感觉做游戏很不可思议&#xff0c;游戏里的人物是怎么移动的&#xff0c;怎么攻击&#xff0c;释放技能。。。。。。现在逐渐了解到之后&#xff0c;发现2d游戏人物的动作更多是图片的拼接&#xff0c;动作是否精细&#xff0c;由这个动作的帧…

鲲鹏展翅 信安高飞 | 鲲鹏开发者峰会2023-麒麟信安技术论坛成功举办!

2023年5月6日-7日&#xff0c;以“创未来 享非凡”为主题的鲲鹏开发者峰会2023在东莞松山湖举办。鲲鹏产业生态繁荣&#xff0c;稳步发展&#xff0c;正在成为行业核心场景及科研领域首选&#xff0c;加速推动数字化转型。 作为鲲鹏生态重要合作伙伴&#xff0c;麒麟信安受邀举…

企企通:B2B商城四种“玩法”,一站式解决端到端全链路需求!

商城系统在电商零售领域中&#xff0c;一直是助力商家搭建商城的核心工具&#xff0c;随着电商行业的发展&#xff0c;各种新模式随即出现&#xff0c;与此同时也出现了各种各样的商城系统&#xff0c;而B2B商城是这其中最为常见的商城系统。 近年来&#xff0c;由于电子商务的…

相遇于此,相交链表的解题心得

本篇博客会讲解力扣“160. 相交链表”的解题思路&#xff0c;这是题目链接。 老规矩&#xff0c;先来审题。这道题的题干有点长&#xff0c;简而言之&#xff0c;就是判断2个链表是否相交&#xff0c;如果相交就返回第一个相交结点&#xff0c;不相交就返回NULL。看看题目原文…

【C++中可调用对象和function】

C中有如下几种可调用对象&#xff1a;函数、函数指针、lambda表达式、bind对象、仿函数。其中&#xff0c;lambda表达式和bind对象是C11标准中提出的(bind机制并不是新标准中首次提出&#xff0c;而是对旧版本中bind1st和bind2st的合并)。个人认为五种可调用对象中&#xff0c;…

FM33A048B LPUART

概述 LPUART 是一个低功耗UART 接口&#xff0c;其工作仅需32768Hz 时钟&#xff0c;可以支持到最高9600 波特率的数据接收。LPUART 功耗极低&#xff0c;可以在Sleep/DeepSleep 模式下工作。 特点&#xff1a; ⚫ 异步数据收发 ⚫ 标准UART帧格式 ◼ 1bit起始位 ◼ 7或8bit数据…

【ChatGPT Prompt Engineering】面向Java开发者的ChatGPT提示词工程(1)

各位Java开发者们&#xff0c;欢迎来到万猫学社&#xff01;在这里&#xff0c;我将和大家分享ChatGPT提示词工程的系列文章&#xff0c;希望能够和大家一起学习和探讨提示词的最佳实践。 虽然互联网上已经有很多有关提示词的材料&#xff0c;比如那些“每个人都必须知道的30个…

lua是什么?lua的基本语法知识点

目录 一、lua是什么&#xff1f; 二、lua的基本语法 1.运行lua脚本文件 2.注释 3.标示符 4.关键词 5.全局变量 三、数据类型 8个基本类型 1.nil(空&#xff09; 2.boolean&#xff08;布尔&#xff09; 3.number(数字&#xff09; 4.string(字符串&#xff09; 5…

一图看懂 six 模块:最常见的 POSIX 系统调用, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 six 模块&#xff1a;最常见的 POSIX 系统调用, 资料整理笔记&#xff08;大全&#xff09; 摘要模块图类关系图模块全展开【six】统计常量intboolstrtuplelist 模块24 fun…

电脑屏幕开机后一直闪不停怎么办?电脑屏幕闪烁的解决方法

不少电脑用户经常会遇到的一种情况&#xff0c;就是开机后&#xff0c;发现电脑屏幕一直闪不停&#xff0c;十分伤眼。驱动人生就为大家带来电脑屏幕闪烁的解决方法。 首先&#xff0c;驱动人生建议可以排查一下出现电脑屏幕闪烁的原因&#xff0c;从而更加针对性的解决故障。…

SpringBoot 整合第三方技术Junit+MyBatis+Druid

测试类中加两个注解就行 SpringBootTest(classes Application.class)//添加SpringBoot 的启动类&#xff0c;万无一失 RunWith(SpringJUnit4ClassRunner.class) public class SpringBootJunitTest {Testpublic void test(){System.out.println("ddddddddddddddddddd&quo…

四象限法则定量分析法,如何客观划分需求优先级?

四象限法按照重要和紧急程度&#xff0c;划分为4个象限&#xff1a;重要且紧急、重要不紧急、不重要但紧急、不重要不紧急。那么我们如何客观地对需求进行评估&#xff0c;并将其放到对应的象限&#xff1f; 我们可以使用定量分析方法对象限进行划分和定值。在横纵坐标中&#…

php+mysql求职招聘人才网站

1&#xff0e;系统登录&#xff1a;系统登录是用户访问系统的路口&#xff0c;设计了系统登录界面&#xff0c;包括用户名、密码和验证码&#xff0c;然后对登录进来的用户判断身份信息&#xff0c;判断是管理员用户还是普通用户[10]。 2&#xff0e;系统用户管理&#xff1a;不…

温湿度换算绝对含水量

常压下 公式如下 y z * ( 8.0141786694E-09*x^5 2.3071566385E-06*x^4 1.3157923494E-04*x^3 1.1376256438E-02*x^2 3.1867343275E-01*x 4.9021104226E00 ) 式子中 z 相对湿度 单位百分比 x 摄氏度 单位度 取值范围 5-100度 y 绝对湿度 单位 克每立方…