飞算JavaAI的在线图书借阅平台的设计与实现,一文吃透!

飞算JavaAI的在线图书借阅平台的设计与实现,一文吃透!
在这里插入图片描述
🎁个人主页:User_芊芊君子
🎉欢迎大家点赞👍评论📝收藏⭐文章
🔍系列专栏:AI
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述

一、需求分析与规划

1.1 命题背景与功能需求

在线图书借阅平台旨在解决传统图书馆线下借阅效率低、用户查询不便等问题,目标用户覆盖在校师生及公共图书馆读者。通过需求调研,平台需实现 五大核心功能模块 ,具体如下表所示:

模块名称核心功能点用户角色
用户管理注册(含邮箱验证)、登录(密码加密)、个人信息维护、角色权限分级(普通用户/管理员)所有用户
图书检索支持关键词(书名/作者)、分类(文学/科技/历史)、库存状态(可借/已借出)多条件组合查询所有用户
借阅管理借书申请(校验库存)、续借操作(延长应还日期)、归还确认(更新库存与记录状态)普通用户
逾期管理自动计算逾期天数、生成违约金(如每日0.5元)、黑名单控制(逾期超3次禁用借阅权限)系统自动/管理员
数据统计借阅量月度报表、热门图书TOP10排行、用户活跃度分析管理员

技术选型依据

  • 后端:Spring Boot 2.7(快速构建RESTful API)、MyBatis-Plus(简化数据库CRUD)、JWT(用户认证令牌)、BCrypt(密码加密)
  • 前端:Vue 3 + Element Plus
  • 数据库:MySQL 8.0(支持事务、索引优化及复杂查询)
  • 开发工具:飞算JavaAI

1.2 核心模块拆解与流程可视化

否是否是否是用户访问平台是否注册?调用注册模块: 输入用户名/密码/邮箱生成用户ID, 写入user表, 发送验证邮件调用登录模块: 校验账号密码校验成功返回 用户名或密码错误生成JWT令牌, 加载用户主页输入关键词 分类 库存条件调用图书检索模块 查询book表+库存关联表返回图书列表及可借状态选择目标图书, 提交借阅申请调用借阅管理模块: 检查库存&生成借阅记录库存充足提示暂无库存更新库存数量, 写入borrow_record表, 返回应还日期借阅到期前3天, 系统自动触发续借提醒用户未续借且逾期, 计算违约金并更新用户状态

二、飞算JavaAI开发

操作步骤:打开飞算JavaAI,选择智能引导:

在这里插入图片描述
  • 这里输入我们需要的项目。
在这里插入图片描述
  • 给我们分析了几个关键点。
在这里插入图片描述
  • 下面等待接口设计。
在这里插入图片描述
  • 可以看到生成了很多;这里只需要等待即可。
在这里插入图片描述
  • 该系统具备用户、图书资源、借阅、还书、预约及搜索查询管理功能,可实现用户身份认证与访问安全保障,对图书信息进行全流程管理,规范借阅归还流程,提升图书利用率与用户体验,满足多样化查找需求;下面只需要下一步。
在这里插入图片描述
  • 等待处理接口的生成。
在这里插入图片描述
  • 可以看到已经生成完了。
在这里插入图片描述
  • 这里还是比较长的;因此等待会。
在这里插入图片描述
  • 最后进行部署即可。

部分代码展示

