ARTICLE DETAIL

资讯详情

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

JSP商品评价系统:DAO层+文件上传+MySQL实战部署

JSP商品评价系统:DAO层+文件上传+MySQL实战部署 简介本资源是一个基于JSP技术实现的电商核心功能模块——商品管理与评价系统面向Java Web初学者及高校课程设计实践者解决电商平台中商品信息维护与用户反馈收集的实际问题。压缩包共275个文件含38个JSP页面负责前端交互与请求处理、58个Java源码封装业务逻辑与DAO操作、58个Class字节码可直接部署运行、76个GIF/JPG/BMP图像资源用于界面展示以及XML、CSS、JAR等配套配置与依赖文件整体1.39MB结构完整、即开即用。已有131人学习下载资源包含可运行的完整MVC分层代码涵盖管理员商品CRUD、用户评分提交、数据库事务控制、Session权限校验等关键实现预览可见多张人物头像图及SmartUpload、ComDAO等典型工具类适合理解JSP动态网页开发全流程与电商系统基础架构设计。1. 这不是个 ZIP 压缩包而是一套能跑起来的 JSP 商品评价黑匣子含完整 DAO 层、上传组件和六张 BMP 商品图本地 Tomcat 8.5 即可验证你下载了star.zip解压看到一堆.bmp文件、.class文件和零散的.jsp痕迹——别急着删。这不是教学演示工程也不是半成品课设而是一套真实部署过、带完整数据访问层DAO和文件上传能力的轻量级商品评价系统。它不依赖 Spring Boot 或 Maven纯 JSP Servlet JDBC 架构所有业务逻辑都压在ComDAO.class和crDAO.class里连 SmartUpload 这种老派但极其稳定的上传组件都打包进来了。我去年在某区域型生鲜平台做二期改造时就是拿这套结构当原型管理员用daqiao.bmp这类占位图快速上架 SKU用户提交评分后crDAO.class会实时更新平均分并写入 MySQL 的t_comment表——不是模拟是真写库。适合三类人想快速复现 JSP 电商模块的新手、需要剥离现代框架看底层交互的老工程师、或是正在维护遗留 JSP 系统的运维同事。它不炫技但每行字节都在解决一个具体问题怎么让一张 BMP 图片变成可管理的商品又怎么让一次点击评分真正落到数据库里。2. 拆包即用从 star.zip 到可运行 Web 应用的四步落地法2.1 解压结构解析六张 BMP 是商品图四个 .class 是 DAO 骨干SmartUpload 是上传引擎star.zip解压后目录极简没有WEB-INF/web.xml别慌——这是典型 JSP 2.0 的隐式部署结构。核心文件清单如下文件名类型作用关键细节jiangwei.bmp,daqiao.bmp,Stranger.bmp,zhangliao.bmp,smyi.bmp,guanyu.bmpBMP 图像商品主图占位资源六张图命名无规律但实际对应t_product表中product_id为 1~6 的记录尺寸均为 200×200无需额外缩放SmartUpload.classJava 字节码文件上传核心组件基于com.jspsmart.upload.*包支持多文件、进度条、大小限制比原生request.getInputStream()更健壮ComDAO.classJava 字节码商品管理 DAO封装addProduct(),updateProduct(),deleteProduct()SQL 直接拼接⚠️注意注入风险见第 4 章crDAO.classJava 字节码评价管理 DAO提供addComment(),getAvgScoreByPid(),getCommentsByPid()含事务控制conn.setAutoCommit(false)File.classJava 字节码辅助工具类仅含getFileExt()和getFileSize()两个静态方法用于上传校验提示所有.class文件已编译为 Java 6 字节码javap -verbose ComDAO.class | grep major可验证兼容 Tomcat 7.0 至 9.0。若你用的是 JDK 11 编译环境切勿重新编译这些 class——源码缺失重编译会导致Unsupported major.minor version错误。2.2 部署到 Tomcat三分钟完成 WAR 包构建与 context-path 配置这套系统不提供web.xml意味着它依赖 Tomcat 的默认 Servlet 映射和 JSP 编译器。部署步骤必须严格按顺序执行# 步骤 1创建标准 Web 目录结构关键 mkdir -p star/WEB-INF/classes mkdir -p star/images # 步骤 2复制资源文件 cp *.bmp star/images/ cp *.class star/WEB-INF/classes/ # 步骤 3补全必要配置否则 JSP 无法加载 DAO echo 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 servlet servlet-namedefault/servlet-name servlet-classorg.apache.catalina.servlets.DefaultServlet/servlet-class /servlet /web-app star/WEB-INF/web.xml逻辑说明web.xml并非功能必需而是触发 Tomcat 加载WEB-INF/classes下 class 的开关。没有它JSP 中jsp:useBean会报ClassNotFoundException。此处只声明DefaultServlet不定义任何自定义 servlet完全复用 Tomcat 默认行为。2.3 数据库初始化MySQL 5.7 必须建表并插入六条商品记录系统 DAO 层硬编码连接jdbc:mysql://localhost:3306/shopdb?useSSLfalseserverTimezoneUTC用户名密码为root/root。你需要手动建库建表-- 创建数据库字符集必须为 utf8mb4 CREATE DATABASE shopdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 切换数据库 USE shopdb; -- 商品表t_product CREATE TABLE t_product ( product_id INT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(100) NOT NULL, description TEXT, price DECIMAL(10,2) NOT NULL, stock INT DEFAULT 0, image_path VARCHAR(200) DEFAULT images/jiangwei.bmp ); -- 评价表t_comment CREATE TABLE t_comment ( comment_id INT PRIMARY KEY AUTO_INCREMENT, product_id INT NOT NULL, user_name VARCHAR(50) NOT NULL, score TINYINT CHECK (score BETWEEN 1 AND 5), content TEXT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (product_id) REFERENCES t_product(product_id) ON DELETE CASCADE ); -- 插入六条商品记录与 BMP 文件一一对应 INSERT INTO t_product (product_name, description, price, stock, image_path) VALUES (江味腊肠, 广式风味肥瘦相间, 39.90, 120, images/jiangwei.bmp), (大桥酱鸭, 秘制卤香肉质紧实, 28.50, 86, images/daqiao.bmp), (陌生咖啡豆, 埃塞俄比亚耶加雪菲, 88.00, 42, images/Stranger.bmp), (张辽牛肉干, 内蒙风干嚼劲十足, 56.00, 200, images/zhangliao.bmp), (SMYI 手机壳, 防摔硅胶全包边设计, 22.80, 315, images/smyi.bmp), (关羽关刀模型, 合金材质可摆动关节, 199.00, 18, images/guanyu.bmp);参数说明image_path字段值必须与star/images/下文件路径一致score字段用TINYINT而非FLOAT因crDAO.class中计算平均分时使用AVG(score)整数类型更精准ON DELETE CASCADE是关键确保删除商品时自动清理关联评价避免 DAO 层手动处理外键异常。2.4 启动验证用 curl 模拟一次真实评价提交部署完成后启动 Tomcat访问http://localhost:8080/star/应看到商品列表页JSP 自动渲染。但真正验证 DAO 是否生效要用命令行绕过前端# 模拟用户提交评价POST 到 addComment.jsp curl -X POST http://localhost:8080/star/addComment.jsp \ -H Content-Type: application/x-www-form-urlencoded \ -d product_id1 \ -d user_name测试用户 \ -d score5 \ -d content味道正宗回购 # 查询数据库确认写入 mysql -uroot -proot -D shopdb -e SELECT * FROM t_comment WHERE product_id1 ORDER BY create_time DESC LIMIT 1;预期输出应包含comment_id,product_id1,score5,content味道正宗回购。若返回空结果说明crDAO.class未正确加载或数据库连接失败——此时需检查 Tomcat 日志中SEVERE级别错误见第 4 章排查。3. DAO 层深度拆解ComDAO.class 与 crDAO.class 的真实调用链与 SQL 注入边界3.1 ComDAO.class 的增删改查实现字符串拼接 SQL 的代价与规避方案ComDAO.class反编译后核心方法addProduct()如下伪代码还原public boolean addProduct(String name, String desc, double price, int stock, String imagePath) { String sql INSERT INTO t_product (product_name, description, price, stock, image_path) VALUES ( name , desc , price , stock , imagePath ); try { stmt.executeUpdate(sql); return true; } catch (SQLException e) { System.err.println(Add failed: e.getMessage()); return false; } }逻辑说明这是典型的未使用 PreparedStatement 的字符串拼接。name或desc若含单引号如商品名OReillys GuideSQL 将直接报错You have an error in your SQL syntax。但该系统在生产环境曾通过前端 JS 过滤replace(//g, )规避而非后端修复——这是历史包袱也是你接手时必须加固的第一道防线。3.2 crDAO.class 的事务控制为什么 addComment() 必须手动 commitcrDAO.class中addComment()方法关键片段public boolean addComment(int pid, String user, int score, String content) { Connection conn null; PreparedStatement pstmt null; try { conn getConnection(); // 获取连接 conn.setAutoCommit(false); // 关键关闭自动提交 String sql INSERT INTO t_comment (product_id, user_name, score, content) VALUES (?, ?, ?, ?); pstmt conn.prepareStatement(sql); pstmt.setInt(1, pid); pstmt.setString(2, user); pstmt.setInt(3, score); pstmt.setString(4, content); pstmt.executeUpdate(); conn.commit(); // 手动提交 return true; } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) {} } return false; } finally { closeResources(pstmt, conn); } }参数说明setAutoCommit(false)是为保证“插入评价 更新商品平均分”原子性。但当前版本只做了插入未更新平均分——getAvgScoreByPid()是只读方法t_product.avg_score字段始终为 NULL。若你要启用实时评分需在addComment()末尾追加// 补充更新商品平均分 String updateSql UPDATE t_product SET avg_score (SELECT AVG(score) FROM t_comment WHERE product_id ?) WHERE product_id ?; PreparedStatement updateStmt conn.prepareStatement(updateSql); updateStmt.setInt(1, pid); updateStmt.setInt(2, pid); updateStmt.executeUpdate();3.3 SmartUpload.class 的上传安全机制文件类型白名单与大小硬限制SmartUpload在upload.jsp中被调用其安全策略体现在两处文件类型白名单smartUpload.setAllowedFilesList(jpg,jpeg,gif,png,bmp)→ 当前star.zip中六张 BMP 图片恰好在此列表内但若你尝试上传.exe会抛出SecurityException: File type not allowed大小硬限制smartUpload.setMaxFileSize(1024*1024)1MB→ 超过此值直接throw new IOException(File size exceeds limit)不会进入 DAO 层避坑提示SmartUpload不校验文件内容魔数magic number仅依赖扩展名。攻击者可将木马重命名为shell.jpg绕过——生产环境必须增加FileInputStream读取头 4 字节校验 BMPBM、PNG89 50 4E 47等。4. 避坑 / 常见问题 / 排查六条血泪经验每一条都来自真实翻车现场4.1 现象JSP 页面报错org.apache.jasper.JasperException: java.lang.ClassNotFoundException: ComDAO原因ComDAO.class未放在WEB-INF/classes/下或 Tomcat 启动时该目录权限为只读Linux 常见解决检查star/WEB-INF/classes/ComDAO.class是否存在且大小 0Linux 下执行chmod -R 755 star/WEB-INF/避免 Tomcat 以tomcat用户身份无法读取 class4.2 现象上传图片后页面空白Tomcat 日志出现java.lang.NoClassDefFoundError: com/jspsmart/upload/SmartUpload原因SmartUpload.class位于WEB-INF/classes/但其依赖的jspsmart.jar缺失该 jar 未打包进star.zip解决下载jspsmart.jarv2.0MD5:a1b2c3...放入star/WEB-INF/lib/若无lib目录则新建并重启 Tomcatjar 必须在 lib 下classpath 才生效4.3 现象商品列表显示图片 404URL 为http://localhost:8080/star/images/daqiao.bmp但实际返回 404原因Tomcat 默认禁用对images/目录的静态资源服务init-paramparam-namereadonly/param-nameparam-valuetrue/param-value/init-param解决编辑conf/web.xml找到DefaultServlet配置段将readonly改为false或更安全做法在star/WEB-INF/web.xml中显式映射 imagesservlet-mapping servlet-namedefault/servlet-name url-pattern/images/*/url-pattern /servlet-mapping4.4 现象评价提交后数据库无记录但addComment.jsp页面显示“提交成功”原因crDAO.class中getConnection()方法硬编码root/root但你的 MySQL root 密码非root解决反编译crDAO.class用jad crDAO.class找到DriverManager.getConnection(...)行修改密码为你的实际密码重新编译javac -source 6 -target 6 crDAO.java替换 class⚠️ 注意重编译必须用 Java 6否则 Tomcat 8.5 会拒绝加载4.5 现象并发提交评价时t_comment表出现重复comment_id或getAvgScoreByPid()返回NULL原因crDAO.class的getAvgScoreByPid()使用SELECT AVG(score) FROM t_comment WHERE product_id ?但未处理WHERE条件无匹配记录时AVG()返回NULL解决在 SQL 中强制转换SELECT COALESCE(AVG(score), 0) FROM t_comment WHERE product_id ?或在 Java 层判断rs.next()后再取rs.getDouble(1)避免NullPointerException5. 进阶技巧用 JSP EL JSTL 替代 scriptlet三步完成评价列表分页与评分可视化5.1 用 JSTL 替代% %脚本让评价列表更易维护原始listComments.jsp中充斥while(rs.next()) { out.print(...); }既难读又易出错。改为 JSTL 方案!-- 引入 JSTL -- % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % !-- 从 request scope 获取评论列表需在 Servlet 中 setAttribute -- c:forEach items${commentList} varcomment div classcomment-item h4${comment.userName}/h4 div classscore-bar c:forEach begin1 end${comment.score} span classstar★/span /c:forEach c:forEach begin${comment.score 1} end5 span classstar muted☆/span /c:forEach span classscore-text(${comment.score}/5)/span /div p${comment.content}/p smallfmt:formatDate value${comment.createTime} patternyyyy-MM-dd HH:mm//small /div /c:forEach逻辑说明commentList必须由 Servlet如CommentServlet.java查询crDAO.getCommentsByPid(pid)后存入request.setAttribute(commentList, list)。JSTL 彻底消除 scriptlet模板与逻辑分离。5.2 分页实现用 LIMIT/OFFSET URL 参数控制不依赖第三方插件crDAO.class无分页方法需自行扩展// 在 crDAO.java 中新增 public ListComment getCommentsByPid(int pid, int offset, int limit) { String sql SELECT * FROM t_comment WHERE product_id ? ORDER BY create_time DESC LIMIT ? OFFSET ?; // ... PreparedStatement 设置参数循环 rs 构建 Comment 对象列表 }JSP 中接收page参数并计算偏移量c:set varcurrentPage value${param.page ! null ? param.page : 1} / c:set varpageSize value5 / c:set varoffset value${(currentPage - 1) * pageSize} / !-- 调用 DAO 获取分页数据 -- % crDAO dao new crDAO(); ListComment comments dao.getCommentsByPid(Integer.parseInt(request.getParameter(pid)), Integer.parseInt(pageOffset), Integer.parseInt(pageSize)); request.setAttribute(commentList, comments); %参数说明offset从 0 开始LIMIT 5 OFFSET 0取第 1~5 条LIMIT 5 OFFSET 5取第 6~10 条。URL 示例listComments.jsp?pid1page25.3 评分可视化用 CSS 实现动态星级避免 JS 依赖.star类定义如下纯 CSS 实现.score-bar { display: inline-flex; align-items: center; } .star { font-size: 14px; color: #ffc107; margin-right: 2px; } .star.muted { color: #e0e0e0; }技巧价值不引入 jQuery 或 Vue减少前端依赖。c:forEach动态生成星数服务端决定渲染几颗实心星——比客户端 JS 计算更可靠尤其在网络延迟高时。从那以后我每次接手 JSP 遗留系统都先用javap -c ComDAO.class | head -20看一眼字节码指令确认是否用了PreparedStatement再抓包验证addComment.jsp的 POST 请求体确保score字段没被 JS 伪造。这套star.zip的价值不在多先进而在它把 DAO 层的脆弱性、上传组件的边界、甚至 BMP 图片的物理尺寸都摊开给你看——它不教你如何造火箭但告诉你燃料罐焊点在哪漏气。希望帮到你。本文还有配套的精品资源点击获取
返回列表