项目实战_图书管理系统(简易版)
你能学到什么
- 一个简单的项目——图书管理系统(浏览器:谷歌)
- 基础版我们只做两个功能(因为其它的功能涉及的会比较多,索性就放在升级版里了,基础版先入个门)
-
- 登录: ⽤⼾输⼊账号,密码完成登录功能
-
- 列表展⽰: 展⽰图书
-
- 升级版将会在下个博客发布
正文
成品效果展示


新建项目

前端代码准备
由于主做后端,写前端代码有些吃力,可以在我分享的网盘中拿到下面的前端文件
链接: https://pan.baidu.com/s/1J9LCqfNmpG6CKykj3l772A?pwd=qqu2
提取码: qqu2

测试前端代码
然后运行整个程序,使用浏览器,访问http://127.0.0.1:8080/login.html
看看是否能正常显示,也能访问其他html文件看看是否能正常显示。如果能正常显示就说明复制过来的前端代码没问题,不要计较前端加载的那些数据,那些都是假数据,后期那些代码是需要我们改的。
直接添加Mybatis依赖发生的问题

运行结果:

由于我们没有配置数据库信息,所以会发生报错,解决方案:
- 1,配置数据库信息
- 2,先将Mybatis的依赖删掉,在用的时候在手动添加上,再配置数据库(注意无论是删除还是添加,最好每进行一步刷新一次Maven,这样就不会有缓存问题了)
这两个就是Mybatis的依赖:

编写后端代码
需求分析
根据需求可以得知, 后端需要提供两个接⼝
- 登录账号密码校验接⼝: 根据输⼊⽤⼾名和密码校验登录是否通过
- 图书列表: 提供图书列表信息
登录接口

