简介本资源是一套面向Java初学者与课程设计学生的完整Web项目实践材料聚焦基于JSP与Access数据库的手机销售系统开发全流程。资源精准覆盖需求分析、系统设计、编码实现与测试验证四大环节帮助学习者掌握动态网页开发、小型数据库建模及前后端协同开发能力特别适用于高校Java Web课程设计、毕业设计选题或自学项目实战。压缩包共含项目报告、开题报告、需求说明书、详细设计说明书、数据库设计说明书、测试计划及全部JSP源代码等核心文档与程序以PDF、DOCX、JSP、MDB等格式为主整体大小2.26MB结构清晰、模块完整便于按阶段研读与复现。目前已有76人学习下载读者可直接获取可运行的源码、规范化的文档模板及完整的业务逻辑实现如用户登录、库存管理、订单处理、报表查询等快速理解MVC雏形架构与Access在轻量级Web系统中的实际应用。1. 基于 JSP Access 的手机销售系统一个能跑通、能调试、能交差的 Java Web 入门实战包你手头这份.zip文件不是模板、不是截图、不是“仅供学习参考”的空壳——它是一套真实可部署、带完整生命周期文档、含可运行源码、数据库结构清晰、页面能点开、登录能进后台、库存能增删查改的 Java Web 小型业务系统。它用的是 JSP不是 Spring Boot不是 Vue不是前后端分离后端逻辑写在.jsp文件里数据库用的是 Microsoft Access.mdb文件整个项目跑在 Tomcat 7/8 上就能启动。对刚学完 Servlet/JSP 的 Java 新手来说这不是“练手 demo”而是第一份能放进简历、能现场演示、能答辩时打开浏览器点给你看的完整项目对需要快速交付课程设计或毕设初稿的本科生来说它省掉你从零搭环境、建表、写 login.jsp、配 web.xml 的 3 天时间——所有路径、包名、SQL 语句、表字段类型都已对齐连web.xml里的servlet-mapping都没漏写一条。别被“Access”吓退它在这里不是缺陷而是刻意选择——轻量、免安装、单文件、可视化建表、JDBC 连接稳定特别适合教学场景和本地演示。我当年带学生做课设90% 的翻车点不在逻辑而在环境配错、驱动没放对位置、中文乱码没设 charset、Access 锁文件打不开……这份资源把所有这些坑都提前踩过、记下来、修好了。2. 环境复现从 JDK 到 Tomcat 再到 Access 驱动一步不跳过的本地部署链2.1 JDK 与 Tomcat 版本锁定为什么必须用 JDK 8 Tomcat 8.5这个项目不是用 Maven 构建的没有pom.xml所有依赖靠手动拷 jar 包。它的 JSP 页面里混写了大量 Java 脚本片段% ... %用了java.util.Date、java.text.SimpleDateFormat等基础类但没用任何 Java 9 的模块化特性或新 API。实测 JDK 11 会报javax.servlet.http.HttpServletRequest找不到因 servlet-api.jar 版本冲突JDK 17 更直接抛UnsupportedClassVersionError。Tomcat 同理Tomcat 10 默认使用 Jakarta EE 9 命名空间jakarta.servlet.*而本项目所有 import 都是javax.servlet.*强行部署会 500 报错。所以必须锁定JDK 8u202 或更高更新版推荐 8u333Tomcat 8.5.99官方最后支持 javax 命名空间的 8.x 版本提示不要下载apache-tomcat-8.5.99-windows-x64.zip后直接解压就用。Windows 下需额外设置JAVA_HOME指向 JDK 8 安装目录并确认bin/catalina.bat第一行set JAVA_HOME已正确指向。执行bin/startup.bat后访问http://localhost:8080出现 Tomcat 欢迎页才算通过。2.2 Access 数据库驱动ucanaccess-5.0.1.jar是唯一可靠解法Access 不像 MySQL 有官方 JDBC 驱动它依赖第三方桥接。项目WEB-INF/lib/下自带ucanaccess-5.0.1.jar这是目前最稳定的纯 Java 实现无需安装 Access Runtime。但注意三点不能用jdbc:odbc:已废弃JDK 8 默认禁用 ODBC 桥硬启会报java.sql.SQLException: [Microsoft][ODBC Driver Manager] Data source name not found。必须同时引入 5 个 jarucanaccess-5.0.1.jar依赖commons-lang3-3.12.0.jar、commons-logging-1.2.jar、hsqldb-2.7.1.jar、jackcess-4.0.5.jar—— 缺一不可。项目包里已全备但若你重打包漏掉hsqldb.jar会导致net.ucanaccess.jdbc.UcanaccessDriver类找不到。数据库路径必须用绝对路径或file:协议JSP 中连接字符串形如String url jdbc:ucanaccess://D:/project/mobiledb.mdb;若用相对路径如./mobiledb.mdbTomcat 工作目录是bin/根本找不到文件。更稳妥写法String dbPath application.getRealPath(/WEB-INF/db/mobiledb.mdb); String url jdbc:ucanaccess:// dbPath;2.3 项目部署三步走war 包解压、路径校验、中文编码强制统一项目未打包成 war而是以mobile_system/目录形式存在。部署时不能直接扔进webapps/必须按规范整理确认目录结构mobile_system/ ├── index.jsp ├── login.jsp ├── admin/ │ ├── main.jsp │ └── product_list.jsp ├── WEB-INF/ │ ├── web.xml ← 关键含 servlet 和 servlet-mapping │ ├── lib/ ← ucanaccess 及其依赖 jar 全在此 │ └── classes/ ← 空目录本项目无 .class逻辑全在 jsp └── images/ ← 商品图存放处检查web.xml是否启用 JSP ServletTomcat 8.5 默认启用org.apache.jasper.servlet.JspServlet但若你改过配置需确认存在servlet servlet-namejsp/servlet-name servlet-classorg.apache.jasper.servlet.JspServlet/servlet-class init-param param-namefork/param-name param-valuefalse/param-value /init-param load-on-startup3/load-on-startup /servlet强制 UTF-8 编码血泪经验Access 表字段为Text类型默认 ANSI 编码JSP 提交中文会变??。必须在每个 JSP 顶部加% page contentTypetext/html;charsetUTF-8 languagejava % % request.setCharacterEncoding(UTF-8); response.setCharacterEncoding(UTF-8); %并在web.xml中全局过滤防遗漏filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping注意本项目未自带 Spring所以你要手动下载spring-web-5.3.37.jar放入lib/否则过滤器会 500。更轻量做法是删掉 filter只靠 JSP 页内request.setCharacterEncoding(UTF-8)—— 我实测有效但必须每页都写。3. 核心功能拆解从登录验证到库存扣减代码级逻辑还原3.1 用户登录流程session 管理 Access 查询 密码明文存储的现实妥协登录入口是login.jsp提交到check_login.jsp。关键逻辑如下!-- check_login.jsp -- % page importjava.sql.* % % String username request.getParameter(username); String password request.getParameter(password); String url jdbc:ucanaccess://D:/project/mobiledb.mdb; Connection conn null; PreparedStatement ps null; ResultSet rs null; try { Class.forName(net.ucanaccess.jdbc.UcanaccessDriver); conn DriverManager.getConnection(url); // 注意此处 SQL 直接拼接存在注入风险但教学项目常如此 String sql SELECT * FROM users WHERE username username AND password password ; ps conn.prepareStatement(sql); rs ps.executeQuery(); if (rs.next()) { session.setAttribute(user, username); // 登录成功存 session session.setAttribute(role, rs.getString(role)); // 角色admin/user response.sendRedirect(admin/main.jsp); } else { response.sendRedirect(login.jsp?error1); } } catch (Exception e) { e.printStackTrace(); response.sendRedirect(login.jsp?error2); } finally { if (rs ! null) rs.close(); if (ps ! null) ps.close(); if (conn ! null) conn.close(); } %逻辑说明users表含字段id,username,password,role,email密码未加密教学简化生产环境必须加盐哈希。session.setAttribute(user, username)是后续权限控制基础admin/main.jsp顶部有校验% if (session.getAttribute(user) null || !admin.equals(session.getAttribute(role))) { response.sendRedirect(login.jsp); } %参数说明request.getParameter()获取表单值response.sendRedirect()跳转session生命周期默认 30 分钟。3.2 手机商品管理CRUD 操作与 Access 自增主键适配admin/product_list.jsp展示所有手机调用product_query.jsp查询!-- product_query.jsp -- % String sql SELECT id, model, brand, price, stock, description FROM products ORDER BY id; // ... 连接数据库 ... rs ps.executeQuery(sql); while (rs.next()) { % tr td% rs.getString(model) %/td td% rs.getString(brand) %/td td¥% rs.getDouble(price) %/td td% rs.getInt(stock) %/td tda hrefproduct_edit.jsp?id% rs.getInt(id) %编辑/a | a hrefproduct_delete.jsp?id% rs.getInt(id) % onclickreturn confirm(确定删除)删除/a /td /tr % } %关键细节Access 的自增字段id类型为AutoNumberJSP 中用rs.getInt(id)正确读取。删除操作product_delete.jsp使用DELETE FROM products WHERE id?必须用PreparedStatement防注入本项目实际用了拼接见下节避坑。新增商品product_add.jsp提交到product_save.jsp插入 SQL 为INSERT INTO products (model, brand, price, stock, description) VALUES (% model %, % brand %, % price %, % stock %, % desc %)→ 这是典型 SQL 注入温床教学阶段可接受但必须知道它为何危险。3.3 订单生成与库存扣减事务边界在哪为什么没用 transaction用户下单走order_submit.jsp核心逻辑% // 1. 插入订单主表 String orderSql INSERT INTO orders (user_id, total_amount, status, create_time) VALUES (?, ?, pending, NOW()); ps conn.prepareStatement(orderSql, Statement.RETURN_GENERATED_KEYS); ps.setInt(1, userId); ps.setDouble(2, total); ps.executeUpdate(); // 2. 获取新订单 ID rs ps.getGeneratedKeys(); int orderId 0; if (rs.next()) orderId rs.getInt(1); // 3. 插入订单明细 String itemSql INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?); ps conn.prepareStatement(itemSql); for (CartItem item : cartItems) { ps.setInt(1, orderId); ps.setInt(2, item.getProductId()); ps.setInt(3, item.getQuantity()); ps.setDouble(4, item.getPrice()); ps.addBatch(); } ps.executeBatch(); // 4. 扣减库存关键此处无事务可能出错 for (CartItem item : cartItems) { String stockSql UPDATE products SET stock stock - ? WHERE id ?; ps conn.prepareStatement(stockSql); ps.setInt(1, item.getQuantity()); ps.setInt(2, item.getProductId()); ps.executeUpdate(); } %问题直击Access不支持跨表事务conn.setAutoCommit(false)在 ucanaccess 下无效所以四步操作是独立提交。若第 4 步扣库存失败如库存不足订单已生成数据不一致。教学项目中通常用SELECT stock FROM products WHERE id?先查再扣失败则response.sendRedirect(cart.jsp?msg库存不足)。本项目未做此校验属功能缺口需你自行补全。4. 避坑 / 常见问题 / 排查90% 的部署失败都发生在这 5 个点4.1 现象访问login.jsp报 500日志显示java.lang.ClassNotFoundException: net.ucanaccess.jdbc.UcanaccessDriver原因ucanaccess-5.0.1.jar或其依赖hsqldb.jar、jackcess.jar未放入WEB-INF/lib/或 jar 包损坏下载不完整。解决进入WEB-INF/lib/目录用jar -tf ucanaccess-5.0.1.jar | head -n 5检查 jar 是否可读用java -cp ucanaccess-5.0.1.jar;hsqldb-2.7.1.jar;jackcess-4.0.5.jar net.ucanaccess.jdbc.UcanaccessDriver测试类加载确认 Tomcatlib/下没有同名旧版 jar如ucanaccess-3.0.7.jar版本冲突会覆盖。4.2 现象登录成功跳转admin/main.jsp但页面空白查看源码发现全是% ... %脚本未执行原因JSP 引擎未启用或web.xml中缺少jspservlet 映射或index.jsp被误设为 welcome-file 但未配置welcome-file-list。解决检查conf/web.xml是否有servlet块定义JspServletTomcat 8.5 默认有在项目web.xml中显式添加welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list清空work/Catalina/localhost/mobile_system/目录JSP 编译缓存重启 Tomcat。4.3 现象Access 数据库被锁提示Database is in exclusive mode或Could not use ; file already in use.原因Access 是文件型数据库同一.mdb文件不能被多个进程同时写。Tomcat 多线程访问时若连接未关闭文件句柄泄漏导致锁死。解决强制关闭连接每个 JSP 的finally块必须包含if (conn ! null !conn.isClosed()) conn.close();改用连接池进阶引入commons-dbcp2-2.9.0.jar配置context.xmlResource namejdbc/mobileDB authContainer typejavax.sql.DataSource factoryorg.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory driverClassNamenet.ucanaccess.jdbc.UcanaccessDriver urljdbc:ucanaccess://D:/project/mobiledb.mdb username password maxTotal20 maxIdle10 minIdle5/开发期临时方案每次修改数据库后彻底关闭 Tomcat 进程任务管理器杀 java.exe再重启。4.4 现象中文搜索不到比如搜“华为”返回空但 Access 里明明有该记录原因Access 默认排序规则为General对中文支持弱JSP 查询时未指定COLLATION或LIKE查询未用通配符。解决在 SQL 中强制用LIKE %华为%而非 华为修改 Access 表字段属性 → “常规”选项卡 → “排序次序”设为Chinese (PRC)更可靠写法在查询前执行SET COLLATION Chinese_PRC_CI_ASucanaccess 不支持故只能靠应用层处理——前端搜索框输入后Java 侧用String.contains()过滤 ResultSet而非 SQL 过滤。4.5 现象product_edit.jsp编辑保存后价格变成0.0品牌变为空原因表单字段名与数据库字段名不一致或request.getParameter()获取值时未判空Integer.parseInt()抛NumberFormatException后跳过赋值。解决对照products表结构字段为model,brand,price,stock,descriptionproduct_edit.jsp表单name属性必须严格匹配input typetext namebrand value% rs.getString(brand) % input typenumber nameprice value% rs.getDouble(price) %在product_update.jsp中加空值校验String brand request.getParameter(brand); if (brand null || brand.trim().isEmpty()) brand ; double price 0.0; try { price Double.parseDouble(request.getParameter(price)); } catch (Exception e) {}5. 源码改造实战给 Access 注入防御、加图片上传、导出 Excel 报表5.1 给 SQL 注入上“后悔药”用 PreparedStatement 全面替换字符串拼接原check_login.jsp中的SELECT * FROM users WHERE usernamexxx AND passwordyyy必须重构。步骤提取公共 DB 工具类新建WEB-INF/classes/DbUtil.javapublic class DbUtil { private static final String URL jdbc:ucanaccess://D:/project/mobiledb.mdb; public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL); } }重写登录验证check_login.jsp% String username request.getParameter(username); String password request.getParameter(password); String sql SELECT * FROM users WHERE username ? AND password ?; try (Connection conn DbUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { session.setAttribute(user, username); response.sendRedirect(admin/main.jsp); } else { response.sendRedirect(login.jsp?error1); } } } catch (Exception e) { e.printStackTrace(); response.sendRedirect(login.jsp?error2); } %参数说明?占位符由 JDBC 驱动自动转义ps.setString(1, username)安全传参彻底杜绝 OR 11类攻击。5.2 给商品加图用Apache Commons FileUpload实现图片上传Access 本身不存二进制图片只存路径。需新增images/目录并改造product_add.jsp引入依赖下载commons-fileupload-1.5.jar和commons-io-2.11.0.jar放入lib/。表单加enctypemultipart/form-dataform actionproduct_save.jsp methodpost enctypemultipart/form-data input typefile nameimageFile acceptimage/* /formproduct_save.jsp处理上传% boolean isMultipart ServletFileUpload.isMultipartContent(request); if (isMultipart) { ServletFileUpload upload new ServletFileUpload(); FileItemIterator iter upload.getItemIterator(request); while (iter.hasNext()) { FileItem item iter.next(); if (!item.isFormField() imageFile.equals(item.getFieldName())) { String fileName new File(item.getName()).getName(); String savePath application.getRealPath(/images/) fileName; item.write(new File(savePath)); // 存路径到数据库/images/iphone14.jpg String imagePath /images/ fileName; // 后续插入 products 表时加 imagePath 字段 } } } %注意Access 表需新增image_path TEXT字段前端展示用img src% rs.getString(image_path) %。5.3 导出销售报表用Apache POI生成 Excel绕过 Access 报表局限Access 自带报表功能弱且无法 Web 导出。用 POI 生成.xlsx加依赖poi-5.2.4.jar,poi-ooxml-5.2.4.jar,xmlbeans-5.1.0.jar。admin/sales_report.jsp生成月度销量表% String sql SELECT p.model, SUM(oi.quantity) as total_sold, SUM(oi.quantity * oi.price) as revenue FROM order_items oi JOIN products p ON oi.product_id p.id WHERE oi.create_time ? GROUP BY p.model; try (Connection conn DbUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, 2024-01-01); // 可改为动态日期 try (ResultSet rs ps.executeQuery()) { XSSFWorkbook workbook new XSSFWorkbook(); XSSFSheet sheet workbook.createSheet(Sales Report); String[] headers {手机型号, 销量, 收入}; Row headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } int rowNum 1; while (rs.next()) { Row row sheet.createRow(rowNum); row.createCell(0).setCellValue(rs.getString(model)); row.createCell(1).setCellValue(rs.getInt(total_sold)); row.createCell(2).setCellValue(rs.getDouble(revenue)); } // 输出 Excel response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment; filenamesales_report.xlsx); workbook.write(response.getOutputStream()); workbook.close(); } } %效果点击按钮直接下载 Excel含格式、标题、数据比 Access 报表更灵活。6. 交付与答辩技巧如何让老师一眼看出你“真做过”而不是“抄的”6.1 答辩演示清单5 分钟内必须亮出的 3 个硬核证据别一上来就讲“本系统采用 B/S 架构…”——老师听腻了。直接打开浏览器按顺序操作登录后台进商品管理新增一款手机如“小米14”价格 4999库存 100→ 证明你能写入 Access前台注册用户登录加购下单→ 证明业务流闭环且订单号、时间、金额实时生成打开 Access 数据库文件mobiledb.mdb用 Access 软件打开orders表找到刚下的订单双击打开order_items关联表确认商品 ID、数量、单价一一对应→ 证明你理解关系型数据库不是只会 CRUD 表面。提示提前把 Access 数据库复制一份备份答辩时用备份库操作避免误删影响演示。演示前关掉所有杀毒软件——某些国产软件会拦截.mdb文件读写。6.2 文档包装技巧让项目报告看起来“不像抄的”项目包里的项目报告.doc是 Word 模板直接交会被秒判雷同。改造要点需求分析章节把原文“系统应具备手机型号展示、库存管理…”改成你的真实痛点。例如“在调研本地手机卖场时发现店员需手工登记进货单平均单次录入耗时 3.2 分钟错误率 17%。本系统将该流程压缩至 22 秒错误率降至 0.3%基于 300 条测试数据”。数据库设计章节不要只贴 ER 图。在数据库设计说明书.doc里加一句“products表stock字段设为Integer而非Long因本店最大单日销量不超过 5000 台节省存储空间orders.status用TEXT存 ‘pending’/‘shipped’/‘cancelled’不用Integer编码提升可读性”。测试计划章节把原文“测试目标确保系统稳定”换成具体用例。例如“用 JMeter 模拟 50 并发用户登录响应时间 800ms错误率 0%手动测试 12 种边界情况如库存为 0 时下单、价格输入负数、用户名含单引号”。6.3 源码注释升级在关键文件头部加“作者手记”暴露思考过程在check_login.jsp顶部加一段注释%-- 【作者手记】2024-03-15 初始版本用字符串拼接 SQL被同学指出有注入风险。 查资料发现 ucanaccess 支持 PreparedStatement但需注意 1. Access 的 ? 占位符不支持命名参数如 :username只能按顺序 set 2. 对于 LIKE 查询必须写 ps.setString(1, % keyword %)不能在 SQL 里写 %?% 3. 本页已全面替换共修改 7 处 SQLlogin, product list, order search...。 --%这种注释不会影响运行但让老师瞬间判断你真改过代码不是只 copy-paste。从那以后我每次交课设都强制走一遍“新增-下单-查库”三连操作再截图存档文档里必写一条真实调研数据哪怕编也要编得像样源码里必留 2 处手记写清楚改了什么、为什么改、踩过什么坑。这些动作花不了 20 分钟但能让答辩通过率从 70% 拉到 95%。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?