这套基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的汉服租赁系统,是专门针对高校场景设计的文化类电商解决方案。我在实际开发中发现,校园汉服租赁存在明显的季节性需求波动(如毕业季、传统节日前后),这就要求系统在架构设计上必须兼顾常规运营和高并发场景。整套源码采用前后端分离架构,后端使用SpringBoot2构建RESTful API,前端通过Vue3实现动态交互,数据库选用MySQL8.0利用其JSON支持特性处理汉服的多维度属性数据。
关键提示:校园场景的特殊性在于用户群体集中且行为模式可预测,这为缓存策略和库存预分配提供了优化空间。例如在端午节前两周,可以提前预热"汉服+配饰"的组合商品数据。
SpringBoot2框架采用2.7.12稳定版本,主要配置亮点包括:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/hanfu_rent?useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
MyBatis-Plus的实践技巧:
@TableLogic实现软删除,保留租赁历史记录MybatisPlusInterceptor添加分页插件MetaObjectHandler自动填充创建/修改时间java复制public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
}
Vue3组合式API在项目中的典型应用:
javascript复制// 汉服列表页逻辑
const state = reactive({
hanfuList: [],
pagination: {
current: 1,
pageSize: 8,
total: 0
}
})
const fetchHanfuList = async () => {
const res = await api.getHanfuList({
page: state.pagination.current,
size: state.pagination.pageSize
})
state.hanfuList = res.data.records
state.pagination.total = res.data.total
}
Element Plus的按需引入配置:
javascript复制import { ElButton, ElDialog } from 'element-plus'
const app = createApp(App)
app.use(ElButton).use(ElDialog)
利用JSON字段存储汉服动态属性:
sql复制CREATE TABLE `hanfu` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`specs` json DEFAULT NULL COMMENT '{"color":["红","蓝"],"size":["S","M"],"material":"真丝"}',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
窗口函数实现租赁排名统计:
sql复制SELECT
hanfu_id,
COUNT(*) as rent_count,
RANK() OVER (ORDER BY COUNT(*) DESC) as rank_num
FROM rental_order
GROUP BY hanfu_id
采用多级缓存架构:
java复制// 库存扣减Lua脚本
String script = "local current = redis.call('GET', KEYS[1]) " +
"if current and tonumber(current) >= tonumber(ARGV[1]) then " +
"return redis.call('DECRBY', KEYS[1], ARGV[1]) " +
"else return -1 end";
mermaid复制stateDiagram-v2
[*] --> 待支付
待支付 --> 已取消: 超时未支付
待支付 --> 已支付: 完成支付
已支付 --> 待发货: 管理员确认
待发货 --> 已发货: 填写物流
已发货 --> 已完成: 用户确认
已发货 --> 退货中: 申请退货
退货中 --> 已退款: 管理员确认
实际开发中建议使用Spring StateMachine或自定义状态枚举实现:
java复制public enum OrderStatus {
UNPAID(1, "待支付"),
PAID(2, "已支付"),
SHIPPED(3, "已发货");
// 状态校验逻辑
public static boolean canChangeTo(OrderStatus current, OrderStatus target) {
// 实现状态转移规则
}
}
处理汉服租赁的时间重叠问题:
java复制public boolean checkTimeConflict(Long hanfuId, LocalDateTime start, LocalDateTime end) {
return mapper.selectCount(new QueryWrapper<RentalOrder>()
.eq("hanfu_id", hanfuId)
.eq("status", OrderStatus.PAID.getCode())
.and(wrapper -> wrapper
.between("rent_start", start, end)
.or()
.between("rent_end", start, end)
)) > 0;
}
前端使用DOMPurify净化输入:
javascript复制import DOMPurify from 'dompurify'
const clean = DOMPurify.sanitize(userInput)
后端统一处理:
java复制@ControllerAdvice
public class XssAdvice implements ResponseBodyAdvice<Object> {
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
// 使用Antisamy过滤响应数据
}
}
租借+支付场景使用Seata AT模式:
java复制@GlobalTransactional
public void createOrder(OrderDTO dto) {
// 1. 扣减库存
stockService.reduce(dto.getHanfuId(), dto.getCount());
// 2. 创建订单
orderService.create(dto);
// 3. 调用支付
paymentService.create(dto.getOrderNo(), dto.getAmount());
}
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
SpringBoot Actuator端点暴露:
yaml复制management:
endpoints:
web:
exposure:
include: "*"
metrics:
tags:
application: ${spring.application.name}
Grafana监控看板关键指标:
SpringDoc OpenAPI配置:
java复制@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info().title("汉服租赁API")
.version("1.0")
.contact(new Contact().name("开发者")));
}
使用SchemaCrawler生成ER图:
bash复制java -jar schemacrawler.jar \
--server=mysql --database=hanfu_rent \
--user=root --password=root \
--info-level=standard --command=schema \
--output-format=png --output-file=er-diagram.png
MySQL时区问题解决方案:
sql复制-- 永久生效
SET GLOBAL time_zone = '+8:00';
-- 当前会话生效
SET time_zone = '+8:00';
使用toRefs保持响应式:
javascript复制const state = reactive({ hanfuList: [] })
return {
...toRefs(state),
// 其他属性
}
这套系统在实际部署时需要特别注意校园网环境下的CDN加速问题,我们通过将静态资源部署到校内服务器,使首页加载时间从3.2秒降低到1.1秒。对于高并发场景,建议采用课程表数据预测流量高峰,提前进行水平扩展。