AI 辅助开发实战:基于 Spring Boot 的租车系统毕设架构优化与代码生成
最近在帮学弟学妹们看毕业设计,发现很多基于 Spring Boot 的租车系统项目,虽然功能基本都能跑通,但代码质量实在是一言难尽。最常见的几个问题就是:Controller 里塞满了业务逻辑、Service 层全是重复的 CRUD、下单接口不加锁导致超卖、接口重复提交也没做防护。这些问题不仅影响系统稳定性,在答辩时也容易被老师问住。
正好我自己也在尝试用一些 AI 辅助编码工具,比如 GitHub Copilot 和通义灵码,来提升日常开发效率。我就想,能不能把这些工具用到毕业设计里,既快速完成功能,又能保证代码有一定的质量?经过一番实践,效果出乎意料的好。下面我就以“车辆预订”这个核心模块为例,分享一下如何用 AI 辅助,高效、高质量地完成一个 Spring Boot 租车系统。

1. 从痛点出发:传统手写代码的“坑”
在开始之前,我们先明确一下手动开发这类系统时常见的痛点,这也是我们引入 AI 辅助想要解决的问题:
- 重复的 CRUD 编码:租车系统离不开用户、车辆、订单、支付等实体,每个实体的增删改查(CRUD)代码结构高度相似。手动编写不仅枯燥,还容易因复制粘贴引入低级错误,比如字段名没改、条件判断遗漏。
- 模糊的事务边界:像“下单”这种操作,通常涉及检查车辆状态、扣减库存(或标记为已预订)、生成订单、初始化支付流水等多个步骤。手动管理
@Transactional注解的范围和回滚条件,对新手来说容易出错,可能导致数据不一致。 - 缺失的接口幂等性:网络波动或用户重复点击,可能导致同一个下单请求被提交多次。如果没有防重机制(如 Token 机制或唯一键约束),就会产生重复订单,这是业务上不允许的。
- 并发安全忽视:热门车辆在促销时可能被多人同时预订。如果只是简单查询
status=0(可租)然后更新,在高并发下极有可能发生超订(一辆车被租给多个人)。
2. 技术选型:AI 辅助 vs. 传统手写
为了解决上述痛点,我对比了两种开发模式在几个关键环节的效率:
-
实体与 CRUD 代码生成:
- 传统手写:需要手动创建 Entity、Mapper、Service、Controller 等类,逐个编写字段和方法。一个简单的实体全套下来,熟练工也要 10-15 分钟。
- AI 辅助:在 IDEA 中安装 Copilot 或通义灵码后,你只需要先创建好数据库表,或者写好 Entity 类的字段。然后,在 Mapper 接口文件中,你只需输入
// 根据车辆ID查询这样的注释,AI 就会自动补全Car selectById(Long id);方法。更进一步,你可以在 Service 接口里写// 分页查询可用车辆,AI 能帮你生成包含分页参数和条件查询的方法签名,甚至自动在对应的 ServiceImpl 和 Controller 中生成骨架代码。效率提升超过 60%。
-
DTO 与 VO 转换:
- 传统手写:需要手动创建
CarDTO、CarVO等类,并在 Service 或 Controller 里写BeanUtils.copyProperties或大量的setter代码进行转换,容易遗漏字段。 - AI 辅助:你可以写一个注释:
// 将Car实体转换为CarResponseVO,然后开始写public CarResponseVO convertToVo(Car car) {,AI 会自动补全方法体,将car的各个字段赋值给vo对象,非常准确。对于复杂的多表关联查询结果转换,AI 也能根据上下文给出不错的建议。
- 传统手写:需要手动创建
-
异常处理与事务注解:
- 传统手写:容易忘记在 Service 方法上加
@Transactional,或者在 Controller 里做事务操作。异常处理也常常是简单的try-catch打印日志,没有统一的全局异常处理机制。 - AI 辅助:当你写一个
public Order createOrder(OrderRequest request)方法时,AI 可能会提示你加上@Transactional(rollbackFor = Exception.class)。如果你在方法内抛出了一个自定义的BusinessException,AI 也能识别出这是需要回滚的业务异常。你可以利用 AI 快速生成全局异常处理器 (@ControllerAdvice) 的代码框架。
- 传统手写:容易忘记在 Service 方法上加
3. 核心实现:AI 助力构建健壮的预订模块
我们以最核心的“车辆预订”接口为例,展示如何结合 Spring Boot、MyBatis-Plus、Redis 和 AI 工具来完成开发。
技术栈:Spring Boot 2.7 + MyBatis-Plus + Redis (Redisson客户端) + JWT
第一步:利用 AI 生成基础实体和 Mapper 首先,创建车辆 (Car) 和订单 (Order) 实体。你只需定义关键字段(如 carId, model, status, stock 等),AI 会提示你加上 @TableName, @TableId 等 MyBatis-Plus 注解。对于 BaseMapper<Car>,AI 能自动补全所有通用 CRUD 方法,无需手写 XML。
第二步:设计并生成 Service 层代码(关键) 在 OrderService 接口中,我们定义下单方法:
/**
* 创建车辆租赁订单
* @param request 订单请求,包含车辆ID、租期等信息
* @return 订单ID
*/
Long createRentalOrder(OrderCreateRequest request);
然后,在 OrderServiceImpl 中实现这个方法。这里是我们需要 AI 重点辅助的地方。我们可以先写出方法签名和基本的注释,然后让 AI 帮我们填充核心逻辑。一个经过优化的、考虑并发和幂等的实现骨架如下:
@Override
@Transactional(rollbackFor = Exception.class) // AI 常能自动建议加上事务注解
public Long createRentalOrder(OrderCreateRequest request) {
// 1. 参数基础校验 (AI 可生成非空、范围等校验代码)
if (request.getCarId() == null || request.getRentalDays() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// 2. 幂等性控制:基于请求唯一标识(如前端传来的orderToken)查询Redis
String orderToken = request.getOrderToken();
if (StringUtils.isNotBlank(orderToken)) {
String key = "order:token:" + orderToken;
// AI 可能生成 redisTemplate.opsForValue().get(key) 的代码
if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
throw new BusinessException(ErrorCode.REPEATED_REQUEST);
}
}
// 3. 防超订:使用 Redisson 分布式锁锁定具体车辆资源
String lockKey = "car:lock:" + request.getCarId();
RLock lock = redissonClient.getLock(lockKey);
try {
// 尝试加锁,最多等待3秒,锁持有10秒自动释放以防死锁
boolean isLocked = lock.tryLock(3, 10, TimeUnit.SECONDS);
if (!isLocked) {
throw new BusinessException(ErrorCode.SYSTEM_BUSY);
}
// 4. 在锁内查询车辆状态与库存(防止并发下的脏读)
Car car = carService.getById(request.getCarId());
if (car == null || car.getStatus() != CarStatus.AVAILABLE.getCode()) {
throw new BusinessException(ErrorCode.CAR_NOT_AVAILABLE);
}
// 假设库存字段为 availableStock
if (car.getAvailableStock() < 1) {
throw new BusinessException(ErrorCode.CAR_STOCK_NOT_ENOUGH);
}
// 5. 扣减库存(乐观锁版本号更新,AI 可能生成 updateById 但需要你引导用 updateWrapper 带版本条件)
boolean updateSuccess = carService.lambdaUpdate()
.eq(Car::getId, car.getId())
.eq(Car::getVersion, car.getVersion()) // 版本号条件
.set(Car::getAvailableStock, car.getAvailableStock() - 1)
.set(Car::getVersion, car.getVersion() + 1)
.update();
if (!updateSuccess) {
// 乐观锁更新失败,说明数据已被其他线程修改,可重试或直接抛异常
throw new BusinessException(ErrorCode.OPERATION_FAILED);
}
// 6. 生成订单实体并保存
Order order = new Order();
// AI 可以帮助完成属性映射,如 order.setUserId(UserContext.getCurrentUserId());
order.setCarId(request.getCarId());
order.setOrderNo(IdUtil.generateOrderNo()); // 生成唯一订单号
order.setStatus(OrderStatus.UNPAID.getCode());
// ... 设置其他字段
orderMapper.insert(order);
// 7. 幂等Token写入Redis,设置过期时间(如5分钟)
if (StringUtils.isNotBlank(orderToken)) {
redisTemplate.opsForValue().set("order:token:" + orderToken, "1", 5, TimeUnit.MINUTES);
}
return order.getId();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new BusinessException(ErrorCode.SYSTEM_ERROR);
} finally {
// 8. 无论如何,最终释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
AI 在生成上述代码时,能极大地减少你编写样板代码的时间,如 Redis 操作、异常捕获、锁的获取与释放模板。你需要做的是提供清晰的注释引导,并在生成后检查关键逻辑(如乐观锁更新、异常处理是否合理)。

4. 性能与安全考量
-
压力测试 (QPS):使用 JMeter 对优化后的下单接口进行压测。在配置了 Redis 防重和分布式锁之后,相较于无防护的版本,系统在防止超订和重复订单方面达到了 100% 的准确率。由于锁的引入,吞吐量 (QPS) 会有所下降,但通过缩小锁粒度(只锁具体车辆ID)和控制锁等待时间,在单机环境下仍能保持数百 QPS,完全满足毕业设计答辩的演示需求。可以将压测结果(如:无防护下出现超卖,有防护后零错误)做成图表,是答辩的亮点。
-
JWT 鉴权与 Token 刷新:使用
jjwt库实现 JWT。AI 可以帮助生成JwtUtil工具类,包含生成 Token、解析 Token、刷新 Token 等方法。关键点是设计刷新机制:在 Token 即将过期时,前端携带旧 Token 调用刷新接口,后端验证后签发新 Token。AI 可以辅助生成刷新接口的逻辑,注意需要将旧 Token 加入短期的黑名单(存 Redis),防止同一 Token 被多次刷新。 -
SQL 注入防护:坚持使用 MyBatis-Plus 的 Lambda 查询或明确的
@Param注解,AI 生成的 SQL 片段也会基于这些安全的写法,从根本上避免拼接字符串导致的 SQL 注入问题。
5. 生产环境避坑:AI 生成代码的“质检”
AI 不是万能的,它生成的代码需要经过严格的人工 Review 和测试:
-
N+1 查询问题:AI 在生成关联查询时,可能会写出在循环中查询数据库的代码。例如,查询一个订单列表,然后在循环里根据每个订单的
carId去查车辆信息。你需要识别出这种情况,并引导 AI 或手动修改为使用 MyBatis-Plus 的@TableField关联查询或者手动编写连表 SQL,一次性查出所有数据。 -
空指针未校验:AI 生成的代码有时会假设对象不为空。例如,
car.getModel().getName(),如果car或getModel()可能为 null,这里就会 NPE。你必须对关键的链式调用进行空指针判断,或者使用 Optional 进行包装。 -
事务传播行为不当:AI 可能会在不需要事务的方法上也加上
@Transactional,或者传播行为使用不当。你需要根据业务逻辑,仔细检查每个@Transactional注解的propagation属性是否合理。 -
异常处理过于宽泛:AI 可能生成
catch (Exception e)然后只打印日志,这可能会“吃掉”重要的业务异常,导致事务不回滚。需要确保业务异常被抛出,或者进行恰当的处理。
人工 Review 流程建议:
- 功能正确性:对照需求,走查核心逻辑分支。
- 数据一致性:检查事务边界和锁的使用是否合理。
- 性能:检查是否有循环查询、大对象序列化等潜在性能瓶颈。
- 安全:检查输入校验、权限校验、敏感信息是否脱敏。
- 代码风格:虽然 AI 生成的代码风格通常不错,但仍需统一团队规范(如命名、注释)。
6. 总结与思考
通过将 AI 辅助工具引入 Spring Boot 租车毕设的开发,我个人的体验是:在熟悉了工具的使用模式后,编码效率的提升是实实在在的,尤其是在搭建项目骨架、编写重复的 CRUD 和模板代码时,估计能节省 40%-50% 的时间。更重要的是,AI 能基于海量开源代码,提供一些“最佳实践”的代码片段,比如分布式锁的写法、事务注解的放置,这对初学者理解这些概念很有帮助。
给你的建议:不妨选择你毕设中的一个模块(比如“用户管理”或“车辆信息管理”),尝试用 GitHub Copilot 或通义灵码从头开始重构。感受一下 AI 如何响应你的注释,如何补全代码。完成后,对比一下手写版本和 AI 辅助版本在代码结构、异常处理、注释完整性上的区别。
最后,留一个思考题:“AI 生成代码的责任边界在哪里?” 当代码出现 Bug 甚至安全漏洞时,责任在于提示词不清晰的开发者,还是在于生成代码的 AI?我的看法是,AI 是强大的“副驾驶”,但“驾驶员”始终是我们自己。我们对最终代码的质量、安全性和业务正确性负有全部责任。AI 提高了我们驾驶(编码)的速度和舒适度,但路线规划(架构设计)和交通规则(代码规范)仍需我们牢牢掌握。用好 AI,让它成为你完成优秀毕业设计的得力助手。
更多推荐



所有评论(0)