2.2.2 生成的实体类与控制器
// 实体类 User.java(自动生成Lombok注解与字段)@Data@TableName("user")publicclassUser{@TableId(type =IdType.AUTO)privateInteger id;privateString username;privateString password;// 实际存储BCrypt加密值privateString email;privateInteger role;// 0-普通用户, 1-管理员@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss")privateLocalDateTime createTime;}// 控制器 UserController.java(自动生成注册/登录逻辑)@RestController@RequestMapping("/api/user")publicclassUserController{@AutowiredprivateUserService userService;@PostMapping("/register")publicResultregister(@RequestBodyUserRegisterDTO dto){if(userService.checkUsernameExists(dto.getUsername())){returnResult.error("用户名已存在");}User user =newUser(); user.setUsername(dto.getUsername()); user.setPassword(BCrypt.hashpw(dto.getPassword(),BCrypt.gensalt()));// 密码加密 user.setEmail(dto.getEmail()); user.setRole(0);// 默认普通用户 user.setCreateTime(LocalDateTime.now()); userService.save(user);returnResult.success("注册成功");}@PostMapping("/login")publicResultlogin(@RequestBodyUserLoginDTO dto){User user = userService.getByUsername(dto.getUsername());if(user ==null||!BCrypt.checkpw(dto.getPassword(), user.getPassword())){returnResult.error("用户名或密码错误");}String token =JwtUtil.generateToken(user.getId(), user.getRole());// JWT生成returnResult.success(token);}}
2.2.3 借阅管理部分:
packagecom.feisuanyz.dto;importjakarta.validation.constraints.NotNull;importlombok.*;/** * <p> * 借阅审批数据传输对象 * </p> * @author z2222 */@Data@NoArgsConstructor@AllArgsConstructorpublicclassBorrowApproveDTO{@NotNull(message ="申请ID不能为空")privateLong applyId;@NotNull(message ="审批状态不能为空")privateInteger approveStatus;// 0-拒绝, 1-通过}
packagecom.feisuanyz.service.impl;importcom.feisuanyz.dto.BookDTO;importcom.feisuanyz.dto.BookQuery;importcom.feisuanyz.dto.RestResult;importcom.feisuanyz.entity.BookDO;importcom.feisuanyz.repository.BookRepository;importcom.feisuanyz.service.BookService;importjava.util.List;importjava.util.stream.Collectors;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.BeanUtils;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;/** * <p> * 图书服务实现类,实现业务逻辑 * </p> * @author z2222 */@Slf4j@ServicepublicclassBookServiceImplimplementsBookService{@AutowiredprivateBookRepository bookRepository;@Override@TransactionalpublicRestResultaddBook(BookDTO bookDTO){if(bookDTO.getIsbn()==null|| bookDTO.getTitle()==null|| bookDTO.getAuthor()==null){returnRestResult.failure("000001","参数不完整");}if(bookRepository.existsByIsbn(bookDTO.getIsbn())){returnRestResult.failure("000001","该图书已存在");}BookDO bookDO =newBookDO();BeanUtils.copyProperties(bookDTO, bookDO); bookRepository.save(bookDO);returnRestResult.success("000000","调用成功", bookDTO);}@Override@TransactionalpublicRestResultupdateBook(BookDTO bookDTO){BookDO bookDO = bookRepository.findById(bookDTO.getId()).orElse(null);if(bookDO ==null){returnRestResult.failure("000001","图书不存在");}BeanUtils.copyProperties(bookDTO, bookDO,"id","isbn"); bookRepository.save(bookDO);returnRestResult.success("000000","调用成功", bookDTO);}@Override@TransactionalpublicRestResultdeleteBook(Long id){BookDO bookDO = bookRepository.findById(id).orElse(null);if(bookDO ==null){returnRestResult.failure("000001","图书不存在");} bookRepository.delete(bookDO);returnRestResult.success("000000","调用成功",null);}@OverridepublicRestResultgetBooksByCategory(BookQuery bookQuery){List<BookDO> books;if(bookQuery.getCategory()!=null&&!bookQuery.getCategory().isEmpty()){ books = bookRepository.findByCategory(bookQuery.getCategory());}else{ books = bookRepository.findAll();}List<BookDTO> bookDTOS = books.stream().map(bookDO ->{BookDTO bookDTO =newBookDTO();BeanUtils.copyProperties(bookDO, bookDTO);return bookDTO;}).collect(Collectors.toList());returnRestResult.success("000000","调用成功", bookDTOS);}}
packagecom.feisuanyz.dto;importjakarta.validation.constraints.NotNull;importlombok.*;/** * <p> * 借阅审批数据传输对象 * </p> * @author z2222 */@Data@NoArgsConstructor@AllArgsConstructorpublicclassBorrowApproveDTO{@NotNull(message ="申请ID不能为空")privateLong applyId;@NotNull(message ="审批状态不能为空")privateInteger approveStatus;// 0-拒绝, 1-通过}
2.2.4 图书资源管理:
packagecom.feisuanyz.controller;importcom.feisuanyz.dto.BookDTO;importcom.feisuanyz.dto.BookQuery;importcom.feisuanyz.dto.RestResult;importcom.feisuanyz.service.BookService;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.validation.annotation.Validated;importorg.springframework.web.bind.annotation.*;/** * <p> * 图书控制器,处理HTTP请求与响应 * </p> * @author z2222 */@Slf4j@RestController@RequestMapping("/books")publicclassBookController{@AutowiredprivateBookService bookService;/** * 新增图书 * @param bookDTO 图书信息 * @return 返回处理结果 */@PostMapping("/add")publicRestResultaddBook(@Validated@RequestBodyBookDTO bookDTO){return bookService.addBook(bookDTO);}/** * 编辑图书 * @param bookDTO 图书信息 * @return 返回处理结果 */@PutMapping("/update")publicRestResultupdateBook(@Validated@RequestBodyBookDTO bookDTO){return bookService.updateBook(bookDTO);}/** * 删除图书 * @param id 图书ID * @return 返回处理结果 */@DeleteMapping("/delete/{id}")publicRestResultdeleteBook(@PathVariableLong id){return bookService.deleteBook(id);}/** * 按分类展示图书 * @param category 图书分类 * @return 返回处理结果 */@GetMapping("/list")publicRestResultgetBooksByCategory(@RequestParam(required =false)String category){BookQuery bookQuery =newBookQuery(); bookQuery.setCategory(category);return bookService.getBooksByCategory(bookQuery);}}
packagecom.feisuanyz.repository;importcom.feisuanyz.entity.UserDO;importjava.util.Optional;importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;/** * <p> * 用户数据访问层接口 * </p> * @author z2222 */@RepositorypublicinterfaceUserRepositoryextendsJpaRepository<UserDO,Long>{/** * 根据用户名查找用户 * * @param username 用户名 * @return Optional包装的UserDO对象 */Optional<UserDO>findByUsername(String username);/** * 判断是否存在指定用户名的用户 * * @param username 用户名 * @return 是否存在该用户名 */booleanexistsByUsername(String username);}
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.feisuanyz</groupId><artifactId>JavaProject</artifactId><version>0.0.1-SNAPSHOT</version><name>JavaProject</name><description>Demo project forSpringBoot</description><properties><java.version>17</java.version><spring.boot.version>3.1.0</spring.boot.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!--WebStarter--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--Data JPA Starter--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--MySQLDriver--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!--Lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--Validation--><dependency><groupId>jakarta.validation</groupId><artifactId>jakarta.validation-api</artifactId><version>3.0.2</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
2.2.5生成的控制器与查询逻辑
// BookController.java@GetMapping("/search")publicResultsearchBooks(@RequestParam(required =false)String keyword,@RequestParam(required =false)String category,@RequestParam(required =false)Boolean available // true-可借, false-已借出){LambdaQueryWrapper<Book> wrapper =newLambdaQueryWrapper<>();if(StringUtils.hasText(keyword)){ wrapper.like(Book::getTitle, keyword).or().like(Book::getAuthor, keyword);}if(StringUtils.hasText(category)){ wrapper.eq(Book::getCategory, category);}if(available !=null){ wrapper.eq(Book::getAvailableCount, available ?1:0);}// 仅返回必要字段,优化性能 wrapper.select(Book::getId,Book::getTitle,Book::getAuthor,Book::getCategory,Book::getAvailableCount);List<Book> books = bookService.list(wrapper);returnResult.success(books);}// Book实体类关键字段@Data@TableName("book")publicclassBook{privateInteger id;privateString title;privateString author;privateString isbn;privateString category;privateInteger total_count;privateInteger available_count;}
2.2.6 生成的事务性代码
// BorrowController.java@PostMapping("/borrow")@Transactional// 飞算AI自动添加事务注解publicResultborrowBook(@RequestParamInteger userId,@RequestParamInteger bookId){Book book = bookService.getById(bookId);if(book ==null|| book.getAvailableCount()<=0){returnResult.error("该图书暂无库存");}// 减少可借库存(原子操作) book.setAvailableCount(book.getAvailableCount()-1); bookService.updateById(book);// 生成借阅记录BorrowRecordrecord=newBorrowRecord();record.setUserId(userId);record.setBookId(bookId);record.setBorrowDate(LocalDateTime.now());record.setDueDate(LocalDateTime.now().plusDays(30));record.setStatus(0);// 0-未归还 borrowRecordService.save(record);returnResult.success("借书成功,应还日期:"+record.getDueDate());}

2.3 逾期管理与数据统计

2.3.1 逾期计算逻辑

需求输入:“每天凌晨检查借阅记录中due_date < 当前日期且status=0的记录,计算逾期天数(当前日期-due_date),若逾期天数>0则更新用户违约金(累计),若逾期天数>30则将用户role标记为1(黑名单)。”

在这里插入图片描述

AI生成代码(定时任务):

// OverdueTask.java(飞算AI生成)@ComponentpublicclassOverdueTask{@AutowiredprivateBorrowRecordService borrowRecordService;@AutowiredprivateUserService userService;@Scheduled(cron ="0 0 0 * * ?")// 每天凌晨执行publicvoidcheckOverdue(){LocalDateTime now =LocalDateTime.now();List<BorrowRecord> overdueRecords = borrowRecordService.list(newLambdaQueryWrapper<BorrowRecord>().lt(BorrowRecord::getDueDate, now).eq(BorrowRecord::getStatus,0)); overdueRecords.forEach(record->{long daysOverdue =ChronoUnit.DAYS.between(record.getDueDate(), now);// 更新用户违约金(简化逻辑:累计1元/天)User user = userService.getById(record.getUserId()); user.setFineAmount(user.getFineAmount()+(int) daysOverdue);if(daysOverdue >30){ user.setRole(1);// 标记为黑名单} userService.updateById(user);record.setStatus(1);// 标记为已逾期 borrowRecordService.updateById(record);});}}

2.4 工程结构全景

最终生成的工程目录结构如下:

online_library/ ├── src/main/java/com/library/online/ │ ├── controller/ # 接口层(UserController, BookController...) │ ├── entity/ # 实体类(User, Book, BorrowRecord...) │ ├── mapper/ # 数据访问层(UserMapper, BookMapper...) │ ├── service/ # 业务逻辑层(UserService, BookService...) │ ├── dto/ # 数据传输对象(UserRegisterDTO, UserLoginDTO...) │ ├── util/ # 工具类(JwtUtil, Result...) │ └── OnlineLibraryApplication.java # 启动类 ├── src/main/resources/ │ ├── application.yml # 数据库配置(spring.datasource.url等) │ └── mapper/ # MyBatis XML文件(如BorrowRecordMapper.xml) 

三、优化与调试心得

3.1 典型问题1:SQL性能瓶颈(库存查询慢)

问题现象:当图书总量超过1万条时,SELECT * FROM book WHERE available_count > 0 查询耗时超过2秒。

解决方案

  • 添加索引:执行SQL ALTER TABLE book ADD INDEX idx_available (available_count);
  • 优化查询:修改生成的BookController.java,限定返回字段(仅id, title, available_count)。

优化后效果:查询时间从2.1s降至120ms。

3.2 典型问题2:JWT令牌过期处理缺失

问题现象:用户登录后,若30分钟内无操作,再次请求接口返回401未授权。

解决步骤

  1. 通过飞算JavaAI的「智能会话」功能,定位到JwtUtil.java中的过期时间配置(原为30分钟)。
  2. 调整配置:修改JwtUtil.generateToken()方法中的expiration参数为2小时(new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000))。
  3. 前端配合:在Vue中存储JWT时,通过拦截器自动刷新令牌(本文聚焦后端,前端逻辑略)。

3.3 其他优化:代码规范性调整

飞算AI生成的初始代码虽功能完整,但部分命名可读性不足(如Result类未明确区分成功/失败字段)。通过手动调整:

  • 统一响应格式:修改Result.java{code: 200, msg: "success", data: {...}} 结构。
  • 日志增强:在关键业务方法(如借阅、归还)中添加@Slf4j注解,记录操作流水(例如:“用户ID 1001 借阅图书ID 2001,应还日期 202X-XX-XX”)。

四、成果展示与总结

4.1 最终工程结构图

首页展示:

在这里插入图片描述

可以对图书进行管理操作:

在这里插入图片描述

对于类型的管理操作:

在这里插入图片描述

在图书信息管页面中可以查看图书名称、图书分类、图片、作者、出版社、数量、可借天数、可借数量、图书简介等信息进行入库、出库、操作盘点,并可根据需要对已有图书信息进行修改或删除等详细操作:

在这里插入图片描述
在这里插入图片描述

查看对应借阅状态:

在这里插入图片描述
还有很多功能这里就不一一展示了。

4.2 飞算JavaAI的优势与不足

优势总结:
  1. 需求驱动开发:通过自然语言描述功能需求,自动生成符合Spring Boot规范的代码(包括实体类、控制器、DTO),减少60%以上的重复编码工作量。
  2. 智能引导精准:对复杂业务逻辑(如借阅事务、定时任务)的描述支持度高,生成的代码可直接运行并通过基础测试。
  3. 调试辅助强大:内置性能分析、接口测试、智能会话功能,快速定位SQL慢查询、令牌过期等问题。
  4. 工程结构标准:自动生成的分层结构符合企业级开发规范(controller-service-mapper),降低后期维护成本。
不足与改进建议:
  1. 复杂逻辑扩展性:对于高度定制化的业务规则(如多级权限校验),生成的代码可能需要手动补充逻辑(例如:管理员与普通用户的借阅限额差异)。
  2. 前端集成局限:当前版本更聚焦后端开发,若需前后端联调,需额外手动编写前端调用代码。

4.3 个人使用体会

本次通过飞算JavaAI开发在线图书借阅平台,深刻体会到智能化工具对开发效率的提升:

  • 新手友好:即使对Spring Boot或MyBatis-Plus不熟悉,也能通过需求描述快速生成可用代码,降低了学习曲线。
  • 效率革命:原本需要3-5天完成的基础功能开发(用户+图书+借阅),通过飞算AI实现核心链路打通,剩余时间用于业务逻辑优化。

未来若结合飞算JavaAI那些高级功能,可进一步缩短全流程开发周期,值得在更多项目中推广使用。

飞算你值得拥有。 点击网页

Read more

LeetCode128:哈希集合巧解最长连续序列

LeetCode128:哈希集合巧解最长连续序列

一、题目回顾 LeetCode 128 题「最长连续序列」是一道中等难度的数组题,核心要求如下:给定一个未排序的整数数组 nums,找出其中数字连续的最长序列(不要求序列元素在原数组中连续)的长度,且必须设计时间复杂度为 O (n) 的算法。 示例直观理解: * 输入 nums = [100,4,200,1,3,2],输出 4(最长序列是 [1,2,3,4]); * 输入 nums = [0,3,7,2,5,8,4,6,0,1],输出 9(完整连续序列 0-8)。 二、

By Ne0inhk
python~基础

python~基础

python~基础 * 1.python介绍 * 2.注释 * 3.波浪线提示 * 4.变量 * 4.1定义 * 4.2变量名命名规范 * 5.数据类型: * 5.1常见数据类型分类: * 5.2数据类型转换 * 6.交互运⾏ Python 代码: * 7.输入与输出 * 7.1 输入 * 7.2输出 * 7.2.1格式化输出 1.python介绍 python为解释型语言,解释器一边翻译一边执行,代码从上到下执行,如果下方代码出现错误,不会影响上方代码的执行 因为计算机只认二进制(0,1),所以需要解释器对代码进行翻译 怎么将python与自动化测试联系起来? Python + requests ->

By Ne0inhk
【C语言】排序算法——希尔排序以及插入排序 ——详解!!!

【C语言】排序算法——希尔排序以及插入排序 ——详解!!!

【C语言】排序算法——希尔排序以及插入排序详解 * 前言 * 一 、插入排序 * 1. 视频演示 * 2. 算法思想 * 3. 实现思路 * 4. 代码演示 * 二 、希尔排序 * 1. 视频演示 * 2. 算法思想 * 3. 实现思路 * (1)分组 * (2)预排序 * (3)最终排序 * (4)gap的取值 * 4. 代码演示 * 结语 前言 在学习循环的时候,我们学习到了冒泡排序这个算法 那么,除了冒泡排序,还有什么排序算法呢? 今天给大家带来的是插入排序以及希尔排序 一 、插入排序 1. 视频演示 首先给大家看一段视频,让大家先看看插入排序是怎么运行的 插入排序演示 2. 算法思想 我们可以从视频里看见,

By Ne0inhk
Python——50道面试题,面试巩固必看,建议收藏!

Python——50道面试题,面试巩固必看,建议收藏!

Python大礼包:《2025年最新Python全套学习资料包】免费领取 题目001: 在Python中如何实现单例模式。 点评:单例模式是指让一个类只能创建出唯一的实例,这个题目在面试中出现的频率极高,因为它考察的不仅仅是单例模式,更是对Python语言到底掌握到何种程度,建议大家用装饰器和元类这两种方式来实现单例模式,因为这两种方式的通用性最强,而且也可以顺便展示自己对装饰器和元类中两个关键知识点的理解。 方法一:使用装饰器实现单例模式。 from functools import wraps def singleton(cls): """单例类装饰器""" instances = {} @wraps(cls) def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return

By Ne0inhk