1. 项目定位与总体构思1.1 核心需求解析在做毕业设计选题时很多同学容易陷入两个极端要么选一个纯管理系统类型的课题后台管理页面堆功能结果答辩时被评委一句“你这个系统解决了什么实际问题”问得哑口无言要么选一个算法难度过高的课题比如基于深度学习的什么什么识别结果开发周期和数学基础都撑不住最后连一个能跑的Demo都拿不出来。“基于SpringBoot与Android的电动汽车电桩管理平台”这个题目刚好卡在了一个非常合适的难度区间。它的核心思路是以电动汽车充电桩为业务对象构建一套由Android客户端、SpringBoot服务端组成的完整业务闭环。用户用手机App查找空闲电桩、扫码启动充电、实时查看充电状态管理员在后台管理电桩设备、查看订单流水、处理异常告警。这个题目最大的优势在于技术栈完全是Java体系内闭环。Android端用Java/Kotlin开发服务端用SpringBoot开发数据库用MySQL通信用RESTful API加JSON。对于计算机专业的本科毕设来说不需要引入Python、Node.js等其他语言学习成本和答辩压力都会小很多。同时充电桩管理这个业务场景有明确的价值主张——新能源出行配套基础设施的数字化管理这在当前的行业背景下本身就具备现实的选题意义评委也更容易认可。1.2 功能边界与模块规划做毕业设计最忌讳的就是“贪多嚼不烂”。我在指导学生的过程中见过太多案例一开始规划了十几个模块做到最后Excel里功能清单打勾率不到六成代码库里堆了一堆半成品论文里还不知道该怎么写。所以这个项目的功能设计要遵循一个原则把一条核心业务链路做完整把周边辅助功能做精简。核心业务链路是注册登录 → 查找电桩 → 扫码/选择电桩 → 启动充电 → 实时监控 → 结束充电 → 支付结算 → 订单查询。围绕这条链路我建议把功能模块切分为三个端用户端Android App登录注册、电桩地图/列表浏览、电桩详情与状态查看、扫码启动充电、充电实时状态展示电流、电压、电量、金额、充电历史订单、个人中心余额、充值、故障报修。管理端Web管理后台SpringBoot Thymeleaf或Vue均可电桩信息CRUD、电桩状态管理启用/禁用/故障标记、用户管理、订单管理、充电价格参数配置、统计数据概览。服务端SpringBoot核心统一认证与鉴权、业务接口、定时任务电桩状态巡检、异常处理与日志记录。管理员后台是否要做成单独的App完全没有必要。用Web页面做管理后台工作量可控演示起来也比手机端方便。我在实际带项目时一般建议学生用Bootstrap Thymeleaf模板引擎快速搞定管理端页面把精力集中在Android端和服务端接口质量上。1.3 技术选型背后的思考选题定了接下来是技术选型。这一步很多同学容易“跟风”看到网上教程用什么就跟着用什么完全不考虑自己项目是否匹配。我在这个项目上的选型思路如下服务端SpringBoot 2.x 系列。选2.x而不是最新的3.x主要原因是3.x基于Jakarta EE规范部分教程和开源组件的兼容性还没有完全跟上网上的学习资料也相对较少。毕业设计求稳2.7.x是一个很成熟的版本资料丰富踩坑成本低。核心依赖包括Spring Web、Spring Data JPA或MyBatis-Plus、Spring Security或者用JWT手动拦截后面细说、MySQL驱动、Lombok等。移动端Android原生Java语言编写。虽然Kotlin现在是Android官方主推语言但考虑到大多数高校的课程体系仍然以Java为主学生用Java写Android更容易上手网上案例也多。网络层用OkHttp RetrofitJSON解析用Gson图片加载用Glide这三个组合是Android网络开发的老牌组合拳文档齐全出问题搜索引擎上直接能找到解决方案。数据库MySQL 5.7或8.0。表结构设计我会在后面的章节详细给出。需要强调的一点是不要把后端逻辑里需要频繁计算的数据强行塞进MySQL的存储过程或视图里保持数据库的“朴素”——只负责存取数据业务规则放在Service层处理。其他关键组件JWT做无状态认证Java 8的日期时间API处理充电时长与计费使用WebSocket或者Android端定时轮询来实现充电状态的实时刷新这个选择我会重点说明使用定时任务实现异常电桩的自动巡检。这个组合落地时遇到的一个常见问题是Lombok在不同JDK版本下的兼容性。如果你本地的JDK版本比较高比如JDK 17建议直接用SpringBoot 2.7.x自带的依赖管理不要手动指定低版本的Lombok否则编译阶段经常报奇怪的unknown enum constant错误。具体问题在后面的排查章节里展开。2. 数据库设计与接口协议2.1 表结构与关键字段设计数据库是这个项目的“地基”。我见过不少学生直接拿现成的开源项目改改表名就当成自己的设计结果答辩时被问到“为什么这个字段要这么设计”就完全答不上来。所以每一张表、每一个关键字段你都得知道设计意图。对于一个电桩管理平台我建议设计6张核心表用户表user主键、手机号唯一索引、密码BCrypt加密存储、昵称、钱包余额DECIMAL(10,2)、状态、创建时间。钱包余额这个字段我建议冗余到用户表里不要单独建一张钱包流水表不然功能量又膨胀了。但需要注意如果用余额支付每次扣款都要做金额校验和并发控制。电桩表pile主键、电桩编号业务唯一编码比如区域码序号、电桩名称、经度、纬度、地址描述、功率类型交流/直流、快充/慢充、当前状态0空闲/1使用中/2故障/3离线、单价元/度、创建时间。经纬度用DECIMAL(10,7)存储这个精度足够支撑地图展示和距离计算。订单表order主键、订单编号项目内唯一我习惯用时间戳随机数生成、用户ID索引、电桩ID索引、开始充电时间、结束充电时间、充电度数DECIMAL(10,2)、充电费用、服务费、订单状态0充电中/1已完成/2已取消/3异常终止、支付状态0未支付/1已支付。充值表recharge主键、用户ID、充值金额、赠送金额、充值时间、支付方式。这张表可以帮助论文里写“平台资金流管理”这种功能点但不增加太多开发量。故障报修表repair主键、用户ID、电桩ID、故障描述、图片URL、状态0待处理/1处理中/2已处理、提交时间、处理时间。这个表是答辩中的“加分项”——体现了你考虑到了用户与平台的互动场景。管理员表admin主键、账号、密码BCrypt加密、角色、最近登录时间、创建时间。这里要提供一个经验之谈字段类型统一用一个规范。比如所有状态字段统一用TINYINT所有金额字段统一用DECIMAL(10,2)所有时间字段统一用DATETIME。这样能避免后期写代码时因为类型不一致产生的各种隐式转换问题。我见过有学生金额用DOUBLE存储结果在做结算时出现了小数点后第三位精度丢失这在计费系统里是不能接受的错误。2.2 RESTful接口设计与约定接口协议是Android端与SpringBoot服务端之间的“对话语言”。我强烈建议在写代码之前先花半天时间把接口文档定义好用表格记录下来这样两个端各自开发时不会互相牵制。以核心业务链路为例接口清单应该是这样的功能点请求方式路径请求参数返回说明用户注册POST/api/user/register手机号、密码、昵称注册成功返回token用户登录POST/api/user/login手机号、密码返回token与用户信息获取电桩列表GET/api/pile/listlatitude、longitude、page、size返回附近电桩分页数据获取电桩详情GET/api/pile/{id}路径参数电桩详情当前状态创建充电订单POST/api/order/startpileId、userId创建订单返回订单号结束充电订单POST/api/order/endorderId结算费用更新状态查询订单状态GET/api/order/detail/{id}路径参数当前充电数据与计费用户余额充值POST/api/user/rechargeuserId、amount更新余额提交故障报修POST/api/repair/submitpileId、description生成报修工单有几个细节需要特别强调。第一所有的接口返回格式必须统一。我建议封装一个统一的ResultT对象包含code、message、data三个字段。成功时code为200业务失败时code为400系列系统异常时code为500。这样Android端接收到响应后可以直接通过code判断业务状态不需要在服务端到处写乱七八糟的判断逻辑。第二接口路径要有前缀区别。/api/user/**、/api/pile/**、/api/order/**这些前缀能让你在写SpringBoot拦截器时非常方便地按需放行或拦截。比如用户未登录访问/api/pile/list是可以放行的但创建订单就必须验证token。第三考虑真实的业务时序状态。启动充电这个动作在真实的充电桩场景里App只是下发了一个“请求指令”电桩硬件执行插枪、认证、通电的动作后才会上报“充电中”状态。毕业设计没有真实硬件就要用软件模拟这个状态机。我采用的方案是用户启动充电后服务端创建订单并生成一个模拟的任务线程让订单状态在几分钟内自动经历“待充电→充电中→充电完成”的变化。这个设计能让你在写论文和做演示时讲清楚状态流转机制而不是简单地用一个SQL更新把状态改掉完事。2.3 计费规则的设计思路计费是充电桩平台的业务核心也是答辩时评委容易追问的点。我的建议是采用“电费服务费”的定价模型规则如下充电费用 充电度数 × 电费单价 充电时长 × 服务费单价举个例子某直流快充桩电费单价为1.2元/度服务费单价为0.5元/小时。用户充了10分钟充入2.5度电那么费用就是 2.5 × 1.2 (10 ÷ 60) × 0.5 3.0 0.0833 ≈ 3.08元。这里要特别注意充电度数的计算用什么模型模拟。真实场景中充电度数由电桩硬件采集电流电压数据后统计算得但我们的软件系统没有硬件数据来源就需要模拟一个合理的“充电过程”。我在项目中用一个后台线程模拟电压恒定220V交流慢充场景电流在30A左右波动每三秒累加一次电能消耗电量 电压 × 电流 × (3秒 ÷ 3600秒) ÷ 1000单位折算为千瓦时。这样计算出来的度数有增长过程Android端就能展示一个动态变化的充电进度演示效果很好而且这个模拟逻辑在论文里可以写成“电桩充电数据采集模块的软件模拟实现”至少能写两页内容。3. SpringBoot服务端的核心实现3.1 项目初始化与目录结构SpringBoot项目我建议直接用IDEA的Spring Initializr创建不要去Spring官网手动下载压缩包再导入效率太低了。创建时需要注意三点Group填com.example或你的个人域名反写Artifact填ev-charging-server这类有业务含义的名字。Java版本选择8或11。对于毕业设计来说Java 8完全够用而且后续部署到服务器时兼容性最好。依赖选择Spring Web、Spring Data JPA、MySQL Driver、Lombok、Validation。暂时不需要引入Spring Security——我建议JWT认证用拦截器HandlerInterceptor手动实现因为Spring Security的配置复杂度对毕设来说是过度设计而且答辩时如果对Security的过滤器链机制讲不清楚反而成为扣分项。项目包结构我习惯采用以下分层com.example.evcharging ├── controller // 接口层只做参数接收和结果返回 ├── service // 业务层核心逻辑所在 ├── mapper/repository // 数据访问层JPA仓库 ├── entity // 数据库实体类 ├── dto // 请求和响应对象 ├── config // 配置类拦截器、跨域、WebMvc配置 ├── interceptor // JWT认证拦截器 ├── utils // 通用工具JWT工具、结果封装类 └── common // 全局异常处理、常量定义这种包结构的逻辑是“请求从上往下穿透、数据从下往上聚合”每一层只做自己该做的事出了问题也能从日志堆栈里快速定位到是哪一层出错。3.2 用户认证与JWT拦截器实现用户登录后服务端签发一个JWT令牌给Android端Android端后续每次请求都在Header里带上Authorization: Bearer token服务端通过拦截器解析token来识别用户身份。这个方案是当前主流做法代码量适中业务上够用。JWT工具类中需要关心的核心操作就三个生成token、解析token、校验token是否过期。token里我建议只放用户ID和手机号不要塞多余信息。过期时间设置为24小时用户App端如果token过期就引导重新登录这个逻辑在Android端可以通过拦截响应码自动处理。拦截器里注意两个细节白名单机制。登录、注册、获取电桩列表这些接口要放行。我在配置类中维护一个ListString whiteList用AntPathMatcher做路径匹配在白名单内直接放行否则取Header里的token解析用户信息并放入ThreadLocal中供后续Service使用。ThreadLocal存储用户信息。这个做法的价值在于后续的Service层方法不需要在参数里到处传userId而是通过UserContext.getUserId()获取当前登录用户。这属于代码可维护性方面的优化放在论文里也算是一个有亮点的设计。提示JWT密钥一定不要硬编码在类里放在application.yml中配置例如jwt.secretyour-secret-key。虽然毕设项目没有太多安全要求但养成好习惯对后续工作有益。3.3 电桩管理和充电订单核心流程电桩管理这部分Controller层的方法逻辑比较机械大部分是调用Service层的CRUD方法。重点在于Service层的业务判断。以“用户扫码启动充电”为例完整的业务序列是这样的Android端扫描电桩上的二维码二维码内容存电桩编号实际演示可以做一个简单的“点击模拟扫码”按钮把电桩编号传给/api/order/start接口。服务端根据电桩编号查询电桩校验电桩是否存在、状态是否为空闲。如果状态为“使用中”或“故障”直接返回对应业务错误码Android端弹Toast提示。检查用户余额是否足够支付本次充电的预估费用。预估方式可以简单按“最低消费金额”校验——比如余额必须大于1元才能启动充电否则返回提示。创建订单状态为“充电中”同时把电桩状态修改为“使用中”。启动一个模拟充电任务的线程定期更新订单中的电量、费用、时长等字段数据。返回订单号和电桩信息给Android端App跳转到充电监控页面。“结束充电”这个接口同样有业务判断只能结束当前用户自己的充电中订单结算费用时要重新读取最新的电量数据计算不能直接用创建订单时的预估数据结算完成后把电桩状态改回空闲。这里还涉及并发控制的隐患——多个用户同时给同一台电桩发起启动请求怎么办。我用了一个简单可靠的方案在MySQL层面对电桩状态更新加条件限制Modifying Query(update Pile p set p.status 1 where p.id :pileId and p.status 0) int lockPile(Param(pileId) Long pileId);当lockPile返回的影响行数为0说明电桩已被其他用户占用Service层直接返回“电桩已被占用”的业务错误。这个方案比Java层的synchronized更可靠因为它是数据库层面的原子操作天然避开了多实例部署时的锁失效问题。3.4 定时任务与异常状态巡检充电过程中可能出现各种“意外情况”比如用户直接杀掉了App进程后端模拟充电线程还在继续跑。针对这个场景我引入了两个定时任务订单超时巡检。每30秒扫描一次“充电中”超过预设最大时长比如2小时模拟值的订单强制结束充电并完成结算把电桩状态恢复为空闲。电桩故障模拟任务。每5分钟随机把部分空闲电桩的状态改为“故障”过一段时间再改回“空闲”模拟真实环境中电桩的随机故障。这个设计有两层好处一是让演示时的地图上能看到各种状态的电桩不然全是绿色空闲页面太单调二是让故障报修功能有实际的数据来源。SpringBoot的定时任务用Scheduled(cron ...)注解就能实现在配置类上加EnableScheduling开启即可。需要注意的坑是Scheduled默认只使用单线程执行器如果有多个定时任务且它们互相无依赖关系最好在配置中指定线程池大小避免一个任务阻塞导致其他任务排队等待。4. Android客户端的功能落地4.1 项目搭建与基础框架Android端我建议用Android Studio开发语言用Java。新建项目时选择的Empty Activity模板就够了不需要复杂的Fragment模板——导航结构用底部导航栏 Fragment的方式实现这是Android开发最主流、也最适合列表内容类App的结构。项目的基础依赖配置build.gradle文件的关键部分implementation com.squareup.okhttp3:okhttp:4.9.3 implementation com.squareup.retrofit2:retrofit:2.9.0 implementation com.squareup.retrofit2:converter-gson:2.9.0 implementation com.github.bumptech.glide:glide:4.13.2 implementation androidx.recyclerview:recyclerview:1.2.1 implementation androidx.cardview:cardview:1.0.0Retrofit加上Gson转换器负责接口请求和数据序列化RecyclerView负责列表展示CardView做电桩卡片的圆角和阴影效果Glide负责展示占位图。这套组合我实测下来编译稳定不用引入RXJava这类学习成本高的响应式框架。4.2 网络层封装与统一Token管理网络层我会封装一层ApiClient静态方法返回Retrofit实例统一配置baseUrl比如http://10.0.2.2:8080/——Android模拟器访问宿主机时必须用这个IP不能用localhost、OkHttp的拦截器、连接超时时间等。Token管理上我自定义一个OkHttp的Interceptor实现自动附加tokenInterceptor tokenInterceptor chain - { Request originalRequest chain.request(); String token SharedPreferencesUtil.getString(context, token, ); if (!TextUtils.isEmpty(token)) { Request newRequest originalRequest.newBuilder() .header(Authorization, Bearer token) .build(); return chain.proceed(newRequest); } return chain.proceed(originalRequest); };这个统一拦截器的价值在于所有的接口调用方法不需要手动写“从SharedPreferences取token再塞进Header”的重复代码以后如果要增加统一的日志打印、统一的错误码处理也可以在这个拦截器里完成。在答辩时你可以把这个Interceptor解释为“客户端AOP思想的落地实践”。4.3 电桩列表页与地图定位展示电桩列表页有两种展示形式列表模式和地图模式。对于毕业设计的功能完整性列表模式用RecyclerView就足够了地图模式需要引入百度地图或高德地图SDK集成和调试成本较高如果时间不够可以砍掉这个功能。但如果你想要亮点也可以做一个简单的“附近电桩分布”功能——不引入地图SDK而是用Android自带的TextView和Canvas画一个简易的分布图画几个代表电桩位置的小圆点根据和用户的距离排序。技术含量不高但演示效果足够生动。列表页的逻辑是进入界面后获取用户位置权限调用/api/pile/list接口传入经纬度服务端通过Haversine公式按距离排序并分页返回电桩数据。Android端渲染时每张电桩卡片展示电桩名称、距离、功率类型、状态标签和单价。状态标签用不同颜色区分——绿色“空闲”、黄色“使用中”、红色“故障”、灰色“离线”。这种视觉上的差异化设计在用户体验上非常重要答辩演示时也能让评委一眼看清电桩状态分布。一个容易忽略的小细节定位权限在Android 6.0及以上需要运行时动态申请在Android 11及以上对位置权限的精确性有了更细的分类。代码里用ActivityCompat.requestPermissions申请ACCESS_FINE_LOCATION即可但要记得在onRequestPermissionsResult回调中处理用户拒绝的情况否则后续获取定位会崩溃。4.4 充电监控页与实时数据刷新充电监控页是整个App最核心的页面建议包含以下元素电桩名称和编号订单号充电时长实时累加当前功率/累计电量动态变化当前费用实时计算电桩状态“充电中”“结束充电”按钮数据刷新方案有两种轮询和WebSocket。我推荐轮询的方式理由有三项目复杂度可控、代码量少、稳定性高。具体做法是在充电监控页启动一个Handler每3秒调用一次/api/order/detail/{id}接口获取最新数据更新UI上的时间、电量、费用三个字段。这个3秒的刷新频率对演示场景完全够用而且没有真实硬件时通过轮询拿到的数据变化本身就模拟了“数据在实时更新”的效果。如果你想让方案在论文和答辩中更有技术含量可以补充说明“在后续工程化落地时可以将轮询替换为WebSocket推送以保证实时性和降低服务端压力”——这样既展现了你的技术思考又不影响当前的实际工作量。还有一个体验细节必须写下来在充电监控页退出时要注销Handler否则Activity销毁后Handler还在持续执行网络请求会造成内存泄漏。这是我见过Android开发中非常高频的Bug在代码里一定加上handler.removeCallbacksAndMessages(null)。4.5 扫码与订单支付的简化策略真实的充电桩扫码流程是用户打开App扫电桩屏幕上的二维码解析出电桩编号App向服务端发起充电请求。毕业设计如果做微信或支付宝的SDK支付接入会遇到两方面困难个人开发者没有支付接口权限而且支付流程会大大提升App的复杂度。这里我建议采用一个合理的简化方案——余额支付。用户可以在个人中心执行“充值”操作。为了演示效果充值过程不要真的对接第三方支付而是输入金额直接点击确定即完成充值同时在后端记录一条充值流水。这实际上模拟了“用户通过第三方支付完成付款后平台收到回调为用户账户增加余额”的完整业务逻辑。这个简化在论文中可以这样定性表述第三方支付涉及商务签约与平台资质审核本项目聚焦于核心充电业务支付环节采用虚拟余额方式进行功能验证工程化部署时可在充值接口中无缝接入第三方支付回调。4.6 App生命周期与会话保持App的会话保持是决定演示体验的重要细节。因为JWT有效期设置为24小时如果用户登录一次后把App切到后台几天再打开时token可能已经过期。如果不处理用户点的每一个操作都会得到“登录状态已过期”的报错体验非常糟糕。推荐做法是在登录成功后将返回的token和用户信息存入SharedPreferencesApp启动时检查SharedPreferences中是否存在token如果存在就直接跳转到主界面不需要重新登录。当接口返回401或业务码提示token失效时清除本地token信息并跳转到登录页。提示Android判断登录态时不能只判断token是否存在还要在接口返回错误后做被动下线处理。我给拦截器加一个“全局401通知”机制在自定义的OkHttp拦截器中判断响应码如果是401则发送一个本地广播所有Activity收到广播后统一执行跳转登录页的逻辑。5. 硬件模拟与数据埋点5.1 充电过程与电桩状态的软件模拟前文提到这个项目最大的设计难点在于没有真实硬件一切设备数据都要靠软件模拟。如何处理这个模块也直接决定了论文的技术深度和答辩质量。我设计了一个ChargeSimulator组件职责是模拟电桩从启动充电到结束充电的完整生命周期。具体实现如下服务端创建充电订单后通过Async注解启动一个异步任务注意主类要加EnableAsync。异步任务内维护一个循环每3秒执行一次更新订单中的已充时长3秒生成一个当前电流值基础值随机扰动比如30A上下波动2A计算本次累加电量累加到订单的总电量字段根据电量与单价实时计算费用判断是否达到预设的充电结束条件比如达到目标电量或最大时长如果是则自动结算并结束。循环中使用Thread.sleep(3000)控制节奏同时用一个标志位stopFlag判断用户是否触发了“结束充电”操作。这个模拟的巧妙之处在于它模拟的不只是“静态数据变了”而是模拟了“电桩设备在持续采集数据并上报”这一过程。你在论文中的相关章节可以用“设备数据采集模块”“充电策略执行引擎”这样的表述来包装这个设计内容深度和代码量都足够支撑一个完整的省级大学生创新创业项目级别的描述。5.2 模拟数据的初始化策略为了让演示效果更丰富服务端启动时最好初始化一批模拟数据在城市中心区域随机生成20~30台电桩覆盖交流慢充和直流快充两种类型随机生成5个左右的注册用户密码统一为123456方便演示时快速登录随机生成一批历史订单数据过去7天内的用于管理端统计图表的展示。数据的初始化可以用SpringBoot的ApplicationRunner接口在应用启动完成后执行一段初始化逻辑。需要注意的是这个初始化要加“条件判断”只有当数据库中电桩表为空时才执行初始化否则每次重启服务都会重复插入数据造成脏数据。历史订单数据很重要它直接决定了管理端统计页面有没有内容可看。我建议生成数据时让订单数量和金额呈现出每天波动的趋势比如工作日订单少、周末订单多这样管理端用ECharts画出来的折线图会有起伏的曲线答辩演示时的视觉效果会好很多。5.3 关键业务指标的数据闭环充电平台的运营管理人员关心什么数据无非是几个维度今日订单量、今日充电量、今日营收金额、电桩空闲率、用户增长趋势。管理后台的Dashboard至少要展示以下指标总电桩数量、当前空闲/使用中/故障数量今日订单量、今日充电总度数、今日总营收近7日订单量与营收折线图近7日新增用户数柱状图这些数据全部从数据库的订单表和用户表中聚合查询出来即可。关于数据库聚合查询写SQL时可以尽量使用DATE_FORMAT(create_time, %Y-%m-%d)做按天分组返回一个ListMapString, Object给前端渲染图表。这样管理后台的功能就有“数据决策”的味道了论文里也能提炼出“充电运营数据可视化分析”这样的子模块标题。6. 联调部署与常见问题排查6.1 Android模拟器与后端联调Android模拟器和本机服务端联调时有一个经典坑在App里访问http://localhost:8080是访问不到的因为模拟器里的localhost指向的是模拟器本身必须使用http://10.0.2.2:8080才能访问宿主机。这个知识点非常重要我在指导学生时反复强调但每年还是有一半的人会踩进去。如果使用真机调试则需要把10.0.2.2换成你电脑在局域网中的IP地址比如http://192.168.1.101:8080。前提是两个设备连接同一个WiFi同时Windows防火墙需要允许Java进程入站访问。如果手机访问不到可以临时关闭防火墙测试确认通了之后再配置入站规则。另外Android 9及以上默认禁止明文HTTP请求。如果你没有配置HTTPS请求http://开头的地址会被直接拒绝。解决方案是在AndroidManifest.xml的application节点加上android:usesCleartextTraffictrue如果希望更规范一点可以定义network_security_config.xml只用明文放行指定域名的请求这样论文里也能多一个“网络安全配置”的内容。6.2 前后端时间一致性与订单结算准确性充电计费和时间强相关如果你开发的App和后端服务端的时间不一致会出现订单时长计算混乱的问题。比如你手机时间比服务端快5分钟启动充电时记录的服务端时间和手机本地时间对不上会造成结算时用手机本地时间计算时长得到一个明显不合理的费用。解决这类问题的一个通用原则是所有时间以服务端时间为准。Android端在展示时间时只做格式化显示所有关于充电时长、充电费用的计算全部在后端逻辑中完成。App端每次拉取订单详情时服务端直接返回已经计算好的“已充电时长秒”和“当前费用元”App端只负责展示。这个原则在论文里可以写成一节“时间统一性设计”说明保证了计费准确性。6.3 高频更新场景下的并发冲突订单详情接口会被Android端每3秒调用一次这在并发量极低的情况下看起来没什么问题但涉及数据库操作时必须考虑一个问题订单结算时读取的数据是不是一致的最新数据。举个例子用户点击“结束充电”的瞬间模拟充电线程正好也执行了一次电量和费用更新这时两个操作并发修改同一条订单数据可能造成最终结算金额和用户看到的最后一次刷新金额不一致。解决方案是所有写操作都通过Service层方法同步执行并且用Transactional事务包裹。在订单结算方法中先通过乐观锁版本号或排他锁SELECT ... FOR UPDATE锁定订单记录再读取最新电量计算费用并完成状态更新。对于模拟充电线程的更新操作要求它不能同时修改“已结束”状态的订单在SQL层加上WHERE order_status 0条件保证状态流转不会反向覆盖。6.4 部署上线与论文素材准备毕设项目只要在本地能跑通就算完成但如果你想在论文中体现“系统部署”这一环节可以找一个云服务器把后端和数据库部署上去。部署方案不复杂就是典型的SpringBoot应用部署云服务器安装JDK 8、MySQL 5.7本地把项目打包成可执行JAR包mvn clean package上传JAR包到服务器用nohup java -jar ev-charging-server.jar 后台启动配置MySQL的远程访问权限修改application.yml里的datasource.url为云数据库地址。如果你在押题“评委会不会问部署细节”可以在Windows服务器阶段先用Tomcat或内嵌Tomcat把JAR包跑起来然后把运行截图放在论文的“运行环境”一节中。这比在论文里写一堆“可实现容器化部署”这种空话要实在得多。部署中常见的一个问题是MySQL的时区配置。国内服务器默认时区是东八区但MySQL的serverTimezone参数如果配置为UTC存储的时间会和本地时间相差8小时。建议在JDBC连接串中显式加上serverTimezoneAsia/Shanghai避免时间错乱坑。6.5 高频问题速查表我把这个项目开发过程中最常遇到的问题整理成一张速查表每一行都是我在实际操练中踩过的坑可以帮你省掉大量搜报错的时间。报错信息或现象根本原因解决方案ConnectException: Failed to connect to /10.0.2.2服务端没启动或端口配置不对先确认后端能通过浏览器访问接口再检查App的baseUrl端口CLEARTEXT communication not permittedAndroid 9禁止明文HTTP在Manifest中添加usesCleartextTraffictrueUnknown constant enum tag本地JDK版本高Lombok版本不匹配用SpringBoot 2.7.x版本管理自带的Lombok版本不手动指定Duplicate entry xxx for key phone重复注册数据库唯一索引冲突在Service层先查重再插入订单状态不变“充电中”永远不结束异步任务没被触发检查主类是否加了EnableAsync以及异步方法是否在另一个类中同类内Async调用无效Table xxx doesnt existJPA自动建表策略未配置spring.jpa.hibernate.ddl-autoupdateMySQL连接8小时超时连接池中的连接空闲时间过长被回收spring.datasource.hikari.max-lifetime1800000金额计算出现小数误差用Double或Float存储金额统一使用BigDecimal进行金额计算数据库用DECIMALRecyclerView滑动卡顿在UI线程做了耗时的数据解析网络请求和解析放在子线程Retrofit的enqueue已做到注意不要在getView中做复杂逻辑6.6 论文写作与答辩材料组织的建议这是给即将面对毕业论文和答辩的同学的最后一个建议。很多学生代码写完了论文却不知道怎么组织说明“把所有东西都塞进去”的错误思路。实际上论文章节和你的代码模块天然有对应关系建议这样切绪论背景写新能源产业政策支持和充电设施缺口选题意义强调数字化管理对运营效率的提升国内外现状可以搜几篇知网的文献各摘一段再改写。需求分析把功能模块图放出来就是本文章1.2节的三端功能划分加上用例图、业务流程图。这部分要写成“功能性需求非功能性需求安全、性能、可维护性”。系统设计写总体架构、数据库表结构设计、接口设计。你的JWT认证方案、统一返回结果处理、时间统一性方案都放在这里突出讲。系统实现逐个模块贴核心代码和截图。关键是核心类名、核心方法名要和论文中的描述一一对应评委如果翻代码能按照论文里的类名找到实现体验会非常好。系统测试用功能测试用例表输入、预期结果、实际结果、结论覆盖核心业务链路再补充简单的并发测试或接口性能测试数据。至于答辩PPT一页一个模块把最终演示效果截图放上去代码只贴核心片段不要贴大段源码。评委最关注的是你有没有真正理解项目——你在回答“为什么这样设计”时的逻辑自洽程度要远比代码行数有说服力。最后再分享一个小技巧做演示时提前准备一套“演示剧本”。从注册登录开始到找桩、启动充电、看电量增加、结束充电、查看订单一气呵成走完整个业务闭环。如果你的演示在这个闭环中每一步都有可见的数据变化反馈这已经是毕业设计答辩中表现最好的那一档了。在此基础上如果还能主动说出“这里的计费规则支持电费与服务费分别定价可以通过管理后台动态调整”那就没有哪个评委能挑出实质性问题了。