ARTICLE DETAIL

资讯详情

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

Java Web餐饮点餐系统源码实战:JDK1.8+Tomcat7/8+MySQL5.7部署指南

Java Web餐饮点餐系统源码实战:JDK1.8+Tomcat7/8+MySQL5.7部署指南 简介这是一套基于Java Web技术栈开发的餐饮点餐管理系统源码面向Java初学者与Web开发入门者解决餐厅前台点餐、订单管理、菜品分类及用户权限控制等典型业务场景。资源包共131个文件含43个JSP页面实现前后端交互与展示、23个Java类封装业务逻辑与DAO操作、23个编译后Class文件支撑MVC各层运行以及SQL脚本、CSS/JS样式脚本、数据库备份文件.db/.sql和配置文件web.xml、xml、classpath等整体729KB结构完整、模块清晰。已有1382人学习下载适合通过实战理解ServletJSPMySQL三层架构设计思想。读者可直接部署运行获取完整MVC分层代码结构、典型CRUD功能实现、数据库建表语句及配套图片资源并参考预览中多个Servlet类如dingdanServlet、caipuServlet、yonghuServlet快速掌握请求分发与业务路由机制。1. 这不是个“Java Web 入门 demo”而是一套能直接跑通、改得动、上线用的餐饮点餐系统源码包你手头这个foodsystem.rar不是网上泛滥的“JSP 学生课程设计”——它没有空壳 DAO、没写死的数据库连接、没注释掉的关键跳转逻辑。它是一套真实部署过、功能闭环的 Java Web 餐饮管理系统从用户注册登录、菜品分类浏览、在线点餐下单、订单状态跟踪到后台的菜品管理、餐桌分配、权限分级管理员/厨师/服务员、菜单分类维护全链路可运行。核心是 MVC 分层清晰*.Servlet是 Controller 层共 8 个覆盖全部业务入口*.class文件是编译后的 Servlet 字节码说明项目已完整构建过.bak后缀的 JSP 和 web.xml 是原始开发态备份意味着你拿到的是开发者本地调试完、准备提交前的快照。技术栈锁定在 JDK 1.8 Tomcat 7/8 MySQL 5.7 组合不碰 Spring Boot、不依赖 Maven 仓库——这意味着你不用折腾依赖冲突但也要亲手配好 JDBC 驱动和数据库初始化脚本。适合两类人一是想拿真实项目练手的 Java 初学者别再写“Hello World Servlet”了二是需要快速搭建内部食堂/小餐馆后台的运维或兼职开发者改改 logo、换换菜品图3 小时就能上线。2. 拆包即用从 rar 解压到 Tomcat 成功启动的六步实操2.1 解压与目录结构还原看清.bak文件的真实身份foodsystem.rar解压后得到的不是扁平文件列表而是标准的 Java Web 应用目录树雏形。关键点在于.bak文件——它们不是垃圾而是开发者为防误操作保留的原始 JSP 和配置文件。你需要做的是# 假设解压到 /home/user/foodsystem/ cd /home/user/foodsystem/ # 查看当前文件注意 .bak 后缀 ls -la # 输出示例 # web.xml.bak dingdanlist.jsp.bak index.jsp.bak # dingdanServlet.class diancaiServlet.class canzhuoServlet.class ...提示.bak文件是安全副本不是待删除文件。真正的web.xml和index.jsp在项目里可能已被覆盖或丢失所以.bak就是你的源文件。下一步必须重命名还原。执行还原命令Linux/macOSmv web.xml.bak web.xml mv index.jsp.bak index.jsp mv dingdanlist.jsp.bak dingdanlist.jsp这三步做完你才拥有了一个合法的WEB-INF/web.xml入口配置、一个可用的首页index.jsp、一个订单列表页dingdanlist.jsp。其他.jsp.bak文件如login.jsp.bak、caipu.jsp.bak同理处理——不要跳过否则访问时 404 是必然结果。2.2 数据库初始化MySQL 5.7 下建库、导入、配账号三行命令搞定系统依赖 MySQL但压缩包里没有.sql文件——这是新手最容易卡住的点。实际数据表结构和初始数据藏在WEB-INF/classes/下的 JDBC 配置或硬编码里。我们反向推导打开WEB-INF/web.xml搜索context-param或init-param找到数据库配置段常见位置在context-param中context-param param-nameurl/param-name param-valuejdbc:mysql://localhost:3306/fooddb?useUnicodetrueamp;characterEncodingUTF-8/param-value /context-param再查WEB-INF/classes/下是否有db.properties或jdbc.properties——本包没有说明连接信息写死在 Servlet 里典型老式写法。那就按惯例建库-- 登录 MySQL假设 root 密码为空 mysql -u root -p -- 创建数据库字符集必须是 utf8mb4否则中文乱码 CREATE DATABASE fooddb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建应用专用账号比 root 安全 CREATE USER fooduserlocalhost IDENTIFIED BY foodpass123; GRANT ALL PRIVILEGES ON fooddb.* TO fooduserlocalhost; FLUSH PRIVILEGES;参数说明utf8mb4是 MySQL 5.7 推荐字符集支持 emoji 和生僻汉字fooduser账号权限仅限fooddb避免用 root 运行 Web 应用密码foodpass123可按需修改但需同步改 Servlet 里的硬编码见 2.4 节。2.3 Tomcat 部署war 包不直接放webapps目录下免打包这个项目没有pom.xml不是 Maven 工程也不生成 war 包。它的部署方式是“直传目录”——把整个解压后的文件夹重命名为foodsystem直接扔进 Tomcat 的webapps目录# 假设 Tomcat 安装在 /opt/tomcat cp -r /home/user/foodsystem /opt/tomcat/webapps/foodsystem # 确保目录结构正确 # /opt/tomcat/webapps/foodsystem/WEB-INF/web.xml # /opt/tomcat/webapps/foodsystem/index.jsp # /opt/tomcat/webapps/foodsystem/WEB-INF/classes/dingdanServlet.class逻辑说明Tomcat 启动时会扫描webapps下所有目录自动将其识别为 Web 应用。WEB-INF是强制存在的安全目录classes下的.class文件会被 JVM 加载web.xml是 Servlet 容器的配置蓝图。这种部署方式省去了javac编译、jar cvf打包等步骤但要求你确保.class文件版本与 Tomcat 的 JDK 版本匹配本包为 JDK 1.8 编译Tomcat 必须用 JDK 1.8 启动。2.4 关键配置项定位改三处硬编码让数据库连上、页面跳转通项目没用配置文件数据库连接和页面跳转路径写死在 Servlet 里。必须手动修改改数据库连接以dingdanServlet.class反编译为例实际开发中你会用 JD-GUI 或在线反编译工具打开dingdanServlet.class搜索jdbc:mysql://。找到类似代码String url jdbc:mysql://127.0.0.1:3306/fooddb; String user root; String password 123456;把127.0.0.1改成localhost适配本地 MySQLroot和123456改成你上一步创建的fooduser和foodpass123。改页面跳转路径以diancaiServlet.java逻辑推断所有 Servlet 的response.sendRedirect()或request.getRequestDispatcher()都用相对路径。例如request.getRequestDispatcher(dingdanlist.jsp).forward(request, response);这没问题但若写成request.getRequestDispatcher(/dingdanlist.jsp)带开头/则会从上下文根找而本项目上下文路径是/foodsystem所以必须删掉开头的/统一用dingdanlist.jsp。改web.xml中的 welcome-file-list确保首页能被正确加载welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list如果写成welcome-filelogin.jsp/welcome-file而login.jsp又没还原.bak就会 404。为什么必须改这三处因为.class文件是编译产物无法像.java源码那样直接编辑。你只能反编译 → 修改 → 重新编译 → 替换。但本包只提供.class没给.java所以最稳妥的做法是用文本编辑器如 VS Code全局搜索jdbc:mysql://、root、123456、/dingdanlist.jsp等字符串在所有.class文件的反编译结果里批量替换JD-GUI 支持导出为.java改完再编译。2.5 启动验证curl 命令测通首页、登录页、订单页不靠浏览器别急着打开浏览器。先用命令行确认基础服务通# 启动 Tomcat确保 JAVA_HOME 指向 JDK 1.8 /opt/tomcat/bin/startup.sh # 等 10 秒检查端口默认 8080 netstat -tuln | grep :8080 # 测试首页返回 HTTP 200 且含 欢迎光临 字样 curl -I http://localhost:8080/foodsystem/ # 应返回HTTP/1.1 200 OK # 测试登录页JSP 页面返回 200 即可 curl -s http://localhost:8080/foodsystem/login.jsp | head -20 # 应看到 HTML 结构如 form actionyonghuServlet # 测试 Servlet 是否映射成功关键 curl -I http://localhost:8080/foodsystem/yonghuServlet # 若返回 404说明 web.xml 中 servlet-mapping 错误若返回 500说明数据库连不上参数说明curl -I只取响应头快且准curl -s静默模式配合head -20查看前 20 行 HTML确认页面结构存在测试yonghuServlet是因为它是用户模块入口牵一发而动全身。这三步通过证明容器、静态资源、动态 Servlet 三层都通了。3. MVC 分层拆解8 个 Servlet 如何协同完成点餐全流程3.1 Controller 层8 个 Servlet 的职责地图附 URL 映射表foodsystem.rar里的 8 个.class文件就是 MVC 中的 Controller。它们不处理业务逻辑只做三件事接收请求参数、调用 DAO 层、转发到 JSP 视图。每个 Servlet 对应一个核心业务域Servlet 类名对应 URL 路径web.xml 中 mapping主要职责关键请求参数示例yonghuServlet/yonghuServlet用户登录/注册/登出actionlogin,usernamexxxdingdanServlet/dingdanServlet订单创建/查询/状态更新actioncreate,dishIds1,2,3diancaiServlet/diancaiServlet点菜添加菜品到临时购物车dishId5,count2caipuServlet/caipuServlet菜品列表展示/搜索/详情actionlist,keyword宫保鸡丁fenleiServlet/fenleiServlet菜品分类管理增删改查actionadd,name川菜quanxianServlet/quanxianServlet权限角色分配管理员/厨师/服务员rolechef,userId101canzhuoServlet/canzhuoServlet餐桌状态管理空闲/占用/清洁tableNo3,statusoccupieddingdanlistServlet/dingdanlistServlet订单列表分页/筛选后台用page1,statuswait选型理由这种“一个 Servlet 对应一个业务模块”的做法是 JSP 时代典型的轻量级 MVC 实践。它避免了 Struts 的复杂配置又比纯 JSP 脚本更易维护。每个 Servlet 的doPost方法里基本结构都是String action request.getParameter(action); if (login.equals(action)) { // 调用 UserDAO.login() // setAttribute(msg, result) request.getRequestDispatcher(index.jsp).forward(request, response); }你不需要重写整个 Servlet只需读懂action分支逻辑就能快速扩展新功能比如加个“取消订单”分支。3.2 DAO 层没有独立 DAO 文件那就在 Servlet 里找 JDBC 模板本包没有单独的UserDAO.java或DishDAO.javaDAO 逻辑直接嵌在 Servlet 里典型的老式写法。以yonghuServlet.class反编译为例你会看到// 1. 加载驱动JDBC 4.0 可省略但老代码常写 Class.forName(com.mysql.jdbc.Driver); // 2. 获取连接硬编码必须改 Connection conn DriverManager.getConnection( jdbc:mysql://localhost:3306/fooddb, fooduser, foodpass123); // 3. 执行查询 PreparedStatement ps conn.prepareStatement(SELECT * FROM users WHERE username? AND password?); ps.setString(1, username); ps.setString(2, password); ResultSet rs ps.executeQuery(); // 4. 封装 BeanUser 类在 WEB-INF/classes/ 下 User user new User(); if (rs.next()) { user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); }逻辑说明这就是 DAO 的本质——封装数据库操作。虽然没抽成独立类但结构清晰Connection→PreparedStatement→ResultSet→Bean。你要做的不是重写 DAO而是复用这套模板新增一个TableDAO就复制粘贴这段代码改 SQL 和 Bean 字段即可。WEB-INF/classes/下的User.class、Dish.class等就是对应的 Bean反编译后可查看字段名确保 SQL 查询列名与rs.getString(xxx)一致。3.3 View 层JSP 里的 Java 脚本不是“坏味道”而是可控的渲染逻辑index.jsp、dingdanlist.jsp等文件里混着% %脚本和 HTML。这不是缺陷而是 JSP 时代的标准实践!-- index.jsp 片段显示最新 5 个订单 -- % ListOrder orders (ListOrder) request.getAttribute(orders); if (orders ! null !orders.isEmpty()) { for (Order order : orders) { % tr td% order.getId() %/td td% order.getTableName() %/td td% order.getStatusDesc() %/td tda hrefdingdanServlet?actiondetailid% order.getId() %查看详情/a/td /tr % } } else { % trtd colspan4暂无订单/td/tr % } %参数说明request.getAttribute(orders)是 Servletforward时存入的数据% %输出变量值% %写 Java 控制逻辑。这种写法的好处是渲染完全可控——你不需要学 Thymeleaf 语法改 HTML 就能改界面。坏处是业务逻辑和视图耦合但对小系统够用。要改样式直接改tr里的 CSS class要加字段在for循环里加td% order.getCreateTime() %/td即可。3.4 Bean 层反编译User.class看字段是后续扩展的唯一依据WEB-INF/classes/下的.class文件就是编译后的 Java Bean。用 JD-GUI 打开User.class你会看到public class User { private int id; private String username; private String password; private String realname; private String phone; private int role; // 0:普通用户, 1:管理员, 2:厨师, 3:服务员 // getter/setter 省略 }为什么必须看 Bean因为所有 JSP 页面的request.getAttribute(user)、所有 Servlet 里的user.getUsername()都依赖这些字段。你想在用户资料页加“邮箱”字段第一步不是改数据库而是在User.class反编译出的 Java 代码里加private String email;和getEmail()/setEmail()在yonghuServlet的登录逻辑里rs.getString(email)赋值在index.jsp里输出% user.getEmail() %最后才去 MySQL 的users表ALTER TABLE users ADD COLUMN email VARCHAR(50)。顺序不能错否则空指针异常直接报在 JSP 页面上。3.5 配置中枢web.xml是整个系统的路由总控台web.xml不只是“配置文件”它是 Servlet 容器的指令集。本包的web.xml关键段落!-- Servlet 定义 -- servlet servlet-nameyonghuServlet/servlet-name servlet-classyonghuServlet/servlet-class /servlet servlet servlet-namedingdanServlet/servlet-name servlet-classdingdanServlet/servlet-class /servlet !-- URL 映射 -- servlet-mapping servlet-nameyonghuServlet/servlet-name url-pattern/yonghuServlet/url-pattern /servlet-mapping servlet-mapping servlet-namedingdanServlet/servlet-name url-pattern/dingdanServlet/url-pattern /servlet-mapping !-- 上下文参数数据库连接 -- context-param param-namedriver/param-name param-valuecom.mysql.jdbc.Driver/param-value /context-param避坑重点servlet-class标签里的类名必须和.class文件名完全一致包括大小写。yonghuServlet.class对应yonghuServlet不能写成YonghuServlet。URL pattern 的/开头表示相对于上下文根所以http://localhost:8080/foodsystem/yonghuServlet才能命中。如果 mapping 写成/servlet/yonghu那 URL 就得是/foodsystem/servlet/yonghu——但本包所有 JSP 里的 form action 都是yonghuServlet所以必须保持 mapping 为/yonghuServlet。4. 避坑指南8 个血泪经验总结专治启动失败、404、5004.1 现象Tomcat 启动后访问http://localhost:8080/foodsystem/返回 404原因web.xml中welcome-file-list未配置或配置的index.jsp文件名与实际不符比如你忘了还原index.jsp.bak目录下只有index.jsp.bak解决检查webapps/foodsystem/目录下是否存在index.jsp不是.bak打开webapps/foodsystem/WEB-INF/web.xml确认welcome-fileindex.jsp/welcome-file存在且拼写正确若仍 404用curl -v http://localhost:8080/foodsystem/index.jsp直接测 JSP排除 welcome-file 配置问题。4.2 现象点击“登录”按钮页面跳转到http://localhost:8080/yonghuServlet并报 404原因HTML 表单的action属性写死了绝对路径没带上下文路径/foodsystem/解决打开login.jsp找到form actionyonghuServlet methodpost改为form action${pageContext.request.contextPath}/yonghuServlet methodpost${pageContext.request.contextPath}会自动解析为/foodsystem适配任意部署路径。4.3 现象登录后跳转index.jsp页面显示java.lang.ClassNotFoundException: com.mysql.jdbc.Driver原因MySQL JDBC 驱动 jar 包未放入WEB-INF/lib/目录Tomcat 8.5 默认不加载$CATALINA_HOME/lib下的驱动解决下载mysql-connector-java-5.1.47.jar适配 MySQL 5.7放入webapps/foodsystem/WEB-INF/lib/目录重启 Tomcat。注意不要放$CATALINA_HOME/lib/老教程常错在这里。4.4 现象登录成功但index.jsp显示“用户名null”订单列表空白原因Servlet 里request.setAttribute(user, user)后forward到了错误的 JSP比如request.getRequestDispatcher(error.jsp).forward()或 JSP 里request.getAttribute(user)拼写错误如User大写解决在yonghuServlet的登录成功分支里确认forward的路径是index.jsp在index.jsp里检查request.getAttribute(user)的 key 是否和 Servlet 中setAttribute(user, ...)完全一致用System.out.println(user attr: request.getAttribute(user));在 Servlet 中打印 debug 日志。4.5 现象新增菜品后caipu.jsp列表不刷新还是旧数据原因JSP 页面被浏览器缓存或 Servlet 没重定向用了forward而非sendRedirect导致页面没重新请求解决在caipuServlet的新增成功分支用response.sendRedirect(caipuServlet?actionlist)强制刷新或在caipu.jsphead中加缓存控制meta http-equivCache-Control contentno-cache, no-store, must-revalidate / meta http-equivPragma contentno-cache / meta http-equivExpires content0 /5. 进阶实战三步改造让系统支持微信扫码点餐无需改架构5.1 第一步暴露 RESTful 接口用现有 Servlet 改造不新增代码foodsystem本身是传统 Web 应用但它的 Servlet 天然支持 POST/GET 请求。我们利用diancaiServlet和dingdanServlet直接对外提供 JSON 接口修改diancaiServlet的doPost方法反编译后在actionadd分支末尾加 JSON 响应逻辑// 原有逻辑添加到购物车... // 新增返回 JSON response.setContentType(application/json;charsetUTF-8); PrintWriter out response.getWriter(); out.print({\code\:200,\msg\:\添加成功\,\cartSize\: cart.size() }); out.flush(); return; // 阻止后续 forward修改dingdanServlet的doPost方法在actioncreate分支同样返回 JSON// 原有逻辑创建订单... // 新增返回订单号 response.setContentType(application/json;charsetUTF-8); PrintWriter out response.getWriter(); out.print({\code\:200,\msg\:\下单成功\,\orderId\: orderId }); out.flush(); return;逻辑说明不引入 Spring MVC只用原生 Servlet 的response.getWriter()输出 JSON。return是关键避免forward到 JSP 导致响应冲突。这样/foodsystem/diancaiServlet就成了一个标准 API 端点。5.2 第二步前端对接微信 H5 页面调用接口写一个极简的微信点餐页weixin-order.html放在webapps/foodsystem/下!DOCTYPE html html head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title微信扫码点餐/title /head body h2扫码点餐/h2 div idmenu/div button onclickcreateOrder()下单/button script // 1. 加载菜品列表调用 caipuServlet fetch(/foodsystem/caipuServlet?actionlist) .then(res res.text()) .then(html document.getElementById(menu).innerHTML html); // 2. 添加菜品调用 diancaiServlet function addToCart(dishId) { fetch(/foodsystem/diancaiServlet, { method: POST, headers: {Content-Type: application/x-www-form-urlencoded}, body: actionadddishId dishId }); } // 3. 创建订单调用 dingdanServlet function createOrder() { fetch(/foodsystem/dingdanServlet, { method: POST, headers: {Content-Type: application/x-www-form-urlencoded}, body: actioncreatetableNo1 }) .then(res res.json()) .then(data alert(订单号 data.orderId)); } /script /body /html参数说明fetch直接调用现有 Servlet/foodsystem/是上下文路径caipuServlet?actionlist返回的是 HTML 片段原 JSP 渲染结果直接innerHTML插入diancaiServlet和dingdanServlet则返回 JSON用.json()解析。这样微信浏览器打开http://your-server:8080/foodsystem/weixin-order.html就能点餐。5.3 第三步权限隔离用微信 openid 区分用户复用yonghuServlet微信用户没有账号但有openid。我们复用yonghuServlet的登录逻辑但绕过密码验证修改yonghuServlet的actionlogin分支String openid request.getParameter(openid); if (openid ! null !openid.trim().isEmpty()) { // 微信用户查库是否存在 openid不存在则插入新用户 User user userDao.findByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); user.setRole(0); // 普通用户 userDao.insert(user); } request.getSession().setAttribute(user, user); response.sendRedirect(index.jsp); return; } // 原有账号密码登录逻辑...在weixin-order.html中获取 openid需微信 JS-SDK此处简化// 实际需用微信 JS-SDK 调用 wx.login() 获取 code再用 code 换 openid // 为演示假设已知 openid const openid oABC1234567890xyz; fetch(/foodsystem/yonghuServlet?actionloginopenid openid);为什么可行yonghuServlet本身就是用户中心只需扩展一个openid参数入口就能接入微信体系。所有订单、购物车逻辑都不用改——因为request.getSession().getAttribute(user)依然有效dingdanServlet创建订单时user.getId()就是微信用户的 ID。从那以后我每次接手老 JSP 项目第一件事就是用curl -I测通三个 URL首页、登录页、核心 Servlet第二件事是反编译所有.class文件用 VS Code 全局搜索jdbc:mysql://和root第三件事是把web.xml打印出来贴在显示器边框上——因为 80% 的 404 都出在 servlet-mapping 和 welcome-file 的拼写上。这套foodsystem不是古董它是能让你在 2 小时内把一个真实点餐系统跑起来的最小可行单元。希望帮到你。本文还有配套的精品资源点击获取
返回列表