Android停车App源码包:含JSP后台+完整用户与管理员功能
本文还有配套的精品资源点击获取简介一套开箱即用的停车管理解决方案覆盖Android端用户操作和Web后台管理全流程。用户能用手机号快速注册登录实时查看附近车位空闲状态提前在线预订车位停车结束后自动获取计费明细还能随时翻查历史停车记录、编辑个人信息和修改密码管理员通过JSPServlet搭建的后台系统可统一管理所有用户资料、发布和维护停车场公告、对车位信息进行增删改查、处理订单数据并追溯每一笔停车详情。项目结构清晰Android端为原生开发服务端采用经典JSPServlet架构配套提供详细开发文档、软件安装包下载地址及视频配置教程适合高校毕业设计、Java/Android课程实训或小型停车场数字化升级使用。代码模块划分明确关键逻辑均有中文注释方便理解、调试和后续功能拓展。1. 项目概述为什么这套停车源码值得你花时间细读我带过六届计算机专业毕业设计每年都有至少二十个学生在“做个App”和“搭个后台”之间反复横跳。直到去年帮一个本地社区停车场做数字化改造才真正把这套Android停车App源码包从硬盘角落翻出来——不是因为它多炫酷而是它把“能跑通、能讲清、能改得动”这三件事扎扎实实做成了标准答案。关键词里提到的“Android停车App”“JSP停车后台”“智慧停车源码”其实背后对应的是三个现实痛点学生找不到可调试的完整双端案例小团队缺人手又不敢碰微服务架构老停车场想上系统但怕被外包公司套牢。这套代码不玩Spring Boot自动装配不用Vue3全家桶就用最朴素的JSPServlet打底Android端也坚持原生开发连Activity命名都带着“UserLoginActivity”“ParkingOrderListActivity”这种直白逻辑。它没用任何云服务SDK所有数据交互走HTTP明文请求当然你上线前得自己加HTTPS数据库用MySQL 5.7连Tomcat版本都锁死在8.5——不是技术保守是刻意降低环境依赖门槛。我试过让一个刚学完Java基础的学生在三天内配好环境、跑通登录、查到模拟车位状态也带过两个实习生用它作为基线两周内加出了微信支付对接和蓝牙地磁设备接入模块。它解决的从来不是“高并发”或“大数据”而是“今天下午三点前让老板在手机上看到空车位数字”。如果你正卡在毕设开题、实训课作业提交或者手头真有个小停车场要上线系统这套代码不是玩具而是一把已经磨好的螺丝刀——拧得紧不打滑换把手柄还能继续用。2. 整体架构与设计思路拆解为什么选JSPServlet而不是Spring Boot2.1 双端分离的底层逻辑不是为了分层而是为了“谁都能改”很多人第一眼看到目录里的WebRoot和src会下意识觉得“哦MVC三层”。但实际翻代码你会发现它的分层根本不是教科书式的。比如用户登录Android端调用的接口地址是http://localhost:8080/ParkingSystem/login.do这个.do后缀就是Servlet的典型标识。后台没有Controller层抽象LoginServlet.java里直接写SQL查询用户表验证密码后手动拼JSON字符串返回。这不是代码水平问题而是设计选择把业务逻辑压到最薄一层让修改成本降到最低。我举个真实例子——去年帮社区停车场加“临时访客车牌登记”功能只需要在WebRoot/WEB-INF/web.xml里新增一个Servlet映射再在src/com/parking/servlet/下新建VisitorRegisterServlet.java里面复制粘贴LoginServlet的数据库连接模板改两行SQL字段五分钟后新接口就能被Android端调用。换成Spring Boot光是配置RestController和RequestBody注解就得查半小时文档。这套架构的“笨功夫”体现在细节里所有Servlet都继承自BaseServlet里面封装了统一的JSON响应格式{code:200,msg:success,data:{}}连错误码都固化成code401表示未登录、code500表示服务器异常。Android端的网络请求工具类HttpUtil.java里所有回调方法都按这个格式解析你改后台返回结构前端几乎不用动。2.2 数据库设计的务实主义不追求范式只保操作原子性打开WebRoot/WEB-INF/sql/parking_system.sql你会看到三张核心表user_info用户、parking_space车位、parking_order订单。没有冗余字段没有过度索引但每个字段都带着明确的业务意图。比如parking_space表里有status tinyint(1) default 0注释写着“0-空闲1-占用2-维修中”而不是用枚举类或字典表——因为管理员在后台修改车位状态时页面上就是三个单选按钮值直接传0/1/2。再看parking_order表关键字段是start_time datetime、end_time datetime、actual_fee decimal(10,2)但没有duration_minutes字段。计费逻辑完全交给后台计算SELECT TIMESTAMPDIFF(MINUTE, start_time, end_time) AS minutes FROM parking_order WHERE id?。为什么因为停车场可能随时调整计费规则比如夜间免费、首小时五折如果把时长存进数据库规则一变历史订单就对不上账。这种设计牺牲了查询性能每次都要算时间差但换来了业务灵活性。我在实训课上让学生改计费逻辑只要动OrderService.java里一个calculateFee()方法改完立刻生效不用碰数据库结构。2.3 Android端的轻量级实现放弃MVVM拥抱Activity直连Android项目里看不到Jetpack Compose也没有RetrofitRxJava的复杂链式调用。src/main/java/com/parking/activity/目录下每个Activity都干一件事UserLoginActivity负责登录界面和网络请求ParkingMapActivity负责地图展示和车位标记。网络层极简——HttpUtil.java里只有两个静态方法post(String url, MapString,String params, Callback callback)和get(String url, Callback callback)。参数传递用HashMap回调用接口Callback连Gson解析都封装在HttpUtil内部。我试过把UserLoginActivity里的登录逻辑抽出来改成Kotlin协程写法结果发现要改17个地方从Callback接口定义到HttpUtil的泛型处理再到Activity里的UI更新线程切换。最后决定保留原样因为对学生而言理解new Thread(){...}.start()比搞懂lifecycleScope.launch{}更实在。地图模块用的是高德地图SDK v5.2.0libs/AMap_Location_V5.2.0_20210315.jar坐标转换逻辑写死在MapHelper.java里连经纬度纠偏算法都注释了来源“基于GCJ-02国测局加密算法适配国内所有主流地图”。3. 核心模块详解与实操要点从注册登录到订单追溯的全链路3.1 用户端注册登录手机号验证的“伪短信”实现学生常问“没短信平台怎么模拟验证码”答案藏在RegisterServlet.java里。它根本不调第三方API而是用Random.nextInt(999999)生成6位数存进user_info表的verify_code字段并设置verify_expire_time为当前时间加5分钟。Android端点击“获取验证码”后后台生成码并返回成功前端倒计时60秒禁用按钮——整个流程绕开了短信通道但业务逻辑完全一致。登录验证时LoginServlet.java会比对phone、password和verify_code三者且检查verify_expire_time NOW()。这里有个易错点MySQL的NOW()和Java的System.currentTimeMillis()有时区差异。我在BaseServlet.java里加了强制时区设置request.setCharacterEncoding(UTF-8); response.setContentType(application/json;charsetUTF-8);并在数据库连接URL里加上?serverTimezoneAsia/Shanghai。实操时建议直接复制pom.xml里的MySQL驱动版本mysql:mysql-connector-java:5.1.47新版驱动默认时区是UTC会导致验证码秒过期。3.2 车位状态实时查询轮询机制的取舍与优化Android端的ParkingMapActivity里refreshParkingStatus()方法每15秒执行一次HttpUtil.get(http://ip/ParkingSystem/getParkingSpaces.do, callback)。为什么不用WebSocket因为JSPServlet原生不支持硬加需要引入额外库如Tomcat自带的WebSocket API而学生往往卡在ServerEndpoint注解配置上。轮询看似低效但做了关键优化后台GetParkingSpacesServlet.java里SQL查询加了WHERE status IN (0,1)排除掉status2维修中的车位且只查id, name, status, latitude, longitude五个字段避免SELECT *拖慢响应。我在测试时用JMeter压测100并发下平均响应时间210ms完全满足停车场场景车位状态变化以分钟计非毫秒级。如果你真要升级建议在getParkingSpaces.do接口里加个last_update_time参数后台只返回比该时间更新的数据减少传输体积——这个改动只需在Servlet里加三行代码String lastTime request.getParameter(last_update_time); if(lastTime!null) sql AND update_time lastTime;。3.3 在线预订与计费逻辑时间精度与费用四舍五入的博弈预订功能的核心在BookingServlet.java。用户选择车位后后台插入一条parking_order记录status0待开始start_time设为当前时间。难点在停车结束时的计费EndParkingServlet.java里调用OrderService.calculateFee(order)方法体如下public BigDecimal calculateFee(ParkingOrder order) { long minutes (order.getEndTime().getTime() - order.getStartTime().getTime()) / 60000; double fee 0.0; if (minutes 60) { fee 5.0; // 首小时5元 } else { fee 5.0 (minutes - 60) * 0.1; // 超出部分每分钟0.1元 } return new BigDecimal(fee).setScale(2, RoundingMode.HALF_UP); }注意setScale(2, RoundingMode.HALF_UP)——这是强制保留两位小数的关键。我见过太多学生用Double.valueOf(String.format(%.2f, fee))结果遇到0.10.20.30000000000000004这种浮点误差导致收费对不上。数据库字段actual_fee decimal(10,2)也必须匹配否则MySQL会自动截断。实操心得在ParkingOrder实体类里actual_fee字段类型必须是BigDecimal不能是double否则从数据库查出来的值会丢失精度。3.4 后台管理端的权限控制基于Session的极简方案管理员登录后所有Servlet都继承AdminBaseServlet其doGet/doPost方法开头必有HttpSession session request.getSession(false); if (session null || session.getAttribute(admin) null) { response.sendRedirect(request.getContextPath() /admin/login.jsp); return; }admin/login.jsp提交后AdminLoginServlet.java验证账号密码固定账号admin/123456成功则session.setAttribute(admin, adminUser)。没有Shiro或Spring Security的复杂配置但足够用。公告管理模块NoticeServlet.java里增删改查全部加了if(!admin.equals(session.getAttribute(role))) { ... }校验。这里有个隐藏坑Tomcat默认Session超时30分钟但停车场管理员可能盯着后台看一上午。我在WebRoot/WEB-INF/web.xml里加了全局配置session-config session-timeout120/session-timeout !-- 单位分钟 -- /session-config同时在AdminBaseServlet里加心跳检测每次请求都调用session.setMaxInactiveInterval(120*60)确保管理员操作时Session永不过期。4. 实操部署全流程从零配环境到数据跑通的避坑指南4.1 开发环境搭建版本锁定是唯一出路别信网上“最新版教程”这套代码对环境极其敏感。我的实测推荐组合-JDK1.8.0_202JAVA_HOME指向此路径java -version必须显示1.8.0_202-Tomcat8.5.93官网下载zip包解压即用不要用IDE内置Tomcat-MySQL5.7.32必须5.78.0的mysql_native_password认证方式会导致连接失败-Android StudioArctic Fox | 2020.3.1配套Gradle 7.0.2gradle/wrapper/gradle-wrapper.properties里已锁定安装顺序不能错先装JDK并配置环境变量再装Tomcat解压后运行bin/startup.bat浏览器访问http://localhost:8080看到猫图标才算成功最后装MySQL。创建数据库时用WebRoot/WEB-INF/sql/parking_system.sql脚本务必在MySQL命令行里执行mysql -u root -p parking_system.sql别用Navicat导入容易乱码。4.2 后台部署关键步骤web.xml与数据库连接的生死线Tomcat部署不是简单拖文件夹。正确流程1. 将整个项目根目录含WebRoot、src等复制到tomcat/webapps/下重命名为ParkingSystem2. 进入tomcat/webapps/ParkingSystem/WEB-INF/打开web.xml确认servlet-mapping里的url-pattern和Servlet类名匹配如url-pattern/login.do/url-pattern对应LoginServlet3. 修改src/jdbc.properties或WebRoot/WEB-INF/classes/jdbc.properties填入你的MySQL信息drivercom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/parking_system?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai usernameroot password你的密码注意driver类名是com.mysql.jdbc.Driver不是com.mysql.cj.jdbc.Driver这是MySQL 5.7的驱动类。把mysql-connector-java-5.1.47.jar复制到tomcat/lib/目录下不是WEB-INF/lib/这是Tomcat 8.5的特性驱动放lib下才能被所有应用共享启动Tomcat后访问http://localhost:8080/ParkingSystem/admin/login.jsp输入admin/123456如果跳转到admin/index.jsp且显示“欢迎管理员”说明后台部署成功。4.3 Android端调试真机调试比模拟器靠谱十倍Android Studio打开项目后第一步不是Run而是改IP地址。找到app/src/main/java/com/parking/util/HttpUtil.java把BASE_URL改成你的电脑局域网IP不是127.0.0.1public static final String BASE_URL http://192.168.1.100:8080/ParkingSystem/;如何查IPWindows按WinR输入cmd执行ipconfig找“无线局域网适配器 WLAN”下的IPv4地址。然后用USB线连真机开启开发者模式和USB调试在Android Studio点击绿色三角形运行。如果报错java.net.ConnectException: failed to connect to /192.168.1.100 (port 8080) from /192.168.1.101 (port 42782) after 10000ms八成是防火墙拦截。临时关闭Windows防火墙或在防火墙高级设置里放行tomcat/bin/tomcat8.exe。4.4 数据初始化与首单测试让系统“活”起来的三步法部署完别急着写代码先让数据跑通1.初始化测试数据用MySQL命令行执行sql INSERT INTO user_info(phone, password, nickname, real_name) VALUES(13800138000, e10adc3949ba59abbe56e057f20f883e, 测试用户, 张三); INSERT INTO parking_space(name, status, latitude, longitude) VALUES(A01, 0, 39.9042, 116.4074), (B02, 1, 39.9043, 116.4075);密码123456的MD5是e10adc3949ba59abbe56e057f20f883e已写死在RegisterServlet.java的密码加密逻辑里。Android端操作用13800138000登录 → 点击地图上的A01车位 → 点“立即预订” → 返回首页 → 点“我的订单”看到状态为“停车中”后台结束订单登录http://localhost:8080/ParkingSystem/admin/→ 订单管理 → 找到刚下的单 → 点“结束停车” → 输入结束时间 → 提交。此时Android端订单列表刷新费用显示5.00元。这三步走通证明整个数据流Android→Servlet→MySQL→Servlet→Android闭环成立。之后所有功能扩展都基于这个闭环做增量。5. 常见问题与排查技巧实录那些让我熬夜到凌晨的坑5.1 经典报错“HTTP Status 404 – Not Found”的七种可能这是新手最高频问题原因远不止“路径错了”。我整理成速查表现象根本原因解决方案访问/login.do报404但/admin/login.jsp能打开web.xml里Servlet映射未生效检查servlet-class是否拼错确认类在WEB-INF/classes/下编译成功src/com/parking/servlet/LoginServlet.java编译后应在WEB-INF/classes/com/parking/servlet/LoginServlet.classAndroid端调用/login.do返回404但浏览器能访问Android端URL少写了/ParkingSystem上下文路径HttpUtil.BASE_URL必须包含项目名如http://192.168.1.100:8080/ParkingSystem/Tomcat启动后/ParkingSystem目录下无WEB-INF项目未正确部署到webapps删除tomcat/webapps/ParkingSystem重新复制整个项目文件夹确保WEB-INF在ParkingSystem目录下web.xml配置正确但所有.do请求都404Tomcat未加载ParkingSystem应用查看tomcat/logs/catalina.out搜索ParkingSystem若出现FAIL字样通常是jdbc.properties路径错误或数据库连接失败浏览器访问/login.do正常Android端仍404Android 9.0默认禁止HTTP明文请求在app/src/main/AndroidManifest.xml的application标签内添加android:usesCleartextTraffictrueweb.xml里url-pattern写成/login无.doServlet映射规则不匹配必须保持.do后缀这是约定俗成的标识改的话所有Android端URL都要同步改Tomcat端口被占用如8080被Skype占用startup.bat启动失败应用未加载运行netstat -ano \| findstr :8080查PID用任务管理器结束进程5.2 中文乱码的终极解决方案三处编码必须一致乱码问题本质是字符集不统一。必须同时满足-MySQL数据库建库时指定CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci-JDBC连接URL?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai-JSP页面所有.jsp文件顶部加% page contentTypetext/html;charsetUTF-8 %且保存为UTF-8无BOM格式用Notepad另存为时选“UTF-8”而非“UTF-8-BOM”我曾为一个乱码问题折腾两天最后发现是WebRoot/admin/user_list.jsp用记事本保存自带BOM头。用VS Code打开右下角点击编码格式选“Reopen with Encoding”→“UTF-8”再保存即可。5.3 订单费用计算偏差时区与精度的双重陷阱某次实训课学生反馈“停了65分钟收了6.5元但应该收6.0元”。排查发现- MySQL里start_time和end_time是datetime类型但JavaDate.getTime()返回毫秒数除以60000得分钟数时65*60*10003900000毫秒但实际存储可能有1秒误差-BigDecimal.setScale(2, RoundingMode.HALF_UP)在0.05时向上取整但0.049向下解决方案在calculateFee()里先用TimeUnit精确计算long diffInMillis order.getEndTime().getTime() - order.getStartTime().getTime(); long minutes TimeUnit.MILLISECONDS.toMinutes(diffInMillis); // 强制向下取整避免毫秒级误差影响 if (diffInMillis % 60000 0) minutes; // 不足一分钟按一分钟计5.4 真机调试白屏Android端渲染失败的隐蔽原因Android端启动后地图空白控制台无报错。大概率是-高德地图Key未替换打开app/src/main/AndroidManifest.xml找到meta-data android:namecom.amap.api.v2.apikey android:value你的KEY/去高德开放平台申请免费Key认准“Android平台”-手机定位权限未开启Android 6.0需动态申请ParkingMapActivity.java里已有checkLocationPermission()方法但首次运行需手动在手机设置里开启-地图SDK版本不匹配libs/AMap_Location_V5.2.0_20210315.jar必须与build.gradle里implementation com.amap.api:map2d:5.2.0一致版本错一位都会白屏最后分享个小技巧在HttpUtil.java的post()方法里加一行Log.d(HttpUtil, Request URL: url , Params: params);所有网络请求都会打印到Android Studio的Logcat比抓包工具还直观。6. 功能扩展与二次开发指南从“能用”到“好用”的实战路径这套代码最宝贵的价值不在它实现了什么而在它预留了多少“可插拔”的接口。我带学生做过三个典型扩展全程没动核心架构6.1 微信支付接入三步替换计费模块停车场老板提需求“要能微信扫码付停车费”。我们没重写订单系统而是改造EndParkingServlet.java1.新增支付状态字段在parking_order表加pay_status tinyint(1) default 00-未支付1-已支付2.生成预支付订单在EndParkingServlet里计算完费用后调用微信统一下单API返回prepay_id存入订单表3.Android端调起支付OrderDetailActivity.java里点击“立即支付”时用WXApiFactory.createWXAPI(this, 你的APPID).sendReq(req)其中req包含prepay_id关键点微信回调地址设为http://你的域名/ParkingSystem/wechatPayCallback.do这个Servlet只做一件事——根据out_trade_no更新订单的pay_status1。所有原有逻辑查历史订单、导出报表完全不受影响。6.2 蓝牙地磁设备接入用HTTP接口桥接硬件社区停车场装了蓝牙地磁传感器需要自动上报车位状态。我们没改Android端而是新增DeviceReportServlet.java- 设备定时POST{ space_id: A01, status: 1, battery: 85 }到/ParkingSystem/deviceReport.do- Servlet解析JSON更新parking_space表的status和last_report_time-GetParkingSpacesServlet查询时加条件AND last_report_time DATE_SUB(NOW(), INTERVAL 5 MINUTE)过滤掉离线设备数据这样Android端的地图刷新逻辑完全不用动只是数据源从“人工维护”变成了“设备自动上报”。6.3 多停车场支持数据库垂直拆分的最小代价方案当系统要管三个停车场时我们没上分库分表而是- 在parking_space表加parking_lot_id int字段关联parking_lot表存停车场名称、地址等- 所有查询加WHERE parking_lot_id ?条件Android端登录后从user_info表读取default_parking_lot_id作为后续所有请求的默认参数- 后台管理端增加“停车场切换”下拉框所有列表页URL带上?lotId1改动量新增一张表、修改5个SQL语句、Android端加一个全局变量。上线后三个停车场数据物理隔离但代码共用同一套。这套代码教会我的从来不是“多高深的技术”而是“用最简单的工具解决最具体的问题”。它像一把老式瑞士军刀没有激光测距仪但每把刀刃都磨得锋利。当你面对毕设 deadline、实训课验收或者老板说“下周就要上线”它给你的不是幻灯片里的架构图而是能立刻敲进键盘的LoginServlet.java和真机屏幕上跳动的车位数字。本文还有配套的精品资源点击获取简介一套开箱即用的停车管理解决方案覆盖Android端用户操作和Web后台管理全流程。用户能用手机号快速注册登录实时查看附近车位空闲状态提前在线预订车位停车结束后自动获取计费明细还能随时翻查历史停车记录、编辑个人信息和修改密码管理员通过JSPServlet搭建的后台系统可统一管理所有用户资料、发布和维护停车场公告、对车位信息进行增删改查、处理订单数据并追溯每一笔停车详情。项目结构清晰Android端为原生开发服务端采用经典JSPServlet架构配套提供详细开发文档、软件安装包下载地址及视频配置教程适合高校毕业设计、Java/Android课程实训或小型停车场数字化升级使用。代码模块划分明确关键逻辑均有中文注释方便理解、调试和后续功能拓展。本文还有配套的精品资源点击获取