1. 项目概述
作为一名从事Java开发多年的程序员,我最近完成了一个基于Spring Boot的相机租赁系统开发项目。这个系统旨在为摄影爱好者提供一个便捷的相机租赁平台,同时也为租赁商家提供高效的管理工具。在开发过程中,我遇到了不少技术挑战,也积累了一些宝贵的经验,今天就来分享一下这个项目的完整开发过程。
相机租赁系统主要解决以下几个核心问题:
- 降低摄影爱好者使用高端设备的门槛
- 提高租赁商家的管理效率
- 实现租赁流程的标准化和自动化
- 提供安全可靠的支付和信用体系
2. 技术选型与架构设计
2.1 技术栈选择
在技术选型上,我主要考虑了系统的稳定性、开发效率和可扩展性:
后端技术:
- Spring Boot 2.7.3:简化配置,快速开发
- Spring Security:安全认证和授权
- MyBatis-Plus:简化数据库操作
- Redis:缓存和会话管理
- JWT:无状态认证
前端技术:
- Vue.js 3:构建响应式用户界面
- Element Plus:UI组件库
- Axios:HTTP客户端
- ECharts:数据可视化
数据库:
- MySQL 8.0:关系型数据库
- 数据库连接池:HikariCP
开发工具:
- IntelliJ IDEA:Java开发IDE
- VS Code:前端开发
- Navicat:数据库管理
- Postman:API测试
2.2 系统架构设计
系统采用经典的三层架构:
表现层:
- 负责接收用户请求和返回响应
- 使用RESTful API设计风格
- 前后端完全分离
业务逻辑层:
- 处理核心业务逻辑
- 实现事务管理
- 处理异常和日志
数据访问层:
- 数据库CRUD操作
- 缓存管理
- 数据校验
架构设计上特别考虑了以下几点:
- 高并发处理:使用Redis缓存热点数据
- 安全性:实现完善的权限控制和数据加密
- 可扩展性:模块化设计,便于功能扩展
- 可维护性:清晰的代码结构和注释
3. 数据库设计与实现
3.1 数据库表设计
系统共设计了20余张表,以下是核心表结构:
用户相关表:
sql复制CREATE TABLE `user` (
`user_id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(20) DEFAULT NULL,
`avatar` varchar(255) DEFAULT NULL,
`status` tinyint NOT NULL DEFAULT '1',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`),
UNIQUE KEY `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
相机信息表:
sql复制CREATE TABLE `camera` (
`camera_id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`brand` varchar(50) NOT NULL,
`model` varchar(50) NOT NULL,
`type_id` int NOT NULL,
`specification` text,
`daily_price` decimal(10,2) NOT NULL,
`deposit` decimal(10,2) NOT NULL,
`status` tinyint NOT NULL DEFAULT '1',
`image_url` varchar(255) DEFAULT NULL,
`description` text,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`camera_id`),
KEY `idx_type` (`type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
租赁订单表:
sql复制CREATE TABLE `rental_order` (
`order_id` int NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL,
`user_id` int NOT NULL,
`camera_id` int NOT NULL,
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`days` int NOT NULL,
`total_amount` decimal(10,2) NOT NULL,
`deposit_amount` decimal(10,2) NOT NULL,
`status` tinyint NOT NULL DEFAULT '0',
`payment_status` tinyint NOT NULL DEFAULT '0',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`order_id`),
UNIQUE KEY `idx_order_no` (`order_no`),
KEY `idx_user` (`user_id`),
KEY `idx_camera` (`camera_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 数据库优化
为了提高系统性能,我做了以下数据库优化:
-
索引优化:
- 为所有外键字段添加索引
- 为高频查询条件添加组合索引
- 避免过度索引,定期分析索引使用情况
-
查询优化:
- 使用EXPLAIN分析慢查询
- 避免SELECT *,只查询必要字段
- 合理使用JOIN,避免笛卡尔积
-
分表分库:
- 对日志表按时间分表
- 用户数据和业务数据分离
4. 核心功能实现
4.1 用户认证与授权
系统采用JWT进行无状态认证,结合Spring Security实现细粒度的权限控制。
认证流程:
- 用户提交用户名和密码
- 服务端验证凭证
- 生成JWT令牌返回给客户端
- 客户端在后续请求中携带令牌
- 服务端验证令牌有效性
关键代码实现:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
4.2 相机租赁流程
租赁流程是系统的核心功能,主要包括以下步骤:
-
相机浏览与搜索:
- 支持按品牌、类型、价格等多维度筛选
- 实现关键词搜索和高级搜索
-
租赁申请:
- 选择租赁日期和时长
- 系统自动计算租金和押金
- 提交租赁申请
-
订单处理:
- 管理员审核订单
- 用户支付租金和押金
- 系统确认订单
-
租赁执行:
- 用户取机或邮寄相机
- 租赁期间状态跟踪
- 归还相机和押金退还
关键业务逻辑代码:
java复制@Service
@Transactional
public class RentalServiceImpl implements RentalService {
@Autowired
private CameraMapper cameraMapper;
@Autowired
private RentalOrderMapper orderMapper;
@Autowired
private PaymentService paymentService;
@Override
public RentalOrder createOrder(Integer userId, CreateOrderDTO dto) {
// 验证相机可用性
Camera camera = cameraMapper.selectById(dto.getCameraId());
if (camera == null || camera.getStatus() != 1) {
throw new BusinessException("相机不可用");
}
// 计算租赁天数
long days = ChronoUnit.DAYS.between(dto.getStartDate(), dto.getEndDate()) + 1;
if (days <= 0) {
throw new BusinessException("租赁日期不合法");
}
// 计算金额
BigDecimal totalAmount = camera.getDailyPrice().multiply(new BigDecimal(days));
BigDecimal depositAmount = camera.getDeposit();
// 创建订单
RentalOrder order = new RentalOrder();
order.setOrderNo(generateOrderNo());
order.setUserId(userId);
order.setCameraId(dto.getCameraId());
order.setStartDate(dto.getStartDate());
order.setEndDate(dto.getEndDate());
order.setDays((int) days);
order.setTotalAmount(totalAmount);
order.setDepositAmount(depositAmount);
order.setStatus(OrderStatus.PENDING.getCode());
order.setPaymentStatus(PaymentStatus.UNPAID.getCode());
orderMapper.insert(order);
return order;
}
private String generateOrderNo() {
return "RO" + System.currentTimeMillis() + RandomUtil.randomNumbers(4);
}
}
4.3 支付系统集成
系统集成了第三方支付平台,支持多种支付方式:
-
支付流程:
- 用户选择支付方式
- 系统生成支付订单
- 跳转到支付平台完成支付
- 支付结果异步通知
-
支付安全:
- 使用HTTPS加密传输
- 签名验证防止篡改
- 支付结果双重确认
-
退款处理:
- 押金自动退款
- 异常情况人工审核
- 退款状态跟踪
支付回调处理代码:
java复制@RestController
@RequestMapping("/api/payment")
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping("/callback/{channel}")
public String paymentCallback(@PathVariable String channel,
HttpServletRequest request) {
// 验证签名
if (!paymentService.verifySign(request, channel)) {
return "FAIL";
}
// 处理支付结果
PaymentResult result = paymentService.parseCallback(request, channel);
boolean success = paymentService.processPayment(result);
return success ? "SUCCESS" : "FAIL";
}
}
5. 系统安全与性能优化
5.1 安全防护措施
-
输入验证:
- 所有用户输入都进行严格验证
- 使用Hibernate Validator进行数据校验
- 防范SQL注入和XSS攻击
-
权限控制:
- 基于角色的访问控制(RBAC)
- 方法级别的权限注解
- 数据权限过滤
-
敏感数据保护:
- 密码加密存储(BCrypt)
- 敏感信息脱敏显示
- 日志过滤敏感数据
5.2 性能优化策略
-
缓存策略:
- 使用Redis缓存热点数据
- 多级缓存设计
- 合理的缓存失效策略
-
异步处理:
- 使用@Async处理非核心流程
- 消息队列解耦
- 定时任务优化
-
数据库优化:
- 读写分离
- 慢查询监控
- 连接池调优
性能监控代码示例:
java复制@Aspect
@Component
@Slf4j
public class PerformanceMonitorAspect {
@Around("execution(* com.camerarental..service..*(..))")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
String methodName = joinPoint.getSignature().toShortString();
try {
return joinPoint.proceed();
} finally {
long elapsedTime = System.currentTimeMillis() - startTime;
if (elapsedTime > 500) {
log.warn("Method {} executed in {} ms", methodName, elapsedTime);
}
}
}
}
6. 测试与部署
6.1 测试策略
-
单元测试:
- 使用JUnit + Mockito
- 核心业务逻辑全覆盖
- 边界条件测试
-
集成测试:
- Spring Boot Test
- 数据库操作测试
- API接口测试
-
压力测试:
- JMeter模拟高并发
- 性能瓶颈分析
- 系统稳定性测试
测试示例代码:
java复制@SpringBootTest
public class RentalServiceTest {
@Autowired
private RentalService rentalService;
@MockBean
private CameraMapper cameraMapper;
@Test
public void testCreateOrderWithInvalidDate() {
// 准备测试数据
CreateOrderDTO dto = new CreateOrderDTO();
dto.setCameraId(1);
dto.setStartDate(LocalDate.now().plusDays(2));
dto.setEndDate(LocalDate.now());
// 模拟相机数据
Camera camera = new Camera();
camera.setStatus(1);
camera.setDailyPrice(new BigDecimal("100.00"));
camera.setDeposit(new BigDecimal("500.00"));
when(cameraMapper.selectById(1)).thenReturn(camera);
// 验证异常
assertThrows(BusinessException.class, () -> {
rentalService.createOrder(1, dto);
});
}
}
6.2 部署方案
系统采用Docker容器化部署,部署架构如下:
-
开发环境:
- 本地Docker Compose
- 集成测试环境
-
生产环境:
- Kubernetes集群
- CI/CD自动化部署
- 蓝绿部署策略
Docker Compose示例:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: camera_rental
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.2
ports:
- "6379:6379"
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/camera_rental
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
SPRING_REDIS_HOST: redis
depends_on:
- mysql
- redis
volumes:
mysql_data:
7. 项目总结与经验分享
7.1 技术难点与解决方案
-
相机库存管理:
- 问题:高并发下库存超卖
- 方案:Redis分布式锁 + 乐观锁
-
支付超时处理:
- 问题:支付状态不一致
- 方案:定时任务 + 补偿机制
-
图片存储优化:
- 问题:服务器存储压力大
- 方案:OSS对象存储 + CDN加速
7.2 项目收获
通过这个项目的开发,我获得了以下经验:
- 复杂业务系统的分析与设计能力
- Spring Boot生态的深入理解
- 性能优化和安全防护的实践经验
- 全栈开发的综合能力提升
7.3 未来优化方向
- 引入Elasticsearch实现更强大的搜索功能
- 增加推荐算法提升用户体验
- 开发移动端APP
- 实现智能合约管理租赁协议
这个相机租赁系统的开发过程让我深刻理解了如何将一个业务需求转化为可落地的技术方案。从需求分析到系统设计,从编码实现到测试部署,每个环节都需要严谨的态度和专业的技术能力。希望我的分享能对正在开发类似系统的同行有所帮助。