
简介这是一份Java无线点餐系统的完整源码包涵盖安卓客户端与服务端代码面向已掌握Java基础、想通过真实项目巩固开发技能的学生或自学者也适合课程设计或实训参考。系统基于无线点餐场景采用MyEclipse、MySQL与Tomcat搭建前后端均用Java实现可集中练习安卓界面布局、页面跳转、网络请求、服务端响应、数据库表设计以及客户端与服务端的整体联调。压缩包共296个文件大小约4.94MB包含84个Java源文件、117个编译后的字节码文件、38张图片、16个xml配置、7个依赖包以及安卓安装包与打包产物。内容中可以看到登录、点餐、订单、更新等典型模块目录围绕客户端和服务端展开源码、配置、界面素材相对齐整便于导入开发工具后对照阅读和二次修改。目前已有129人浏览学习资料体量不大适合快速运行验证也便于理解小型点餐系统从前端到后台的协作链路。1. 别急着解压这个 java 点餐系统源码包到底值不值得看拿到一个java点餐系统源码(含android端和服务端代码).zip很多人第一反应就是解压然后满屏找 exe 或安装包。实际这个 zip 不是拿来“一键安装”的而是一份完整工程师交付物服务端负责菜品、订单、登录态、支付回调的数据处理Android 端负责点餐、下单、订单列表的交互。对准备 java 面试题、做课程设计或想给本地小店做一套自助点餐工具的人来说这类源码最值得看的地方不是写了多少类而是“服务端 移动端”怎么约定接口、怎么传 token、怎么把一张订单从加购到完成串起来。下面这篇我按实际动手顺序来从看目录、起服务端、配 Android 端到改表改接口给你一条能照着复现的路径顺带把最常见的坑提前摆出来。2. 把服务端跑起来从项目结构到接口返回 JSON 的最小路径2.1 先看目录结构不要急着点开 Android Studio拿到源码包先别双击直接用命令行看目录是最不容易被误导的。这个包既然标了“含 android 端和服务端代码”根目录通常会有server和android两个子工程或者在同一个父工程下挂着两个模块。服务端如果是 Spring Boot 或 Spring MVC根目录一定找得到pom.xml或build.gradleAndroid 端则是settings.gradle加app目录。Windows 下用tree /F /AMac/Linux 下用tree -L 2 -d能快速区分“源码目录”和“编译产物目录”避免被target、build这类文件夹带偏。# Linux / macOS tree -L 2 -d . # Windows tree /F /A # 常见结构 # ├── server # │ ├── src/main/java # │ ├── src/main/resources # │ ├── pom.xml # ├── android # │ ├── app/src/main # │ ├── settings.gradle如果服务端目录里没有 pom.xml而是大量.jsp和web.xml说明这是传统 SSM 或 SSH 工程启动方式完全不同你需要先装 Tomcat再把 war 包丢进 webapps。现在多数点餐系统源码已经开始用 Spring Boot 内嵌容器看到spring-boot-starter-web也就意味着只需要 JDK 8 或 11不必单独装 Tomcat。这一步判断的误差会直接决定你后面折腾的是“代码问题”还是“环境问题”。另外记得看一眼pom.xml里的java.version标签。很多老源码写着1.8你用 JDK 17 直接启动大概率会碰到Unsupported class file major version这类兼容性报错。常见做法是安装 JDK 8或者在 IDEA 的 Project Structure 里把 SDK 切到 8不要一上来就迁到高版本因为点餐系统用到的旧依赖很可能没跟上新 JDK 的模块化限制。2.2 改数据库连接application.yml 里逃不掉的三个位置点餐系统一定会连数据库最常用的是 MySQL。在server/src/main/resources下找到application.yml或application.properties打开后重点看spring.datasource这一段。需要改的有三个值url里的数据库名、username、password。但新手最容易漏的是serverTimezoneMySQL 8 以上驱动不指定时区启动时会直接报Could not create connection to database server因为驱动不知道拿哪个时区跟数据库比对。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/order_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你的数据库密码 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.order.entityuseSSLfalse是开发环境的标准配置否则 MySQL 8 每次连接都要多一次 SSL 握手开发时又慢又容易超时。serverTimezoneAsia/Shanghai解决的是“时间差 8 小时”的根源之一jackson.time-zone则保证接口返回的时间是东八区可读字符串而不是一串时间戳。如果你看到mybatis.mapper-locations指向的 XML 路径和实际目录对不上启动时会报Invalid bound statement这时候不用急着改代码先把pom.xml里的资源过滤配置打开确保src/main/java下的 mapper XML 也能被打进 classpath很多源码就是在这里漏掉才让你误以为要重写整个 MyBatis 配置。改完配置还要确认数据库本身已经创建好了。源码包里一般会带sql目录或doc目录找到.sql文件用source命令或 Navicat 执行一遍。不要只建一个空库因为点餐系统的菜品分类、管理员账号、测试数据都靠这个脚本来初始化。2.3 启动主类并用 curl 验证接口不是 404找到带SpringBootApplication的入口类确认 main 方法存在然后在 IDEA 里直接 Run。如果用命令行先mvn clean package再java -jar或者直接mvn spring-boot:run等看到Started ... in x seconds才代表应用启动完成。注意控制台里出现 Tomcat started 不代表应用层面健康很多源码包会写一个CommandLineRunner启动时自动往里灌测试数据如果灌到一半抛异常应用还是挂着但你后边一访问接口就是各种空指针或数据错乱。# 服务启动后先验证健康检查或最简单的菜品列表接口 curl -i http://localhost:8080/api/health # 期望看到 HTTP/1.1 200 和一段 JSON curl -i http://localhost:8080/api/dishes/list如果返回的是 404 页面说明你访问的路径本身不对不是服务没起来。很多点餐系统把/api前缀去掉或者 controller 类上加的是RequestMapping(/order)你要先去 controller 里看注解别靠猜。如果返回 401 或 403那也很正常源码里多半配了登录拦截器需要先拿admin账号登录拿 token再带 token 访问。这一步决定后边调 Android 端时能不能跑通所以宁愿多花几分钟打一次 curl也不要只盯着 IDEA 控制台看“启动成功”。3. Android 端配置模拟器、真机和局域网 IP 的三处必改3.1 在 Android Studio 里定位网络请求基址打开 Android 端前先把 Android Studio 装好并确认 SDK 版本。源码包里的 Android 工程通常可以直接File - Open选择android目录Gradle 会自动同步。如果同步很慢或失败先看build.gradle里的compileSdk和targetSdk是不是太高老源码用compileSdk 28而你本地只有 API 34兼容问题会一堆。同步成功后去app/src/main/java下找网络层用 Retrofit 的会有一个RetrofitClient或ApiClient类用原生HttpURLConnection的则有一个HttpUtil工具类。public class RetrofitClient { // 模拟器可以直接用 10.0.2.2真机换成同一局域网下的电脑 IP private static final String BASE_URL http://192.168.1.100:8080/; private static Retrofit getInstance() { return new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } }这里的BASE_URL是三处必改的其中一处。注意 Retrofit 的baseUrl必须以/结尾否则运行时直接抛IllegalArgumentException: baseUrl must end in /。如果你服务端接口路径是/api/dishes/list那 baseUrl 写http://192.168.1.100:8080/方法注解就写GET(api/dishes/list)不要两边都写斜杠也别在方法注解里以/开头。3.2 查一下电脑局域网 IP顺便处理 Windows 防火墙模拟器里用10.0.2.2就能访问宿主机但真机必须走局域网 IP。Windows 用ipconfigMac/Linux 用ifconfig或ip addr找到IPv4地址填进去。手机和电脑必须连同一个 Wi-Fi否则会一直超时。改完 IP 仍然超时八成不是代码问题而是 Windows 防火墙把 8080 入站连接拦了。你先用手机浏览器访问一下http://电脑IP:8080/api/health如果能看到 JSON说明网络通如果打不开去防火墙设置里把 8080 端口放行或者临时关掉防火墙再试一次。# Windows 查看局域网 IP ipconfig # 先确认电脑本机可以访问 curl http://localhost:8080/api/health # 再确认手机浏览器能否访问 # http://192.168.1.100:8080/api/health这一步特别容易让新人翻车服务端代码在 IDEA 里打印了 Started手机端却一直Failed to connect然后开始怀疑自己是不是把接口路径写错了。实际上“局域网 IP 不通”和“接口路径不对”是两类问题先用浏览器验证网络再用日志验证接口能省掉一大半无效排查时间。3.3 Android 9 及以上默认禁止明文 http两条解法如果你的手机系统是 Android 9API 28以上直接用http://访问局域网 IP运行时就会抛CLEARTEXT communication not permitted这是系统安全策略不是源码 bug。很多老点餐源码还停留在 http 时代所以必须手动放行。解法有两种临时开启usesCleartextTraffic或者用网络安全配置精确放行。!-- 方案一开发期在 AndroidManifest.xml 的 application 标签上加属性 -- application android:usesCleartextTraffictrue android:themestyle/Theme.App.Light ... !-- 方案二上线前res/xml/network_security_config.xml 精确放行 -- network-security-config domain-config cleartextTrafficPermittedtrue domain includeSubdomainsfalse192.168.1.100/domain /domain-config /network-security-config使用方案二时还要在application标签里加android:networkSecurityConfigxml/network_security_config。我一般建议开发期用方案一跑通一条完整点餐流程后再收敛成方案二。方案一虽然简单但会把所有 http 流量都放开如果 app 里接入了 WebView风险会变大。另外如果服务端用的是 HTTPS 但证书是自签名的那此时报错就不是“明文流量”而是“证书校验失败”处理方式要去全局信任该证书或单独处理 SSL跟这里完全不同。4. 点餐流程的数据表与接口约定看懂源码才知道改哪张表4.1 菜品、订单、订单明细的三表关系点餐系统的数据模型非常固定菜品、订单、订单明细。拿到服务端源码后先不要急着读 controller找到sql里的建表语句把这三张表的关系看懂。一般会有category分类表、dish菜品表、orders订单表和order_detail订单明细表具体字段名不一定一样但核心关系不会变。-- 常见建表结构具体以源码包里的 sql 文件为准 CREATE TABLE dish ( id int NOT NULL AUTO_INCREMENT, name varchar(64) NOT NULL, price decimal(10,2) NOT NULL, image varchar(255) DEFAULT NULL, category_id int DEFAULT NULL, status tinyint DEFAULT 1 COMMENT 1上架 0下架, PRIMARY KEY (id) ); CREATE TABLE orders ( id int NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL, user_id int NOT NULL, total_amount decimal(10,2) NOT NULL, status tinyint NOT NULL COMMENT 0待支付 1已支付 2制作中 3已完成 4已取消, create_time datetime DEFAULT NULL, PRIMARY KEY (id) ); CREATE TABLE order_detail ( id int NOT NULL AUTO_INCREMENT, order_id int NOT NULL, dish_id int NOT NULL, dish_name varchar(64) DEFAULT NULL, quantity int NOT NULL, amount decimal(10,2) NOT NULL );注意很多源码把dish_name冗余到order_detail而不是去关联dish表这是一种刻意设计订单是历史快照菜品之后改名、改价都不应该影响已经下单的记录。理解了这一点你就不会再问“为什么订单详情里的菜名和菜品列表不一致”。订单状态里的 0 和 1 特别关键如果 Android 端没有接真实支付下单后订单状态会停在 0 或 1你需要到数据库手动改成 2 或 3才能看到完整的“制作中”和“已完成”状态流转。这也是验证整个系统有没有跑通的重要节点。4.2 服务端统一返回体Result 里 code、msg、data 的分工大多数 Java 点餐源码会用一个ResultT包装类统一返回格式。你抓接口时会发现返回的不是裸 JSON而是{code:0,msg:success,data:{...}}这样一层包装。这个包装结构非常重要因为 Android 端解析时不能直接new Gson().fromJson(response, DishList.class)要带着泛型去解析。{ code: 0, msg: success, data: { list: [ {id: 1, name: 宫保鸡丁, price: 28.00} ] } }源码里通常有对应的 Java 类Android 端也要写一个同结构的类来承接。如果服务端失败时返回code: 1, msg: token 失效但客户端还在按data.list来解析Gson 就会抛Expected BEGIN_OBJECT but was STRING。很多从没有接触过源码包的开发者在第一次拿到点时系统项目就被这个报错卡住其实不是数据不对而是没判断code就直接取data。public class ResultT { private int code; private String msg; private T data; public boolean isSuccess() { return code 0; } // getter / setter 省略 } // Android 端这样拿泛型 List ResultListDish result new Gson().fromJson(json, new TypeTokenResultListDish() {}.getType());如果你的源码返回的不是这种结构而是直接一个裸数组那说明没有统一返回封装Android 端可能直接在 service 接口方法上用了CallListDish。我建议不管原包是不是统一封装至少保留一个Result类后续接支付回调、接优惠券、接门店开关时你会在code分支里省很多功夫。4.3 接口路径与方法注解登录 token 是怎样一路传进 Header 的点餐系统不可能没有登录。服务端通常用RequestHeader(Authorization)来取 tokenAndroid 端在登录成功后把 token 存进 SharedPreferences再通过 Retrofit 的Interceptor统一加到每个请求的 Header 里。这是最主流的一种做法源码里只要看到Interceptor或OkHttpClient基本就是这个套路。public class AuthInterceptor implements Interceptor { Override public Response intercept(Chain chain) throws IOException { Request.Builder builder chain.request().newBuilder(); String token SharedPreferencesUtil.getToken(); if (!TextUtils.isEmpty(token)) { builder.addHeader(Authorization, Bearer token); } return chain.proceed(builder.build()); } }看到这段你就明白为什么服务端接口单独测试通了Android 端一进点餐列表却弹“未登录”。问题可能根本不在接口而在 Android 端登录成功后没有把 token 存下来或者服务端要求Authorization客户端只传了token两边对不上时整个流程卡在下单那一步。调接口时先把日志打开在 logcat 里搜一下有没有Authorization头比盲改服务端代码快得多。另外注意如果服务端用的是自定义 token 而不是 JWT那就不需要Bearer前缀具体看源码里拦截器怎么解析不要照搬网上的写法。5. 避坑拿过来就能跑的点餐源码通常有五个地方等你翻车5.1 服务端没报错但接口一直 404前缀被吞了现象启动日志正常curl 访问/api/dishes/list却返回 404IDEA 里也没报错。原因服务端 controller 类上是RequestMapping(/dishes)方法上是GetMapping(/list)根本没有/api前缀而 Android 端 Retrofit 注释写的是api/dishes/list。解决去 controller 上统一加/api前缀或者改 Android 端方法注解为dishes/list。不要两边各猜一半以服务端为准。更省事的方法是在application.yml里加server.servlet.context-path: /api这样 controller 不用改Android 端也能对上。这一条属于源码包最常见的“服务端版本和 Android 端版本对不上”问题。5.2 中文乱码MySQL 连接串和表编码没对齐现象菜品接口通了但返回的菜名全是问号控制台打印的中文也乱。原因数据库连接串没有characterEncodingutf8或者建库时用的字符集是latin1还有可能是 Windows 下启动服务端时读到的 yml 文件本身不是 UTF-8。解决先执行SHOW CREATE DATABASE order_system看库默认字符集再把连接串改成useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai最后用 IDEA 打开 yml 看右下角编码是否 UTF-8改完重启服务端并重新导入 sql。只改连接串不重建表乱码还会在旧数据里残留所以要先清数据再导入。5.3 图片加载不出来静态资源目录没暴露现象Android 端菜品列表有文字有价格但图片全是空白加载失败。原因源码把图片存到了服务端的uploads目录但没有配置 Spring Boot 静态资源映射或者 Android 端拼的图片地址是http://localhost:8080/uploads/1.jpg在真机上访问的自然是你自己手机而不是电脑。解决服务端写一个WebMvcConfigurer把本地目录映射到/uploads/**Android 端再把图片地址拼成http://电脑局域网IP:8080/uploads/ 相对路径。这是点餐系统源码最典型的“电脑上能看手机上白屏”问题。Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String uploadPath System.getProperty(user.dir) /uploads/; registry.addResourceHandler(/uploads/**) .addResourceLocations(file: uploadPath); } }这里还有一个容易忽略的点如果服务端是通过java -jar启动的System.getProperty(user.dir)是 jar 包所在目录不是 IDEA 里的工程目录。所以尽量不做相对路径直接配一个绝对路径比如/home/app/uploads或者 Windows 下的D:/order/uploads宁可写死也不要让部署环境变化把图片路径带偏。5.4 时间戳和本地时间差 8 小时三处时区设置都要对齐现象数据库订单创建时间是对的Android 端列表里显示的时间却早 8 小时或晚 8 小时。原因服务端 JVM 时区、MySQL 连接时区、Jackson 的时区这三个没有全部对齐。解决JVM 启动参数加-Duser.timezoneGMT08MySQL 连接串带serverTimezoneAsia/Shanghaiapplication.yml里 jackson 的time-zone: GMT8。三处都要改只改其中一处换台电脑或换部署环境就会复现。这个问题在 Docker 部署时更阴间因为很多基础镜像默认时区是 UTC启动容器后你会发现宿主机时间正常容器里的 Java 进程却比本地慢 8 小时。5.5 Android 端首次运行黑屏或闪退混淆和架构目录现象用 Android Studio 直接 Run 没问题打包 release 后一进点餐页就闪退。原因打包开了混淆而项目里用了反射比如 Gson 泛型、Retrofit 的 service 接口没有加 keep 规则。解决在proguard-rules.pro里把 service 接口、实体类全部 keep简单粗暴的是-keep class com.example.order.entity.** { *; }再加一条-keep interface com.example.order.api.** { *; }。另一个坑是libs里有.so文件只支持armeabi-v7a你在 x86 模拟器上会直接闪退真机 arm64 反而没事。遇到闪退先看 Logcat 的FATAL EXCEPTION第一行多半能定位到是哪个类被混淆或哪个 so 找不到。6. 把点餐系统改成你自己的从换菜品图到接支付前的验证清单真正把一套点餐系统源码变成自己的项目不是改个包名和 logo 就完事而是要按一条业务主流程做完整验证。我的建议是先在本地跑通“登录 → 点餐 → 下单 → 改状态 → 查询订单”这五个动作再考虑接支付。验证时不要每次都开 Android 模拟器先用 curl 模拟客户端请求会更快。先用 admin 账号登录拿到 token再带 token 查菜品、下单把服务端接口流程调通。下面的命令可以当作一条最小验证链# 1. 登录拿 token curl -i -X POST http://localhost:8080/api/login \ -H Content-Type: application/json \ -d {username:admin,password:123456} # 2. 把返回的 token 放入变量 TOKEN上面返回的token # 3. 带 token 查询菜品 curl -i http://localhost:8080/api/dishes/list \ -H Authorization: Bearer $TOKEN # 4. 创建一个测试订单注意菜品 id 要和上面返回的一致 curl -i -X POST http://localhost:8080/api/order/create \ -H Authorization: Bearer $TOKEN \ -H Content-Type: application/json \ -d {items:[{dishId:1,quantity:2}]}curl 这一套跑通之后再回 Android Studio 里点真机调试你会发现自己脑子里的“业务链路”清晰很多。如果直接改代码接微信支付我一般会先在 order 表预留transaction_id和pay_time字段后端先写一个“支付成功回调”的 mock 接口Android 端下单后手动触发这个 mock而不是一上来就申请商户号、配回调域名因为支付回调的坑比想象中多尤其回调地址必须是公网 HTTPS本地开发时要靠内网穿透工具这又是一层不确定性。一个我很想提醒你的习惯是拿到源码后先记一份“改动日志”。例如把原来的包名com.olddomain.order改成你自己的包名如果只在 Android Studio 里手动改目录忘了改applicationId和proguard里的包名打包时一定会翻车。我自己的翻车经验是图省事只改了 Android 端包名结果服务端返回的数据实体类路径和客户端不一致Gson 解析反射找不到字段整个订单页崩溃。从那以后我改项目都先搜一遍全工程里的旧包名和旧域名不急着写新代码。点餐系统本身不难难的是把“服务端接口约定”和“Android 端数据解析”这两端对齐。希望这篇能帮你少走一段弯路让手里的 zip 真正跑起来而不是解压完就放在硬盘里吃灰。本文还有配套的精品资源点击获取