跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

Spring Boot + jQuery 前后端分离图书管理系统实战

基于 Spring Boot 和 jQuery 构建前后端分离的图书管理系统,涵盖实体类设计、控制器接口编写及 Mock 数据模拟策略。重点解析登录验证流程与列表渲染逻辑,并通过调试手段排查前后端交互问题。深入探讨 GET 与 POST 请求在参数位置、数据格式及安全性的实际差异,强调 Body 传参时前后端协议一致性的重要性,为开发提供实用的接口设计与排查思路。

晚风叙旧发布于 2026/3/21更新于 2026/6/421 浏览
Spring Boot + jQuery 前后端分离图书管理系统实战

图书管理系统

1. 准备前端代码

前端资源可参考项目仓库获取,这里主要关注后端接口设计与前后端联调逻辑。

2. 约定前后端交互接口

这是一个相对完整的项目案例,我们先聚焦核心功能实现:用户登录与图书列表展示。

文章配图

2.1 登录接口

文章配图

2.2 图书列表展示

文章配图

字段说明:

字段说明
id图书 ID
bookName图书名称
author作者
count数量
price定价
publish图书出版社
status图书状态(1 - 可借阅,其他 - 不可借阅)
statusCN图书状态中文含义

3. 后端核心逻辑实现

3.1 实体类定义

创建 BookInfo 类,对应数据库中的图书信息表结构。

@Data
public class BookInfo {
    // 图书 ID
    private Integer id;
    // 书名
    private String bookName;
    // 作者
    private String author;
    // 数量
    private Integer count;
    // 定价
    private BigDecimal price;
    // 出版社
    private String publish;
    // 状态 0-不允许借阅 1-允许借阅
    private Integer status;
    private String statusCN;
    // 创建时间
    private Date createTime;
    // 更新时间
    private Date updateTime;
}
3.2 控制器开发

UserController:处理登录验证。

import jakarta.servlet.http.HttpSession;
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;
        }
        // 账号密码正确,账号 admin & 密码 admin
        if ("admin".equals(name) && "admin".equals(password)) {
            session.setAttribute("userName", name);
            return true;
        }
        // 账号密码错误
        return false;
    }
}

BookController:获取图书列表。

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 = mockData();
        // 处理页面展示
        for (BookInfo book : books) {
            if (book.getStatus() == 1) {
                book.setStatusCN("可借阅");
            } else {
                book.setStatusCN("不可借阅");
            }
        }
        return books;
    }

    /**
     * 数据 Mock 获取图书信息
     */
    public List<BookInfo> mockData() {
        List<BookInfo> books = new ArrayList<>();
        for (int i = 1; i <= 15; i++) {
            BookInfo book = new BookInfo();
            book.setId(i);
            book.setBookName("图书" + i);
            book.setAuthor("作者" + i);
            book.setCount(new Random().nextInt(100));
            book.setPrice(new BigDecimal(new Random().nextInt(100)));
            book.setPublish("出版社" + i);
            book.setStatus(i % 5 == 0 ? 2 : 1);
            books.add(book);
        }
        return books;
    }
}

关于 Mock 数据的说明:

在开发和测试过程中,环境可能不稳定或协同同事未完成接口,此时构造真实数据成本较高。Mock(模拟)就是创建虚拟对象或数据样本,辅助开发或测试。简单来说,就是用假数据占位。

将 Mock 逻辑封装成独立方法的好处很明显:代码整洁规范,后续接入真实数据库时,只需替换该方法内部逻辑即可,无需修改调用处。

4. 前端交互与渲染

4.1 登录页面

添加登录处理逻辑,使用 jQuery 发送 AJAX 请求。

<script src="js/jquery.min.js"></script>
<script>
function login() {
    $.ajax({
        type: "post",
        url: "/user/login",
        data: {
            name: $("#userName").val(),
            password: $("#password").val()
        },
        success: function (result) {
            if (result) {
                location.href = "book_list.html";
            } else {
                alert("账号或密码不正确!");
            }
        }
    });
}
</script>
4.2 图书列表展示

删除前端伪造的静态内容,改为从后端获取数据并动态渲染。

  1. 清理 <body></body> 标签中的硬编码内容。
  2. 完善获取图书方法。
function getBookList() {
    var finalHtml = "";
    $.ajax({
        type: "get",
        url: "/book/getList",
        success: function (result) {
            console.log(result);
            if (result != null) {
                for (var book of result) {
                    finalHtml += "<tr><input type='checkbox' name='selectBook' value='" + book.id + "'></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><div>" + book.statusCN + "</div></td>";
                    finalHtml += "<td><a href='book_update.html?bookId=" + book.id + "'>修改</a>";
                    finalHtml += "<a href='javascript:void(0)' onclick='deleteBook(" + book.id + ")'> 删除</a></td>";
                    finalHtml += "</tr>";
                }
                $("tbody").html(finalHtml);
            }
        }
    });
}

