ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SpringBoot+Vue图书管理系统全栈开发实战:从设计到部署完整指南

2026/9/1 19:29:38 拓冰建站 浏览量
SpringBoot+Vue图书管理系统全栈开发实战:从设计到部署完整指南 简介这是一套面向计算机类本科毕业设计与课程设计的完整图书管理系统实现方案基于SpringBootVue前后端分离架构解决图书馆、学校及企业等场景下的图书信息管理、借阅流程管控与用户权限协同问题。资源包含81个文件涵盖33个Java后端核心逻辑文件含MyBatis映射与Service层、12个Vue组件及API调用JS脚本、10个CSS样式文件、6个XML配置与Mapper定义以及SQL建库脚本、论文文档.docx与.md双格式、部署说明与项目结构说明等压缩包仅1.12MB轻量易部署。已有64人学习下载适合软件工程、Java Web开发初学者及毕设选题者快速上手。读者可直接运行源码验证功能结合结构清晰的分层代码Controller-Service-Mapper、详细中文注释、完整需求分析至测试验证的毕业论文以及数据库脚本与启动命令mvnw.cmd高效完成系统复现、二次开发或答辩材料准备。 别一上来就打开编辑器敲代码。图书管理系统这个题目我在毕业设计和实际项目里见过太多版本了说句实话凡是一开始就埋头写代码的最后基本都会被借书还书流程里纠缠不清的状态绕晕。这个项目看着简单实际上是一个特别典型的“麻雀虽小五脏俱全”的全栈练习它既要有人物的权限区分又得有核心业务流程的闭环还得有数据的统计与展示。把它做扎实了SpringBoot和Vue两条线都能练得很透论文也好写答辩也好讲因为每块功能都有实际的业务逻辑支撑不是那种为了凑功能而堆砌的模块。这篇文章我就把这个项目从设计到部署完整拆开把它当成一个真实项目来复盘。我尽量把每一步为什么这么做也讲清楚不是让你照着抄一份源码就完了而是让你有本事自己从头搭一个。不管是用来交课程设计、毕业设计还是想靠这个小项目入门全栈看完你都会对整体脉络非常清楚。1. 别急着写代码先把系统这张图画清楚1.1 管理端与用户端到底要拆多细大多数初学者拿到“图书管理系统”这个需求第一反应就是建一张图书表然后写增删改查。但实际进去做之后你会发现如果只停留在“图书表的CRUD”那这个系统根本没有业务闭环论文也会写得非常单薄。我拆解这个项目的时候会先把它按角色分成两条线。第一条线是管理员端。这个端的核心目标是解决图书和读者的管理效率问题功能上要有图书分类管理类别要支持树形层级比如“文学”下面拆“小说”“散文”、图书信息管理ISBN、书名、作者、出版社、馆藏数量、可借数量、读者管理账号禁用与启用、借阅管理借书、还书、续借、超期处理、公告管理发布系统通知。到这里还算常规很多参考项目也都有。第二条线是读者端。读者的诉求很纯粹快速找到书、知道能不能借、能借多久、什么时候该还。所以页面设计要围绕检索、详情、借阅、续借、历史记录展开而不是把管理员那一大堆表格直接丢给读者看。我的设计原则是“读者看到的永远是简化过的视图”你只需要让读者看到“这本书是否可借”“我借了几本”“是否超期”背后复杂的库存扣减和状态流转不要让他感知。1.2 借书还书的业务闭环不能断图书管理系统最核心的地方不是图书管理而是“借阅流程”。借书不是简单地往借阅表里插一条记录还书也不是删掉记录。你得把图书的库存数量、借阅记录的状态、读者的在借数量绑定在一起看。我习惯画一条状态流转线图书总数在架可借数已借出数。读者发起借书系统先判断该读者是否存在未归还的超期图书再判断图书可借数量是否大于0如果都通过就扣减可借数量、插入一条借阅记录状态设为“借出中”同时计算应还时间默认30天。还书的时候系统更新借阅记录状态为“已归还”同时把可借数量加回去然后判断是否超期如果超期就计算罚金。续借操作就更有意思了不是简单把应还时间往后推30天还要限制只能续借一次、不能对超期图书续借、不能对已有续借记录的图书再次续借。这套逻辑理顺了后端的接口设计就非常自然论文里的“业务流程分析”章节也能画出漂亮的时序图。反过来如果你上来就建表后期很容易出现“还了书库存没加回去”这种严重bug。1.3 一句话说清楚系统定位严格意义上这是一个面向高校图书馆或小型企业图书室的管理系统而不是庞大的数字图书馆平台。用户规模控制在几十到几百人就足够不需要引入复杂的消息队列或缓存中间件。技术上选择SpringBootVue就是为了在有限的代码量内实现一个足够规范的前后端分离架构既能展示后端的业务处理能力又能体现前端交互的现代感。搞清楚定位之后很多技术选型就不会纠结了比如不需要引入Redis做会话共享MySQL加单机部署完全够用。2. 技术选型不是抄作业你得知道为什么是它2.1 为什么后端是SpringBoot而不是SSH或SSM你去看那些热度很高的项目源码十个里有八个是SpringBoot这背后是有原因的。传统的SSH或者SSM你看完成本很高需要手工配置大量的XML文件很多精力花在“配置框架”而不是“实现业务”上。SpringBoot的核心思想是“自动装配”它把这些繁琐的配置变成了约定你引入一个starter依赖框架就自动帮你把相关的Bean注入容器比如你引入spring-boot-starter-web内嵌的Tomcat和SpringMVC就直接可用了。但我要提醒一件事SpringBoot的“自动配置”是方便但不是魔法。如果你完全不懂Spring的IOC和AOP原理遇到“明明引入了依赖但Bean没注入”这类问题时会非常头疼。所以我建议用SpringBoot来做项目但在论文和准备面试时一定要把Spring的Bean生命周期、依赖注入方式、自动配置原理这些基础补上不然答辩的时候一问就露馅。2.2 Vue到底选Vue2还是Vue3这是很多同学最纠结的问题。我的建议很直接如果你用Element UI就选Vue2如果你用Element Plus就选Vue3。但稳妥起见毕业设计我通常推荐Vue2Element UI不是因为它新而是因为Element UI的文档和坑都被踩得差不多了遇到问题一定能搜到解决方案组件的稳定性和社区积累是最重要的。Vue3Element Plus也很成熟生态越来越好但你可能会撞上一些刚踩通的新坑对赶时间交论文的人来说不划算。Vue的优势在于它把DOM操作彻底从业务里剥离了。你只需要维护data里的数据页面自动跟着变。对开发图书管理系统来说最明显的体验就是“图书列表筛选”这种功能以前用jQuery要手动拼HTML、绑定事件Vue里就是一个computed计算属性的事数据一变视图自己就更新了。这种响应式思想是值得在论文里作为核心技术点写清楚的。2.3 版本搭配与项目结构规划我列一下我这边的标准搭配照着配基本不会出错组件推荐版本说明JDK1.8稳定兼容性好虽然新版JDK已到17但8的生态依然最稳SpringBoot2.7.x兼容JDK1.8自动配置成熟不要盲目用3.xMySQL5.7或8.0推荐8.0注意驱动差异MyBatis-Plus3.5.x强化了单表CRUD代码量省一大截Vue2.6.x配合Element UIElement UI2.15.x管理后台开发神器Node14或16Vue2环境推荐用14/16太新的Node版本可能有兼容问题项目结构上我建议一个项目目录下直接分两个子目录比如book-manage-backend和book-manage-frontend后端负责提供RESTful API前端负责页面渲染两者通过JSON数据交互。这样做的好处是部署时可以完全分离比如后端打成jar包部署在一台服务器前端打成静态文件交给Nginx托管互不影响。3. 数据库设计这个系统的成败就看这几张表3.1 哪些表必须设计出来图书管理系统的数据模型不会特别复杂但也不该潦草到只有“图书表”和“借阅表”两张表。我梳理下来核心表至少有七张用户表管理员和读者放在同一张表用role字段区分图书分类表图书信息表借阅记录表公告信息表续借记录表如果你不做单独的续借记录字段也可以合并到借阅记录表里罚款记录表读者和管理员放一张表很多人会觉得奇怪为什么不拆成两张我的考虑是他们的认证逻辑是相同的都是账号密码登录只是登录后看到的菜单和能访问的接口权限不同。拆成两张表反而会导致登录时多一次判断增加复杂度。一张用户表一个role字段是这里最经济和清晰的做法。3.2 核心表字段设计直接照着抄我直接给出最关键的两张表的建表SQL你可以直接拿去改。用户表相对简单这里不贴了重点看图书表和借阅记录表。CREATE TABLE book ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键, isbn varchar(20) NOT NULL COMMENT 国际标准书号, book_name varchar(100) NOT NULL COMMENT 书名, author varchar(50) DEFAULT NULL COMMENT 作者, publisher varchar(100) DEFAULT NULL COMMENT 出版社, category_id bigint(20) DEFAULT NULL COMMENT 分类ID, total_count int(11) NOT NULL DEFAULT 1 COMMENT 馆藏总数, borrowed_count int(11) NOT NULL DEFAULT 0 COMMENT 已借出数量, cover_url varchar(255) DEFAULT NULL COMMENT 封面图地址, description text COMMENT 简介, status tinyint(4) NOT NULL DEFAULT 1 COMMENT 状态1上架 0下架, create_time datetime DEFAULT NULL COMMENT 创建时间, update_time datetime DEFAULT NULL COMMENT 更新时间, PRIMARY KEY (id), KEY idx_isbn (isbn), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT图书信息表;注意total_count和borrowed_count这两个字段它们是库存控制的关键。可借数量不用单独立字段直接通过total_count - borrowed_count算出来。这比额外存一个available_count要可靠得多因为可借数量属于派生数据一旦图书归还或借出都只需要维护borrowed_count一个字段避免数据不一致。借阅记录表CREATE TABLE borrow_record ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键, book_id bigint(20) NOT NULL COMMENT 图书ID, user_id bigint(20) NOT NULL COMMENT 用户ID, borrow_time datetime NOT NULL COMMENT 借书时间, due_time datetime NOT NULL COMMENT 应还时间, return_time datetime DEFAULT NULL COMMENT 实际归还时间, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 状态0借出中 1已归还 2已续借 3超期未还, renew_count int(11) NOT NULL DEFAULT 0 COMMENT 续借次数, fine_amount decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 罚款金额, PRIMARY KEY (id), KEY idx_user (user_id), KEY idx_book (book_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT借阅记录表;3.3 时间字段的坑你避开了吗时间字段别用timestamp我遇到过太多坑了。timestamp存在2038年问题而且它跟数据库时区绑定前后端传输时容易产生奇怪的8小时偏移。最简单的办法就是用datetime后端统一用LocalDateTime接收处理起来非常顺手。还有别偷懒不在建表语句里写create_time和update_time这两个字段在后期排查数据问题时是救命的。你论文里的“数据库设计”章节也会因为这些细节显得严谨。4. 后端开发落地写接口像搭积木4.1 后端分层每一层干什么必须清楚后端的代码组织我坚持用经典的四层结构千万别把业务逻辑堆在Controller里。Controller层只负责接收请求、参数校验、调用Service、封装返回值Service层写具体的业务逻辑Mapper层操作数据库DTO/VO层做数据的封装和转换。为什么一定要拆这么细说一个真实场景。你写借书接口的时候如果直接把库存扣减逻辑写在Controller里第一版能跑但后面要加“借书限额校验”和“超期禁止借书”判断时Controller就会越来越臃肿。而放进Service层每个方法只做一件事代码可读性会高很多论文里也能这样描述Controller为表现层Service为业务逻辑层清晰明了。分层之后接口路径也很有规律。我习惯这样设计RESTful接口POST /api/user/login登录GET /api/book/page分页查询图书GET /api/book/{id}图书详情POST /api/book新增图书管理员PUT /api/book修改图书管理员DELETE /api/book/{id}删除图书管理员POST /api/borrow借书PUT /api/borrow/return还书PUT /api/borrow/renew续借GET /api/borrow/my查询当前用户的借阅记录4.2 统一返给前端的响应结构长什么样前端调用后端接口的时候最怕今天这个接口返回{success:true}明天那个接口返回{code:200}后天另一个又直接返回了一堆裸数据。所以后端必须有一个统一的响应包装类。我一般这么写Data public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }别小看这个类它能让前端处理逻辑非常统一。Axios响应拦截器里只需要判断code是不是200是就正常取数据不是就统一弹错误提示。否则你在前端每个请求里都要写一遍错误处理代码丑且重复还容易漏。4.3 借书接口事务必须安排上借书这个操作在数据库层面其实是两步扣减图书可借数量插入借阅记录。这两步要么都成功要么都失败绝不能出现“库存扣了但记录没插入”这种脏数据。所以这个方法上必须加Transactional注解。Transactional(rollbackFor Exception.class) public ResultString borrowBook(Long bookId, Long userId) { // 1. 查询图书 Book book bookMapper.selectById(bookId); if (book null) { return Result.error(图书不存在); } if (book.getBorrowedCount() book.getTotalCount()) { return Result.error(该图书已全部借出); } // 2. 查询该用户是否有超期未还的书 Integer overdueCount borrowRecordMapper .selectOverdueCountByUserId(userId); if (overdueCount 0) { return Result.error(存在超期未归还图书无法借阅); } // 3. 扣减库存 book.setBorrowedCount(book.getBorrowedCount() 1); bookMapper.updateById(book); // 4. 插入借阅记录 BorrowRecord record new BorrowRecord(); record.setBookId(bookId); record.setUserId(userId); record.setBorrowTime(LocalDateTime.now()); record.setDueTime(LocalDateTime.now().plusDays(30)); record.setStatus(0); record.setRenewCount(0); borrowRecordMapper.insert(record); return Result.success(借书成功); }这里有个容易被忽略的点就是并发问题。如果真的上生产环境理论上一本书只剩最后库存时两个用户同时发起借书可能都会通过“剩余数量”判断最后造成超借。但这是毕业设计通常不会引入Redis分布式锁或数据库乐观锁那么重的方案。我建议在图书表的更新语句里加一个乐观锁也就是UPDATE book SET borrowed_count borrowed_count 1 WHERE id ? AND borrowed_count total_count用受影响行数判断是否借出成功这样简单也有效。4.4 登录认证用JWT才是主流做法传统做法是用Session保存登录状态但这在前后端分离架构下体验很差前端是独立的进程Session也不好跨域处理。现在主流做法是JWT鉴权用户登录成功后后端生成一个token返回给前端前端每次请求在请求头里带上Authorization: Bearer token后端通过拦截器或过滤器验证token有效性。JWT的结构是“Header.Payload.Signature”三部分都是Base64编码其中Payload可以存用户ID用户名角色这些信息。这里要注意一点Payload里的信息不是加密的只是编码所以别把密码放进去。真正保证安全的是签名签名是用服务端密钥对Header和Payload做哈希算出来的客户端无法伪造。后端配合SpringBoot的实现思路是登录接口校验用户名和密码成功后利用jjwt库生成token然后写一个拦截器JwtInterceptor在preHandle方法里取出请求头中的token并解析解析失败就返回401。对于管理员接口可以在拦截器里再判断一次角色角色不对返回403。这套逻辑比Session方式更适合写进论文而且“前后端分离下的认证方案”也是一个很好的答辩加分点。5. 前端页面实现让数据在页面上流动起来5.1 手把手搭一个Vue后台骨架前端我用的是Vue2Vue RouterElement UIVuex页面布局采用经典的后台管理模式左侧菜单栏右侧内容区。整体思路是入口路由是/login登录成功后跳转到/layoutLayout组件包含侧边栏和头部子页面都在Layout的内容区通过router-view渲染。路由需要做权限控制这个点很重要。不能只做到“登录后能进系统”还要做到“不同角色看到的菜单不同”。做法是路由的meta里配置roles: [ADMIN]或者roles: [USER]在全局前置守卫router.beforeEach里通过当前登录用户的角色判断是否放行。前端路由守卫只能控制页面显示真正的安全还得靠后端接口权限但前端这种处理能显著提升用户体验让读者看不到他用不了的功能。5.2 Axios封装一个项目维护一套网络请求方案图书管理系统牵扯的接口有二十来个如果每个页面里都直接this.$http.get(...)并且每个接口都要处理token、处理错误码那维护成本会爆炸。我建议在src/utils/request.js里封装一次Axios实例import axios from axios import { Message } from element-ui import router from /router const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动带token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer token } return config }) // 响应拦截器统一处理业务错误 request.interceptors.response.use( response { const res response.data if (res.code ! 200) { Message.error(res.message) return Promise.reject(new Error(res.message)) } return res }, error { if (error.response error.response.status 401) { Message.error(登录已过期请重新登录) localStorage.removeItem(token) router.push(/login) } else { Message.error(网络异常请稍后重试) } return Promise.reject(error) } ) export default request然后需要封装具体的API模块比如src/api/book.js里导出getBookPage(params)、addBook(data)这些方法。这样页面里的组件只需要调用这些API方法完全不关心请求细节。这是非常标准的前端项目结构值得你参照。5.3 核心页面的交互细节图书管理页面是主菜页面上要有搜索栏关键字、分类下拉筛选、图书表格、分页器、新增/编辑弹窗。这个页面的所有交互都围绕data里的queryParams和tableData展开。搜索按钮触发查询时只需要把queryParams传给getBookPage方法后端返回分页数据后前端把数据放进tableData表格自动渲染。Element UI的el-table绑定:data属性字段列通过prop映射即可非常方便。借阅管理页面的设计稍微复杂一些。管理员需要看到所有借阅记录并且能对记录进行标记归还操作。这里要注意“操作”列的按钮状态如果记录状态是“借出中”显示“归还”和“续借”按钮如果状态是“已归还”按钮全部隐藏。这个条件渲染用Vue的v-if就能实现逻辑并不复杂但要细心。前端还有一个容易被忽略的细节日期显示格式。后端返回的LocalDateTime默认格式是yyyy-MM-ddTHH:mm:ss中间有个T直接展示给用户看非常不友好。处理方式是后端在application.yml里配置全局时间格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8或者在VO类的日期字段上用JsonFormat(pattern yyyy-MM-dd HH:mm:ss)注解。无论选哪种记得统一不然有的页面是对的有的页面是错的排查起来非常痛苦。5.4 前后端联调时跨域问题怎么破联调阶段最容易报错的就是跨域。开发环境下前端跑在Vue CLI默认的http://localhost:8080后端跑在http://localhost:8081两者端口不同浏览器基于同源策略会拦截请求。解决思路有两种。后端配置CORS全局跨域或者用WebMvcConfigurer实现Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true); } }但我更推荐的是用Vue CLI的代理方式在前端vue.config.js里设置module.exports { devServer: { port: 8080, proxy: { /api: { target: http://localhost:8081, changeOrigin: true } } } }这样前端请求的是/api/xxxDevServer会把这个请求转发到后端浏览器看到的是同源请求就不会拦截了。而且这个代理只影响开发环境生产环境打包后的静态文件只要跟Nginx配置好也不会涉及跨域问题。6. 常见问题与排查技巧实录6.1 启动失败大户端口被占用和依赖冲突我见过的最常见的问题就是后端启动时提示Port 8080 was already in use这时候按两步走。第一步找出占用8080端口的进程Windows下用netstat -ano | findstr 8080Linux和macOS下用lsof -i:8080找到PID后结束进程。第二步为了以后省事直接把后端端口改成8081避免和前端端口冲突。前端8080后端8081这种组合我用了好多年基本不会再出乱子。另一个问题是Maven依赖冲突。如果你发现运行时某个类找不到大概率是依赖版本不一致。解决办法是调整pom.xml里的版本管理尽量依赖SpringBoot父项目管理的版本不要自己随便指定一个高版本的依赖尤其是MyBatis-Plus和SpringBoot的兼容性用3.5.x的MyBatis-Plus配合2.7.x的SpringBoot基本不会有兼容性问题。6.2 MyBatis-Plus的字段映射坑MyBatis-Plus有个很大的便利是实体类字段自动映射数据库列名默认开启驼峰转换也就是说Java里的bookName会映射到数据库的book_name。这符合数据库的下划线命名习惯确实方便但也带来了两个坑。第一个坑如果你某个实体字段不想映射数据库字段必须加TableField(exist false)注解比如一个“借阅人数”这种虚拟字段。不加注解的话MyBatis-Plus会以为它是数据库表字段执行SQL时就会报字段不存在。第二个坑如果数据库有特殊字段名比如description和Java里的description一样没问题但如果有reader这种不属于表结构的字段一定要检查实体类是否忘了加TableField(exist false)。这个坑在写“图书借阅记录”联表查询时最容易踩。6.3 前端404、找不到资源和路由刷新白屏前端部署完刷新页面突然404或者用nginx部署后点击菜单没问题但直接刷新子路由页面就白屏。这个锅通常由Vue Router的history模式背。history模式下的URL路径是真实的路径但静态服务器上没有这个物理文件刷新时服务器返回404。解决办法是把服务器的404请求重定向到前端index.html。Nginx配置里加上这段location / { try_files $uri $uri/ /index.html; }如果不改配置也可以直接用hash模式URL会变成/#/book/list虽然不那么好看但不会出现刷新404。这里提醒一下开发环境一般没有这个问题但如果报告里写了部署上线一定要把Nginx这段配置写进论文这也是一个容易被问倒的细节。6.4 中文乱码从源头解决接口返回中文乱码或者新增图书后数据库里中文变成???基本都是字符集没统一。确认四层第一数据库表用utf8mb4第二数据库连接URL带参数characterEncodingutf8第三后端接口返回的响应头设置text/json;charsetutf-8通常SpringBoot默认已经做了第四前端页面meta charsetUTF-8。四层都统一了基本不会再有乱码。特别提醒MySQL 8.0的驱动连接URL里serverTimezoneAsia/Shanghai也别忘了不然日期时间字段会差8个小时。7. 从源码到论文答辩和文档的实用思路7.1 论文大纲怎么搭才能既有深度又好写这个项目写论文有天然优势因为它的核心模块多业务逻辑完整。我的建议是把重心放在“借阅业务流程的设计与实现”上而不是泛泛地把所有模块各写两句话。大纲大概可以这样搭第一章 绪论背景、意义、国内外研究现状、主要工作第二章 相关技术介绍SpringBoot、Vue、MyBatis-Plus、MySQL每项技术写清楚“是什么”和“为什么用它”第三章 系统分析可行性分析、功能需求分析、用例图第四章 系统设计总体架构图、功能模块划分、数据库设计表结构、E-R图第五章 系统实现核心界面截图核心代码段重点写借书、还书、续借、登录认证第六章 系统测试功能测试用例表、测试结果分析这里有个写作技巧系统实现章节的代码不要大段全贴挑关键方法的15-20行就够。重点放在“这个方法解决了什么问题”和“逻辑是怎么流转的”这样论文查重也容易通过答辩时老师问起来你也讲得清楚。7.2 快速把项目跑起来的顺序拿到任何一套完整源码先别急着写论文一定要确保项目能在自己机器上跑通。按照这个顺序操作半小时内搞定创建数据库比如book_manager然后导入项目里的sql文件注意看SQL里的字符集设置后端项目用IDEA打开等待Maven下载依赖打开application.yml修改数据库用户名和密码在后端启动类里右键运行看到Started Application in xxxx seconds就说明后端起来了前端项目用VSCode打开在终端执行npm install安装依赖如果下载慢可以用npm config set registry https://registry.npmmirror.com换国内镜像然后执行npm run serve浏览器访问前端地址用管理员账号通常源码里会写比如admin/123456登录如果在这个过程里遇到npm install报错多半是Node版本问题把Node降到14或16再试。后端如果启动报数据库连接失败先检查MySQL服务有没有启动再检查密码。7.3 部署上线给你的项目收个漂亮的尾系统做完了不能只停留在本地。部署的时候后端打成jar包用mvn package命令生成然后上传到服务器执行java -jar book-manage.jar。注意生产环境的数据库连接地址要改成服务器的不能用localhost了。前端打包是npm run build生成一个dist目录把这个目录上传到Nginx的静态目录然后修改Nginx配置把/api开头的请求反向代理到后端的8081端口location /api/ { proxy_pass http://127.0.0.1:8081/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }这个配置是一次完整的“前后端分离部署”实践写进论文的“系统部署”章节是很有分量的内容。8. 写到最后几点实在话做这个项目的过程中我最大的体会是用SpringBootVue做图书管理系统代码量其实不大难的是把业务逻辑理清楚、把常见的坑避开。你可能觉得借书还书不是很简单吗真正动手写就会发现库存扣减、超期判断、续借限制、权限区分每一个细节都考验你对业务的理解深度。所以我也特别建议你哪怕是买现成的源码也一定要自己动手把关键的借阅流程再走一遍最好能自己重构一遍把别人的代码吃透。答辩的时候老师问的绝对不是“这些代码怎么背”而是“你为什么这么做”“如果遇到某个需求你会怎么改”。想清楚这些比代码本身更有价值。最后再分享一个小技巧给图书管理系统加上导出Excel的功能在毕业设计里是一个性价比很高的加分项。用EasyExcel或者POI写一个导出接口前端放一个导出按钮整个系统看起来完成度和实用性会立刻上一个台阶。希望这篇文章能帮你把这个经典项目做出自己的水平。本文还有配套的精品资源点击获取