【基于SpringBoot的图书购买系统】Redis中的数据以分页的形式展示:从配置到前后端交互的完整实现

基于 Spring Boot 的图书购买系统:Redis 中的数据以分页形式展示完整实现

在图书购买系统中,我们常常需要将图书数据缓存到 Redis 中(如热门图书列表),并支持分页展示。这可以提高查询效率,避免频繁访问数据库。本教程基于 Spring Boot 3.x(最新 LTS 版本),使用 Redis 作为缓存层,实现从配置到前后端交互的完整流程。

前提假设

  • 项目使用 Spring Boot + Redis + Spring Data Redis。
  • 图书实体(Book):包含 id、title、author、price 等字段。
  • 数据存储在 Redis 的 List 或 Sorted Set 中(推荐 Sorted Set 以支持排序和高效分页)。
  • 分页策略:Redis 无原生分页,使用 ZRANGE(Sorted Set)或 LRANGE(List)模拟。基于工具搜索结果,Sorted Set 是高效选择(O(log N + M) 复杂度,M 为页面大小)。
  • 前端:简单使用 HTML + JavaScript(Fetch API)调用 REST 接口展示分页数据。生产环境可换 Vue/React。

项目结构概览

src/main/java ├── com.example.bookstore │ ├── BookstoreApplication.java │ ├── config/RedisConfig.java │ ├── entity/Book.java │ ├── service/BookService.java │ ├── controller/BookController.java resources/application.properties frontend/index.html // 前端页面(可选,放在 static 目录或单独前端项目)
步骤 1: 项目初始化与依赖配置
  1. 创建 Spring Boot 项目

    • 使用 Spring Initializr(https://start.spring.io/)创建项目。
    • 选择:Spring Boot 3.2.x、Java 17+、依赖:Spring Web、Spring Data Redis、Lombok(可选)。
  2. 添加依赖(pom.xml):

<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Lombok 简化代码 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>
  1. 安装 Redis
    • Windows/macOS:下载 Redis 官方版或用 Docker:docker run -d -p 6379:6379 redis
    • 默认端口 6379,无密码。
步骤 2: Redis 配置
  1. application.properties配置 Redis 连接:
# Redis 配置 spring.data.redis.host=localhost spring.data.redis.port=6379 # 可选:密码、数据库 # spring.data.redis.password=yourpassword # spring.data.redis.database=0 # 缓存配置(可选,启用缓存) spring.cache.type=redis spring.cache.redis.time-to-live=600000 # 缓存 TTL 10 分钟
  1. Redis 配置类(RedisConfig.java):自定义 RedisTemplate,支持序列化。
packagecom.example.bookstore.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializer;@ConfigurationpublicclassRedisConfig{@BeanpublicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryconnectionFactory){RedisTemplate<String,Object>template=newRedisTemplate<>();template.setConnectionFactory(connectionFactory);// 使用 JSON 序列化(支持复杂对象)RedisSerializer<?>jsonSerializer=newGenericJackson2JsonRedisSerializer();template.setDefaultSerializer(jsonSerializer);template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);returntemplate;}}
  • 解释:默认 StringRedisTemplate 只支持字符串;这里用 RedisTemplate 支持对象存储。JSON 序列化便于存储 Book 对象。
步骤 3: 图书实体与数据存储到 Redis
  1. Book 实体(Book.java):
packagecom.example.bookstore.entity;importlombok.Data;@DatapublicclassBook{privateLongid;privateStringtitle;privateStringauthor;privateDoubleprice;}
  1. BookService:存储图书到 Redis 的 Sorted Set(键:“books”,score 为 id 或 price 以支持排序)。
packagecom.example.bookstore.service;importcom.example.bookstore.entity.Book;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.core.ZSetOperations;importorg.springframework.stereotype.Service;importjava.util.List;importjava.util.Set;importjava.util.stream.Collectors;@ServicepublicclassBookService{@AutowiredprivateRedisTemplate<String,Object>redisTemplate;privatestaticfinalStringBOOKS_KEY="books";// Redis Sorted Set 键// 添加图书(score 为 id,假设 id 自增)publicvoidaddBook(Bookbook){ZSetOperations<String,Object>zSetOps=redisTemplate.opsForZSet();zSetOps.add(BOOKS_KEY,book,book.getId());// score = id}// 分页查询(使用 ZRANGE 模拟分页)publicList<Book>getBooksByPage(intpage,intsize){ZSetOperations<String,Object>zSetOps=redisTemplate.opsForZSet();// ZRANGE start = (page-1)*size, end = page*size -1Set<Object>booksSet=zSetOps.range(BOOKS_KEY,(page-1)*size,page*size-1);returnbooksSet.stream().map(obj->(Book)obj).collect(Collectors.toList());}// 获取总记录数publiclonggetTotalBooks(){returnredisTemplate.opsForZSet().size(BOOKS_KEY);}}
  • 分页实现:使用 Sorted Set 的 ZRANGE,按 score 分页。page 从 1 开始。
  • 为什么 Sorted Set:支持排序和范围查询,效率高于 List 的 LRANGE(List 为 O(N) 最坏情况)。
  • 数据初始化:可在应用启动时(或测试方法)添加样例数据:
// 在服务中添加测试方法或 CommandLineRunnerpublicvoidinitData(){addBook(newBook(1L,"Java编程思想","Bruce Eckel",99.0));addBook(newBook(2L,"Spring Boot实战","Craig Walls",89.0));// ... 添加更多}
步骤 4: 后端控制器(REST API)

BookController.java:提供分页 API,支持 ?page=1&size=10 参数。

packagecom.example.bookstore.controller;importcom.example.bookstore.entity.Book;importcom.example.bookstore.service.BookService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RestControllerpublicclassBookController{@AutowiredprivateBookServicebookService;@GetMapping("/books")publicResponseEntity<Map<String,Object>>getBooks(@RequestParam(defaultValue="1")intpage,@RequestParam(defaultValue="10")intsize){List<Book>books=bookService.getBooksByPage(page,size);longtotal=bookService.getTotalBooks();Map<String,Object>response=newHashMap<>();response.put("books",books);response.put("total",total);response.put("currentPage",page);response.put("totalPages",(total+size-1)/size);returnResponseEntity.ok(response);}}
  • 解释:返回 JSON,包括图书列表、总记录、页码。使用 Spring 的 @RequestParam 处理分页参数。
步骤 5: 前端交互(简单 HTML + JS)

假设前端页面为 index.html(放在 src/main/resources/static/ 下,或单独前端项目)。

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>图书购买系统 - 分页展示</title><style>table{border-collapse:collapse;width:100%;}th, td{border:1px solid #ddd;padding:8px;}.pagination{margin-top:10px;}button{margin:0 5px;}</style></head><body><h1>Redis 中的图书列表(分页)</h1><tableid="bookTable"><thead><tr><th>ID</th><th>标题</th><th>作者</th><th>价格</th></tr></thead><tbody></tbody></table><divclass="pagination"><buttonid="prevBtn"disabled>上一页</button><spanid="pageInfo"></span><buttonid="nextBtn">下一页</button></div><script>letcurrentPage=1;constpageSize=10;asyncfunctionfetchBooks(page){constresponse=awaitfetch(`/books?page=${page}&size=${pageSize}`);constdata=awaitresponse.json();consttbody=document.querySelector('#bookTable tbody');tbody.innerHTML='';// 清空表格data.books.forEach(book=>{consttr=document.createElement('tr');tr.innerHTML=`<td>${book.id}</td><td>${book.title}</td><td>${book.author}</td><td>${book.price}</td>`;tbody.appendChild(tr);});document.getElementById('pageInfo').textContent=`${data.currentPage}页 / 共${data.totalPages}页 (总${data.total}本书)`;document.getElementById('prevBtn').disabled=data.currentPage===1;document.getElementById('nextBtn').disabled=data.currentPage>=data.totalPages;}// 按钮事件document.getElementById('prevBtn').addEventListener('click',()=>{if(currentPage>1){currentPage--;fetchBooks(currentPage);}});document.getElementById('nextBtn').addEventListener('click',()=>{currentPage++;fetchBooks(currentPage);});// 初始加载fetchBooks(currentPage);</script></body></html>
  • 解释:使用 Fetch API 调用后端 /books 接口,动态渲染表格和分页按钮。点击“上一页/下一页”触发请求。
步骤 6: 测试与运行
  1. 启动应用:运行 BookstoreApplication.java,确保 Redis 运行。
  2. 初始化数据:在服务中调用 initData() 或手动通过 Redis CLI 添加。
  3. 访问前端:浏览器打开 http://localhost:8080/index.html,查看分页效果。
  4. 验证 Redis:用 Redis CLI:ZRANGE books 0 -1 WITHSCORES查看数据。
注意事项与优化
  • 性能:分页大小(size)不宜太大(<100),避免 O(N) 开销。
  • 错误处理:添加 try-catch 处理 Redis 连接异常。
  • 生产优化:用 Lettuce 连接池(默认配置)、添加缓存注解 @Cacheable(如果结合数据库)。
  • 扩展:结合数据库(JPA),Redis 只缓存热门图书;前端用 Element UI 或 Ant Design 提升 UI。
  • 最佳实践(基于搜索结果):Sorted Set 适合带排序的分页;若无排序需求,可用 List + LRANGE。

这个实现覆盖了从配置到交互的全链路。如果需要完整源码或特定调整(如用 Vue),随时告诉我!🚀

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

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

相关文章

SmartTaskbar终极指南:让Windows任务栏自动隐藏变得如此简单

SmartTaskbar终极指南&#xff1a;让Windows任务栏自动隐藏变得如此简单 【免费下载链接】SmartTaskbar A lightweight utility which can automatically switch the display state of the Windows Taskbar. 项目地址: https://gitcode.com/gh_mirrors/smar/SmartTaskbar …

5个高可用图像转视频开源镜像推荐:免配置一键部署

5个高可用图像转视频开源镜像推荐&#xff1a;免配置一键部署 Image-to-Video图像转视频生成器 二次构建开发by科哥 在AIGC内容创作领域&#xff0c;图像转视频&#xff08;Image-to-Video, I2V&#xff09; 正成为极具潜力的技术方向。相比静态图像生成&#xff0c;动态视频能…

DOL游戏模组终极完整使用指南:快速上手与最佳配置方案

DOL游戏模组终极完整使用指南&#xff1a;快速上手与最佳配置方案 【免费下载链接】DOL-CHS-MODS Degrees of Lewdity 整合 项目地址: https://gitcode.com/gh_mirrors/do/DOL-CHS-MODS 想要轻松体验DOL游戏的中文化魅力&#xff1f;本教程将为你提供最完整的DOL游戏模组…

收藏!Python都不会能直接学AI大模型?小白程序员入门避坑指南

“博主&#xff0c;我连Python都不会&#xff0c;能直接学AI大模型吗&#xff1f;” 最近后台私信快被这类问题淹没了&#xff1a; “想入门AI大模型&#xff0c;求一份从零到一的学习路径&#xff01;” “我是前端开发&#xff0c;转AI大模型方向需要多久能上手&#xff1f;”…

多情感语音合成的商业价值:Sambert-HifiGan案例研究

多情感语音合成的商业价值&#xff1a;Sambert-HifiGan案例研究 引言&#xff1a;中文多情感语音合成的技术演进与商业机遇 随着人工智能在人机交互领域的深入发展&#xff0c;语音合成&#xff08;Text-to-Speech, TTS&#xff09; 已从早期机械、单调的“机器人音”逐步迈向…

大模型学习路线图:Transformer、微调、RAG等核心技术全解析,建议收藏!

本文系统介绍大模型核心技术&#xff0c;涵盖Transformer架构与混合专家模型&#xff0c;五大微调技术策略&#xff0c;传统RAG与Agentic RAG、HyDE、Graph RAG等变体对比&#xff0c;文本分块方法&#xff0c;智能体系统等级划分&#xff0c;以及KV缓存优化技术。内容全面覆盖…

OpenSpeedy加速方案:让Image-to-Video运行更快的3种方式

OpenSpeedy加速方案&#xff1a;让Image-to-Video运行更快的3种方式 &#x1f680; 背景与挑战&#xff1a;I2VGen-XL模型的性能瓶颈 Image-to-Video图像转视频生成器&#xff08;基于I2VGen-XL模型&#xff09;为静态图像注入动态生命力&#xff0c;实现了从单张图片到连贯视频…

JVM 堆内存分代

今天我们一起来聊一聊 JVM 堆内存。 Java Heap&#xff08;堆内存&#xff09;由 Young Generation&#xff08;新生代&#xff0c;约占 1/3 &#xff09;和 Old Generation&#xff08;老年代&#xff0c;约占 2/3 &#xff09;组成。 Young Generation 又由 Eden Space&…

Spring Boot 配置文件深度解析

Spring Boot 配置文件深度解析&#xff08;2026 最新版&#xff09; Spring Boot 的配置文件是整个应用的核心“控制中心”&#xff0c;它决定了应用的端口、数据库连接、日志级别、自定义属性等几乎所有行为。Spring Boot 提供了强大而灵活的配置机制&#xff0c;支持多种格式…

马克思主义与认识论:巴舍拉、康吉莱姆与福柯的思想交汇

马克思主义与认识论&#xff1a;巴舍拉、康吉莱姆与福柯的思想交汇在哲学与科学的互动谱系中&#xff0c;马克思主义认识论始终以历史唯物主义为根基&#xff0c;强调知识生产与社会历史条件的辩证关联。巴舍拉、康吉莱姆与福柯三位思想家&#xff0c;通过对科学知识形成机制、…

响应式Web测试最佳实践

响应式Web测试的重要性与挑战在当今多设备互联的时代&#xff0c;响应式网页设计&#xff08;Responsive Web Design, RWD&#xff09;已成为Web开发的标配&#xff0c;它确保网站能在智能手机、平板、桌面等多种屏幕尺寸上自适应展示。然而&#xff0c;对于软件测试从业者而言…

Image-to-Video生成失败?这5个CUDA错误解决方案必看

Image-to-Video生成失败&#xff1f;这5个CUDA错误解决方案必看 背景与问题定位&#xff1a;Image-to-Video二次开发中的典型GPU挑战 在基于 I2VGen-XL 模型的 Image-to-Video 图像转视频生成器 二次构建过程中&#xff0c;开发者“科哥”成功实现了本地化部署和WebUI交互功能。…

2026年移动测试工具Top 5

移动测试工具的演变与2026年展望移动应用测试已成为软件开发生命周期的核心环节&#xff0c;随着5G普及、AI融合和跨平台需求激增&#xff0c;2026年移动测试工具正经历革命性变革。本文基于行业报告&#xff08;如Gartner预测&#xff09;和实际案例&#xff0c;为测试从业者深…

Sambert-HifiGan语音合成服务性能基准测试

Sambert-HifiGan语音合成服务性能基准测试 &#x1f4ca; 测试背景与目标 随着AI语音技术的普及&#xff0c;高质量、低延迟的中文语音合成&#xff08;TTS&#xff09;系统在智能客服、有声阅读、虚拟主播等场景中需求激增。Sambert-HifiGan 作为 ModelScope 平台上表现优异的…

Sambert-HifiGan多情感语音合成:如何实现情感自然过渡

Sambert-HifiGan多情感语音合成&#xff1a;如何实现情感自然过渡 引言&#xff1a;中文多情感语音合成的现实需求 随着智能客服、虚拟主播、有声阅读等应用场景的不断拓展&#xff0c;传统单一语调的语音合成&#xff08;TTS&#xff09;已难以满足用户对表达自然性与情感丰富…

codex思维迁移:如何构建自己的AI视频生成器?

codex思维迁移&#xff1a;如何构建自己的AI视频生成器&#xff1f; Image-to-Video图像转视频生成器 二次构建开发by科哥 “从一张静态图到一段动态影像&#xff0c;背后是扩散模型与时空建模的深度融合。” 在AIGC浪潮中&#xff0c;图像生成已趋于成熟&#xff0c;而视频生…

JAVA中对象的几种比较

Java 中对象的几种比较方式详解 Java 中对象的“比较”主要分为两种需求&#xff1a; 判断两个对象是否“相等”&#xff08;内容是否相同&#xff09;判断两个对象的大小关系&#xff08;排序用&#xff09; 对应地&#xff0c;Java 提供了多种机制来实现对象的比较。下面系…

云服务器按小时计费:节省50%算力开支的方法

云服务器按小时计费&#xff1a;节省50%算力开支的方法 背景与挑战&#xff1a;AI生成任务的算力成本困局 在当前AIGC&#xff08;人工智能生成内容&#xff09;爆发式增长的背景下&#xff0c;图像转视频&#xff08;Image-to-Video&#xff09;等高算力需求任务已成为内容创作…

【Java毕设全套源码+文档】基于springboot的网络云端日记本系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Sambert-HifiGan语音合成服务的自动化测试方案

Sambert-HifiGan语音合成服务的自动化测试方案 引言&#xff1a;为何需要自动化测试&#xff1f; 随着语音合成技术在智能客服、有声阅读、虚拟主播等场景中的广泛应用&#xff0c;服务稳定性与输出质量的一致性成为工程落地的关键挑战。Sambert-HifiGan 作为 ModelScope 平台上…