5. 问题排查与调试

当效果未达预期时,不要盲目猜测,建议按以下步骤排查:

  1. 检查两端代码:肉眼可见范围有限,优先通过 Debug 和日志分析。
  2. 后端测试:使用 Postman 直接调用接口。
    • 第一步确认请求是否到达后端(打印参数变量)。
    • 第二步检查参数解析和返回结果是否正确。
    • 没问题再交给前端联调。
  3. 前端测试:查看浏览器控制台 Console 日志,确认 Ajax 回调数据是否符合预期。

6. GET 与 POST 的实战区别

在实际开发中,GET 和 POST 的区别主要体现在参数位置和数据格式约定上,而非简单的'能不能传参'。

6.1 参数位置差异
  • GET:参数只能放在 URL 中(Postman 里的 Params)。前后端配合简单,不存在格式解析问题。
  • POST:参数既可以放在 URL,也可以放在 Body 中。实际开发中最常用的是 Body。
6.2 数据格式一致性

一旦使用 POST 的 Body 传参,前后端必须严格约定格式:

  • 前端用 JSON,后端必须按 JSON 解析。
  • 前端用 form-data,后端也要用对应方式接收。
  • 前端用 x-www-form-urlencoded,后端同样需匹配。

否则会出现'前端传了,后端收不到'的经典问题。

6.3 语义与安全性
  • GET:用于获取资源,幂等且可缓存。受 URL 长度限制,不适合传大量数据,且参数暴露在 URL 中,不适合敏感信息。
  • POST:用于提交资源,非幂等。无明确大小限制,参数在 Body 中,相对更安全(需配合 HTTPS)。
6.4 Postman 的约束本质

Postman 默认隐藏 GET 请求的 Body 输入框,并非强制禁止,而是遵循行业最佳实践,引导开发者写出符合规范的代码。虽然可以通过抓包工具强行给 GET 加 Body,但这属于非常规操作,存在兼容性风险(如 Nginx、CDN 可能丢弃 Body 数据)和缓存失效问题,不建议在生产环境中使用。

总结:实际开发中,GET 和 POST 的最大区别在于 POST 的 Body 传参需要前后端格式一致,而 GET 没有这个问题。

目录

  1. 图书管理系统
  2. 1. 准备前端代码
  3. 2. 约定前后端交互接口
  4. 2.1 登录接口
  5. 2.2 图书列表展示
  6. 3. 后端核心逻辑实现
  7. 3.1 实体类定义
  8. 3.2 控制器开发
  9. 4. 前端交互与渲染
  10. 4.1 登录页面
  11. 4.2 图书列表展示
  12. 5. 问题排查与调试
  13. 6. GET 与 POST 的实战区别
  14. 6.1 参数位置差异
  15. 6.2 数据格式一致性
  16. 6.3 语义与安全性
  17. 6.4 Postman 的约束本质
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 OpenCode + OpenSpec 的企业级 AI Coding 工程化落地实践
  • C++ 内存管理:new/delete 操作自定义类型的构造与析构原理
  • AI 大模型通信机制解析:流式传输与数据封装逻辑
  • 牧神记圣女司幼幽 AI 绘图工作流搭建:Z-Turbo 模型实战
  • 主流大模型的优势与未来发展趋势分析
  • 基于深度学习的无人机洪水图像分割与水量估算
  • 双指针算法实战:唯一雪花、逛画展与丢手绢
  • 远程控制软件安全分析:ToDesk、RayLink、TeamViewer 与 Splashtop 机制对比
  • AI 大模型时代下 2024 年医疗器械网络安全应对与挑战
  • AI 大模型技术入门与全栈开发实战指南
  • 智慧农业-无人机枸杞树病害检测数据集 深度学习框架基于YOLOV8枸杞病害检测系统 无人机智慧农业枸杞病害巡检
  • C++ 函数重载:原理、匹配规则与底层实现
  • 单链表核心操作全实现与深度解析
  • 第十四届蓝桥杯 C/C++ 省赛 B 组题解
  • 深入解析 Spark 数据读取与 Hive 数据来源
  • 快速排序非递归实现详解:栈模拟与代码实战
  • 前端精确数字运算:使用 BigNumber.js 解决 JavaScript 精度问题
  • LLM 存储优化实战:解决大量 QA 与长对话记忆问题
  • C++ 基础数据类型详解与课后练习
  • 金仓 KingbaseES 融合架构实践:从多库并存到一库多能

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online