基于Spring Boot的个人财务管理系统的设计与实现
·
一、 项目背景与意义
在数字化时代,个人财务管理的需求日益增长。传统的记账方式如纸质账本或简单的电子表格,存在数据易丢失、统计不便、缺乏可视化分析等痛点。随着移动互联网和云计算的普及,开发一款功能完善、操作便捷的个人财务管理系统,对于帮助用户清晰掌握收支状况、培养良好消费习惯、实现财务目标具有重要的现实意义。
本项目旨在设计并实现一个基于Spring Boot的个人财务管理系统。该系统将提供一个集中管理个人收入、支出、资产、负债的平台,通过数据可视化图表直观展示财务状况,并具备预算管理、报表生成等进阶功能,最终帮助用户实现科学的个人财务管理。
二、 技术栈选型
本系统采用前后端分离的架构模式,后端基于Spring Boot框架构建,前端使用Vue.js,数据库选用MySQL。具体技术栈如下:
2.1 后端技术栈
- 核心框架: Spring Boot 2.7.x
- 安全框架: Spring Security + JWT (JSON Web Token)
- 数据持久层: Spring Data JPA (集成Hibernate)
- 数据库: MySQL 8.0
- API文档: SpringDoc OpenAPI (Swagger UI)
- 缓存: Redis (用于会话管理或热点数据缓存)
- 任务调度: Spring Scheduler
- 构建工具: Maven
2.2 前端技术栈
- 核心框架: Vue.js 3 + Composition API
- 构建工具: Vite
- UI组件库: Element Plus
- 状态管理: Pinia
- 路由: Vue Router
- HTTP客户端: Axios
- 图表库: ECharts
2.3 开发与部署
- 版本控制: Git
- 容器化: Docker, Docker Compose
- 部署: 可部署至云服务器(如阿里云ECS)或使用容器平台。
三、 系统核心功能模块设计
系统主要分为以下几个核心模块:
- 用户认证与授权模块: 负责用户注册、登录、JWT令牌签发与验证、权限管理。
- 账户管理模块: 管理用户的现金账户、银行卡、信用卡、数字钱包等资产账户。
- 收支记录模块: 核心功能,支持记录每一笔收入与支出,包含金额、分类、时间、备注、关联账户等信息。
- 分类管理模块: 自定义收入与支出的分类树(如餐饮、交通、工资、理财收入等)。
- 预算管理模块: 支持按周期(月、年)和分类设置预算,并实时监控预算执行情况。
- 数据统计与报表模块: 通过图表(饼图、柱状图、趋势图)多维度展示收支对比、资产构成、消费趋势。支持导出报表。
- 系统设置模块: 用户个人资料修改、系统参数配置等。
四、 数据库核心表设计
以下是几个核心实体对应的数据库表结构:
-- 用户表
CREATE TABLE `sys_user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '加密后的密码',
`email` varchar(100) DEFAULT NULL,
`nickname` varchar(50) DEFAULT NULL,
`avatar` varchar(500) DEFAULT NULL,
`status` tinyint DEFAULT '1' COMMENT '状态:0-禁用,1-正常',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB COMMENT='系统用户表';
-- 账户表
CREATE TABLE `finance_account` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '所属用户ID',
`account_name` varchar(100) NOT NULL COMMENT '账户名称(如:招商银行储蓄卡)',
`account_type` varchar(20) NOT NULL COMMENT '账户类型:CASH, BANK_CARD, CREDIT_CARD, DIGITAL_WALLET',
`balance` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '当前余额',
`currency` varchar(10) DEFAULT 'CNY' COMMENT '货币',
`remarks` varchar(500) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
CONSTRAINT `fk_account_user` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB COMMENT='财务账户表';
-- 收支分类表
CREATE TABLE `finance_category` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`parent_id` bigint DEFAULT '0' COMMENT '父分类ID,0表示根分类',
`category_name` varchar(50) NOT NULL,
`type` tinyint NOT NULL COMMENT '类型:1-收入,2-支出',
`icon` varchar(100) DEFAULT NULL,
`sort_order` int DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_user_type` (`user_id`,`type`)
) ENGINE=InnoDB COMMENT='收支分类表';
-- 收支记录表(核心业务表)
CREATE TABLE `finance_record` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`account_id` bigint NOT NULL COMMENT '关联账户ID',
`category_id` bigint NOT NULL COMMENT '分类ID',
`type` tinyint NOT NULL COMMENT '记录类型:1-收入,2-支出',
`amount` decimal(15,2) NOT NULL COMMENT '金额,正数',
`record_time` datetime NOT NULL COMMENT '交易时间',
`description` varchar(500) DEFAULT NULL COMMENT '描述/备注',
`tags` varchar(255) DEFAULT NULL COMMENT '标签,逗号分隔',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_time` (`user_id`,`record_time`),
KEY `idx_account` (`account_id`),
KEY `idx_category` (`category_id`),
CONSTRAINT `fk_record_account` FOREIGN KEY (`account_id`) REFERENCES `finance_account` (`id`),
CONSTRAINT `fk_record_category` FOREIGN KEY (`category_id`) REFERENCES `finance_category` (`id`),
CONSTRAINT `fk_record_user` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB COMMENT='收支记录表';
-- 预算表
CREATE TABLE `finance_budget` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`category_id` bigint NOT NULL COMMENT '预算针对的分类(0表示总预算)',
`budget_amount` decimal(15,2) NOT NULL COMMENT '预算金额',
`period_type` varchar(10) NOT NULL COMMENT '周期类型:MONTH, YEAR',
`period_value` varchar(20) NOT NULL COMMENT '周期值,如2025-08',
`actual_amount` decimal(15,2) DEFAULT '0.00' COMMENT '实际已发生金额',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_category_period` (`user_id`,`category_id`,`period_type`,`period_value`),
CONSTRAINT `fk_budget_category` FOREIGN KEY (`category_id`) REFERENCES `finance_category` (`id`),
CONSTRAINT `fk_budget_user` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB COMMENT='预算表';
五、 核心代码实现示例
5.1 实体类 (JPA Entity)
// 收支记录实体
@Entity
@Table(name = "finance_record")
@Data
@EqualsAndHashCode(callSuper = false)
public class FinanceRecord extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "account_id", nullable = false)
private FinanceAccount account;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id", nullable = false)
private FinanceCategory category;
@Column(nullable = false)
private Integer type; // 1-收入,2-支出
@Column(nullable = false, precision = 15, scale = 2)
private BigDecimal amount;
@Column(name = "record_time", nullable = false)
private LocalDateTime recordTime;
private String description;
private String tags;
}
5.2 数据访问层 (Repository)
@Repository
public interface FinanceRecordRepository extends JpaRepository<FinanceRecord, Long>, JpaSpecificationExecutor<FinanceRecord> {
// 查询指定用户某时间范围内的收支记录
List<FinanceRecord> findByUserAndRecordTimeBetweenOrderByRecordTimeDesc(User user, LocalDateTime start, LocalDateTime end);
// 统计指定用户某时间段内的总收入/总支出
@Query("SELECT SUM(fr.amount) FROM FinanceRecord fr WHERE fr.user = :user AND fr.type = :type AND fr.recordTime BETWEEN :start AND :end")
BigDecimal sumAmountByUserAndTypeAndPeriod(@Param("user") User user,
@Param("type") Integer type,
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end);
}
5.3 业务逻辑层 (Service)
@Service
@RequiredArgsConstructor
@Slf4j
public class FinanceRecordService {
private final FinanceRecordRepository recordRepository;
private final FinanceAccountService accountService;
@Transactional
public FinanceRecord createRecord(FinanceRecordCreateDTO createDTO, Long userId) {
User user = // ... 获取当前用户
FinanceAccount account = accountService.getAccountByIdAndUser(createDTO.getAccountId(), user);
FinanceCategory category = // ... 获取分类
// 构建记录
FinanceRecord record = new FinanceRecord();
record.setUser(user);
record.setAccount(account);
record.setCategory(category);
record.setType(createDTO.getType());
record.setAmount(createDTO.getAmount());
record.setRecordTime(createDTO.getRecordTime());
record.setDescription(createDTO.getDescription());
record.setTags(createDTO.getTags());
// 更新账户余额
BigDecimal balanceChange = createDTO.getType() == 1 ? createDTO.getAmount() : createDTO.getAmount().negate();
accountService.updateBalance(account.getId(), balanceChange);
return recordRepository.save(record);
}
// 获取月度收支统计
public MonthlyStatDTO getMonthlyStat(Long userId, YearMonth yearMonth) {
LocalDateTime start = yearMonth.atDay(1).atStartOfDay();
LocalDateTime end = yearMonth.atEndOfMonth().atTime(23, 59, 59);
BigDecimal totalIncome = recordRepository.sumAmountByUserAndTypeAndPeriod(userId, 1, start, end);
BigDecimal totalExpense = recordRepository.sumAmountByUserAndTypeAndPeriod(userId, 2, start, end);
MonthlyStatDTO stat = new MonthlyStatDTO();
stat.setYearMonth(yearMonth);
stat.setTotalIncome(totalIncome != null ? totalIncome : BigDecimal.ZERO);
stat.setTotalExpense(totalExpense != null ? totalExpense : BigDecimal.ZERO);
stat.setBalance(stat.getTotalIncome().subtract(stat.getTotalExpense()));
return stat;
}
}
5.4 控制器层 (Controller)
@RestController
@RequestMapping("/api/finance/records")
@RequiredArgsConstructor
@Tag(name = "收支记录管理")
public class FinanceRecordController {
private final FinanceRecordService recordService;
@PostMapping
@Operation(summary = "新增收支记录")
public ResponseEntity<FinanceRecordVO> createRecord(@Valid @RequestBody FinanceRecordCreateDTO createDTO,
@AuthenticationPrincipal UserDetails userDetails) {
Long userId = Long.parseLong(userDetails.getUsername());
FinanceRecord record = recordService.createRecord(createDTO, userId);
return ResponseEntity.ok(FinanceRecordVO.fromEntity(record));
}
@GetMapping("/monthly-stat")
@Operation(summary = "获取月度收支统计")
public ResponseEntity<MonthlyStatDTO> getMonthlyStat(@RequestParam @DateTimeFormat(pattern = "yyyy-MM") YearMonth yearMonth,
@AuthenticationPrincipal UserDetails userDetails) {
Long userId = Long.parseLong(userDetails.getUsername());
MonthlyStatDTO stat = recordService.getMonthlyStat(userId, yearMonth);
return ResponseEntity.ok(stat);
}
}





六、 总结与展望
本文详细阐述了一个基于Spring Boot的个人财务管理系统的设计与实现,涵盖了项目背景、技术栈选型、核心功能模块、数据库设计以及关键代码示例。该系统采用主流的Java技术栈,架构清晰,具备良好的可扩展性和可维护性。
未来,可以考虑从以下几个方面进行功能增强:
- 多端同步: 开发移动端App(React Native/Flutter),实现数据云端同步。
- 智能分析: 集成机器学习算法,对消费行为进行分析,提供个性化的省钱建议和财务规划。
- 账单导入: 支持从银行短信、邮件或账单文件(CSV、PDF)自动解析并导入交易记录。
- 多用户/家庭账本: 支持创建家庭账本,实现家庭成员间的财务共享与协作。
- 投资跟踪: 增加股票、基金等投资资产的跟踪与盈亏计算功能。
通过持续迭代,该系统有望成为一个功能全面、体验优秀的个人财务管理工具。
更多推荐


所有评论(0)