十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JavaWeb图书管理系统全流程实战:Servlet+JSP+JDBC从零构建

JavaWeb图书管理系统全流程实战:Servlet+JSP+JDBC从零构建 简介这是一份基于JavaWeb技术栈的图书管理系统完整项目包面向正在学习JSP、Servlet、JavaBean、JDBC及DAO模式的开发者可用于课程设计、毕业设计或项目实战练习。资源共3个文件压缩包约4.52MB内含项目源码zip、系统设计报告docx和数据库脚本sql源码覆盖前端页面、后端逻辑与数据访问层报告涵盖需求分析、架构设计、数据库设计及功能实现SQL文件则提供图书和用户等核心数据表。目前已有19439人学习下载适合希望系统掌握JavaWeb开发全流程、理解前后端交互和MVC架构的读者通过对照源码和设计文档可快速完成环境搭建、功能扩展与排错复盘。1. 立项前先把底子打好技术选型与项目骨架1.1 为什么2025年还要用传统JavaWeb做图书管理系统说实话现在出去面试或者做课程设计十个里面八个会让你用Spring Boot写管理系统。但我做这个JavaWeb图书管理系统项目的时候坚决没用框架就用Servlet JSP JDBC这套最原始的技术栈。原因有三个。第一这个项目最核心的定位是打基础。Spring Boot把什么都封装好了注解一标、依赖一引业务代码往里面一塞就完事。但问题是很多人写完Spring Boot项目连HTTP请求怎么被Servlet接收的都不知道更别说理解Session生命周期、Filter执行顺序这些底层机制。而用传统JavaWeb每一步都是手动的写Servlet、配置web.xml、处理请求参数、手动获取数据库连接整个过程会让你把Web开发的基础链路彻底摸透。第二部署环境极其友好。只需要一个Tomcat把项目打成war包丢进webapps目录启动就完事不需要Maven中央仓库拉几百MB依赖不用配Redis、Nacos这些中间件。我拿一台Windows 7老机器都跑起来过放在课程设计答辩现场演示稳定性完全够用。第三图书管理系统本身够典型。它的业务逻辑足够复杂但又不至于复杂到撑不起传统开发方式。读者管理、图书管理、借阅归还、逾期统计每个模块都能讲清楚每个操作都能落到SQL上。用它来做JavaWeb的完整案例再合适不过。注意如果你已经有Spring Boot经验回头补这个传统JavaWeb项目理解反而会更透彻。Netty、Tomcat这些容器之间的区别会在这个项目里有很直观的感受。1.2 项目结构设计与开发环境搭建我用的是经典的MVC分层结构没有用Maven直接手动管理jar包这样对初学者更友好不会在构建工具的坑里绕太久。BookManager/ ├── src/ │ ├── com.book.entity # 实体类User、Book、BorrowRecord │ ├── com.book.dao # 数据访问层JDBC操作数据库 │ ├── com.book.service # 业务逻辑层 │ ├── com.book.servlet # Servlet控制层 │ ├── com.book.util # 工具类DBUtil、MD5Util、VerifyCodeUtil │ └── com.book.filter # Filter过滤器 ├── web/ │ ├── static/ # 静态资源CSS、JS、图片 │ ├── WEB-INF/ │ │ ├── web.xml # 核心配置文件 │ │ └── jsp/ # 视图层页面 │ └── index.jsp └── lib/ # mysql-connector-java.jar等开发环境这块我给出我实测的组合JDK 1.8兼容性最好Tomcat裸跑不需要额外配置Tomcat 9.0对应Servlet 4.0规范支持JDBC 4.2MySQL 5.7InnoDB引擎默认事务支持成熟IDEA 2023.2 或 VS Code Tomcat插件如果你用的是VS Code需要装这几个扩展Extension Pack for Java、Tomcat for Java、MySQL Shell for VS Code。配置Tomcat的时候注意要选Tomcat安装目录的根路径不是bin目录。IDEA的话直接在Run Configuration里加一个Tomcat Server即可然后Deployment里添加Artifact。1.3 核心配置文件web.xml的写法传统JavaWeb项目里web.xml是整个项目的总开关。Servlet 3.0之前只能在这里配3.0之后可以用注解代替但我强烈建议你在入门阶段手写一遍web.xml因为这是理解Servlet映射路径的绝佳机会。web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 display-nameJavaWeb图书管理系统/display-name !-- 编码过滤器 -- filter filter-nameCharacterEncodingFilter/filter-name filter-classcom.book.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameCharacterEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping !-- 登录验证过滤器 -- filter filter-nameLoginFilter/filter-name filter-classcom.book.filter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern/jsp/*/url-pattern /filter-mapping welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list /web-app这里有两个细节值得反复琢磨。第一个是url-pattern的匹配规则/*和/的区别很多人在这个上面翻车。/*是匹配所有路径包括JSP页面而/是匹配Servlet路径但排除JSP。如果登录过滤器的url-pattern配成/*那你连login.jsp都会拦就会形成死循环——登录页面都进不去还怎么登录所以我把登录过滤器配在/jsp/*上只拦JSP页面Servlet层自己判断。第二个是Filter的init-param如果你有多个Filter需要不同的编码参数这地方就要区分清楚别一把梭全部用同一个。2. 数据库是系统的地基图书管理系统的数据建模与关键SQL设计2.1 三张核心表的设计思路图书管理系统听起来简单但数据模型如果设计得不好后面写业务代码的时候会四处漏风。我这个项目一共用了四张表用户表、图书表、借阅记录表还有一个数据字典表存图书分类。用户表的设计关键是你得考虑角色。图书管理系统里管理员和读者是两种完全不同的角色但很多人一上来就建两套表admin表、user表各来一套这其实没必要。就用一张表加一个role字段类型用TINYINT1代表管理员0代表普通用户。登录之后根据role字段决定跳转到哪个页面操作权限再去控制逻辑清晰又省事。CREATE TABLE t_user ( id INT NOT NULL AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) NOT NULL COMMENT 用户名, password VARCHAR(64) NOT NULL COMMENT 密码(MD5加密), real_name VARCHAR(50) DEFAULT NULL COMMENT 真实姓名, role TINYINT NOT NULL DEFAULT 0 COMMENT 角色: 0-用户 1-管理员, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;图书表的设计核心是ISBN字段。ISBN是图书的唯一标识但在实际图书管理场景里同一本书可能会有多本副本比如《Java编程思想》有3本。所以不要把ISBN设成主键而是建立一个自增主键ISBN单独加普通索引。书名、作者、出版社、出版日期、库存总量、可借数量这些字段都要有。其中available_count这个字段很关键它代表当前可借的数量每次借书还书都会更新它。借阅记录表是整个系统里最核心的表也是出问题最多的地方。CREATE TABLE t_borrow_record ( id INT NOT NULL AUTO_INCREMENT, book_id INT NOT NULL COMMENT 图书ID, user_id INT NOT NULL COMMENT 借阅人ID, borrow_date DATETIME NOT NULL COMMENT 借书时间, due_date DATETIME NOT NULL COMMENT 应还时间, return_date DATETIME DEFAULT NULL COMMENT 实际归还时间, status TINYINT NOT NULL DEFAULT 0 COMMENT 状态: 0-借出 1-已还 2-逾期, PRIMARY KEY (id), KEY idx_user_id (user_id), KEY idx_book_id (book_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;status字段为什么要设0、1、2三种状态而不是借出的记录删掉、还书的记录加一条因为你需要保留完整的借阅历史这个字段帮助你查询哪些书还没还、哪些逾期了不用去算借出时间和当前时间的时间差。逾期状态不是借书的时候定好的而是还书的时候判断的如果actual_return_date due_date就更新status为2。还有人会纠结要不要记录逾期天数我的建议是不要存用SQL函数DATEDIFF(return_date, due_date)现算保证数据一致性。2.2 数据库连接工具类的封装与连接池选型传统JavaWeb里连接数据库最原始的写法是Class.forName(com.mysql.jdbc.Driver); String url jdbc:mysql://localhost:3306/book_manager?useUnicodetruecharacterEncodingUTF-8; Connection conn DriverManager.getConnection(url, root, password);这种写法开发阶段没问题但生产环境绝对不能这么干。因为每次请求都创建一个物理连接数据库的连接数是有限的并发一高就直接把数据库拖垮。实际开发中有个库存管理系统的朋友跟我聊过他们线上就出过这个问题——20个并发请求进来数据库连接数直接占满剩下的请求全部排队等待接口响应时间从几十毫秒飙到十几秒。这个项目的做法是引入Druid连接池阿里开源的监控功能强大配置简单。在项目的lib目录下加入druid-1.1.23.jar然后在src目录下建一个druid.properties配置文件driverClassNamecom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/book_manager?useUnicodetruecharacterEncodingUTF-8useSSLfalse usernameroot password123456 initialSize5 maxActive20 maxWait60000然后封装一个DBUtil工具类里面有一个静态方法获取当前线程绑定的连接这是整个项目数据访问的基础设施。如果没有连接池你打开连接、关闭连接几行代码看起来简单但一旦池化之后你会发现很多并发问题都自动消失了connection不再频繁创建销毁。这里的关键一点是利用ThreadLocal保证一个事务里面的多个DAO操作共用同一个Connection否则你Service层开了事务但DAO层各拿各的连接事务就是废的。2.3 事务处理借用还书必须保证原子性借书这个动作并不只是往借阅记录表插入一条数据那么简单。它要同时干三件事往借阅记录表插记录、把图书表对应记录的available_count减1、检查该用户有没有没还的书。这三步里任何一步失败都不能让另外两步的修改生效。JDBC原生写法里事务控制的代码很冗余。每次都要conn.setAutoCommit(false)、try...catch里conn.rollback()、最后conn.commit()。我把这个逻辑抽到了一个TransactionTemplate里用一个极简的模板方法模式解决问题。核心思想是在Service层开启事务给整个业务方法包装一层拦截。public class TransactionManager { public static T T execute(TransactionCallbackT callback) { Connection conn DBUtil.getConnection(); try { conn.setAutoCommit(false); T result callback.doInTransaction(); conn.commit(); return result; } catch (Exception e) { conn.rollback(); throw new RuntimeException(事务执行失败, e); } finally { conn.setAutoCommit(true); DBUtil.closeConnection(); } } }Service层调用的时候把业务代码扔进execute()方法里事务边界就自动划好了。这个思想其实就是Spring的TransactionTemplate的原型。你先理解这一层之后再去学Spring的声明式事务会立刻明白它省掉了哪些样板代码。注意事务只在Service层控制DAO层的方法全部用自动提交模式不要在每个DAO方法里单独管理事务否则多层嵌套事务会出现难以排查的锁问题。3. 功能模块逐个拆解登录验证、图书检索与借阅闭环3.1 验证码与登录流程安全细节不能少图书管理系统虽然是个教学项目但登录这个模块不能做太草率。我的方案是图形验证码 Session校验 密码MD5加密三层防护。验证码用Java原生Graphics2D画出来核心代码大概是这样的public class VerifyCodeUtil { public static String generate(HttpServletResponse response) throws IOException { int width 68, height 42; BufferedImage image new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g image.createGraphics(); g.setColor(Color.LIGHT_GRAY); g.fillRect(0, 0, width, height); String chars abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789; StringBuilder code new StringBuilder(); Random random new Random(); for (int i 0; i 4; i) { char c chars.charAt(random.nextInt(chars.length())); code.append(c); g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256))); g.setFont(new Font(Arial, Font.BOLD, 28 random.nextInt(6))); g.drawString(String.valueOf(c), 8 i * 15, 32 random.nextInt(5)); } // 画干扰线 for (int i 0; i 8; i) { g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height)); } g.dispose(); ImageIO.write(image, JPEG, response.getOutputStream()); return code.toString(); } }验证码的校验有一个容易忽略的坑Session里存的验证码要用完即删。如果你不删除用户刷新页面之前同一个验证码会一直有效这就给了脚本暴力破解的空间。我在登录成功和验证码刷新两个地方都执行了session.removeAttribute(verifyCode)。密码MD5加密记住一句MD5不够安全的不是算法而是没有加盐。直接对密码做MD5用户群体里只要两三个人用了弱密码就能被彩虹表反查出来。我在这里加了一个固定的盐值或者每个用户随机生成一个盐存在用户表里把盐和密码拼在一起再做MD5这个做法能有效防彩虹表。登录流程我画个简单的逻辑链路用户提交用户名、密码、验证码 - Filter检查Session里是否有验证码 - 校验验证码是否匹配 - 根据用户名查用户 - 查出来的用户判断密码是否匹配 - 设置Session用户信息 - 根据role跳转。这个流程里任何一步失败都返回错误信息到登录页不提供任何详细错误的提示。否则别人可以通过报错信息判断账号存不存在。3.2 图书检索分页查询与条件组合图书检索功能最菜的做法是把所有数据一次性load到前端然后用JavaScript做过滤。这在小数据量下没问题图书表超过几千条数据就卡到不行。我采用的是服务端分页 MySQL的LIMIT语法。前端页面展示一个搜索框 分类下拉框 搜索结果表格表格底部是分页按钮。后端接收pageNum、pageSize、keyword、categoryId四个参数拼SQL的时候注意参数预编译千万不能用字符串拼接SQL否则这就是最经典的SQL注入漏洞。public ListBook searchBooks(String keyword, Integer categoryId, int pageNum, int pageSize) { StringBuilder sql new StringBuilder(SELECT * FROM t_book WHERE 11); ListObject params new ArrayList(); if (keyword ! null !keyword.trim().isEmpty()) { sql.append( AND (title LIKE ? OR author LIKE ? OR isbn LIKE ?)); params.add(% keyword %); params.add(% keyword %); params.add(% keyword %); } if (categoryId ! null) { sql.append( AND category_id ?); params.add(categoryId); } sql.append( LIMIT ?, ?); params.add((pageNum - 1) * pageSize); params.add(pageSize); // 使用 PreparedStatement 执行 }分页的关键还有一个配套的统计总数SQL。用户看到的那个共X条记录第Y/Z页这个总页数就是根据总数算出来的int totalCount bookDao.countByCondition(keyword, categoryId); int totalPages (int) Math.ceil((double) totalCount / pageSize);分页参数里(pageNum - 1) * pageSize这个公式必须理解清楚。LIMIT的语法是LIMIT offset, countoffset从0开始所以页码减1再乘以每页大小就是跳过的行数。这个小地方写错了翻到第二页就会丢一条数据或者重复一条数据。3.3 借书与还书的完整闭环借书流程的Service层逻辑我把每一步都用注释标注出来Transactional(rollbackFor Exception.class) public void borrowBook(int bookId, int userId) { // 1. 查图书判断库存 Book book bookDao.findById(bookId); if (book null || book.getAvailableCount() 0) { throw new BusinessException(图书不存在或已借完); } // 2. 查用户当前未归还的借阅记录 int unreturnedCount borrowDao.countUnreturnedByUserId(userId); if (unreturnedCount MAX_BORROW_LIMIT) { throw new BusinessException(已达到最大借阅数量); } // 3. 插入借阅记录 BorrowRecord record new BorrowRecord(); record.setBookId(bookId); record.setUserId(userId); record.setBorrowDate(new Date()); Calendar cal Calendar.getInstance(); cal.add(Calendar.DAY_OF_MONTH, 30); // 默认借期30天 record.setDueDate(cal.getTime()); record.setStatus(0); borrowDao.insert(record); // 4. 扣减库存 bookDao.decreaseAvailable(bookId); }这一步很多人会漏考虑一个东西一个用户能借几本书我设了MAX_BORROW_LIMIT 5这个常量用户在借未还的书超过5本就直接拒绝。这个上限在真实图书馆系统里一般是10到20本课程设计用5本足够展示逻辑。借书成功之后页面上要能看到自己的借阅列表且能区分在借和已还状态。还书流程就相对简单更新借阅记录的return_date为当前时间根据是否超过due_date设置status为1或2再把图书的available_count加回去。但有一个细节还书的时候要判断这本书是不是这个用户借的防止用户A知道了一个借阅记录ID就把用户B借的书给还了。权限校验在Web应用里无处不在写的时候要养成习惯。3.4 管理员专属功能图书上下架与用户管理管理员登录和用户在同一个Session里靠role字段区分。管理员的额外功能主要是图书的新增、编辑、删除以及用户列表查看和启用/停用。图书新增和编辑的区别在于新增是INSERT编辑是UPDATE。我懒得写两个Servlet就用一个BookEditServlet通过请求里有没有bookId参数来决定是新增还是编辑模式。这个技巧在实际项目里也常用一个资源接口同时承载创建和更新两种语义关键是响应不同的HTTP状态码。删除图书的时候有一个大坑如果这本书已经有借阅记录直接DELETE会违反外键约束如果表里设置了外键或者产生孤儿数据。我的做法是逻辑删除给图书表加一个status字段0正常、1下架。删除操作只是把status改成1历史借阅记录不受影响前端查询的时候默认只查status0的。这个设计其实是从电商系统的商品下架学来的数据永远不物理删除只做标记。4. 联调时会踩的坑真实开发中的高频问题与排查实录4.1 中文乱码——三个层面逐个排查几乎每个做JavaWeb的新人都会被中文乱码折磨。乱码分三种情况我记得第一次做完这个项目展示给同学看页面上全是浣犲ソ这种火星文那种心情真的不想再体验。第一个层面是请求乱码。POST请求的参数乱码是因为Tomcat默认用ISO-8859-1解码请求体。解决办法就是在web.xml里配置CharacterEncodingFilter或者手动在Servlet里写request.setCharacterEncoding(UTF-8)。GET请求的乱码更隐蔽是因为Tomcat的URI编码默认也是ISO-8859-1需要修改Tomcat的server.xml在Connector标签上加URIEncodingUTF-8这个属性。第二个层面是响应乱码。response.setContentType(text/html;charsetUTF-8)这行代码要放在getWriter()调用之前。如果你先拿了Writer再设编码那已经写出去的内容编码就固定了怎么设置都没用。第三个层面是数据库乱码。连接URL上要加characterEncodingUTF-8数据库建表时要指定DEFAULT CHARSETutf8mb4JDBC驱动连接属性里也需要指定编码。这三个地方缺一个数据存进去的时候就会变成问号或者乱码。我见过太多人只改了数据库的编码忘了连接URL上的参数结果数据一插进去就全变问号。我建议在项目最开始写一个专门的编码测试Servlet把所有涉及编码的环节测一遍确认无误再往下开发。别等到所有功能做完才开始联调那时候排查范围太大极其痛苦。4.2 连接池报错与数据库连接泄露用上Druid连接池之后我遇到过一个经典问题运行一段时间后控制台报连接池已关闭或者com.alibaba.druid.pool.GetConnectionTimeoutException连接数达到maxActive上限。这种问题十有八九是连接没关闭。很多人在DAO层写了conn DBUtil.getConnection()之后只关了ResultSet和PreparedStatement唯独忘了关Connection。在连接池模式下conn.close()不是真的关闭物理连接而是把连接返还给连接池所以这个close绝对不能省。排查方法很简单在Druid的配置里开启监控页或者我在代码里打日志查看每个线程拿到连接后都在干什么。最后发现还有一个隐性坑代码里某个分支提前return了而finally块里的关闭代码放在了return之后根本执行不到。所以正确写法一定是Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); ps conn.prepareStatement(sql); // 执行逻辑 } finally { if (rs ! null) rs.close(); if (ps ! null) ps.close(); if (conn ! null) conn.close(); }不想写这么啰嗦的话Java 7的try-with-resources语法你值得拥有。注意Connection实现了AutoCloseable接口JDBC 4.1及以上都支持。配合上连接池的maxActive20、initialSize5、minIdle5系统跑个几千次操作都不会有什么连接问题。4.3 TIMESTAMP字段的范围问题MySQL 5.7里有个默认行为TIMESTAMP类型默认范围是1970-01-01到2038-01-01。如果借书或还书的日期设置超出这个范围就会报Data truncation: Incorrect datetime value。这个坑特别容易在测试时踩到。你测试还书功能写了一个return_date 2099-01-01的数据然后数据库直接拒绝插入。解决办法有两个一是建表的时候把所有日期字段都改成DATETIME类型DATETIME的范围是1000-01-01到9999-12-31几乎不会超二是在Java代码里不要用java.sql.Timestamp去set日期直接用java.util.Date配合setObject()方法传参让JDBC驱动自己转换。我在项目里统一用的是DATETIME类型彻底绕开这个困扰。4.4 常见问题速查表我把这个项目开发过程中遇到过的问题整理成了一个表方便你开发的时候对照排查现象可能原因解决方式登录页面加载不出来登录Filter误拦截了JSP文件检查web.xml里Filter的url-pattern是否配成/jsp/*而不是/*验证码图片不显示输出流没关闭或Content-Type没设置确认response.setContentType(image/jpeg)且不用关闭ServletOutputStream数据库中文变成??连接URL缺少characterEncodingUTF-8在JDBC URL上追加编码参数翻页时数据重复/缺失LIMIT偏移量计算错误用(pageNum - 1) * pageSize作为offset并发借同一本书超卖没有在事务中锁行使用SELECT ... FOR UPDATE锁定图书行事务提交后释放借书成功后库存没变借阅记录和库存扣减不在同一个事务确保两个DAO操作使用同一个数据库连接5. 这个项目还能怎么挖深一层从课程设计到简历实战5.1 用Filter ThreadLocal实现事务与请求追踪很多人做完CRUD就收工了但如果能在项目里加上一些工程化的小设计面试的时候讲出来会加分不少。比如我在这个项目里用ThreadLocal让DAO层自动获取当前请求线程绑定的数据库连接这样Service层开启动态代理之后事务边界就清晰了。这个技巧的进阶用法是实现一个简单的请求日志过滤器记录每次请求的URL、执行时间、用户信息输出到日志文件。这种横切关注点的概念其实就是AOP思想的雏形。public class LogFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long start System.currentTimeMillis(); HttpServletRequest req (HttpServletRequest) request; chain.doFilter(request, response); long cost System.currentTimeMillis() - start; System.out.printf(Request: %s, cost: %dms%n, req.getRequestURI(), cost); } }5.2 可视化统计报表的扩展思路图书管理系统如果停留在增删改查它只是一个数据库练习。真正让它有价值的是你能从数据里看到运营指标。扩展一个统计页每月借阅量趋势图、图书分类占比饼图、逾期率TOP10图书排行。这些数据通过一条SQL就能查出来前端用ECharts展示。JSP页面引入ECharts很简单通过CDN直接引用在页面初始化时用Ajax请求后端一个统计Servlet拿到JSON数据后绘制图表。这一步做出来我就觉得这个项目不是能跑而是能展示了。我当时扩展了一个管理员Dashboard页放上整个图书馆的借阅量、馆藏量、逾期量三个核心指标演示效果比一堆表格好太多。5.3 简历上面试官爱问的几个衍生点做完这个项目面试官大概率会顺着问几个问题你得提前准备Servlet的生命周期是怎样的init、service、destroy分别在什么时候被调用GET和POST的区别什么时候用GET什么时候用POSTSession和Cookie的区别Session的实现原理是什么事务的ACID四大特性是什么你在哪段代码里用到了事务MySQL的索引底层数据结构是什么为什么用B树不用哈希什么是SQL注入你的代码里怎么防止它这些问题都能在这个项目里找到对应的代码和设计依据。我当年就是把借书事务那一段代码背熟然后把事务隔离级别、Spring事务传播行为这些概念串联起来讲面试效果比纯背八股文好得多。写在最后的实操建议跑一遍这个项目的完整流程从建库建表到部署到Tomcat我粗略估算了一下一天半左右就能完成核心功能。真正费时间的不是写代码而是排查那些你以为没问题但就是不对的细节比如编码、连接关闭、路径映射。所以我建议你别急着把所有功能一次性写完先完成一个最小闭环登录 - 图书列表 - 借书 - 还书每一步都跑通了再往上面加功能。做项目的过程里还有一个习惯值得坚持每解决一个bug把它记下来写清什么现象、什么原因、怎么解决的。这个笔记既不占时间又是你后续面试、写博客的最宝贵素材。说实话我写这篇复盘文章用的很多案例就是从当年的bug记录里翻出来的。本文还有配套的精品资源点击获取
返回列表