Servlet+JSP水果超市项目:JavaWeb完整CRUD实战

发布时间:2026/9/17 1:45:27
Servlet+JSP水果超市项目:JavaWeb完整CRUD实战 简介一份基于Servlet与JSP技术实现的水果超市后台管理项目主要面向Java Web初学者以模拟水果超市的商品管理为场景完整覆盖添加、删除、修改、查询等基础操作并扩展了用户注册登录功能适合用来串联HTTP请求处理、Servlet业务逻辑、页面跳转和数据库增删改查的完整Web开发流程。资源包共85个文件压缩后大小约2.1MB核心内容包括Java源文件、JSP动态页面、XML部署配置、前端CSS与JavaScript脚本、图片素材另外还包含已编译的class文件与IDEA工程配置文件导入开发工具即可查看项目结构。项目按标准Web工程组织目录src保存Java类web目录集中存放JSP与静态资源out目录单独保存编译产物模块划分明确。搭配Tomcat服务器运行后可用IDEA打开并配合Navicat管理数据库适合作为课程设计或Servlet/JSP阶段练手的参考项目。目前已有1288人学习深入阅读其中的Servlet跳转逻辑、注册登录实现和数据库访问代码能够较快建立Java Web开发的整体认知。1. Servlet JSP 的水果超市一个能跑通的 JavaWeb 最小闭环FruitWeb 这套水果超市 JavaWeb 项目解压后不是一堆半成品类文件而是一个闭合的 Servlet JSP 应用index.jsp打开商品列表add.jsp和update.jsp做表单录入register.jsp处理注册后端由src/cn/cst下的 Servlet 和工具类撑起增删改查。它没有 Spring、没有 MyBatis连 JSTL 都可能没引全但这恰恰是它的价值——你可以完整看到一次 HTTP 请求如何穿过 Tomcat、Servlet、JDBC 落到 MySQL 表中间没有框架遮住任何一步。适合刚学完 Servlet 语法想找完整实战的人也适合做课程设计时需要一个非框架型演示系统的读者。整个运行链路直白几乎不存在黑盒。2. 从 FruitWeb.iml 到 web.xml先看懂这个 JavaWeb 项目的目录语言2.1 解压后的文件到底在说什么拿到FruitWeb.zip第一件事别急着导入 IDEA先对照文件结构确认它是不是你预期的那种 JavaWeb 工程。解压后能看到以下关键对象路径作用FruitWeb.imlIDEA 的模块描述文件记录源码目录、依赖和编译输出位置.idea/IDEA 的工作区配置包含misc.xml、modules.xml、workspace.xmlsrc/cn/cst/Java 源码根Servlet 类、DAO、实体类都在这里web/Web 应用根目录JSP、CSS、JS、图片全在web下web/WEB-INF/web.xml部署描述符Servlet 的注册和映射从这里读out/artifacts/FruitWeb_war_explodedIDEA 的编译输出目录等价于解压后的 WAR 包FruitWeb.iml和.idea是给人看的调试信息真正决定程序行为的是src与web两个目录的配合。web下的admin.css.bak这类备份文件说明原作者在改样式时保留了工作痕迹对学习者反而是个参考点。2.2 web.xml 里配置了什么对于一个不用注解的 Servlet 项目web.xml是入口。打开web/WEB-INF/web.xml核心配置通常长这样?xml version1.0 encodingUTF-8? 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-nameFruitWeb/display-name servlet servlet-nameFruitServlet/servlet-name servlet-classcn.cst.servlet.FruitServlet/servlet-class /servlet servlet-mapping servlet-nameFruitServlet/servlet-name url-pattern/fruit/url-pattern /servlet-mapping welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list /web-app这段配置的逻辑很直接servlet-class告诉容器去哪个类找处理逻辑url-pattern把浏览器访问路径绑定到该类。welcome-file-list决定访问根路径时默认打开index.jsp。这里有几个初学者常犯的错url-pattern忘记写前导斜杠或者映射路径和 JSP 表单里的action对不上结果表单提交直接 404。遇到这种情况优先去web.xml查映射别急着看 Java 代码。2.3 Tomcat 怎么把这套目录变成可访问的 Web 应用Tomcat 对 JavaWeb 应用的部署方式有三种直接放置 WAR 包、放置解压目录、在server.xml里配置 Context。本项目在 IDEA 里跑时用的是out/artifacts/FruitWeb_war_exploded这个目录内部结构已经和web/是镜像关系Tomcat 把它当作 docBase读取WEB-INF/web.xml完成 Servlet 注册和映射。WEB-INF下的classes存放编译后的.classlib存放 JDBC 驱动等第三方 JAR这个目录对浏览器不可见是容器和业务代码的隔离边界。3. 水果 CRUD 的核心Servlet 接管 HTTP 请求后的数据流3.1 数据库侧水果表该怎么设计Servlet 只是中间层数据最终落在 MySQL。演示项目一般会建一张水果表和一张用户表表设计直接决定 DAO 层代码的复杂度。水果表常见设计是CREATE TABLE fruit ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT 主键ID, name VARCHAR(50) NOT NULL COMMENT 水果名称, price DECIMAL(10,2) NOT NULL COMMENT 单价保留两位小数, stock INT NOT NULL DEFAULT 0 COMMENT 库存数量, unit VARCHAR(10) DEFAULT 斤 COMMENT 计量单位, description VARCHAR(255) COMMENT 备注描述 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有个容易被忽略的细节价格字段用DECIMAL(10,2)而不是FLOAT。FLOAT存2.99这类小数时二进制浮点会引入精度误差做金额比较或求和会出现预期外的结果。DECIMAL在 MySQL 内部按字符串存储精度是精确的。实测中用FLOAT存几万条数据后做SUM结果经常差出几分钱对水果超市这种单价不高但流水高频的场景账面对不上才是大坑。另外字符集选utf8mb4避免特殊字符和 Emoji 写入时报Incorrect string value。3.2 Servlet 里怎么组织增删改查这个项目的 Servlet 组织方式很典型——一个FruitServlet通过action参数分发到不同处理方法相当于手动实现前端控制器。核心骨架如下WebServlet(/fruit) public class FruitServlet extends HttpServlet { private FruitDao fruitDao new FruitDao(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String action req.getParameter(action); if (delete.equals(action)) { int id Integer.parseInt(req.getParameter(id)); fruitDao.deleteById(id); resp.sendRedirect(req.getContextPath() /fruit?actionlist); } else if (edit.equals(action)) { int id Integer.parseInt(req.getParameter(id)); req.setAttribute(fruit, fruitDao.findById(id)); req.getRequestDispatcher(/update.jsp).forward(req, resp); } else { req.setAttribute(fruitList, fruitDao.findAll()); req.getRequestDispatcher(/list.jsp).forward(req, resp); } } Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String action req.getParameter(action); if (add.equals(action)) { // 读取表单字段并调用 dao.insert } else if (update.equals(action)) { // 读取表单字段并调用 dao.update } resp.sendRedirect(req.getContextPath() /fruit?actionlist); } }代码逻辑说明doGet里处理所有幂等操作——删除、回显编辑页、查询列表doPost处理写操作——新增和修改。这样区分的原因是实现 REST 语义的简化版GET 不应该产生数据变更POST 才是提交数据的入口。resp.sendRedirect在写操作后重定向到列表页避免用户刷新浏览器时重复提交表单这是 Post-Redirect-Get 模式的简化版对上课演示够了。参数方面有个注意点Integer.parseInt解析id时如果参数不是数字会抛NumberFormatException生产环境需要加 try-catch 或使用int包装类做判空这里课堂上图省事直接 parse 是很常见的写法。3.3 中文乱码的两个关键位置JavaWeb 中文乱码几乎集中在两个位置请求参数乱码和响应输出乱码。项目里doPost开头那句req.setCharacterEncoding(UTF-8)能解决表单 POST 提交的中文但解决不了 GET 请求 URL 里的中文参数。Tomcat 7 及以下默认URIEncoding是ISO-8859-1必须到conf/server.xml改连接器配置Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 URIEncodingUTF-8 /Tomcat 8 及以上默认就是 UTF-8改动可省略。响应侧的乱码则在每个 Servlet 输出前设置resp.setContentType(text/html; charsetUTF-8);这个设置要和 JSP 头部的pageEncodingUTF-8一致否则 Servlet 转发到 JSP 后JSP 以错误编码渲染页面中文仍然会花屏。排查乱码时按「请求编码 → 响应编码 → 数据库字符集」三处逐一确认见效最快。4. 从 index.jsp 到 updatepw.jsp前端表单和后端 Servlet 的对接4.1 list.jsp 怎么把数据库里的水果渲染成表格列表页是用户第一眼看到的东西也是 DAO 查询结果的展示层。传统 JSP 渲染有两种选择直接用% %脚本片段四处输出或者用 JSTL 标签保持页面整洁。这个项目里list.jsp的写法偏向脚本片段风格% ListFruit fruitList (ListFruit) request.getAttribute(fruitList); if (fruitList ! null !fruitList.isEmpty()) { for (Fruit f : fruitList) { % tr td% f.getId() %/td td% f.getName() %/td td% f.getPrice() %/td td% f.getStock() %/td td a hreffruit?actioneditid% f.getId() %修改/a a hreffruit?actiondeleteid% f.getId() % onclickreturn confirm(确定删除该水果吗)删除/a /td /tr % } } %用脚本片段写循环的好处是直观任何学过 Java 语法的人都能对出来坏处是页面里混合了 Java 代码维护时会看到out.println和 HTML 标签交错。再深一层% f.getPrice() %直接输出浮点数如果表中price是FLOAT类型会出现1.1999999这种结果这也是前面强调用DECIMAL的连带好处。列表页的删除链接带了个onclickreturn confirm(...)这个细节避免了误删是很实用的界面交互成本控制。4.2 register.jsp 的注册数据怎么落到数据库register.jsp对应的是一段独立的注册流程可能直接由RegistServlet处理也可能混在用户 Servlet 中。它的表单结构典型如下form actionregister methodpost label用户名/label input typetext nameusername required maxlength20 label密码/label input typepassword namepassword required minlength6 label确认密码/label input typepassword nameconfirmPwd required button typesubmit注册/button /form对应 Servlet 端至少要做两件事判空和密码一致性校验。常见的校验代码String username req.getParameter(username); String password req.getParameter(password); String confirmPwd req.getParameter(confirmPwd); if (username null || username.trim().isEmpty()) { resp.getWriter().write(scriptalert(用户名不能为空);history.back();/script); return; } if (!password.equals(confirmPwd)) { resp.getWriter().write(scriptalert(两次密码不一致);history.back();/script); return; }注意这段代码的密码比对用的是 Java 字符串的equals如果直接用password confirmPwd是比较对象引用结果永远为 false这是 Java 新手最常见的逻辑雷点。项目里有提示updatepw.jsp存在说明密码修改流程也已实现修改时通常需要校验旧密码这一步其实就是「查询用户→比对旧密码→更新新密码」的串行操作可以在UserDao里增加一个updatePassword方法完成。4.3 pintuer.css这个项目的前端框架选型web/css目录下有pintuer.css和pintuer.js这表明项目使用了 Pintuer 这个轻量级 CSS 框架。它的 class 命名风格类似 Bootstrap但体积更小适合无构建工具的传统 JSP 项目。项目里常见用法class 名用途container页面居中容器table/table-bordered表格样式及边框修饰button/bg-green按钮基础样式与背景色form-group表单控件分组布局text-center文本水平居中这种框架的取舍在于它比手写 CSS 干净又比 Bootstrap 轻适合教学项目里快速搭出「看得过去」的管理界面。.bak后缀文件提示开发者在调样式时保留过旧的 CSS 副本这也是没有版本控制时代的土办法。5. 部署与排错的关键路径从 IDEA 启动到验证一个完整流程5.1 IDEA 里 Artifact 和 Tomcat 没对上导入项目后File - Project Structure - Artifacts要能看到FruitWeb_war_explodedRun 配置里 Tomcat Server 的 Deploy 页签要确认 Application context 设为/FruitWeb_war_exploded或自定义的/fruit。上下文路径和web.xml里的映射不冲突但它决定浏览器访问的根 URL。现实中大量 404 来自这里代码改了、Servlet 重编了但 IDEA 没有重新 build artifact导致部署到 Tomcat 的是旧 class。遇到「改了代码不生效」先在Build - Rebuild Project后重启 Tomcat。5.2 数据库连不上的排查顺序项目WEB-INF/lib如果已经带了mysql-connector-java驱动问题就少一半。连不上时按顺序检查MySQL 服务是否启动、驱动类名是否匹配、URL 端口是否默认 3306、用户名密码是否硬编码在 JDBC 工具类中。这里给一个稳妥的 JDBC 连接参数参考String url jdbc:mysql://localhost:3306/fruitdb?useUnicodetruecharacterEncodingUTF-8useSSLfalseserverTimezoneAsia/Shanghai; String user root; String password 123456;characterEncodingUTF-8和serverTimezone是排查乱码和时间报错的两个必要参数尤其 MySQL 8.x 客户端不指定时区会直接抛CST相关异常。修改数据库连接的信息后在 Navicat 里先测一次连接排除数据库端问题再看 Java 代码别两头瞎猜。5.3 验证 CRUD 最佳路径与最后建议完整验证这个项目的健康度最有效的顺序是启动 Tomcat 访问index.jsp确认欢迎页加载点击「新增」提交一条带中文的记录看列表页是否正常显示且不乱码点「修改」改价格和库存刷新后确认更新点「删除」确认弹窗返回列表后确认记录消失注册一个账号后登录检查 Session 跳转是否正常。这一套流程走通Servlet JSP DAO MySQL 这条链路就没问题。如果某个环节断了优先在对应 Servlet 的doGet或doPost入口打一行System.out.println输出 action 参数确认请求是否进到了预期方法。对于一个教学项目这比引入 Log4j、配置日志级别更直接花的时间也更少。最后建议有兴趣的读者尝试把FruitServlet里的action分发重构为switch和独立方法或者把脚本片段改成 JSTL——这是这个项目留给你的升级空间。本文还有配套的精品资源点击获取