Java点餐系统源码解析:Android客户端与Servlet服务端架构实战
简介这是一套面向Java初学者与Android入门开发者的无线点餐系统实战源码采用客户端与服务端分离架构适合在掌握Java基础语法后通过完整项目巩固所学。服务端基于MyEclipse10、MySQL与Tomcat搭建客户端为Android应用涵盖登录、主菜单、下单、更新等典型业务模块能帮助读者理解移动端与后台的数据交互流程。压缩包共296个文件约4.94MB包含84个java源文件、117个class编译文件、16个xml布局与配置、38张jpg图片资源、7个jar依赖包以及apk安装包、dex与properties配置等源码与可运行产物兼备便于对照阅读与调试。目前已有129人学习下载。对于想练手Java Web与安卓结合项目的同学可从中获取完整的目录结构、数据库脚本与接口调用思路是较为实用的课程设计或毕业设计参考素材。1. 从一份 APK 反推架构无线点餐系统到底能跑通什么很多人第一次拿到java点餐系统源码(含android端和服务端代码).zip第一反应是解压看目录然后被resources.ap_、jarlist.cache、MainMenuActivity.class这些编译产物劝退。其实这份资源的定位很清晰它是一套完整的 C/S 架构练手项目Android 客户端负责点餐交互Java 服务端负责订单与菜单数据落库中间靠 HTTP 通信。适合刚学完 Java 基础、想找一个能同时摸到 Android 四大组件和 Servlet 数据流的开发者。你不需要从零搭环境但需要理解它为什么用PayServlet而不是直接操作数据库以及MenuProvider和TableProvider在客户端扮演什么角色。下面按「能跑起来 → 看懂结构 → 改得动 → 避得开坑」的顺序拆一遍。2. 环境搭建与工程导入MyEclipse10 Tomcat MySQL 的版本对齐2.1 为什么这套老环境反而省事这份源码标注的开发环境是 MyEclipse10 MySQL Tomcat开发语言 Java。放到现在看MyEclipse10 确实老但它的好处是工程结构简单没有 Maven 依赖树所有 jar 包都在WEB-INF/lib下摆着不会出现「依赖下载失败」这种玄学问题。我一般会先确认三件事JDK 版本、Tomcat 版本、MySQL 驱动版本。源码里的PayServlet继承的是HttpServlet说明它跑在 Servlet 2.5/3.0 容器上Tomcat 7 或 8 都能吃。MySQL 驱动如果是mysql-connector-java-5.x那数据库连接串里必须带useUnicodetruecharacterEncodingutf8否则中文菜名会变问号。2.2 服务端导入步骤先把 zip 解压找到服务端工程目录通常带WebRoot或WebContent。在 MyEclipse 里新建一个 Web Project名字随意然后把src下的 Java 包和WebRoot下的页面、WEB-INF整体拷进去。注意web.xml里的 servlet 映射要和服务端代码里的WebServlet或 XML 配置一致否则PayServlet会 404。# 检查服务端目录结构确认关键文件存在 find . -name PayServlet.java -o -name web.xml -o -name *.jar | head -20 # 输出示例 # ./src/com/wireless/servlet/PayServlet.java # ./WebRoot/WEB-INF/web.xml # ./WebRoot/WEB-INF/lib/mysql-connector-java-5.1.47.jar这段命令用来快速定位服务端核心文件。PayServlet.java是支付/下单入口web.xml决定 URL 映射lib下的驱动包决定数据库能不能连上。如果find结果里没有mysql-connector需要手动补一个 5.x 版本的驱动别用 8.x因为 8.x 的驱动类名和 URL 参数格式都变了老代码会直接抛ClassNotFoundException。2.3 数据库初始化与连接参数源码里通常带一个.sql文件用 Navicat 或命令行导入即可。导入后重点看两张表菜单表和订单表。菜单表存菜名、价格、图片路径订单表存桌号、菜品 ID、数量、状态。服务端连接数据库的配置一般写在db.properties或直接硬编码在DBUtil类里。// 典型的 JDBC 连接代码参数需要按自己环境改 public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/wireless_order?useUnicodetruecharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; // 改成你自己的密码 public static Connection getConnection() throws SQLException { try { Class.forName(com.mysql.jdbc.Driver); // 5.x 驱动类名 } catch (ClassNotFoundException e) { e.printStackTrace(); } return DriverManager.getConnection(URL, USER, PASSWORD); } }这里URL里的wireless_order是数据库名必须和导入的 sql 文件里CREATE DATABASE的名字一致。characterEncodingutf8不加的话客户端传上来的中文菜名会在服务端变成乱码。Class.forName那行是显式加载驱动虽然 JDBC 4.0 以后可以省略但老容器里留着更稳。提示Tomcat 启动后如果报java.sql.SQLException: Access denied先检查 MySQL 用户权限再确认root是否允许从localhost连接。别急着改代码。3. Android 客户端结构拆解从 MainMenuActivity 到 MenuProvider3.1 客户端工程导入与 APK 对照Android 端源码在 zip 里通常是一个 Eclipse ADT 工程带AndroidManifest.xml和res目录。导入时选「Existing Android Code Into Workspace」如果 ADT 版本太新可能会提示project.properties里的 target 版本不对改成你本地有的 SDK 版本即可。WirelessOrder_Client.apk是编译好的安装包可以先用它验证服务端是否正常再回头调源码。!-- AndroidManifest.xml 里关键权限和 Activity 注册 -- uses-permission android:nameandroid.permission.INTERNET / application activity android:name.LoginActivity / activity android:name.MainMenuActivity / activity android:name.OrderActivity / activity android:name.UpdateActivity / /applicationINTERNET权限必须加否则客户端发不出 HTTP 请求。四个 Activity 的分工是LoginActivity登录MainMenuActivity展示菜单OrderActivity下单UpdateActivity更新菜品或桌位状态。如果导入后 R 文件报错先检查res目录下有没有文件名大写或含中文的图片Android 资源命名只允许小写字母、数字和下划线。3.2 MenuProvider 与 TableProvider 的职责MenuProvider和TableProvider是客户端的数据访问层不是 Android 四大组件里的 ContentProvider而是自定义的类封装了 HTTP 请求和 JSON 解析。MenuProvider负责从服务端拉菜单列表TableProvider负责查桌位状态。这种分层的好处是 Activity 里不直接写HttpURLConnection改接口地址时只动 Provider 一处。// MenuProvider 里典型的 HTTP GET 请求 public class MenuProvider { private static final String BASE_URL http://10.0.2.2:8080/WirelessOrder/; public static ListMenu getMenuList() { ListMenu list new ArrayList(); try { URL url new URL(BASE_URL menu?actionlist); HttpURLConnection conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(GET); conn.setConnectTimeout(5000); // 5 秒超时避免卡 UI if (conn.getResponseCode() 200) { // 读取 InputStream用 JSON 解析成 Menu 对象 } } catch (Exception e) { e.printStackTrace(); } return list; } }BASE_URL里的10.0.2.2是 Android 模拟器访问宿主机localhost的固定地址。如果你用真机调试要改成电脑的局域网 IP比如192.168.1.100。setConnectTimeout(5000)是血泪经验不设超时的话服务端没开时客户端会一直转圈用户以为死机了。menu?actionlist这种 URL 风格说明服务端可能用了一个总的 Servlet 根据action参数分发而不是每个功能一个 Servlet。3.3 登录与下单的数据流LoginActivity把用户名密码 POST 到服务端服务端查数据库后返回一个状态码或用户 ID。OrderActivity把桌号、菜品 ID、数量拼成 JSON 或表单发给PayServlet。PayServlet收到后写订单表返回成功或失败。整个链路里最容易翻车的是编码客户端用UTF-8写输出流服务端用request.setCharacterEncoding(UTF-8)读两边不一致就会导致菜名乱码或订单备注丢失。// OrderActivity 里提交订单的片段 JSONObject order new JSONObject(); order.put(tableId, tableId); order.put(menuId, menuId); order.put(count, count); URL url new URL(BASE_URL pay); HttpURLConnection conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(POST); conn.setDoOutput(true); conn.setRequestProperty(Content-Type, application/json; charsetUTF-8); OutputStream os conn.getOutputStream(); os.write(order.toString().getBytes(UTF-8)); // 必须指定 UTF-8 os.flush(); os.close();setRequestProperty里的charsetUTF-8和getBytes(UTF-8)要成对出现。只写一个的话服务端可能按默认 ISO-8859-1 解码中文直接变乱码。PayServlet那边如果用的是request.getParameter而不是读流那客户端就不该发 JSON应该发application/x-www-form-urlencoded。这一点要对照服务端代码确认别两边各写各的。4. 避坑与排查老项目里最容易翻车的五个点4.1 现象Tomcat 启动报 404访问任何 Servlet 都不通原因通常是web.xml的url-pattern和客户端请求路径不匹配或者工程没有部署到 Tomcat 的webapps下。解决在 Tomcat 的conf/server.xml里确认Host的appBase指向或者在 MyEclipse 的 Servers 视图里重新 Add Deployment。另外检查web.xml的servlet-mapping里url-pattern是不是/pay而客户端请求的是/PayServlet大小写敏感。4.2 现象客户端能登录但菜单列表空白原因一般是MenuProvider解析 JSON 时字段名对不上。服务端返回的可能是{name:宫保鸡丁,price:28}而客户端解析的是menu_name和menu_price。解决用浏览器或 Postman 直接访问服务端菜单接口看真实返回的 JSON 结构然后改客户端的解析键名。别靠猜。4.3 现象真机安装 APK 后连不上服务端原因BASE_URL写的是10.0.2.2那是模拟器专用地址。真机必须用电脑的局域网 IP且手机和电脑在同一网段。解决把BASE_URL改成http://192.168.x.x:8080/WirelessOrder/同时确认电脑防火墙允许 8080 端口入站。如果还不行在手机浏览器里访问一下这个地址看能不能看到 Tomcat 首页。4.4 现象MySQL 插入订单时报Incorrect string value原因数据库或表的字符集不是utf8而客户端传了中文。解决建库时指定CHARACTER SET utf8 COLLATE utf8_general_ci或者对订单表的备注字段单独执行ALTER TABLE orders MODIFY remark VARCHAR(255) CHARACTER SET utf8;。别用utf8mb4去改老代码除非你确认驱动和连接串都支持。4.5 现象jarlist.cache或resources.ap_导致 Eclipse 报错原因这些是 ADT 编译产生的缓存文件直接导入源码时如果带着它们Eclipse 可能误判工程状态。解决删掉bin目录和jarlist.cache然后 Project → Clean。resources.ap_是打包后的资源文件源码工程里不需要它留着反而干扰。注意改完任何配置后先 Clean 再 Run老 Eclipse 的增量编译经常留旧 class 文件导致你改了代码但行为没变。5. 二次开发与验证把点餐系统改成你想要的形状5.1 加一个「菜品分类」筛选原版MainMenuActivity大概率是把所有菜平铺展示。想加分类先在服务端菜单表加一个category字段然后在MenuProvider的请求 URL 里带category参数服务端 SQL 加WHERE category ?。客户端加一个 Spinner 或 TabBar选中后重新调getMenuList(category)。这样改动量小且不破坏原有下单逻辑。-- 服务端菜单表加分类字段 ALTER TABLE menu ADD COLUMN category VARCHAR(50) DEFAULT 热菜; -- 查询时按分类过滤 SELECT id, name, price, image FROM menu WHERE category ? ORDER BY id;ALTER TABLE之后要同步更新服务端MenuServlet里的查询语句否则新字段不会被返回。客户端解析时多取一个category字段即可。注意别在OrderActivity里依赖分类下单只认菜品 ID。5.2 用 Postman 验证服务端接口在改客户端之前先用 Postman 把服务端每个接口跑一遍。登录接口用 POST参数username和password菜单接口用 GET下单接口用 POSTbody 用 JSON。这样能把「客户端问题」和「服务端问题」分开。我一般会建一个环境变量baseUrl指向http://localhost:8080/WirelessOrder/切换真机调试时只改变量值。接口方法参数预期返回/loginPOSTusername, password{status:ok,userId:1}/menu?actionlistGET无[{id:1,name:宫保鸡丁,price:28}]/payPOSTJSON: tableId, menuId, count{status:ok,orderId:1001}这张表建议手写在便签上改代码时对照着看。如果某个接口返回 500先看 Tomcat 控制台的异常栈通常是 SQL 语法或空指针。5.3 验证客户端与服务端联调是否真正跑通别只看界面能点要验证数据真的落库了。下单后去 MySQL 里SELECT * FROM orders ORDER BY id DESC LIMIT 1;看有没有新记录字段值对不对。然后再看客户端有没有收到成功提示。如果数据库有记录但客户端提示失败说明服务端返回的 JSON 格式和客户端解析不匹配。如果数据库没记录但客户端提示成功说明服务端根本没执行插入可能是事务没提交或PayServlet里逻辑分支走错了。从那以后我每次拿到这种 C/S 老项目都强制先跑通「登录 → 拉菜单 → 下单 → 查库」这一条最短链路再动任何代码。链路不通的时候改界面就是给自己挖坑。希望帮到你。本文还有配套的精品资源点击获取