【JavaEE进阶】 图书管理系统开发日记——叁

news2024/11/19 15:36:02

🌴前言

在前面我们实现了用户登录的接口。现在我们来实现图书列表展示页面。

🎋数据准备

创建图书表,并初始化数据

-- 图书表
DROP TABLE IF EXISTS book_info;
CREATE TABLE `book_info` (
	`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
	`book_name` VARCHAR ( 127 ) NOT NULL,
	`author` VARCHAR ( 127 ) NOT NULL,
	`count` INT ( 11 ) NOT NULL,
	`price` DECIMAL (7,2 ) NOT NULL,
	`publish` VARCHAR ( 256 ) NOT NULL,
	`status` TINYINT ( 4 ) DEFAULT 1 COMMENT '0-⽆效, 1-正常, 2-不允许借阅',
	`create_time` DATETIME DEFAULT now(),
	`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

-- 初始化图书数据
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('活
着', '余华', 29, 22.00, '北京⽂艺出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('平凡的
世界', '路遥', 5, 98.56, '北京⼗⽉⽂艺出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('三
体', '刘慈欣', 9, 102.67, '重庆出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('⾦字塔
原理', '⻨肯锡', 16, 178.00, '⺠主与建设出版社');

MyBatis和MySQL驱动依赖已经在用户登录时已经配置过了,直接用即可

🎄需求分析

首先我们先来看一下页面展示的效果
在这里插入图片描述

在分页时,第一页就展示10条数据,第二页我们也只显示10条数据

要想实现这个功能,从数据库中进⾏分⻚查询,我们要使⽤ LIMIT 关键字,格式为:limit 开始索引每⻚显⽰的条数(开始索引从0开始)

通过观察与思考,我们可以发现

开始索引的计算公式:开始索引=(当前⻚码-1)*每⻚显⽰条数

基于前端⻚⾯的分析,得出以下结论:

  1. 前端在发起查询请求时,需要向服务端传递的参数
  • currentPage当前⻚码 //默认值为1
  • pageSize每⻚显⽰条数 //默认值为10
  1. 后端响应时,需要响应给前端的数据
  • records所查询到的数据列表(存储到List集合中)
  • total总记录数(⽤于告诉前端显⽰多少⻚,显⽰⻚数为: (total + pageSize-1)/pageSize

翻⻚请求和响应部分,我们通常封装在两个对象中,并放在model文件路径下

🚩翻⻚请求对象类

除了需要currentPage当前⻚码和pageSize每⻚显⽰条数

我们还需要根据currentPage和pageSize,计算出来开始索引

代码如下:

@Data
public class PageRequest {
    private int currentPage = 1; // 当前⻚
    private int pageSize = 10; // 每⻚中的记录数
    private int offset;
    public int getOffset() {

        return (currentPage-1) * pageSize;
    }
}

🚩翻页响应对象类

该类博主设计的是返回一个对象。

该对象应该含有以下属性。

  • records所查询到的数据列表
  • total总记录数
  • PageRequest属性

添加PageRequest属性是为了避免后续还需要其他请求处的信息

同时给出相应的构造方法。

代码实现如下:

@Data
public class PageResult<T> {
    private int total;//所有记录数

    private List<T> records; // 当前⻚数据

    private PageRequest pageRequest;
    public PageResult(Integer total, PageRequest pageRequest, List<T> records)
    {
        this.total = total;
        this.pageRequest = pageRequest;
        this.records = records;
    }
}

🍃约定前后端交互接⼝

基于以上分析,我们来约定前后端交互接⼝

[请求]
/book/getListByPage?currentPage=1&pageSize=10
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
[参数]
[响应]
Content-Type: application/json
{
“total”: 25,
“records”: [{
“id”: 25,
“bookName”: “图书21”,
“author”: “作者2”,
“count”: 29,
“price”: 22.00,
“publish”: “出版社1”,
“status”: 1,
“statusCN”: “可借阅”
}, {

} ]
}

我们约定,浏览器给服务器发送⼀个 /book/getListByPage 这样的HTTP请求,通过currentPage参数告诉服务器,当前请求为第⼏⻚的数据,后端根据请求参数,返回对应⻚的数据

第一页可以不传递参数,默认为1

🌲后端服务器代码实现

依旧利用分层思想进行代码实现

🚩控制层

在该层我们只需要调用业务层的代码返回就好

@Slf4j
@RequestMapping("/book")
@RestController
public class BookController {
    @Autowired
    private BookService bookService;
    @RequestMapping("/getListByPage")
    public PageResult<BookInfo> getListByPage(PageRequest pageRequest) {
        log.info("获取图书列表, pageRequest:{}", pageRequest);
        PageResult<BookInfo> pageResults = bookService.getBookListByPage(pageRequest);
        return pageResults;
    }

}

🚩业务层

在书写业务层代码时我们需要考虑以下几点

  1. 翻⻚信息需要返回数据的总数和列表信息,需要查两次SQL

  2. 图书状态:图书状态和数据库存储的status有⼀定的对应关系

如果后续状态码有变动,我们需要修改项⽬中所有涉及的代码,这种情况,我们通常采⽤枚举类来处理映射关系

枚举类代码如下:

public enum BookStatus {
    DELETED(0,"⽆效"),
    NORMAL(1,"可借阅"),
    FORBIDDEN(2,"不可借阅");
    private Integer code;
    private String name;
    BookStatus(int code, String name) {
        this.code = code;
        this.name = name;
    }
    public static BookStatus getNameByCode(Integer code){
        switch (code){
            case 0: return DELETED;
            case 1: return NORMAL;
            case 2: return FORBIDDEN;
        }
        return null;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

此时我们只需要调用相应的数据层代码,查询相应的数据,并对查询到的数据进行状态码的更新。

最后构造新的响应对象,返回即可

代码实现如下:

@Service
public class BookService {
    @Autowired
    private BookInfoMapper bookInfoMapper;
    public PageResult<BookInfo> getBookListByPage(PageRequest pageRequest) {
        Integer count = bookInfoMapper.count();
        List<BookInfo> books = bookInfoMapper.queryBookListByPage(pageRequest);
        for (BookInfo book:books){
            book.setStatusCN(BookStatus.getNameByCode(book.getStatus()).getName());
        }
        return new PageResult<>(count,pageRequest, books);
    }

}

🚩数据层

数据层我们只需要进行两个查询即可

一个是返回最大数据长度,一个是查询当前页码的所有数据。

代码实现如下:

@Mapper
public interface BookInfoMapper {
    @Select("select count(1) from book_info where status<>0")
    Integer count();

    @Select("select * from book_info where status !=0 order by id desc limit #{offset}, #{pageSize}")
    List<BookInfo> queryBookListByPage(PageRequest pageRequest);
}

🚩测试后端代码

到这里后端代码就写完了,我们可以进行简单的测试,只需要在浏览器中输入

  • http://127.0.0.1:8080/book/getListByPage返回1-10条记录(按id降序)
  • http://127.0.0.1:8080/book/getListByPage?currentPage=2返回11-20条记录

此时说明后端代码已经书写成功

🌳客户端代码的完善

这里博主直接给出改变的相应代码。

实现如下:

getBookList();
function getBookList() {
    $.ajax({
        type: "get",
        url: "/book/getListByPage"+location.search,
        success: function (result) {
            console.log(result);
            if (result != null) {
                var finalHtml = "";
                for (var book of result.records) {
                    finalHtml += '<tr>';
                    finalHtml += '<td><input type="checkbox" name="selectBook" value="'+book.id+'" id="selectBook" class="book-select"></td>'
                    finalHtml += '<td>' + book.id + '</td>';
                    finalHtml += '<td>' + book.bookName + '</td>';
                    finalHtml += '<td>' + book.author + '</td>';
                    finalHtml += '<td>' + book.count + '</td>';
                    finalHtml += '<td>' + book.price + '</td>';
                    finalHtml += '<td>' + book.publish + '</td>';
                    finalHtml += '<td>' + book.statusCN + '</td>';
                    finalHtml += '<td><div class="op">';
                    finalHtml += '<a href="book_update.html?bookId=' + book.id + '">修改</a>'
                    finalHtml += '<a href="javascript:void(0)" onclick="deleteBoook(' + book.id + ')">删除</a>'
                    finalHtml += '</div></td>';
                    finalHtml += "</tr>";
                }
                $("tbody").html(finalHtml);

                //翻页信息
                $("#pageContainer").jqPaginator({
                    totalCounts: result.total, //总记录数
                    pageSize: 10,    //每页的个数
                    visiblePages: 5, //可视页数
                    currentPage: result.pageRequest.currentPage,  //当前页码
                    first: '<li class="page-item"><a class="page-link">首页</a></li>',
                    prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',
                    next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',
                    last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',
                    page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',
                    //页面初始化和页码点击时都会执行
                    onPageChange: function (page, type) {
                        console.log("第" + page + "⻚, 类型:" + type);
                        if (type != 'init') {
                            location.href = "book_list.html?currentPage=" + page;
                        }
                    }
                });
            }
        }
    });
}

在这里插入图片描述

⭕总结

关于《【JavaEE进阶】 图书管理系统开发日记——叁》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

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

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

相关文章

【数据开发】pyspark入门与RDD编程

【数据开发】pyspark入门与RDD编程 文章目录 1、pyspark介绍2、RDD与基础概念3、RDD编程3.1 Transformation/Action3.2 数据开发流程与环节 1、pyspark介绍 pyspark的用途 机器学习专有的数据分析。数据科学使用Python和支持性库的大数据。 spark与pyspark的关系 spark是一…

CMake Msys2 搭配vscode

(一)MSYS2介绍 MSYS2&#xff08;Minimal SYStem 2&#xff09;是一个集成了大量的GNU工具链、工具和库的开源软件包集合。它提供了一个类似于Linux的shell环境&#xff0c;可以在Windows系统中编译和运行许多Linux应用程序和工具。 MSYS2基于MinGW-w64平台&#xff0c;提供了…

分布式事务 seata+nacos 部署

分布式事务 seatanacos 部署 一、下载seata二、解压配置三、导入数据库四、nacos配置五、配置要引入事务的模块的配置文件六、启动七、测试 这里使用的版本&#xff1a; nacos&#xff1a;2.0.4 seata&#xff1a;1.5.2 seata官方地址&#xff1a;https://seata.apache.org/zh-…

unity addressables 加载资源和场景 显示进度条(主要用于WebGL)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、addressables是什么&#xff1f;二、导入Addressables三、创建Addressables Settings 资产包管理四、资源打包五、环境模拟六、查看重复资源七、选择Bundle…

WordPress主题YIA的文章页评论内容为什么没有显示出来?

有些WordPress站长使用YIA主题后&#xff0c;在YIA主题设置的“基本”中没有开启“一键关闭评论功能”&#xff0c;而且文章也是允许评论的&#xff0c;但是评论框却不显示&#xff0c;最关键的是文章原本就有的评论内容也不显示&#xff0c;这是为什么呢&#xff1f; 根据YIA主…

【毕业日记】2024.01 - 慢下来,静待花开

转眼距离930离开鹅厂已经120天了&#xff0c;我是很能拖延的&#xff0c;或者是很懂自我麻痹的&#xff0c;这三个多月&#xff0c;一直想要写点东西纪念&#xff0c;一直拖一直拖一直拖…… 疫情这几年经济下行里裁员是个茶余饭后“嬉笑”之余经常被提起的词&#xff0c;部门滚…

python 实现 macOS状态栏 网速实时显示

安装依赖包&#xff1a; pip install pillow psutil rumpsnetSpeedApp.py from PIL import Image, ImageDraw, ImageFont import psutil import rumpsclass NetSpeedApp(rumps.App):def __init__(self):super(NetSpeedApp, self).__init__("NetSpeed")self.titlese…

Node需要了解的知识

Node能执行javascript的原因。 浏览器之所以能执行Javascript代码&#xff0c;因为内部含有v8引擎。Node.js基于v8引擎封装&#xff0c;因此可以执行javascript代码。Node.js环境没有DOM和BOM。DOM能访问HTML所有的节点对象&#xff0c;BOM是浏览器对象。但是node中提供了cons…

Postgres与DynamoDB:选择哪个数据库

启动新项目时需要做出的决定之一是使用哪个数据库。如果您使用的是Django这样的包含电池的框架&#xff0c;那么没有理由再三考虑。选择一个受支持的数据库引擎&#xff0c;就可以了。另一方面&#xff0c;如果你使用像FastAPI或Flask这样的微框架&#xff0c;你需要自己做出这…

手把手教你搭建属于自己的网站(获取被动收入),无需服务器,使用github托管

大家好&#xff0c;我是亚洲著名程序员青松&#xff0c;本次教大家如何搭建一个属于自己的网站。 下面是我自己搭建的一个网站&#xff0c;是一个网址导航网站。托管在了github上面&#xff0c;目前已经运营了三个月&#xff0c;每天的访问量大约有100ip左右。 下图是在51.la上…

一键部署FC超级马里奥web游戏

效果展示 安装 拉取镜像 #拉取镜像 docker pull stayhungrystayfoolish666/mario #创建并启动容器 docker run -d -p 10034:8080 --name maliao --restartalways stayhungrystayfoolish666/mario:latest 使用 浏览器打开 http://你的ip:10034/

微信小程序 安卓/IOS兼容问题

一、背景 在开发微信小程序时&#xff0c;不同的手机型号会出现兼容问题&#xff0c;特此记录一下 二、安卓/IOS兼容问题总结 2.1、new Date()时间转换格式时&#xff0c;IOS不兼容 问题&#xff1a;在安卓中时间格式2024-1-31 10:10:10&#xff0c;但是在iOS中是不支持 &q…

基于FFT + CNN - BiGRU-Attention 时域、频域特征注意力融合的电能质量扰动识别模型

目录 往期精彩内容&#xff1a; 引言 1 快速傅里叶变换FFT原理介绍 第一步&#xff0c;导入部分数据&#xff0c;扰动信号可视化 第二步&#xff0c;扰动信号经过FFT可视化 2 电能质量扰动数据的预处理 2.1 导入数据 第一步&#xff0c;按照公式模型生成单一信号 2.2 …

JavaScript基础五对象 内置对象 Math.random()

内置对象-生成任意范围随机数 Math.random() 随机数函数&#xff0c; 返回一个0 - 1之间&#xff0c;并且包括0不包括1的随机小数 [0, 1&#xff09; 如何生成0-10的随机数呢&#xff1f; Math.floor(Math.random() * (10 1)) 放大11倍再向下取整 如何生成5-10的随机数&…

wespeaker项目grpc-java客户端开发

非常重要的原始参考资料&#xff1a; 链接: triton-inference-server/client github/grpc java ps&#xff1a; 使用grpc协议的其它项目python/go可以参考git hub目录client/tree/main/src/grpc_generated下的其它项目 其它链接&#xff1a; 想要系统了解triton-inference-ser…

最近nvm安装报错的原因找到了——npm原淘宝镜像正式到期!

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 背景 错误原因 问题排查 淘宝镜像 证书到期 问题解决 结语 背景 我们…

在PostgreSQL中不开归档?恭喜你!锅你背定了

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

获取ping值最小IP

有时候我们访问一个网站&#xff0c;想要选择最佳的IP地址&#xff0c;那就可能需要修改hosts文件。那么怎么获取最佳的IP地址呢&#xff0c;我们以访问github为例。 获取IP 首先是看对应的url会解析出哪些IP。可以在通过站长工具测试多个地点Ping服务器,网站测速 - 站长工具…

【循环结构·js】

变量命名原则 变量名由字母、下划线、$ 或数字组成&#xff0c;并且必须由字母、下划线、$ 开头。 变量名不能命名为系统关键字和保留字。 JS代码在sourse里面调试 document.write(str); /*在页面上输出变量 str 的值*/数据类型的分类 为什么要标识数据类型&#xff1a; 不…

【C语言】通讯录实现(下)

目录 1.进阶通讯录特点&#xff08;下&#xff09; 2.实现步骤 &#xff08;1&#xff09;保存增加的联系人数据到文件中 &#xff08;2&#xff09;加载保存的联系人数据 3.完整C语言通讯录代码 &#xff08;1&#xff09;contact.h (2)test.c (3)contact.c 4.结语 1.…