首页 / 资讯中心 / 文章详情

基于SpringBoot+Vue的充电桩管理平台设计与实现

基于SpringBoot+Vue的充电桩管理平台设计与实现 ★ FEATURED ARTICLE
1. 项目定位与需求拆解1.1 这个项目到底在做什么先说结论这是一个基于 SpringBoot Vue 的 B2C 式电车充电管理平台系统覆盖了“找桩—预约—充电—支付—评价”的完整闭环同时提供后台运营管理的全套能力。说白了就是把线下充电站的业务搬上线用户能搜到附近有空闲状态的充电桩、扫码启动充电、实时查看充电进度、完成后自动扣费运营方能在后台维护充电桩信息、查看营收数据、管理用户和订单。做这个选题的同学很多人一开始会纠结一个问题市面上充电系统那么多我做一个会不会显得很普通我的看法是毕设的本质不是“造一个别人没做过的东西”而是在一个真实业务场景里证明你具备需求分析、系统建模、技术落地、排错优化的完整能力。充电系统刚好具备典型业务系统的所有要素——状态管理桩的待机/充电/故障、并发问题多用户同时扫码、资金安全钱包扣费和流水、定时任务订单超时关闭——这些都是面试官和答辩评委最看重的点。毕设阶段我最推荐的定位是做一个功能完整、业务闭环清晰、技术栈主流、代码可读性强的系统而不是一味追求花哨功能。这套系统如果做完你的收获其实集中在四个层面完整的后端工程能力SpringBoot 全家桶的使用、数据库设计能力核心是充电订单和桩状态的建模、典型业务难题的解决并发和资金一致性问题、前后端联调部署的全栈经验。1.2 用户角色与核心业务流程这个系统我建议拆成两个端用户端微信H5或浏览器访问和管理端后台PC系统。用户端面向普通车主。核心流程很简单但是里面藏着细节用户注册登录后在地图上或者列表页看到充电桩列表列表要能展示桩的实时状态空闲/占用/故障空闲状态下可以发起预约或者直接下单充电充电过程中前端页面要轮询或者通过 WebSocket 推送当前电量、电压、充电时长、已扣金额充电结束包括充满自动结束、用户手动结束、余额不足停止后生成订单展示明细并扣款。管理端面向充电站运营人员。需要覆盖充电桩管理增删改查、设备状态监控、订单管理按各种维度筛选查询、用户管理封禁/解封、财务管理充值流水、消费流水、营收统计、数据看板今日充电量、今日营收、活跃用户数。这里还要注意“全流程”三个字它强调的是流程闭环。很多同学做系统喜欢把功能堆上去却不管业务逻辑比如用户充电充到一半没钱了怎么办、预约了但人没到场桩却一直被占着怎么办。这些流程分支恰恰是本项目的加分项。1.3 功能清单与验收标准我列出当时实现的功能清单你可以作为参考的基准线用户端注册/登录JWT鉴权、充电桩地图与列表、充电桩详情与状态筛选、预约充电限时段占位、扫码/手动选择充电枪、充电中实时监控、订单列表与详情、钱包充值、在线支付模拟/接入、消费评价、个人信息管理。管理端管理员登录RBAC权限、充电桩/电站管理、用户管理、订单管理、评论管理、钱包流水管理、数据统计。这套功能做完已经超过大多数同类毕设的规模。如果你的时间比较紧张建议砍掉地图功能用列表代替和WebSocket用轮询代替优先保住充电流程这一段的主链路。2. 技术选型与架构设计2.1 为什么是 SpringBoot 而不是 SSM 或 SSH现在做 Java 毕设SpringBoot 基本是默认答案了。原因有三第一SpringBoot 的自动配置和约定优于配置理念让项目的启动和维护成本大幅降低你不用再像 SSM 时代那样写一堆 XML第二当前企业招聘描述里 SpringBoot 是高频词写进简历和论文里的技术栈对口度直接关系到答辩老师的观感第三SpringBoot 生态成熟集成 MyBatis、Redis、Spring Security 等都是一把梭。但我要提醒一点用 SpringBoot 不等于不用理解 Spring 原理。答辩时老师大概率会问“SpringBoot 的自动配置原理是什么”“Spring IOC 和 AOP 在项目里怎么体现的”这些还是得提前准备。我在后面的答辩问题部分会展开说。可能有人会问热点词里还有“SpringBoot整合Flink”、“SpringBoot整合ActiveMQ”这类组合项目里要不要加我的建议是除非你论文的核心创新点就是流处理或消息队列否则不要为了追求“冷门组合”而硬接中间件。Flink 在充电系统里其实有真实的应用场景比如对充电行为日志做实时统计但如果你对 Flink 不熟接入后只会增加部署复杂度和答辨风险。2.2 后端技术组合与版本选择这是我的推荐组合也是网上流传度最高的一套搭配稳定性经过大量项目验证基础框架SpringBoot 2.7.xORM框架MyBatis-Plus 3.5.x数据库MySQL 8.0缓存Spring Data Redis Spring Cache安全认证JWTjjwt 0.9.1 / hutool-jwt工具库Hutool、Lombok、MapStruct接口文档Knife4jswagger-bootstrap-ui的增强版SpringBoot 版本这里要特别说一句。现在启动项目时选择初始版本很多人会直接拉到 3.x 甚至 4.x。SpringBoot 3.x 基于 SpringFramework 6 和 JDK 17整体没问题但问题出在配套生态上——早期 3.x 版本对 MyBatis-Plus、Knife4j 等还是基于 javax 命名空间而 3.x 改成了 jakarta如果你用了老版本的依赖会出现 “程序包 javax.servlet 不存在” 之类的报错。毕设阶段求稳我建议直接用 2.7.18这是 2.x 系列的最终版本后续如果要升级再按官方迁移指南走。2.3 前端方案Vue 全家桶还是服务端渲染如果前端基础一般我建议使用 Vue2 Element UI 的组合。原因很直白Element UI 的中文文档完善表格、表单、弹窗、分页这些后台系统常用组件都是现成的改造成本低Vue2 Element UI 的案例数量和网上踩坑贴最多遇到问题基本都有解。考虑到毕设时间紧我还见过一个更省事的方案管理端直接用 Vue Element UI 的后台模板改比如若依RuoYi、vue-element-admin把登录逻辑和业务页面改造一下整体出图效率极高。但这里有一个值得注意的问题——直接拿若依系统接 SpringBoot 后端论文里如果大篇幅写“使用了若依脚手架”答辩时容易被追问底层框架逻辑。我的建议是用模板可以但核心业务代码充电流程、订单状态机、计费逻辑必须自己写论文里也只体现自己写的部分。用户端的话可以用 Vant UI移动端Vue组件库做H5页面也可以用平板适配的后台响应式页面。我的做法是用户端和管理端共用一套 SpringBoot 后端 API前端独立部署通过 Nginx 或直接前后端分离开发。2.4 系统整体架构与项目分包从架构图上看这里用文字描述请求先到 SpringBoot 控制层通过 Service 层调用业务逻辑数据访问由 MyBatis-Plus 的 Mapper 完成跨模块的通用能力用 Redis 和工具类解决。安全层面用 JWT 拦截器做登录校验权限用简单的 RBAC角色-菜单/权限表实现。后端项目分包我会这样组织com.example.charging ├── controller # 接口层 ├── service # 业务接口 ├── service.impl # 业务实现 ├── mapper # MyBatis-Plus Mapper ├── entity # 数据库实体 ├── dto # 数据传输对象 ├── vo # 视图对象返回前端 ├── config # 配置类Redis、拦截器、CORS ├── common # 通用类Result、异常处理、常量 ├── utils # 工具类 ├── aspect # AOP切面 └── ChargingApplication.java不少同学喜欢把所有逻辑堆在 controller 里三五百行的接口方法看着就头疼。我的经验是controller 层只做参数接收和结果返回业务逻辑全部下沉到 service事务注解加在 service 方法上。这样做的直接好处有三层代码可读性大幅提升、事务边界清晰可控、答辩时你能很自然地讲清楚分层职责而不是被追问时支支吾吾。3. 数据库设计充电业务的基础底座3.1 核心表结构总览数据库设计是整个系统的地基地基不稳上层直接塌。我列一下核心表你们感受一下规模用户表、充电桩点位表、充电桩表一个点位多个充电桩、充电订单表、预约记录表、钱包表、钱包流水表、评论表、管理员表、角色表、菜单权限表。下面挑几张最容易踩坑的表细说。3.2 充电桩与充电订单表的设计要点充电桩表是“状态表”一定要有冗余的状态字段和实时信息字段CREATE TABLE charging_pile ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键, pile_code VARCHAR(32) NOT NULL COMMENT 充电桩编号, station_id BIGINT NOT NULL COMMENT 所属电站ID, type TINYINT NOT NULL DEFAULT 1 COMMENT 枪类型 1-慢充 2-快充, status TINYINT NOT NULL DEFAULT 0 COMMENT 状态 0-空闲 1-充电中 2-预约占用 3-故障, power DECIMAL(10, 2) DEFAULT NULL COMMENT 实时功率kW, voltage DECIMAL(10, 2) DEFAULT NULL COMMENT 实时电压V, electric_quantity DECIMAL(10, 2) DEFAULT NULL COMMENT 实时电量kWh, is_deleted TINYINT NOT NULL DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_pile_code (pile_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT充电桩表;这里有个经验之谈状态字段用 tinyint 而不是字符串枚举前端通过数据字典映射显示文案。原因不只是省空间字符串对比和数字对比在索引命中和查询效率上差距明显这在论文中也可以当成优化点来写。充电订单表是核心核心字段要比你们想象的“宽”。我强烈建议加上settlement_status结算状态和refund_status退款状态这类冗余字段和充电主流程解耦CREATE TABLE charging_order ( id BIGINT NOT NULL AUTO_INCREMENT, order_no VARCHAR(64) NOT NULL COMMENT 订单号, user_id BIGINT NOT NULL COMMENT 用户ID, pile_id BIGINT NOT NULL COMMENT 充电桩ID, station_id BIGINT NOT NULL, start_time DATETIME NOT NULL COMMENT 充电开始, end_time DATETIME DEFAULT NULL COMMENT 充电结束, duration_minutes INT DEFAULT 0 COMMENT 充电时长分钟, total_power DECIMAL(10, 2) DEFAULT 0 COMMENT 充电电量kWh, start_soc INT DEFAULT NULL COMMENT 起始电量百分比, end_soc INT DEFAULT NULL COMMENT 结束电量百分比, price_per_kwh DECIMAL(10, 4) COMMENT 单价, service_fee_per_kwh DECIMAL(10, 4) COMMENT 服务费单价, amount DECIMAL(10, 2) COMMENT 订单金额, status TINYINT DEFAULT 0 COMMENT 0-充电中 1-已完成 2-已取消 3-退款中 4-已退款, is_deleted TINYINT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_user_id (user_id), KEY idx_pile_id (pile_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT充电订单表;**金额字段一定用 DECIMAL不要用 DOUBLE。**这是一个非常经典的坑。DOUBLE 是浮点数0.1 0.2 的结果会让你在日常调账单的时候怀疑人生。DECIMAL(10, 2) 在260万以内的金额都能存下拿来存充电订单绰绰有余。3.3 预约表与钱包表两个容易被忽略的表预约表要解决的核心问题是“桩被占着但人没来”。我的做法是加一个过期时间用户在预约成功后获得一个锁定时间窗口比如15分钟超过时间窗口预约自动过期桩状态从“预约占用”回到“空闲”。这里用 Redis 做定时失效管理比较方便也可以每天跑一个定时任务扫表。预约表里还需要一个字段记录预约状态待履约、已完成、已过期、已取消这会直接决定用户信用记录。钱包表的设计更要注意因为涉及资金逻辑。不要把充值金额和消费金额只放在钱包表里就完事流水表才是保证资金对账清晰的基础。每个充值和消费动作既要更新钱包表里的余额也要在流水表里insert一条记录。流水表字段建议包括流水号、用户ID、类型1-充值 2-消费 3-退款、变动金额正负、变动前余额、变动后余额、关联订单号、创建时间。变动前/后的余额这两个字段是这个表设计的灵魂日后如果用户说自己余额不对翻流水的对账效率能提升十倍。3.4 表关系与核心查询设计用户表与订单、钱包表是一对多关系电站表和充电桩表是一对多订单表关联用户和充电桩管理员和角色直接关联即可。查询层面我提两个建议。第一充电桩列表页的状态查询一次 join 就能解决不需要搞得太复杂第二后台管理端的订单列表必然有“按时间区间”“按状态”“按桩号”多条件组合查询的场景这里用 MyBatis-Plus 的 Wrapper 条件构造器拼条件即可但要注意时间字段边界问题比如查某一天的数据包含当天0点到23点59分59秒不要只查 0 点导致漏数据。4. 核心功能实现与关键代码解析4.1 用户端扫码充电主流程的实现用户端最核心的一个接口就是“用户发起充电”的接口。它是典型的写多表的事务操作检查桩的状态、校验余额、更新桩状态、生成订单、扣减预扣款或者不预扣、创建流水。Transactional(rollbackFor Exception.class) public ResultChargingOrderVO startCharging(StartChargingDTO dto) { // 1. 校验充电桩状态 ChargingPile pile pileMapper.selectById(dto.getPileId()); if (pile null || pile.getStatus() ! 0) { throw new BizException(充电桩不存在或不可用); } // 2. 校验用户钱包余额余额低于阈值拒绝启动 UserWallet wallet walletMapper.selectByUserId(dto.getUserId()); if (wallet null || wallet.getBalance().compareTo(BigDecimal.valueOf(10)) 0) { throw new BizException(余额不足请先充值); } // 3. 更新桩状态为充电中 pile.setStatus(1); pileMapper.updateById(pile); // 4. 创建订单 ChargingOrder order new ChargingOrder(); order.setOrderNo(OrderNoGenerator.generate()); order.setUserId(dto.getUserId()); order.setPileId(pile.getId()); order.setStatus(0); order.setStartTime(new Date()); orderMapper.insert(order); // 5. 生成充电启动记录记录起始电量和金额 return Result.success(chargingOrderVO); }这段代码的逻辑并不复杂复杂度全部藏在Transactional里。事务保证了更新桩状态和生成订单要么全部成功要么全部失败避免出现“桩显示充电中但订单没建”的业务脏数据。事务注解是必备的但要注意自调用问题——同一个类内部的startCharging调另一个方法事务会失效。我当时就踩过这个坑排查半天才意识到是事务自调用导致回滚没生效。4.2 充电中监控轮询还是 WebSocket充电过程中端上需要实时显示“当前电量、电压、功率、已用时长、实时金额”。实现方式有两种方式一前端定时轮询GET /api/pile/currentStatus?pileIdxxx接口比如每3秒请求一次。简单可靠无需维护连接但会带来无效请求。方式二后端用 WebSocket 推送充电状态。SpringBoot 里用 Spring WebSocket 模块就能实现每个用户建立连接后后端通过会话推送充电数据但要做心跳检测和断线重连。对于毕设来说轮询完全够用且实现成本最低。你可以在前端写一个 setInterval 定时器每23秒调一次实时状态接口用 setTimeout 递归代替 setInterval 可以避免重叠请求的问题如果上一次请求还没返回就发起下一次调用。我在项目里就是轮询方案加了一个“接口返回异常时自动停止轮询”的保护逻辑最后在论文的“系统优化与改进”里把“后续可接入WebSocket”写成预期扩展反而多了一个亮点。4.3 管理端充电桩管理模块的实现思路管理端的核心是运营效率不是简单增删改查。我的充电桩管理页面包含搜索筛选区电站、状态、类型、桩编号关键字、表格区桩码、类型、状态、实时数据、创建时间、操作按钮、新增/编辑弹窗绑定电站、填写功率类型。这里有个细节桩的“状态”修改不能直接改数据库字段。例如一个正在充电中的桩管理员如果强行改成“空闲”会造成订单和桩状态不一致。我的实现是在管理端只允许维护“故障/维护”状态充电中和空闲的切换只能由用户充电流程触发这就是职责分离的体现答辩的时候可以主动提这个设计考量。4.4 JWT认证与权限控制的落地登录注册环节我建议用 JWT 而不是传统的 Session。原因很简单前后端分离架构下Session 需要处理跨域携带 Cookie、集群共享 Session 等一堆问题JWT 自包含用户信息无状态分布式友好并且和现在企业项目的使用习惯一致。JWT 的核心流程用户登录 - 后端验证账号密码 - 生成 token 返回前端 - 前端后续请求在 Header 里带Authorization: Bearer token- 后端拦截器验签解析用户信息 - 放行或拒绝。拦截器配置有一个细节很容易写错Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns(/**) .excludePathPatterns( /api/user/login, /api/user/register, /api/pile/list, /api/pile/detail, /doc.html, /webjars/**, /v3/api-docs/** ); }注意放行的路径要包含接口文档相关的路径否则你调试接口的时候登录都登录不了。权限控制我用的是 RBAC 的最简实现管理员表里存 role超级管理员/运营人员拦截器里校验角色如果是运营人员对用户管理等敏感接口做拒绝处理。完整版的 RBAC用户-角色-权限点适合放在加分项里。4.5 计费逻辑核心业务参数的拆分计费逻辑是答辩老师最容易深挖的地方值得认真设计。我把费用拆成两部分基础电费单价 服务费单价。日间和夜间单价可以不同峰谷电价这个在系统中我使用电价策略表来管理。核心公式如下订单总金额 SUM(每个时间段充电电量 × 对应单价) 服务费最常见也最好实现的是阶梯价/分时计费模式。我在系统里定义了 PriceStrategy 表CREATE TABLE price_strategy ( id BIGINT PRIMARY KEY, type TINYINT COMMENT 1-基础电费 2-服务费, name VARCHAR(32) COMMENT 时段名称如尖峰、平段、谷段, start_time VARCHAR(8) COMMENT 开始时间 08:00, end_time VARCHAR(8) COMMENT 结束时间 12:00, price DECIMAL(10,4) COMMENT 单价元/度, is_active TINYINT DEFAULT 1 ) COMMENT电价时段策略表;结算的时候根据充电开始时间和结束时间逐段计算每个电价时段的电量。如果只用总电量乘以单一电价省事但在论文里体现不出业务深度。建议一定要做分时计费哪怕只做“尖峰平谷四个时段”答辩差距一眼就能看出来。4.6 定时任务与订单超时处理用户发起充电后如果一直没有上传结束信息我需要一个兜底机制自动把状态改为“充电完成”或“异常结束”。我用 Spring 的Scheduled注解来定时扫描“充电中”的订单判断其持续时间是否超过阈值若超过比如6小时则自动标记为结束并执行结算退费。Scheduled(cron 0 */5 * * * ?) public void autoFinishTimeoutCharging() { ListChargingOrder timeoutOrders orderMapper.selectTimeoutChargingOrders(360); for (ChargingOrder order : timeoutOrders) { // 执行结束充电逻辑计算电量、金额、更新订单状态、恢复桩状态 finishCharging(order, true); } }这种定时任务在论文里是一个加分亮点因为体现了你考虑了“异常边界情况”而不是只写了理想主流程。但注意了由于单机定时任务在部署多个副本时会重复执行可以在调度逻辑里通过 Redis 分布式锁做幂等保护。毕设阶段跑单实例不用处理但要在论文中提一下“生产环境可以引入XXL-Job或Redis锁”。5. 实操部署与本地跑通流程5.1 环境准备与初始化开发这个项目需要的软件清单JDK 8 或 11、Maven 3.6、MySQL 8.0、Redis 6.x、Node.js 14、IDEA 2023。初始化项目我建议直接用 IDEA 的 Spring Initializr 创建勾选 Web、MySQL、Redis 相关依赖再用 MyBatis-Plus 官网的 starter 手动引入 MyBatis-Plus。这样做的好处是初始依赖干净、版本可控不会出现一些课程项目里视版本混乱。项目创建后第一时间做三件事配置application.yml里的数据源和 Redis 连接写一个/api/ping接口测试启动在数据库执行建表 SQL。先把地基打稳再开发功能很多同学上来就写业务结果数据库没连上排查半天浪费时间。5.2 本地联调的关键配置前后端联调阶段最烦的就是跨域问题。SpringBoot 里统一配置跨域即可Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }注意allowedOriginPatterns在 SpringBoot 2.4 之后替代了allowedOrigins(*)目的是兼容 allowCredentials(true) 的情况。如果你跟着老教程写可能直接报 “When allowCredentials is true, allowedOrigins cannot be specified with *”。接口文档我用 Knife4j 生成访问/doc.html就能看到所有接口前端同学和我对接的时候就靠它省了大量的沟通成本。这也是一个非常推荐的实践所有有前后端分离的项目都应该引入接口文档这不是加分项是必要项。5.3 打包部署与演示环境演示的时候最怕环境不一致导致白屏、请求失败。我的经验是提前一周就准备好两个环境一个本地开发环境、一个演示环境。演示环境可以是虚拟机里装一套 Docker也可以是一台云服务器。SpringBoot 打包mvn clean package -DskipTests java -jar charging-manager-1.0.0.jar --spring.profiles.activeprod前端打包后 可以用 Nginx 部署注意一个最常见的坑Vue 打包后vue-router如果不是用的 Hash 模式刷新页面会 404。要么改用 Hash 模式路由要么在 Nginx 里配置 try_fileslocation / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; }这个坑几乎每周都能在网上看到有人问提前配置好能减少演示事故。6. 常见问题与排查技巧实录6.1 启动类问题速查表问题现象原因解决办法Failed to configure a DataSource数据源配置缺失或连接串错误检查application.yml的 url/username/password确认 MySQL 已启动ClassNotFound: javax.xml.bind.JAXBExceptionJDK 版本过高javax.xml 模块被移除使用 JDK 8/11或引入javax.xml.bind依赖端口被占用本地 8080 被其他进程占用更换server.port或lsof -i:8080查杀进程MyBatis-Plus实体映射不上表名或字段名驼峰不一致确认map-underscore-to-camel-case: true或TableName注解这里最常遇到的是第一个。很多同学把application.yml里的数据库密码写错或者数据库名写错启动时控制台直接报错。建议把url里加useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8不然会出现时区问题或者 SSL 握手告警。6.2 SpringBoot 版本不一致引发的依赖冲突热点词里有一条“springboot版本太高”我深有体会。有次帮学弟调项目他的 SpringBoot 是 3.2.xMyBatis-Plus 用的还是 3.5.3 版本编译报错报得让人怀疑人生。原因是 MyBatis-Plus 3.5.3 依赖了mybatis-spring2.x它对 Boot 3.x 的自动配置机制不兼容。解决有三个思路一是把 SpringBoot 降到 2.7.x二是把 MyBatis-Plus 升到 3.5.5适配 jakarta 命名空间三是用mybatis-plus-spring-boot3-starter这个专用 starter。毕设建议直接走方案一省事。6.3 前端联调的经典错误接口 404检查 controller 的 RequestMapping 路径是否和前端请求一致尤其注意项目有没有配置server.servlet.context-path。接口 500打开后端控制台看详细堆栈大部分是空指针、SQL 错误、参数绑定失败。登录后请求返回 401检查 token 是否放到了 Header拦截器是否把该接口放行。前端请求跨域报错确认后端 CORS 配置是否覆盖了该路径确认是否使用了正确的前端代理。我印象最深的一次排错前端一直报 401排查发现是 token 里保存的用户 ID 是字符串后端拦截器解析出来变成数字而用户 ID 在数据库中正好有前缀零比如“000123”解析后变成了123导致查询用户失败。这就是典型的“类型不一致导致看似权限问题实际是业务问题”的场景。所以拦截器里解析 token 之后一定要做一次用户真实验证而不是盲目信任 token 里的数据。6.4 答辩高频问题与应答思路根据过往经验答辩老师对这类系统最常问的问题如下SpringBoot 自动配置原理是什么答SpringBootApplication组合了SpringBootConfiguration、EnableAutoConfiguration、ComponentScan其中EnableAutoConfiguration通过AutoConfigurationImportSelector加载META-INF/spring/...ImportSelector里注册的自动配置类再根据条件注解ConditionalOnClass、ConditionalOnMissingBean等判断是否生效。表的设计为什么这样分答按业务聚合拆分避免单表字段过多和与主流程无关的冗余订单和流水分离便于对账。并发场景如何解决答核心是悲观锁和数据库唯一约束。充电订单号唯一索引防止重复修改桩状态可以用UPDATE charging_pile SET status1 WHERE id? AND status0的乐观/条件更新方式避免两个用户同时抢到同一个空闲桩。JWT 和 Session 的区别答Session 存在服务端靠 Cookie 关联JWT 存在客户端服务端无状态靠签名防篡改。JWT 更适合分布式系统但无法主动失效过期时间要控制合理。项目里的难点和亮点答难点是充电桩状态一致性、分时计费和订单异常闭环亮点是引入了 JWT 统一鉴权、定时任务自动兜底、资金流水可追溯。6.5 毕设避坑心得最后分享几个坑过无数人的心得都是网上教程不会写但你大概率会踩的第一不要上来就敲代码。先花两天把需求文档、ER 图、接口文档画好后面开发速度快十倍。我做这个充电系统前期设计花了整整一周真正编码也就三周。第二预留足够的测试时间。很多人前六周拼命写代码最后两天才开始跑通流程结果演示现场漏电、充不上电、订单金额不对全翻车。至少留一周做全流程回归测试注册、登录、充值、扫码充电、结算、退款每个环节都要人工跑两遍。第三要留一手“心机设计”。比如给充电订单加一个“充电历史趋势图”这样的统计分析功能成本很低但答辩的时候非常有画面感。论文里也可以借此多写一节既撑了字数又亮了技术点。我自己的体会是做毕设真正的收获不在系统本身而在“把一个模糊的业务需求变成一套清晰可运行的系统”这个过程。充电系统这个选题非常适合拿来练手它的复杂度刚好在一个本科生的能力边界——有挑战但踮脚能够着做完了你会对 SpringBoot 整个生态有非常扎实的掌握。后面还可以在这个基础上扩展多电站管理、充电预约分时定价、App 扫码整个项目甚至能变成一个真正可运营的产品雏形。
阅读完成 · 觉得有帮助?
咨询建站