1. 项目概述
这套企业级网上租赁系统是我在研究生期间参与开发的一个实际项目,经过多次迭代已经稳定运行于多家中小企业的租赁业务中。系统采用SpringBoot+Vue.js+MyBatis的主流技术栈,实现了从物品管理、订单处理到支付结算的全流程数字化解决方案。
在实际部署中,系统平均能支撑500+并发请求,订单处理响应时间控制在300ms以内。特别适合需要管理设备、车辆或办公空间租赁的企业使用,相比传统人工管理方式能提升60%以上的运营效率。
2. 技术架构解析
2.1 后端技术选型
SpringBoot 2.7.4作为基础框架,主要基于以下考虑:
- 内嵌Tomcat服务器简化部署
- 自动配置减少XML配置工作量
- 完善的Starter生态快速集成其他组件
数据持久层采用MyBatis-Plus 3.5.3,相比原生MyBatis:
- 内置通用Mapper减少30%以上CRUD代码
- 支持Lambda表达式避免硬编码字段名
- 分页插件自动处理物理分页逻辑
安全认证使用JWT+Spring Security组合:
java复制// JWT配置示例
@Configuration
public class JwtConfig {
@Bean
public JwtFilter jwtFilter() {
return new JwtFilter();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
2.2 前端技术方案
Vue 3组合式API带来以下优势:
- 更好的TypeScript支持
- 按需引入组件减小打包体积
- Composition API提升代码复用性
Element Plus作为UI框架:
- 内置表单验证规则减少前端校验代码
- 表格组件支持服务端分页和排序
- 主题定制能力满足企业品牌需求
重要提示:前后端分离架构中,务必配置CORS白名单。我们在生产环境吃过亏,曾因漏配导致API请求被拦截。
2.3 数据库设计优化
MySQL 8.0采用InnoDB引擎,关键优化点:
- 所有表字段使用NOT NULL约束
- 金额字段使用DECIMAL(10,2)避免浮点误差
- 建立复合索引提升查询性能:
sql复制CREATE INDEX idx_order_user ON rent_order(user_id, create_time);
Redis缓存应用场景:
- 用户权限信息缓存(TTL 30分钟)
- 热门租赁物品缓存(LRU淘汰策略)
- 分布式锁控制库存扣减
3. 核心功能实现
3.1 租赁业务流程
完整的租赁状态机设计:
- 待支付 → 2. 已支付 → 3. 使用中 → 4. 已完成
↘ 5. 已取消
关键代码逻辑:
java复制@Transactional
public OrderResult createOrder(OrderDTO dto) {
// 1. 校验库存
InventoryItem item = inventoryMapper.selectById(dto.getItemId());
if (item.getStockCount() <= 0) {
throw new BusinessException("库存不足");
}
// 2. 计算费用
long days = ChronoUnit.DAYS.between(dto.getStartDate(), dto.getEndDate());
BigDecimal total = item.getRentPrice().multiply(new BigDecimal(days));
// 3. 创建订单
RentOrder order = new RentOrder();
BeanUtils.copyProperties(dto, order);
order.setTotalFee(total);
orderMapper.insert(order);
// 4. 扣减库存
inventoryMapper.updateStock(dto.getItemId(), -1);
return OrderResult.success(order.getOrderId());
}
3.2 支付对接方案
系统支持三种支付方式:
- 支付宝沙箱环境(测试用)
- 微信支付Native API
- 企业银行转账(线下对账)
支付回调处理要点:
- 验证签名防止伪造请求
- 使用幂等设计避免重复处理
- 异步更新订单状态
3.3 权限控制系统
RBAC模型实现:
- 角色分为:超级管理员、业务管理员、财务人员、普通用户
- 权限粒度控制到按钮级别
- 前端动态路由根据权限生成
权限校验拦截器:
java复制public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String token = request.getHeader("Authorization");
Claims claims = JwtUtil.parseToken(token);
String uri = request.getRequestURI();
if (!permissionService.hasPermission(claims.get("role"), uri)) {
throw new UnauthorizedException("无访问权限");
}
return true;
}
4. 性能优化实践
4.1 数据库层面
- 慢查询优化:
- 添加EXPLAIN分析执行计划
- 对rent_order表的user_id字段添加索引
- 避免SELECT * 只查询必要字段
- 连接池配置:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
4.2 缓存策略
多级缓存设计方案:
- 本地Caffeine缓存(有效期5分钟)
- Redis集群缓存(有效期30分钟)
- 数据库原始数据
缓存击穿解决方案:
java复制public ItemDetail getItemDetail(Long itemId) {
String cacheKey = "item:" + itemId;
// 1. 先查本地缓存
ItemDetail detail = localCache.getIfPresent(cacheKey);
if (detail != null) return detail;
// 2. 查Redis缓存
detail = redisTemplate.opsForValue().get(cacheKey);
if (detail != null) {
localCache.put(cacheKey, detail);
return detail;
}
// 3. 加分布式锁查DB
RLock lock = redissonClient.getLock("lock:" + cacheKey);
try {
lock.lock();
// 二次检查缓存
detail = redisTemplate.opsForValue().get(cacheKey);
if (detail == null) {
detail = itemMapper.selectById(itemId);
redisTemplate.opsForValue().set(cacheKey, detail, 30, TimeUnit.MINUTES);
}
localCache.put(cacheKey, detail);
} finally {
lock.unlock();
}
return detail;
}
4.3 前端性能提升
- 打包优化:
- 配置splitChunks分割代码
- 开启Gzip压缩
- 使用CDN加载第三方库
- 懒加载实现:
javascript复制const routes = [
{
path: '/items',
component: () => import('./views/ItemList.vue')
}
]
5. 部署与监控
5.1 容器化部署
Docker Compose编排方案:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- ./mysql-data:/var/lib/mysql
redis:
image: redis:6.2
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
5.2 监控方案
Prometheus + Grafana监控指标:
- JVM内存使用率
- 接口响应时间P99
- 数据库连接池活跃数
- Redis缓存命中率
日志收集架构:
Filebeat → Logstash → Elasticsearch → Kibana
5.3 压力测试
使用JMeter模拟100并发:
- 登录接口:平均响应时间 120ms
- 订单查询:平均响应时间 80ms
- 支付回调:平均响应时间 200ms
优化后指标:
- CPU使用率降低40%
- GC次数减少65%
- 错误率降至0.1%以下
6. 踩坑经验分享
- 分布式事务问题:
- 库存扣减和订单创建需要保证原子性
- 最终采用本地消息表+定时任务补偿
- 日期重叠校验:
sql复制SELECT COUNT(*) FROM rent_order
WHERE item_id = #{itemId}
AND (
(start_date <= #{endDate} AND end_date >= #{startDate})
OR (start_date >= #{startDate} AND start_date <= #{endDate})
)
- 金额计算精度:
- 使用BigDecimal进行精确计算
- 避免使用double直接运算
- 数据库存储使用DECIMAL(10,2)
- 前端常见问题:
- 表单重置时未清除验证状态
- 路由守卫未正确处理403错误
- 表格分页器未重置页码
这套系统在实际交付过程中,我们发现企业用户最关心的三个点是:租赁流程的简便性、财务对账的准确性以及系统运行的稳定性。特别是在月末结算时,系统要能高效生成各类统计报表。