1. 项目背景与技术栈选型
众筹平台作为互联网金融的创新模式,近年来在国内发展迅速。善筹网这类Java Web项目采用SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0技术组合,正是当前中大型互联网项目的典型架构选择。这套技术栈的优势在于:
-
Spring Boot 2:简化了传统SSM框架的配置复杂度,内置Tomcat服务器,支持快速启动和自动化配置。2.x版本在性能上比1.5.x提升约30%,特别是在高并发场景下的吞吐量表现优异。
-
Vue 3:相比Vue 2,Composition API使代码组织更灵活,性能提升2倍以上。对于需要频繁更新DOM的众筹项目前台页面,Vue 3的虚拟DOM优化能显著减少渲染开销。
-
MyBatis-Plus:作为MyBatis的增强工具,内置通用Mapper和分页插件,能减少约60%的常规SQL编写工作。其Lambda表达式写法让代码更易维护。
-
MySQL 8.0:支持JSON数据类型、窗口函数等新特性,查询性能比5.7版本提升约2倍。对于需要处理复杂业务数据的众筹系统,8.0版本的事务处理能力也更可靠。
这套技术组合的另一个优势是社区生态完善。根据2023年StackOverflow开发者调查,这四项技术在各自领域的占有率均超过65%,意味着开发者能快速找到解决方案和人才资源。
2. 系统架构设计解析
2.1 整体架构分层
善筹网采用典型的前后端分离架构:
code复制前端层(Vue3)
├── 用户端(移动端适配)
└── 管理后台(Element Plus)
接入层
├── Nginx反向代理
└── 负载均衡
应用层(SpringBoot2)
├── 用户服务
├── 项目服务
├── 支付服务
└── 风控服务
数据层
├── MySQL8.0(主从复制)
├── Redis缓存
└── Elasticsearch(搜索)
2.2 核心模块设计
用户模块:
- 采用JWT+Redis实现无状态认证
- 密码加密使用BCrypt算法(迭代10次)
- 第三方登录集成微信/支付宝快捷登录
项目模块:
- 支持图文混排的富文本编辑器(基于Quill)
- 项目进度时间轴展示
- 实时支持人数统计(WebSocket推送)
支付模块:
- 支付宝/微信支付双渠道接入
- 资金托管账户体系设计
- 每日自动对账机制
风控模块:
- 基于规则引擎的敏感词过滤
- 用户行为异常检测(如频繁修改项目)
- 提现反欺诈校验
3. 数据库设计与优化
3.1 核心表结构
sql复制-- 项目表
CREATE TABLE `project` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '发起人ID',
`title` varchar(100) NOT NULL COMMENT '项目标题',
`target_amount` decimal(12,2) NOT NULL COMMENT '目标金额',
`current_amount` decimal(12,2) DEFAULT '0.00',
`cover_image` varchar(255) NOT NULL COMMENT '封面图',
`video_url` varchar(255) DEFAULT NULL COMMENT '介绍视频',
`content` text NOT NULL COMMENT '项目详情',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-待审核 1-众筹中 2-成功 3-失败',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_status` (`user_id`,`status`),
KEY `idx_time_status` (`end_time`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- 支持记录表
CREATE TABLE `support` (
`id` bigint NOT NULL AUTO_INCREMENT,
`project_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
`amount` decimal(10,2) NOT NULL COMMENT '支持金额',
`reward_id` bigint DEFAULT NULL COMMENT '回报ID',
`payment_no` varchar(64) DEFAULT NULL COMMENT '支付流水号',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-未支付 1-已支付 2-已退款',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_payment` (`payment_no`),
KEY `idx_project` (`project_id`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
3.2 性能优化实践
-
索引策略:
- 为所有外键字段添加普通索引
- 高频查询组合建立联合索引(如status+end_time)
- 使用覆盖索引减少回表(SELECT需要的字段全在索引中)
-
分库分表:
- 支持记录表按月分表(support_202301)
- 项目评论数据单独分库
-
缓存设计:
- 热门项目信息缓存到Redis(过期时间2小时)
- 使用Redis原子操作实现支持计数器
- 项目分类信息本地缓存(Caffeine)
4. 关键功能实现细节
4.1 支付流程实现
支付模块的时序设计尤为重要:
- 前端发起支付请求 →
- 后端生成预支付订单(状态为待支付) →
- 调用支付宝/微信预支付接口 →
- 返回支付参数给前端 →
- 前端调起支付SDK →
- 支付成功异步通知 →
- 修改订单状态并更新项目金额
java复制// 支付回调处理示例
@PostMapping("/notify")
public String payNotify(@RequestBody String notifyData) {
// 1. 验证签名
if(!alipaySignature.verify(notifyData)) {
return "failure";
}
// 2. 解析支付结果
PayResult result = parseNotifyData(notifyData);
// 3. 处理幂等(防止重复通知)
if(paymentService.isProcessed(result.getOutTradeNo())) {
return "success";
}
// 4. 更新订单状态
paymentService.updatePaymentStatus(
result.getOutTradeNo(),
result.getTradeNo(),
result.getTotalAmount()
);
// 5. 更新项目支持金额
projectService.updateSupportedAmount(
result.getProjectId(),
result.getTotalAmount()
);
return "success";
}
4.2 实时数据展示
对于需要实时显示支持人数和金额的场景,采用两种方案结合:
-
WebSocket长连接:
- 项目页建立WS连接
- 后端每5秒广播最新支持数据
- 前端使用Vue3的reactive响应式更新
-
降级方案:
- WS不可用时自动切换为轮询(每10秒AJAX请求)
- 使用localStorage暂存最新数据避免页面闪烁
javascript复制// Vue3组合式API实现
import { ref, onMounted } from 'vue'
import { useWebSocket } from '@vueuse/core'
export default {
setup() {
const supportCount = ref(0)
const amount = ref(0)
const { status, data } = useWebSocket(
`wss://api.example.com/ws/project/${projectId}`
)
onMounted(() => {
watch(data, (newVal) => {
const msg = JSON.parse(newVal)
supportCount.value = msg.count
amount.value = msg.amount
})
// 降级处理
if(status.value === 'CLOSED') {
setInterval(fetchData, 10000)
}
})
return { supportCount, amount }
}
}
5. 安全防护方案
5.1 常见攻击防御
-
XSS防护:
- 前端使用vue-dompurify过滤HTML输入
- 后端统一对用户输入进行转义处理
-
CSRF防护:
- 关键操作校验自定义请求头X-Requested-With
- 敏感表单使用动态Token(存储在Vuex)
-
SQL注入防护:
- MyBatis-Plus严格使用#{}参数绑定
- 禁止拼接SQL语句
5.2 资金安全设计
-
双重金额校验:
- 前端计算支持金额
- 后端再次校验金额逻辑
-
关键操作日志:
- 记录所有资金变动操作
- 使用数据库事务确保日志与业务一致
-
提现风控规则:
- 新用户24小时延迟提现
- 大额提现人工审核
- 同IP多账号提现预警
6. 部署与监控
6.1 容器化部署
使用Docker Compose编排主要服务:
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: root123
MYSQL_DATABASE: shanchou
ports:
- "3306:3306"
volumes:
- ./mysql-data:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
- ./redis-data:/data
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./dist:/usr/share/nginx/html
6.2 监控体系
-
应用监控:
- Spring Boot Actuator暴露健康指标
- Prometheus收集JVM指标
- Grafana展示实时数据
-
业务监控:
- 支付成功率监控
- 项目审核时效监控
- 用户投诉率看板
-
日志分析:
- ELK收集分析错误日志
- 关键操作链路追踪(SkyWalking)
7. 开发经验与避坑指南
-
MyBatis-Plus分页优化:
- 避免使用select *,只查询必要字段
- 大数据量表分页使用lastId优化(where id > ? limit ?)
- 分页参数做上限限制(如pageSize ≤ 100)
-
Vue3性能调优:
- 大列表使用vue-virtual-scroller虚拟滚动
- 复杂计算使用computed缓存
- 适当使用v-once减少不必要的响应式开销
-
事务处理注意事项:
- @Transactional注解避免跨多Service使用
- 事务方法内捕获异常需手动回滚
- 分布式事务使用Seata或本地消息表
-
缓存一致性问题:
- 使用Redis事务或Lua脚本保证原子性
- 数据库更新后立即删除缓存(非更新)
- 热点数据设置随机过期时间避免雪崩
这个项目架构在实际运行中可支撑日活10万级别的流量。我在部署过程中发现,MySQL连接池配置对性能影响很大,建议根据压测结果调整druid的initialSize、maxActive等参数。另外Vue3的keep-alive组件对动态路由的支持需要特殊处理,这是从文档中不容易发现的实践细节。
