1. 项目背景与核心需求
高校班级财务管理一直是学生自治中的痛点。传统纸质记账本容易丢失、Excel表格难以协同、微信群收款记录混乱...作为带过三届班委的技术宅,我亲眼见过班长因为5毛钱差额对账到凌晨两点的崩溃现场。这个基于SpringBoot的班费管理系统,就是要用技术手段解决这些实际问题。
核心需求非常明确:
- 多角色权限控制(辅导员查看/班委操作/同学查询)
- 电子化收付款流水记录
- 自动生成可视化报表
- 全流程线上公示
- 重要操作留痕审计
2. 技术选型解析
2.1 为什么选择SpringBoot
作为毕业设计项目,SpringBoot的快速开发特性完美匹配需求:
- 内嵌Tomcat避免环境配置坑(新手杀手)
- Starter依赖一键集成MyBatis/JPA
- Actuator监控接口方便答辩演示
- 与Thymeleaf模板天然契合
实测用Spring Initializr生成基础框架,15分钟就能跑通第一个接口。对比SSM框架的XML配置地狱,开发效率提升300%以上。
2.2 Thymeleaf的独特优势
放弃Vue/React而选用Thymeleaf模板引擎,主要考虑:
- 零前端分离带来的部署复杂度
- 天然支持Spring表达式语言
- 静态HTML原型可直接复用
- 内联文本国际化支持
特别适合班级场景下可能出现的:
html复制<!-- 缴费状态动态显示 -->
<span th:text="${payStatus} ? '已缴纳' : '待支付'"
th:class="${payStatus} ? 'badge-success' : 'badge-warning'">
</span>
2.3 安全控制方案
采用Spring Security实现三级权限:
java复制@PreAuthorize("hasRole('MONITOR') || hasRole('COMMITTEE')")
@PostMapping("/expense")
public String addExpense(...) {
// 仅班长/班委可操作
}
特别注意要关闭CSRF防护(否则文件上传会报403):
java复制@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
3. 核心功能实现细节
3.1 财务流水设计
数据库表关键字段:
sql复制CREATE TABLE `transaction` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`type` TINYINT COMMENT '1-收入 2-支出',
`amount` DECIMAL(10,2) NOT NULL,
`balance` DECIMAL(10,2) NOT NULL COMMENT '实时余额',
`operator` VARCHAR(20) NOT NULL COMMENT '操作人学号',
`proof_url` VARCHAR(255) COMMENT '凭证图片OSS地址',
`audit_status` TINYINT DEFAULT 0 COMMENT '0-未审核 1-已审核'
);
余额计算要特别注意事务处理:
java复制@Transactional
public void addTransaction(Transaction transaction) {
// 查询当前余额
BigDecimal lastBalance = mapper.selectLastBalance();
// 计算新余额
BigDecimal newBalance = transaction.getType() == 1
? lastBalance.add(transaction.getAmount())
: lastBalance.subtract(transaction.getAmount());
transaction.setBalance(newBalance);
mapper.insert(transaction);
}
3.2 微信支付集成
使用官方JSAPI支付时要注意:
- 统一下单接口需要获取用户openid
- 支付结果通知要做签名验证
- 校内场景需申请特约商户
核心代码结构:
code复制│── wechat
│ ├── config # 证书配置
│ ├── constant # 交易类型枚举
│ ├── service # 支付服务
│ └── controller # 回调接口
3.3 公示系统设计
采用"提交->审核->公示"流程:
- 班委提交支出申请
- 辅导员后台审核
- 自动生成公示页面
- 7天异议期后可归档
公示页面关键要素:
- 消费事由及凭证
- 审批人及时间戳
- 异议反馈入口
- 区块链存证哈希值
4. 典型问题解决方案
4.1 并发修改问题
当多个班委同时操作时,可能出现余额不一致。解决方案:
java复制@Transactional(isolation = Isolation.SERIALIZABLE)
public void updateBalance() {
// 使用最高级别事务隔离
}
4.2 历史数据追溯
采用触发器记录数据变更日志:
sql复制CREATE TRIGGER log_transaction_change
AFTER UPDATE ON transaction
FOR EACH ROW
BEGIN
INSERT INTO transaction_audit
VALUES(OLD.id, OLD.amount, NEW.amount, NOW());
END;
4.3 性能优化实践
- 账单列表分页查询优化:
java复制// 错误做法:先查全部再内存分页
List<Transaction> all = mapper.selectAll();
return all.stream().skip().limit().collect();
// 正确做法:数据库层分页
PageHelper.startPage(pageNum, pageSize);
return mapper.selectByCondition(condition);
- 使用Redis缓存常用数据:
java复制// 班级总人数等不常变数据
@Cacheable(value = "classInfo", key = "#classId")
public Integer getStudentCount(String classId) {
return mapper.countStudents(classId);
}
5. 扩展功能建议
5.1 智能预警系统
基于历史数据分析:
- 异常大额支出提醒
- 周期性收入缺失预警
- 余额不足提前通知
实现方案:
java复制@Scheduled(cron = "0 0 18 * * ?") // 每天18点执行
public void checkBalance() {
BigDecimal balance = mapper.selectLastBalance();
if(balance.compareTo(new BigDecimal("100")) < 0) {
wechatService.sendAlert("班费余额不足100元!");
}
}
5.2 多维度统计分析
使用ECharts实现:
- 收支类别饼图
- 时间趋势折线图
- 班级对比柱状图
前端数据接口示例:
javascript复制axios.get('/api/stat?type=category').then(res => {
myChart.setOption({
series: [{
type: 'pie',
data: res.data
}]
});
});
6. 部署注意事项
6.1 生产环境配置
application-prod.yml关键配置:
yaml复制spring:
datasource:
url: jdbc:mysql://master:3306/class_finance?useSSL=false&serverTimezone=Asia/Shanghai
hikari:
maximum-pool-size: 20 # 连接池大小
servlet:
multipart:
max-file-size: 10MB # 凭证上传限制
6.2 微信支付证书处理
切勿将cert.p12放在resources目录下!正确做法:
- 通过环境变量指定证书路径
- 使用配置中心动态加载
- 设置400权限限制访问
6.3 数据备份策略
推荐方案:
- 每日凌晨全量备份
- binlog实时增量备份
- OSS异地存储凭证图片
备份脚本示例:
bash复制mysqldump -uroot -p class_finance > /backup/$(date +%Y%m%d).sql
find /backup -mtime +7 -exec rm {} \; # 删除7天前备份
7. 答辩技巧分享
7.1 演示数据准备
建议预制三类数据:
- 正常流程数据(占比70%)
- 边界测试数据(超大金额/0元交易)
- 异常场景数据(审核驳回记录)
7.2 高频问题应对
提前准备这些问题的回答:
- 如何防止班委篡改数据?
- 系统能否支持毕业班结算?
- 与微信/支付宝的对接方式?
- 数据安全如何保障?
7.3 性能压测报告
用JMeter做基础测试:
- 50并发用户连续操作
- 平均响应时间<500ms
- 错误率<0.1%
最后提醒:记得在演示前清除测试时产生的"测试数据1"、"aaa"这类随意命名的记录,专业度瞬间提升50%!