在高校校园文化活动中,汉服租赁需求近年来呈现爆发式增长。传统线下租赁模式存在诸多痛点:学生需要亲自到实体店挑选试穿,租赁流程繁琐;商家难以实时掌握库存状态,经常出现预订冲突;纸质合同管理不便,容易产生纠纷。这个基于SpringBoot2+Vue3的汉服租赁系统正是为解决这些问题而设计。
我在实际开发中发现,高校汉服租赁场景有几个特殊需求:1)租赁周期通常与校园活动周期强相关(如开学典礼、传统文化周等);2)学生用户对价格敏感,需要灵活的押金和租金计算机制;3)汉服的特殊性要求系统必须支持多维度展示(形制、朝代、颜色等)。这些需求在系统设计阶段都需要重点考虑。
SpringBoot2作为后端框架的选择基于以下考量:1)自动配置特性大幅减少了XML配置,让开发者能聚焦业务逻辑;2)内嵌Tomcat服务器简化部署流程;3)与MyBatis-Plus的天然集成提供了强大的ORM支持。我在项目中使用的是SpringBoot 2.7.3版本,这个版本在性能和稳定性方面都有不错的表现。
MyBatis-Plus相比原生MyBatis的优势在于:1)内置通用CRUD方法,减少30%以上的重复DAO代码;2)强大的条件构造器简化复杂查询;3)分页插件实现物理分页零配置。实际开发中,通过继承BaseMapper接口,汉服信息表的常规操作代码量减少了60%。
Vue3的组合式API相比Options API更适合复杂前端应用开发。这个项目中使用的主要特性包括:1)ref和reactive实现响应式数据管理;2)setup语法糖简化组件编写;3)Vite构建工具实现秒级热更新。特别值得一提的是,Element Plus组件库为表单验证、表格展示等常用功能提供了开箱即用的解决方案。
MySQL8.0的选择主要基于其JSON支持、窗口函数等新特性。系统核心表的设计有几个关键点:1)汉服信息表使用TINYINT存储状态字段,通过位运算实现多状态共存;2)订单表采用DECIMAL(8,2)确保金额计算精确;3)所有表都包含create_time和update_time实现审计追踪。以下是优化后的汉服信息表DDL:
sql复制CREATE TABLE `hanfu_info` (
`hanfu_id` bigint NOT NULL AUTO_INCREMENT,
`costume_name` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '汉服名称',
`style_type` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '形制分类',
`dynasty` varchar(15) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '朝代',
`color_scheme` varchar(30) COLLATE utf8mb4_bin NOT NULL,
`size_range` varchar(15) COLLATE utf8mb4_bin NOT NULL,
`rental_price` decimal(8,2) NOT NULL DEFAULT '0.00',
`deposit_amount` decimal(8,2) NOT NULL DEFAULT '0.00',
`stock_status` tinyint NOT NULL DEFAULT '1' COMMENT '1-可租 2-已租 4-维修中',
`main_image` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`detail_images` text COLLATE utf8mb4_bin,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`hanfu_id`),
KEY `idx_style_type` (`style_type`),
KEY `idx_status` (`stock_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
完整的租赁流程包含以下步骤:
核心下单代码片段:
java复制@Transactional
public R createOrder(OrderDTO dto) {
// 1. 验证汉服库存
HanfuInfo hanfu = hanfuInfoService.selectById(dto.getHanfuId());
if (hanfu == null || hanfu.getStockStatus() != STOCK_AVAILABLE) {
return R.error("该汉服不可租赁");
}
// 2. 验证租期
if (dto.getLeaseDays() < 1 || dto.getLeaseDays() > MAX_LEASE_DAYS) {
return R.error("租赁天数不合法");
}
// 3. 计算金额
BigDecimal total = hanfu.getRentalPrice()
.multiply(new BigDecimal(dto.getLeaseDays()))
.add(hanfu.getDepositAmount());
// 4. 创建订单
UserOrder order = new UserOrder();
BeanUtils.copyProperties(dto, order);
order.setTotalPayment(total);
order.setOrderStatus(OrderStatus.UNPAID.getCode());
userOrderService.insert(order);
// 5. 锁定库存
hanfu.setStockStatus(STOCK_RENTED);
hanfuInfoService.updateById(hanfu);
return R.ok().put("orderId", order.getOrderId());
}
针对校园活动期间可能出现的流量高峰,系统做了以下优化:
库存扣减的分布式锁实现:
java复制public boolean lockHanfu(Long hanfuId) {
String lockKey = "lock:hanfu:" + hanfuId;
String requestId = UUID.randomUUID().toString();
try {
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(lockKey, requestId, 30, TimeUnit.SECONDS);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取分布式锁异常", e);
return false;
}
}
public void unlockHanfu(Long hanfuId) {
String lockKey = "lock:hanfu:" + hanfuId;
String requestId = redisTemplate.opsForValue().get(lockKey);
if (requestId != null && requestId.equals(Thread.currentThread().getName())) {
redisTemplate.delete(lockKey);
}
}
推荐使用Docker Compose部署方案,包含以下服务:
docker-compose.yml关键配置:
yaml复制version: '3'
services:
app:
image: openjdk:11-jre
ports:
- "8080:8080"
volumes:
- ./app.jar:/app.jar
command: java -jar /app.jar
depends_on:
- redis
- mysql
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: hanfu_rental
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
Vue3项目通过以下步骤构建部署:
npm run buildNginx配置示例:
nginx复制server {
listen 80;
server_name hanfu.example.com;
gzip on;
gzip_types text/plain application/xml text/css application/javascript;
location / {
root /var/www/hanfu/dist;
try_files $uri $uri/ /index.html;
expires 1d;
}
location /api {
proxy_pass http://app:8080;
proxy_set_header Host $host;
}
}
CORS配置示例:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
MyBatis-Plus分页失效:
Vue3响应式数据不更新:
事务不生效:
JWT失效问题:
基于现有系统,可以考虑以下扩展:
在开发过程中,我深刻体会到良好的架构设计对后期扩展的重要性。比如将支付模块设计为可插拔架构,使得后续接入支付宝等其他支付渠道变得非常容易。同时,清晰的代码分层(controller-service-dao)也让团队协作效率大幅提升。