实训项目做到第4天,通常都是同一个心态:后台代码、数据库、Servlet路由这些硬骨头都啃完了,就剩下一堆JSP页面,觉得“不过是写几个网页嘛”,结果真正动手改的时候才发现,JSP层才是整个图书管理系统里最磨人的部分。如果你也是在做javaweb实训作业的图书管理系统,这几天大概也遇到了类似的情况——后台明明能查到数据,页面就是显示不出来;明明能跳转,路径就是一直404;明明写的是中文,浏览器里全变成问号。这篇文章就把我这几天完善JSP层的实战过程梳理一遍,从页面职责划分、JSP脚本片段和EL表达式的配合,到前后端数据贯通、编码路径数据库连接的坑,再到最终“源码+数据库”交付前的高分自查清单,完整走一遍。
1. JSP层在图书管理系统中的真实定位:不是“最后随便写写”,而是“成绩单的门面”
很多同学做实训项目容易陷入一个误区:把JSP当成“把Java代码塞进HTML里”的工具,觉得JavaWeb项目就是前端页面套几个Java语法。这种理解在图书管理系统这个场景里特别危险,因为实训老师评分的时候,真正打开浏览器一个一个点的,不是你的Service层写得有多优雅,而是页面能不能正常显示、操作能不能顺利走通、报错会不会直接甩出一个500页。
1.1 前3天做了什么,第4天到底还剩什么
按照正常的javaweb实训进度,前3天大概完成了这些事情:
- 第1天:搭项目结构,配好Tomcat、MySQL,建好数据库表(图书表、读者表、借阅表、管理员表、分类表),写好JDBC工具类。
- 第2天:写完实体类和DAO层,实现图书、读者、借阅记录的增删改查。
- 第3天:写完Servlet,配置好web.xml或者注解路由,把请求转发和重定向的基本流程调通。
到这一步,项目的“后端能力”已经齐了——你可以在Servlet里直接调用DAO拿到数据,然后用response.getWriter().println()在页面上输出一行图书列表的JSON。但实训作业要求的是完整的图书管理系统,老师要在浏览器里看到的是一个能操作、能展示、能跳转的Web应用,不是返回JSON字符串的接口。所以第4天的核心任务就是把JSP层补全,把Servlet里的数据变成浏览器里漂亮的表格和表单。
1.2 为什么说JSP层是“成绩单的门面”
实训评分有一个特别现实的逻辑:功能再怎么完善,如果打开页面白屏、布局错乱、字体全是乱码,老师的第一印象就毁了。JSP层在这个项目里承担三个角色:
- 数据展示:把数据库里的图书信息、读者信息、借阅记录渲染成HTML表格,让用户能“看到”数据。
- 流程入口:通过表单提交、超链接跳转,把用户的请求发送给对应的Servlet。
- 状态反馈:操作成功或失败后的提示页面,比如“借阅成功”“该图书已借出”“请先登录”。
这三个角色听起来简单,但做起来很容易翻车。尤其是第4天把JSP层完善以后,会遇到很多“后台明明没问题,页面却出问题”的情况,后面我逐一展开讲。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实训项目里JSP页面的代码组织方式:脚本片段、EL表达式和JSTL各干各的活
刚开始写JSP的时候,大多数人都习惯这样写:在页面顶部写一大段<% ... %>JSP脚本片段,把Java代码直接怼进页面里,然后HTML里穿插无数个<%= %>输出。
jsp复制<%
List<Book> bookList = new BookDao().findAll();
for (Book book : bookList) {
out.println("<tr><td>" + book.getName() + "</td></tr>");
}
%>
这种写法在功能上没问题,也能跑通,但项目一旦复杂起来就会很难受。第4天完善JSP层的时候,我做的第一件事就是把这些脚本片段逐步替换成EL表达式和JSTL标签。不是单纯为了“看起来规范”,而是有实操层面的好处。
2.1 为什么不要在每个页面都写<% ... %>
图书管理系统至少有图书列表、图书添加、图书修改、图书删除确认、读者列表、借阅列表、登录页、注册页、个人信息页这些JSP页面。如果每个页面都用脚本片段写业务逻辑,会出现三个问题:
- JSP页面越来越臃肿。一个图书列表页,光Java代码可能就要几十行,HTML结构反而淹没在
<% %>和<%= %>里,后期维护想改个表格样式都看不清结构。 - 异常处理很混乱。脚本片段里的Java代码如果抛出异常,页面直接显示500,而且异常堆栈会暴露在控制台里,想定位问题得在一堆页面里找你到底在哪个JSP写了这段逻辑。
- 数据获取的代码会重复。比如每个页面都要从
session里拿当前登录用户,如果每次都用脚本片段写一遍,代码浪费不说,还容易出现低级Bug。
实训阶段最重要的事情是保证页面稳定。把业务逻辑留在Servlet,JSP只负责用EL表达式取数据、用JSTL标签做循环和判断,页面的容错率会高很多。
2.2 EL表达式和JSTL在图书管理系统里的实际用法
EL表达式的核心作用是从作用域对象(request、session、application)里取值。比如登录成功后把管理员对象丢进session:
java复制HttpSession session = request.getSession();
session.setAttribute("admin", admin);
JSP页面里就可以这样取:
jsp复制<p>欢迎你,${sessionScope.admin.username}</p>
图书列表页是最典型的场景。Servlet查询完列表后放request里:
java复制request.setAttribute("bookList", bookList);
request.getRequestDispatcher("bookList.jsp").forward(request, response);
JSP页面里用JSTL的c:forEach循环输出:
jsp复制<table border="1">
<tr>
<th>编号</th>
<th>书名</th>
<th>作者</th>
<th>价格</th>
<th>库存</th>
<th>操作</th>
</tr>
<c:forEach items="${bookList}" var="book">
<tr>
<td>${book.id}</td>
<td>${book.name}</td>
<td>${book.author}</td>
<td>${book.price}</td>
<td>${book.stock}</td>
<td>
<a href="BookServlet?action=edit&id