有了需求文档我们就知道了下一步该做什么,要想验证密码和用户名正不正确,前端肯定会向后端发送用户名和密码。此时我们只需要将用户传过来的用户名和密码和我们存储的用户名和密码对比,如果相同就返回true,反之,返回false。
这里为了方便起见我们就先将用户名和密码写死
name:zhangsan
password:123456
接下就是写代码了,为了实现应用分层,我还是在Controller包里写controller代码
package com.example.blogssystems_blogs.Controller;import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;//注意:一定不要写错注解,否则会付出血和泪的教训啊
@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public boolean login(String name, String password, HttpSession session){//账号或密码为空if (!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){return false;}if("zhangsan".equals(name) && "123456".equals(password)){//如果正确,就将该信息储存在session里session.setAttribute("username",name);return true;}return false;}}
测试登录代码
我们使用Postman来测试一下

图书列表展示接口

接下来就是获取图书列表接口了,我们知道要想返回图书信息,我们得先有一个图书类啊,用来描述图书

图书实体类代码:
package com.example.blogssystems_blogs.model;import lombok.Data;import java.math.BigDecimal;
import java.util.Date;@Data
public class BookInfo {//图书IDprivate Integer id;//书名private String bookName;//作者private String author;//数量private Integer count;//定价,BigDecimal有兴趣的可以查一查这个类型private BigDecimal price;//出版社private String publish;//状态 0-⽆效 1-允许借阅 2-不允许借阅private Integer status;//statusCN是根据status来改变的,比如:status是0——》statusCN就是 “不可借阅”// status是1——》statusCN就是 ”可借阅“// status是2——》statusCN就是 “不可借阅”//本质上statusCN这个属性就是根据status的状态来改变对前端页面的显示(反过来想一想:你总不可能在前端直接显示0,1,2吧//或者如果你直接使用statusCN,那样传参会很麻烦,之后升级版会有更简单的方法(使用枚举))private String statusCN;//创建时间,这里的Date是util包里的(先用起来,下面会说)private Date createTime;//更新时间private Date updateTime;
}
- BigDecimal 的官方文档

其实说人话:BigDecimal就是精确的小数,可以和BigInteger类比一下,至于多精确,那还得看官方文档,这里就不深究了。 - 这是Date的官方文档

图书类都创建好了,接下来就是提供图书信息的功能了
package com.example.blogssystems_blogs.Controller;import com.example.blogssystems_blogs.model.BookInfo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;@RequestMapping("/book")
@RestController
public class BookController {@RequestMapping("/getList")public List<BookInfo> getList(){List<BookInfo> books = mockBookData();//在这里就将StatusCN用上了,就是这样用的for (BookInfo book: books) {if(book.getStatus() == 1){book.setStatusCN("可借阅");}else{book.setStatusCN("不可借阅");}}return books;}//创建一个假的图书列表,由于我们还没有引进数据库,所以就先将就一下private List<BookInfo> mockBookData() {List<BookInfo> books = new ArrayList<>();for (int i = 0; i < 5; i++) {BookInfo book = new BookInfo();book.setId(i);book.setBookName("书籍" + i);book.setAuthor("作者" + i);book.setCount(i * 5 + 3);book.setPrice(new BigDecimal(new Random().nextInt(100)));book.setPublish("出版社" + i);book.setStatus(1);books.add(book);}return books;}
}
测试图书列表接口代码
我们还是使用Postman来发送请求。
可以看到没有任何问题

前端代码修改
前端登录
后端的代码确保正确了以后,就该修改前端代码了。由于我提供的前端代码只是个框架,所以还需要修改
我们先修改前端的登录页面:
前端只需要修改login函数里的代码就行了。
<script>function login() {$.ajax({type:"post",url:"user/login",data:{name:$("#userName").val(),password:$("#password").val()},//ret是后端的返回值,如果是true说明账号密码正确,跳转至图书列表页面success:function (ret){if(ret == true){location.href = "book_list.html"}else{alert("账号或密码错误")}}});}</script>
测试前端登录代码

前端图书展示

代码:
function getBookList() {$.ajax({type:"post",url:"book/getList",success:function (ret) {if(ret != null){var finalHtml = "";for (var book of ret) {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>";finalHtml+="<div class=\"op\">";finalHtml+="<a href=\"book_update.html?bookId=4\">修改</a>";finalHtml+="<a href=\"javascript:void(0)\" οnclick=\"deleteBook(4)\">删除</a>";finalHtml+="</div>";finalHtml+="</td>";finalHtml+="</tr>";}$("tbody").html(finalHtml);}}});
测试图书展示代码
可以看到图书的显示没有任何问题

- 注意:

简易版只实现上述两个功能,如有兴趣还请看下一期的升级版,升级版将会实现页面上的各个功能,以及解决统一事务的处理方式。
一个小瑕疵
由于我的大意,将图书管理系统BooksSystem的名字起成了博客系统BlogsSystem,在写的时候我竟然一点都没有察觉,写完了才发现名字起的不对,如果要改,截图就都要一起改了,成本有点大,再加上最近也在准备升级版,希望大家见谅,凑合着看,很抱歉,以后我一定会严于律己,不再马虎的。出错的只有名字,不耽误图书管理的功能的,大家可以放心看内容。
相关文章:
项目实战_图书管理系统(简易版)
你能学到什么 一个简单的项目——图书管理系统(浏览器:谷歌)基础版我们只做两个功能(因为其它的功能涉及的会比较多,索性就放在升级版里了,基础版先入个门) 登录: ⽤⼾输⼊账号,密码完成登录功…...
Gazebo之MyRobot建立
Gazebo之MyRobot建立 1. 源由2. 示例Step 1: 新建一个简单世界Step 2: 新建一个模型(model)Step 3: 机器人组成链接(Links)Step 3.1: 新增底盘(Links/Chassis)Step 3.1.1: 惯性属性(Inertial properties)Step 3.1.2: 视觉(Visual)Step 3.1.3: 碰撞(Collision) Step 3.2: 新增左…...
WPF学习(5)- Border控件(边框布局)+GridSplitter分割窗口
严格来说,Border并不是一个布局控件,因为它并不是Panel的子类,而是Decorator装饰器的子类,而Decorator继承于FrameworkElement。我们要先看看它的父类Decorator。 public class Decorator : FrameworkElement, IAddChild {public…...
ADAS芯片及方案
一 ADAS芯片及方案 1.1 高通SA8775P Snapdragon Ride Flex(SA8775P)舱驾融合平台可通过单颗SoC同时支持数字座舱和智能驾驶功能,在CPU、GPU、NPU的处理能力方面具备强大的性能表现与领先优势,支持实现复杂的智能座舱功能&#x…...
5 mysql 查询语句
1.DML:对数据进行增删改查 提示:Execute执行 Execute and Suppress 执行并且抑制这个警告 person表的结构 /* DML:Data Manipulation Language 数据操作语言,对数据进行 增删改查操作,因为査询的操作太频繁和复杂,将…...
从网络上下载并展示图像数据
一、代码 from PIL import Image import requests from io import BytesIO import matplotlib.pyplot as pltimage_url "https://www.alleycat.org/wp-content/uploads/2019/03/FELV-cat.jpg" response requests.get(image_url) # response.content 获取 HTTP 响…...
Machine-Learning 机器学习
目录 基本概念与分类 工作原理 应用领域 发展趋势 机器学习中的深度学习是如何工作的,以及它如何影响其他机器学习算法? 在机器学习中,哪些特定的数据预处理技术最有效,特别是在处理大规模数据集时? 强化学习在…...
CSP 2023 普及组第一轮 - CSP/S 2023初试题 基础部分解析
第 1 题 在 C 中,下面哪个关键字用于声明一个变量, 其值不能被修改?(B) A. unsigned B. const C. static D. mutable 【const声明的变量不可修改】 第 2 题 八进制数 12345670(8) 和 07654321(8) 的和为(D) A. 222222…...
解锁IPython的跨平台魔法:深入探索%%script命令的神秘力量
IPython 的 %%script 魔法命令是一种强大的工具,它允许你在 IPython 环境中执行外部脚本。这个特性特别适用于需要在 IPython Notebook 中直接与 Web 技术交互的场景。下面我将为你详细介绍 %%script 命令的使用方法,并通过代码示例展示其强大功能。 一…...
如何避免项目发布后用户从浏览器WebPack中看到源码
打包前在config->index.js中设置productionSourceMap为false productionSourceMap: false,...
java学习19VUE
VUE NPM npm的全称是Node Package Manager 中文名为Node.js包管理器,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。NPM可以方便地从一个全球的代码库中获取并安装Node.js模块,这些模块可以用于构建应用程序、…...
Redis7(四)哨兵、集群
哨兵 吹哨人巡查监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为主库,继续对外服务 哨兵的作用: 监控redis运行状态,包括master和slave当master宕机了,能自动将slave转换为master 哨兵的功能…...
校园课程助手【3】-使用枚举类封装异常优雅处理全局异常
接着2中登录模块补充一个点: //可以看到这里返回给前端控制器的是一个类而不是html页面public RespBean doLogin(Valid LoginVo loginVo, HttpServletRequest request,HttpServletResponse response){return userService.doLogin(loginVo, request, response);}首先…...
LeetCode面试150——58最后一个单词的长度
题目难度:简单 默认优化目标:最小化平均时间复杂度。 Python默认为Python3。 目录 1 题目描述 2 题目解析 3 算法原理及代码实现 3.1 反向遍历 参考文献 1 题目描述 给你一个字符串 s,由若干单词组成,单词前后用一些空格字…...
MySQL——数据库的操作,数据类型,表的操作
MySQL——数据库的操作,数据类型,表的操作 1. 数据库的操作1.1 显示当前数据库1.2 创建数据库舍弃当前所写的SQL语句查看当前数据库服务全局的默认字符集 1.3 使用数据库1.4 查看当前操作的数据库查看MySQL的帮助 1.5 删除数据库 2. 常见数据类型2.1 数值…...
Go 临界资源 安全问题
临界资源安全的问题: 临界资源: 指并发环境中多个 进程/线程/协程 可以共享(都可以调用)的资源/变量,如果在并发环境中处理不当,就会造成一些 严重、问题 func main() {//临界资源a : 10go func() {a 100f…...
安卓常用控件(上)
文章目录 TextViewButtonEditText TextView textview主要用于在界面上显示一段文本信息。 属性名描述id给当前控件定义一个唯一的标识符。layout_width给控件指定一个宽度。match_parent:控件大小与父布局一样;wrap_content:控件大小刚好够包…...
基于 RabbitMQ 实现延迟消息的订单处理流程
文章目录 订单创建流程1. 商品查询与订单数据初始化2. 总价计算与订单保存3. 扣减库存与购物车清理4. 延迟消息与支付状态检测 订单延迟消息监听器支付成功与订单取消1. 订单支付成功2. 订单取消与库存恢复 总结 在现代电商系统中,订单处理是一个复杂且关键的环节。…...
使用Python将Word文档转换为PNG图片
在这篇博客中,我将介绍一个使用Python编写的小工具,它能够将指定文件夹中的所有Word文档(.doc和.docx格式)转换为PNG图片。这个工具基于wxPython库构建图形用户界面,并结合了win32com和PyMuPDF库实现文档格式的转换。接…...
Qt创建Json对象时浮点数的精度控制
我们在Qt中使用Json都是使用QJsonDocument、QJsonArray、QJsonObject、QJsonValue等类。 当我们在QJsonObject中插入浮点数字段时,会发现浮点数的小数位数很长,如下所示: #include <QJsonDocument> #include <QJsonArray> #incl…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
