资讯动态

JavaWeb图书管理系统源码解析:JSP+Servlet+MySQL三层架构实战

发布时间:2026/10/9 6:03:19 来源:尧图企业网站定制
简介这是一份基于JavaWeb的图书管理系统完整毕业设计项目包含前端页面、后端源码与数据库脚本面向计算机相关专业正在准备毕业设计、课程设计或期末大作业的学生也适合需要JavaWeb项目实战练习的学习者。系统经导师指导并通过98分评价代码经过严格调试可直接运行使用。压缩包共352个文件约64.72MB内容涵盖Java源码、class编译文件、Jar依赖库、JSP/HTML/CSS/JS前端页面、SQL数据库脚本以及Excel操作工具类等目录结构清晰便于部署和二次开发。已有240人学习浏览。资料中包括图书信息管理、用户管理、Excel批量导入导出等典型业务模块可作为完整项目方案参考也能帮助理解JavaWeb分层开发、数据库交互和前端页面整合的实战思路。1. 拿到这份基于 JavaWeb 的图书管理系统源码先看它值不值得作为毕设底子打开这份基于 JavaWeb 的图书管理系统源码包我第一反应不是看界面截图而是先确认它是不是一个能从登录跑到借阅归还的完整闭环。这个项目确实做到了前端页面、后端业务、MySQL 数据库齐全图书和用户两条主线带 Excel 导入导出导师评估 98 分说明它早就过了“能运行”这一关是能直接拿去答辩的那种完整度。适合两类人正在做毕设或课程设计、需要一份能讲清楚每一行代码的项目源码的计算机专业学生以及刚学完 Servlet、JSP、JDBC想看看真实 JavaWeb 项目长什么样的学习者。你要关心的不是它有多花哨而是怎么把它跑起来、讲明白、扛住老师提问。这篇笔记就按这个顺序拆。2. JavaWeb 技术栈与运行环境JDK 1.8、Tomcat 8.5、MySQL 5.7 为什么是黄金组合2.1 三层架构JSP、Servlet、DAO 各自负责什么拿到源码第一步不是急着启动而是先看它的代码分层。这个项目是典型的 JSP Servlet JavaBean JDBC 结构也就是很多教材里说的三层架构。从前端到数据库职责边界非常清楚JSP 页面负责展示和收集用户操作它是视图层Servlet 负责接收请求、调用业务逻辑、决定跳转到哪个页面它是控制层JavaBean 和 DAO 类负责封装数据和操作数据库它是模型层。你会在源码里看到BookInfoOperate、UserInfoOperate这样的类名这些就是典型的业务操作类。UserInfoOperate管用户数据BookInfoOperate管图书数据它们内部的增删改查方法对应的是数据库里的user表和book表。这个命名方式在毕业设计里非常常见也符合答辩老师对“结构清晰”的期望。前端文件集中在 Web 目录下JSP 页面配合 CSS 和 JavaScript搜索框、表格、按钮这些交互都写在页面里。后端 Servlet 通过web.xml或注解做 URL 映射请求从页面发起后Tomcat 根据映射规则找到对应 ServletServlet 再调 DAO 方法访问数据库最后把结果交给 JSP 渲染。理解这条链路后你改任何功能都知道该去哪一层改这对答辩时讲明白项目帮助很大。2.2 版本搭配为什么不是 JDK 17 和 Tomcat 10我见过不少学生下载了源码一运行报一堆红错第一个原因就是环境版本不对。这个项目的兼容范围落在 JDK 1.8、Tomcat 8.5、MySQL 5.7 这一档这是 JavaWeb 项目最稳的组合。JDK 1.8 对 Servlet 3.0/3.1 的支持非常成熟Tomcat 8.5 也完全兼容MySQL 5.7 的 SQL 语法稳妥网上绝大多数资料也都是围绕这个版本写的。如果你的电脑装的是 JDK 17 或更高版本Tomcat 建议选 9 而不是 10。Tomcat 10 开始把包名从javax.servlet换成了jakarta.servlet而这份源码里写的还是javax.servlet直接部署会报包不存在。JDK 8 虽然发布很久了但针对 JavaWeb 教学和毕设项目它反而是最不容易踩坑的版本甚至很多公司老项目生产环境也还在用 JDK 8。组件推荐版本说明JDK1.8Servlet 3.1 兼容性最好Tomcat 8.5 直接配Tomcat8.5稳定支持javax.servlet包MySQL5.7语法兼容性好字符集配置简单IDEA2020 以后任意版本社区版也能跑旗舰版配置更顺2.3 IDEA 导入步骤从解压到部署的完整操作我通常的导入流程是这样先把压缩包解压到一个路径里没有中文的目录比如D:\projects\book-manager路径带中文有时候 Tomcat 会出奇怪的问题。然后打开 IDEA选File - New - Project from Existing Sources定位到解压目录选中它的.iml文件或直接选目录根IDEA 会识别成一个 Web 项目。如果你的项目是用 Maven 管理的根目录下会有pom.xmlIDEA 会提示Auto Import等依赖下载完再继续。如果项目里只有WEB-INF/lib目录下的一堆 jar 包没有 pom 文件那就是普通 Web 项目结构需要通过File - Project Structure - Libraries把lib目录手动添加进去。接下来是配置 Tomcat点击顶部工具栏的Add Configuration选Tomcat Server - Local在Application server里指向你本地的 Tomcat 安装目录。然后在Deployment标签页点击加号选Artifact把项目打成的 war 包添加进去。Application context 默认写成/book就行这样启动后访问地址就是http://localhost:8080/book/。2.4 启动前检查清单配置文件、依赖、数据库连接第一次启动前我建议你花五分钟过一遍这几个位置能避免 80% 的翻车现场。第一是数据库连接配置通常会有一个.properties文件或者 DBUtil 类写在源码里找到jdbc:mysql://localhost:3306/数据库名这一段确认数据库名、用户名、密码和你本机一致。第二是 MySQL 服务是否启动Windows 下在服务管理器里看mysql服务是不是运行中Linux 下用systemctl status mysqld确认。第三是导入 SQL 脚本的顺序这份源码包里通常会带.sql文件用 Navicat 或命令行导入前先看清楚脚本里有没有DROP DATABASE语句避免把本地已有数据库清空。第四是检查项目的字符集过滤器是否配置很多乱码问题的根源不是数据库而是请求和响应没有统一用 UTF-8。启动后如果看到中文乱码或者表单提交的数据变成???第一个要查的就是 web.xml 里的CharacterEncodingFilter。3. 数据库设计从 class 文件名反推表结构建库脚本怎么写不返工3.1 反推表结构user、book、borrow 三张核心表源码里有BookInfoOperate和UserInfoOperate对应图书信息和用户信息的管理又因为有借阅归还的需求你会发现借阅记录表是少不了的。所以这个项目最核心的表就是三张用户表、图书表、借阅记录表。有的版本还会拆出一张管理员表但多数毕设把管理员也放进用户表用一个role或type字段区分这样登录时判断角色就能跳转到不同页面。用户表的字段一般长这样id、username、password、realname、student_no或work_no、phone、create_time。图书表的核心字段是id、book_name、author、publisher、isbn、total_count、remain_count、create_time。借阅记录表则要关联前两张表id、user_id、book_id、borrow_time、return_time、status。3.2 建库建表 SQL字段类型、默认值与索引设计很多同学建表时随意写字段类型后面查询速度慢、数据对不上才回头改其实不如一开始就规范。下面这一段是核心表的建表语句字段注释已经写在里面照着这个思路设计基本不会返工CREATE DATABASE IF NOT EXISTS book_manager DEFAULT CHARACTER SET utf8mb4; USE book_manager; CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录账号唯一, password VARCHAR(100) NOT NULL COMMENT 登录密码建议存加密后的值, realname VARCHAR(50) DEFAULT NULL COMMENT 真实姓名, student_no VARCHAR(20) DEFAULT NULL COMMENT 学号或工号, role TINYINT DEFAULT 0 COMMENT 角色0普通用户1管理员, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE book ( id INT PRIMARY KEY AUTO_INCREMENT, book_name VARCHAR(100) NOT NULL COMMENT 书名, author VARCHAR(50) DEFAULT NULL, publisher VARCHAR(100) DEFAULT NULL, isbn VARCHAR(20) DEFAULT NULL COMMENT ISBN号可加唯一索引, total_count INT DEFAULT 1 COMMENT 馆藏总量, remain_count INT DEFAULT 1 COMMENT 当前剩余可借数量, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE borrow ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL COMMENT 外键关联user表, book_id INT NOT NULL COMMENT 外键关联book表, borrow_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 借出时间, due_time DATETIME DEFAULT NULL COMMENT 应还时间, return_time DATETIME DEFAULT NULL COMMENT 实际归还时间, status TINYINT DEFAULT 0 COMMENT 状态0借出中1已归还2逾期, KEY idx_user_id (user_id), KEY idx_book_id (book_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段 SQL 里有几个设计点值得你答辩时展开讲。用户表的username加UNIQUE约束防止注册时重复图书表里total_count和remain_count分开因为“馆藏总量”和“当前可借数”语义不同如果只用一个字段还书时还得判断是否超出总量。借阅记录表用status加KEY索引是因为查询大概率会按“未归还”这个状态过滤索引能明显加快查逾期列表的速度。注意统一用utf8mb4它比utf8多支持 emoji 和生僻字导入书名时不容易报字符集错误。DATETIME DEFAULT CURRENT_TIMESTAMP能自动写入创建时间不需要 Java 端手动new Date()再传进来少写一行代码也避免时区问题。3.3 JDBC 连接配置MySQL 驱动与 URL 参数详解数据库建好之后Java 代码要通过 JDBC 连上去。这个项目里一般会有一个 DBUtil 类或jdbc.properties文件核心配置不外乎下面几项。我给一段最常见的写法你拿到源码后可以对照检查public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/book_manager?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 你的密码; static { try { Class.forName(com.mysql.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }URL 里的三个参数值得说明。useSSLfalse是关闭 SSL 加密握手本地开发不需要加密而且不关的话很多 MySQL 版本会打出警告日志。serverTimezoneAsia/Shanghai用来指定时区不加可能出现日期差 8 小时的问题。characterEncodingutf8确保驱动层面的字符集统一配合数据库的utf8mb4全链路的中文才能不乱。如果源码里用的是com.mysql.jdbc.Driver这是老版本的驱动包MySQL 5.7 配mysql-connector-java 5.1.x时没问题。如果你的 lib 里驱动是 8.x建议把驱动类改成com.mysql.cj.jdbc.DriverURL 里的参数保留不变连接也能正常工作。3.4 查询设计图书状态与借阅记录的关联数据库最有含金量的部分是一张查询在借记录的关联 SQL。你要在页面显示“谁借了什么书、什么时候到期”就要把borrow表和user、book两张表连起来。常见写法是先按status0过滤“借出中”的记录再关联查用户名和书名。SELECT u.realname, u.student_no, b.book_name, br.borrow_time, br.due_time FROM borrow br JOIN user u ON br.user_id u.id JOIN book b ON br.book_id b.id WHERE br.status 0 ORDER BY br.due_time ASC;这里用JOIN而不是直接在 Java 端拆两次查询是为了减少数据库往返次数也保证结果的一致性。ORDER BY br.due_time ASC按到期时间从早到晚排序逾期风险最高的记录排在最上面。答辩时如果老师问“为什么不在 service 里循环查”你可以回答一次 JOIN 能拿到全部关联信息循环查询会产生 N1 次数据库请求数据量稍大就会出现明显延迟。4. 核心功能实现登录、增删改查与借阅归还的链路怎么讲清楚4.1 登录与 Session 管理登录模块看起来简单但它是整个系统的第一道门也是答辩时最容易展开讲的点。逻辑上需要做到三点校验用户名密码是否匹配、把登录成功的信息放进 Session、未登录用户访问受保护页面时自动跳回登录页。下面这个是校验接口的常见骨架WebServlet(/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username request.getParameter(username); String password request.getParameter(password); User user userOperate.findByUsernameAndPassword(username, password); if (user ! null) { HttpSession session request.getSession(); session.setAttribute(loginUser, user); response.sendRedirect(request.getContextPath() /index.jsp); } else { request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(/login.jsp).forward(request, response); } } }这段代码演示了一个关键区别登录成功用sendRedirect失败用forward。登录成功后必须重定向因为浏览器会单独发起一次新请求地址栏变成首页地址用户刷新页面不会重复提交表单失败时用转发把错误信息放回同一个请求里登录页面能直接显示提示。如果你反过来用用户按一次 F5 就会重复提交一次登录请求。密码存储方面如果源码里是明文密码毕业论文里就会是个扣分点。建议至少用 MD5 加盐或者 BCrypt 做一层哈希UserOperate里比对时把输入密码用同样算法处理后再查库。这个改动不大但对答辩评分的提升非常明显。4.2 图书增删改查DAO 层的通用写法图书模块是整个系统的核心增删改查一个不少。DAO 层最好遵循固定套路一个方法对应一条 SQL方法名清晰表达意图。拿分页查询来说常见做法是传入当前页和每页条数SQL 用LIMIT截取一段结果public ListBook findBooksByPage(int pageNum, int pageSize) { String sql SELECT * FROM book ORDER BY id DESC LIMIT ?, ?; return queryRunner.query(sql, new BeanListHandler(Book.class), (pageNum - 1) * pageSize, pageSize); } public int countBooks() { String sql SELECT COUNT(*) FROM book; return queryRunner.query(sql, new ScalarHandler(Long.class)).intValue(); }如果项目用的是 Apache Commons DbUtils 的QueryRunner上面这种写法就是标准姿势。分页参数里有几个点容易被忽视LIMIT的第一个参数是偏移量也就是跳过多少行所以第 2 页的偏移量是(2 - 1) * 10 10第二个参数是页大小。ORDER BY id DESC让新录入的图书排前面符合管理员查看新书的习惯。这里的?占位符用 PreparedStatement 预编译不需要手动拼接字符串既避免 SQL 注入又不用关心值里带不带单引号。我在代码里看到有同学直接SELECT * FROM book WHERE book_name name 这种方式最好不要模仿用户搜索一本书名时输入 OR 11就能把整张表拖出来。4.3 借阅归还事务边界放在哪一层借阅归还看起来只是改两个表的记录但最容易出问题。借书时要做两步操作往borrow表插入一条记录同时把book表的remain_count减一。这两步必须在一个事务里否则插入成功但扣减失败图书库存就错了。正确做法是在 Service 或者 Servlet 层开启事务DAO 只负责单条 SQLConnection conn DBUtil.getConnection(); try { conn.setAutoCommit(false); borrowDao.insertBorrowRecord(conn, userId, bookId); bookDao.decreaseRemainCount(conn, bookId); conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); DBUtil.close(conn); }这段代码的关键点是setAutoCommit(false)之后后面的两条 SQL 不会自动提交只有执行到conn.commit()时才一次性生效任何一步抛异常conn.rollback()会把前面已执行的操作撤销。还有一点要注意DAO 方法里不能再各自去DBUtil.getConnection()否则两个连接各自带自己的事务永远不会同步。这也是为什么借阅逻辑里 DAO 方法需要显式接收一个Connection参数的原因。归还图书的逻辑相反更新borrow表的状态为已归还、写入实际归还时间同时把book表的remain_count加一。同样放在一个事务里。判断是否逾期则在更新之前比较due_time和当前时间逾期就把状态置为 2。4.4 前端 JSP 与后端的数据流转前面说的都是后端但前端 JSP 也是这个项目能跑通的关键一环。JSP 页面里用表单收集数据提交到WebServlet映射的地址后端通过request.getParameter拿到值做完处理后再把结果放到request或session作用域里由 JSP 取出来展示。这个流转链路如果断了一环表现就是数据进不了数据库或者页面刷新后数据不显示。数据方向载体典型问题前端到后端Form 表单 POST、URL 参数 GET请求方法不匹配405 错误后端到 JSPrequest.setAttribute 转发用了重定向导致 attribute 丢失跨页面保持状态session关闭浏览器后重新打开需要重新登录数据展示JSTL 的 c:forEach集合数据没放进正确作用域我见过最多的翻车点是后端往request放了列表数据结果用sendRedirect跳去列表页。转发和重定向的差异在这里就看出来了转发是同一次请求内完成的request.setAttribute的数据还能读到重定向等于让浏览器重新发起请求原来的 request 属性全部丢失。列表展示类操作一律用forward新增、修改、删除成功后则用sendRedirect防止表单重复提交这两个原则记住前后端数据流转基本不会出大问题。5. Excel 导入导出与常见问题排查从 class 文件还原逻辑到四个翻车现场5.1 从 class 文件看导入导出链路ExcelOperate 与 Service 的分工源码里有一组类名特别值得注意BookInfoExcelOperate、UserInfoExcelOperate、AppendUserInExcelService。从命名可以还原出它的业务逻辑前面两个分别负责图书和用户数据与 Excel 文件之间的转换AppendUserInExcelService负责把新增用户追加写进已有的 Excel 文件。也就是说系统里存在两条 Excel 操作线一条是从 Excel 导入数据到数据库一条是把数据库数据导出成 Excel。这个设计是典型的“工具类 业务类”分工。Excel 操作类只关心文件的读写读取工作簿的哪一行、哪一列写到什么位置不关心业务Service 类才关心数据从 Excel 里拿出来之后怎么落到数据库、字段怎么对齐。你在答辩时可以这样讲老师会认为你对项目结构有真正的理解而不是只会背源码。如果你在源码里看到的是jxl包的导入那是比较老的 Excel 处理库如果是org.apache.poi开头就是 Apache POI。两者都支持读写 xls 和 xlsxPOI 更主流社区资料也更多。出问题时优先查 POI 的版本和 Excel 文件格式是否匹配。5.2 导入实现读 Excel 写数据库的代码骨架导入的本质是用 POI 把 Excel 文件解析成 Java 对象再逐行调用 DAO 写入数据库。常见的做法是先读第一个 Sheet从第二行开始遍历第一行通常是表头把每一列的值按字段顺序填进实体类然后批量插入。下面这段是图书信息导入的核心逻辑Workbook workbook WorkbookFactory.create(new FileInputStream(filePath)); Sheet sheet workbook.getSheetAt(0); for (int rowIndex 1; rowIndex sheet.getLastRowNum(); rowIndex) { Row row sheet.getRow(rowIndex); if (row null) { continue; } Book book new Book(); book.setBookName(row.getCell(0).getStringCellValue()); book.setAuthor(row.getCell(1).getStringCellValue()); if (row.getCell(2).getCellType() CellType.NUMERIC) { book.setTotalCount((int) row.getCell(2).getNumericCellValue()); } bookOperate.insert(book); } workbook.close();这里有几个必须处理的细节。row.getCell(0)可能返回 null尤其当某一行的前面几个单元格是空的时候调用前最好加判空。getStringCellValue()对文本类型有效但如果单元格是数字类型它会直接抛异常所以像数量这样的数字列要先用getCellType()判断类型再取值。getLastRowNum()返回的是行的最大索引而不是行数循环条件里要用。批量导入几百行数据时逐条 insert 虽然可用但效率偏低。更稳的做法是用 JDBC 的addBatch()把一批 SQL 攒在一起提交或者至少每 50 条 commit 一次。事务要保证“要么全导入要么全不导入”导入过程中有一条数据格式不对导致异常前面已经写进去的记录必须回滚否则用户导了一次库里多了一半数据他自己都不知道哪几条是成功的。5.3 导出实现把数据库表写成 Excel 的代码骨架导出是导入的反向操作逻辑是查数据库、创建工作簿、按行填充、写响应流。后端导出时通常会让浏览器弹出下载框所以除了往 Workbook 里填数据还要设置响应头。核心代码如下try (Workbook workbook new XSSFWorkbook(); OutputStream out response.getOutputStream()) { Sheet sheet workbook.createSheet(图书列表); String[] headers {书名, 作者, 出版社, 库存}; Row headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } ListBook bookList bookOperate.findAll(); int rowIndex 1; for (Book book : bookList) { Row row sheet.createRow(rowIndex); row.createCell(0).setCellValue(book.getBookName()); row.createCell(1).setCellValue(book.getAuthor()); row.createCell(2).setCellValue(book.getPublisher()); row.createCell(3).setCellValue(book.getRemainCount()); } response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment; filenamebooks.xlsx); }XSSFWorkbook对应 Excel 2007 以上的 xlsx 格式比老的HSSFWorkbook功能更多也支持更大的数据量。响应头的Content-Type必须是 Excel 对应的 MIME 类型否则浏览器可能把它当成 html 下载Content-Disposition里的attachment告诉浏览器这是附件弹出下载而不是直接打开。5.4 四个高频踩坑记录现象、原因、解决坑一Excel 里的日期导入后变成一串数字。比如借阅日期导入数据库里存的值是44231.0这种数字。原因POI 读取日期单元格时拿到的是 Excel 内部的日期序列号不是格式化后的日期字符串。解决读取前判断getCellType()是不是NUMERIC再用DateUtil.isCellDateFormatted(cell)判断是否为日期格式是日期就用cell.getDateCellValue()取值再转成java.sql.Date写入。坑二导出的 Excel 用 WPS 打开乱码。原因有两个方向一是响应头没设置text/html以外的 Content-Type二是文件名带了中文却没有做编码转换导致 HTTP 头的解析错乱。解决文件名用URLEncoder.encode(图书列表.xlsx, UTF-8)之后再拼进Content-Disposition响应类型固定写application/vnd.openxmlformats-officedocument.spreadsheetml.sheet。坑三导入 500 行数据时页面卡死或内存溢出。原因XSSFWorkbook在解析时会把整个 Excel 的 DOM 结构加载进内存行数多了以后堆内存直接吃满。解决导入用WorkbookFactory让 POI 根据文件大小自动选择解析方式导出大数据量时改用SXSSFWorkbook它只保留一部分行在内存里其余写进临时文件内存占用能降一个量级。坑四部署后登录页和列表页的 CSS、JS 样式全部丢失。原因页面里写的资源路径是绝对路径比如/css/style.css但项目部署后的上下文路径是/book浏览器找的是根路径下的资源自然 404。解决把所有静态资源引用改成相对路径或 JSP 表达式动态拼接上下文比如%request.getContextPath()%/css/style.css或者用${pageContext.request.contextPath}前缀这样换任何部署名都不会再丢样式。6. 部署验证与调试思路启动、自测、再往前走一步先把验证清单过一遍。项目部署完、数据库导入完成后不要急着看业务功能先走一条最基础的链路启动 Tomcat访问登录页确认页面样式正常用管理员账号登录进到图书列表试一次新增、一次编辑、一次删除再试一次借书和还书去数据库里查对应记录的状态和库存数量有没有同步变化。这一套走完项目的主体功能就算验证通过了。验证项操作预期结果环境启动 Tomcat 访问登录页页面正常加载无 500 异常导入导出上传一个测试 Excel数据入库无乱码、无数字日期借阅流程借一本书再归还borrow 表状态变更book 表 remain_count 先减后加权限控制未登录直接访问列表页地址跳回登录页或提示未登录全部验证通过之后如果你想把这份 JavaWeb 项目在毕设里做出差异化有一个成本很低的进阶方向把 JSP 改成前后端分离。底层的那套 Servlet 接口其实已经具备接收请求、操作数据库的能力缺的只是把响应格式改成 JSON。你可以在现有 Servlet 里把request.getRequestDispatcher().forward()换成用 Jackson 或 Gson 输出response.setContentType(application/json;charsetutf-8)把实体类序列化输出。前端随便用一个静态页面接fetch就能继续跑这一改系统的技术栈就从 JSP 变成了前端 H5 Java 后端接口答辩的讨论空间直接大一截。我以前做 JavaWeb 课程设计时吃过一次亏项目调通了就直接交没做二次验证结果演示时导入 Excel 里有一行日期格式不对当场报错。从那以后我每次拿到这类毕业设计源码都会强制自己先走一遍“环境—数据—业务—异常”四步验证不光验证正常流程还要故意输入错误数据看系统怎么反应。希望你拿到这份源码时也先跑一遍我上面的清单别等到答辩前夜才发现问题希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