1. 项目背景与需求分析
校园电动车短租系统是近年来高校智慧校园建设中的新兴需求。随着校园面积不断扩大,师生日常通勤距离增加,电动车成为校园内高效便捷的代步工具。但电动车购置成本高、维护麻烦,使得短时租赁需求日益凸显。
传统租赁方式存在诸多痛点:
- 人工登记效率低下,高峰期排队时间长
- 车辆状态无法实时监控,调度困难
- 租金结算不透明,易产生纠纷
- 用户身份核验流程繁琐
我们设计的这套基于SpringBoot+Vue的Web系统,主要解决以下核心问题:
- 实现电动车资源的可视化管理和智能调度
- 提供便捷的在线预约和支付功能
- 建立完善的用户信用评价体系
- 通过物联网技术实现车辆状态实时监控
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体技术栈选型
后端技术栈:
- SpringBoot 2.7.x:提供快速开发框架和自动配置
- MyBatis-Plus:简化数据库操作
- Redis:处理高并发场景下的缓存和会话管理
- RabbitMQ:异步处理订单消息
- MinIO:对象存储服务,用于存放车辆图片等资源
前端技术栈:
- Vue 3.x:采用Composition API编写组件
- Element Plus:UI组件库
- Axios:处理HTTP请求
- ECharts:数据可视化展示
- Vue Router:前端路由管理
数据库设计:
sql复制CREATE TABLE `vehicle` (
`id` bigint NOT NULL AUTO_INCREMENT,
`plate_number` varchar(20) NOT NULL COMMENT '车牌号',
`battery_level` int DEFAULT '100' COMMENT '电量百分比',
`status` tinyint DEFAULT '0' COMMENT '0-空闲 1-使用中 2-维修中',
`location` varchar(255) DEFAULT NULL COMMENT '当前GPS位置',
`type_id` int DEFAULT NULL COMMENT '车型ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `rental_order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL COMMENT '订单编号',
`user_id` bigint NOT NULL,
`vehicle_id` bigint NOT NULL,
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`actual_end_time` datetime DEFAULT NULL COMMENT '实际还车时间',
`total_amount` decimal(10,2) DEFAULT NULL COMMENT '订单总金额',
`status` tinyint DEFAULT '0' COMMENT '0-待支付 1-已支付 2-使用中 3-已完成 4-已取消',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 系统模块划分
-
用户服务模块
- 学生/教职工身份认证(对接学校统一认证)
- 信用积分管理
- 押金缴纳与退还
-
车辆管理模块
- 车辆信息维护
- 实时状态监控
- 维修保养记录
-
订单服务模块
- 预约下单
- 费用计算
- 订单状态流转
-
支付服务模块
- 微信/支付宝支付对接
- 账单生成
- 退款处理
-
调度服务模块
- 车辆位置追踪
- 供需预测
- 智能推荐停车点
3. 核心功能实现
3.1 车辆定位与状态同步
采用物联网技术实现车辆状态实时更新:
java复制// 车辆状态更新接口
@RestController
@RequestMapping("/api/vehicle")
public class VehicleController {
@Autowired
private VehicleService vehicleService;
@PostMapping("/status")
public Result updateStatus(@RequestBody VehicleStatusDTO dto) {
// 处理IoT设备上报的数据
vehicleService.updateStatus(dto);
return Result.success();
}
}
// 定时任务检查车辆状态
@Scheduled(cron = "0 */5 * * * ?")
public void checkVehicleStatus() {
List<Vehicle> vehicles = vehicleMapper.selectList(
new LambdaQueryWrapper<Vehicle>()
.eq(Vehicle::getStatus, 1));
vehicles.forEach(v -> {
if (v.getBatteryLevel() < 15) {
notifyUser(v.getCurrentUserId(), "电量不足提醒");
}
});
}
3.2 智能调度算法实现
基于校园地图和用车历史数据设计调度策略:
java复制public class SchedulingService {
public List<Vehicle> recommendVehicles(UserLocation userLoc) {
// 1. 获取用户周边500米内的可用车辆
List<Vehicle> available = vehicleMapper.selectAvailableNearby(
userLoc.getLongitude(),
userLoc.getLatitude(),
500);
// 2. 根据车型偏好筛选
if (userLoc.getPreferType() != null) {
available = available.stream()
.filter(v -> v.getTypeId().equals(userLoc.getPreferType()))
.collect(Collectors.toList());
}
// 3. 按距离排序并返回前5个结果
return available.stream()
.sorted(Comparator.comparingDouble(v ->
calculateDistance(userLoc, v.getLocation())))
.limit(5)
.collect(Collectors.toList());
}
private double calculateDistance(UserLocation loc1, String loc2) {
// 实现经纬度距离计算
}
}
3.3 订单状态机设计
使用状态模式管理订单生命周期:
java复制public interface OrderState {
void pay(Order order);
void cancel(Order order);
void use(Order order);
void complete(Order order);
}
@Component
public class UnpaidState implements OrderState {
@Override
public void pay(Order order) {
// 支付逻辑
order.setState(new PaidState());
}
@Override
public void cancel(Order order) {
// 取消逻辑
order.setState(new CancelledState());
}
}
// 在Order类中维护当前状态
public class Order {
private OrderState state;
public void pay() {
state.pay(this);
}
// 其他状态方法...
}
4. 前端关键实现
4.1 地图组件集成
使用高德地图API实现车辆位置展示:
vue复制<template>
<div class="map-container">
<el-amap
:zoom="zoom"
:center="center"
@init="initMap">
<el-amap-marker
v-for="vehicle in vehicles"
:key="vehicle.id"
:position="[vehicle.longitude, vehicle.latitude]"
@click="showVehicleInfo(vehicle)">
<template #content>
<div class="marker-content">
<img :src="getVehicleIcon(vehicle.type)" />
<span class="battery">{{ vehicle.battery }}%</span>
</div>
</template>
</el-amap-marker>
</el-amap>
</div>
</template>
<script setup>
import { ref } from 'vue';
const zoom = ref(16);
const center = ref([116.397428, 39.90923]);
const vehicles = ref([]);
const initMap = (map) => {
loadVehicles();
};
const loadVehicles = async () => {
const res = await axios.get('/api/vehicles/nearby');
vehicles.value = res.data;
};
</script>
4.2 订单流程状态管理
使用Pinia管理复杂的订单状态:
javascript复制// stores/order.js
export const useOrderStore = defineStore('order', {
state: () => ({
currentOrder: null,
historyOrders: []
}),
actions: {
async createOrder(vehicleId, startTime, duration) {
const res = await axios.post('/api/orders', {
vehicleId,
startTime,
duration
});
this.currentOrder = res.data;
},
async cancelOrder(orderId) {
await axios.put(`/api/orders/${orderId}/cancel`);
this.currentOrder = null;
}
}
});
// 在组件中使用
const orderStore = useOrderStore();
const handleCreateOrder = () => {
orderStore.createOrder(vehicle.value.id, date.value, hours.value)
.then(() => {
router.push('/order/detail');
});
};
5. 系统安全设计
5.1 认证与授权
采用JWT + RBAC实现细粒度权限控制:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/user/**").hasRole("USER")
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
}
// JWT工具类
public class JwtUtil {
private static final String SECRET = "your-secret-key";
private static final long EXPIRATION = 86400000L; // 24小时
public static String generateToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.claim("roles", user.getAuthorities())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public static boolean validateToken(String token) {
// 验证逻辑...
}
}
5.2 数据安全防护
- 敏感数据加密
java复制// 使用AES加密用户敏感信息
public class CryptoUtil {
private static final String KEY = "your-encryption-key";
public static String encrypt(String data) {
// AES加密实现
}
public static String decrypt(String encrypted) {
// AES解密实现
}
}
- SQL注入防护
- 使用MyBatis-Plus的Wrapper构建查询条件
- 对用户输入进行严格校验和转义
- XSS防护
- 前端使用DOMPurify对用户输入进行净化
- 后端对存储的内容进行HTML实体编码
6. 性能优化实践
6.1 缓存策略设计
- 多级缓存架构
java复制@Service
public class VehicleServiceImpl implements VehicleService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
@Cacheable(value = "vehicles", key = "#id")
public Vehicle getById(Long id) {
// 先查Redis,没有再查数据库
String key = "vehicle:" + id;
Vehicle vehicle = (Vehicle) redisTemplate.opsForValue().get(key);
if (vehicle == null) {
vehicle = vehicleMapper.selectById(id);
redisTemplate.opsForValue().set(key, vehicle, 30, TimeUnit.MINUTES);
}
return vehicle;
}
}
- 热点数据预加载
java复制@Scheduled(fixedRate = 600000) // 每10分钟执行一次
public void preloadHotVehicles() {
List<Long> hotVehicleIds = orderMapper.selectHotVehicleIds();
hotVehicleIds.forEach(id -> {
Vehicle vehicle = vehicleMapper.selectById(id);
redisTemplate.opsForValue().set("vehicle:" + id, vehicle);
});
}
6.2 数据库优化
- 索引设计
sql复制ALTER TABLE `rental_order` ADD INDEX `idx_user_status` (`user_id`, `status`);
ALTER TABLE `vehicle` ADD INDEX `idx_location_status` (`location`, `status`);
- 查询优化
java复制// 使用MyBatis-Plus的优化查询
public Page<Vehicle> queryAvailableVehicles(PageParam param) {
return vehicleMapper.selectPage(new Page<>(param.getPage(), param.getSize()),
new LambdaQueryWrapper<Vehicle>()
.eq(Vehicle::getStatus, 0)
.orderByAsc(Vehicle::getUpdateTime));
}
7. 部署与监控
7.1 容器化部署
使用Docker Compose编排服务:
yaml复制version: '3.8'
services:
app:
image: your-registry/vehicle-rental:${TAG:-latest}
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- redis
- mysql
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: vehicle_rental
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.2
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:
7.2 监控方案
- Spring Boot Actuator配置
yaml复制management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
metrics:
enabled: true
- Prometheus + Grafana监控
yaml复制# prometheus.yml
scrape_configs:
- job_name: 'vehicle-rental'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['app:8080']
8. 项目总结与展望
在实际开发过程中,有几个关键经验值得分享:
-
物联网设备对接:车辆状态同步最初采用HTTP轮询,后改为WebSocket长连接,服务器压力降低70%
-
并发控制:热门车辆预约采用Redis分布式锁,避免超卖
java复制public boolean lockVehicle(Long vehicleId, Long userId) {
String lockKey = "lock:vehicle:" + vehicleId;
return redisTemplate.opsForValue()
.setIfAbsent(lockKey, userId, 30, TimeUnit.SECONDS);
}
- 信用体系设计:结合租还车准时率、车辆爱护程度等维度建立用户信用评分模型
未来可扩展方向:
- 接入更多校园服务(如充电桩预约)
- 引入智能推荐算法预测用车需求
- 开发微信小程序扩大用户覆盖面
系统已在某高校试运行3个月,日均订单量200+,车辆利用率达到85%,显著改善了校园短途出行体验。
