1. 项目背景与核心价值
在大学计算机专业的毕业设计中,开发一个功能完整、技术栈主流的个人记账系统是个非常务实的选择。这个选题既能让开发者深入掌握企业级开发流程,又能产出具有实际应用价值的作品。SpringBoot作为当前Java领域最主流的开发框架,其简化配置、快速开发的特性特别适合毕业设计的开发周期要求。
记账系统看似简单,实则涵盖了用户管理、数据录入、统计分析等典型业务场景。我在实际开发中发现,这类系统最能锻炼开发者的全栈能力——从前端页面交互到后端业务逻辑,从数据库设计到报表生成,每个环节都需要精心设计。特别是对收支数据的可视化呈现,往往能成为毕业答辩中的亮点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计
2.1 基础技术栈
核心框架采用SpringBoot 2.7.x版本,这个长期支持版兼具稳定性和新特性。数据库选用MySQL 8.0,其JSON字段类型特别适合存储动态的收支明细。前端采用Thymeleaf模板引擎配合Bootstrap 5,既能快速搭建界面又方便后端数据绑定。
提示:建议使用SpringBoot的starter-parent作为父项目,可以省去大量依赖版本管理的工作。我在pom.xml中通常会锁定MySQL驱动版本为8.0.28,避免兼容性问题。
2.2 分层架构设计
采用经典的三层架构:
- 表现层:处理HTTP请求和页面渲染
- 业务层:核心记账逻辑和规则校验
- 持久层:数据存取和事务管理
特别在业务层,我设计了独立的财务计算服务(FinanceCalculator),将收支统计、分类汇总等复杂计算与基础CRUD操作分离。这种设计使得后期添加新报表功能时,只需扩展计算服务而不会影响原有代码。
3. 核心功能实现细节
3.1 用户认证模块
采用Spring Security实现基于角色的访问控制(RBAC)。开发时特别注意以下几点:
- 密码必须使用BCrypt加密存储
- 登录失败次数限制(5次锁定30分钟)
- 会话超时设置为30分钟
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/assets/**").permitAll()
.antMatchers("/register").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.failureHandler(loginFailureHandler())
.permitAll();
}
@Bean
public AuthenticationFailureHandler loginFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
}
3.2 记账数据建模
收支记录的核心字段包括:
- 交易金额(DECIMAL(12,2))
- 交易类型(收入/支出)
- 分类标签(餐饮、交通等)
- 交易时间
- 备注信息
数据库表设计特别注意了索引优化:
sql复制CREATE TABLE `transaction` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` BIGINT NOT NULL,
`amount` DECIMAL(12,2) NOT NULL,
`type` ENUM('INCOME','EXPENSE') NOT NULL,
`category` VARCHAR(50) NOT NULL,
`transaction_time` DATETIME NOT NULL,
`remark` TEXT,
PRIMARY KEY (`id`),
INDEX `idx_user_time` (`user_id`, `transaction_time`),
INDEX `idx_user_category` (`user_id`, `category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.3 统计报表实现
使用JFreeChart生成可视化报表时,我总结了几点优化经验:
- 预先生成周报/月报数据并缓存
- 对大数据量采用分页统计
- 前端使用ECharts实现动态交互
java复制public class ReportService {
public PieDataset createCategoryPie(Long userId, DateRange range) {
List<Transaction> transactions = transactionRepo
.findByUserAndDateRange(userId, range);
DefaultPieDataset dataset = new DefaultPieDataset();
transactions.stream()
.collect(Collectors.groupingBy(
Transaction::getCategory,
Collectors.summingDouble(Transaction::getAmount)
))
.forEach(dataset::setValue);
return dataset;
}
}
4. 开发中的典型问题与解决方案
4.1 日期时间处理
初期直接使用java.util.Date导致时区问题,后来统一改为:
- 数据库存储UTC时间
- 前端传递时间戳
- 后端使用Java 8的LocalDateTime
注意:MySQL的DATETIME类型不会存储时区信息,应用层必须明确处理时区转换。
4.2 事务管理
在批量导入交易记录时,遇到部分失败导致数据不一致的问题。最终解决方案:
java复制@Transactional
public void batchImport(List<Transaction> transactions) {
for (int i = 0; i < transactions.size(); i++) {
try {
transactionRepo.save(transactions.get(i));
} catch (Exception e) {
log.error("导入第{}条记录失败: {}", i+1, e.getMessage());
// 记录失败但继续执行
}
}
}
4.3 性能优化
当用户交易记录超过1万条时,统计报表响应变慢。采取的措施:
- 添加数据库索引
- 使用Spring Cache缓存常用报表
- 实现异步报表生成
java复制@Cacheable(value = "monthlyReport", key = "#userId+'-'+#year+'-'+#month")
public MonthlyReport generateMonthlyReport(Long userId, int year, int month) {
// 耗时统计逻辑
}
5. 项目扩展与定制建议
5.1 功能扩展方向
- 多账户管理:支持绑定银行卡、电子钱包等
- 预算功能:设置各类别支出限额
- 数据导出:Excel/PDF格式报表
- 移动端适配:响应式设计或开发App
5.2 毕业设计答辩技巧
根据我带毕设的经验,答辩时应重点展示:
- 系统架构图和技术选型理由
- 核心算法(如统计报表的生成逻辑)
- 解决的关键技术难题
- 完整的测试用例
建议准备一个演示用的数据集,包含:
- 100条以上的模拟交易记录
- 3-5个分类标签
- 跨3个月的时间范围
6. 项目部署与运维
6.1 生产环境配置
application-prod.properties典型配置:
properties复制spring.datasource.url=jdbc:mysql://localhost:3306/finance?useSSL=false&serverTimezone=UTC
spring.datasource.username=finance_prod
spring.datasource.password=StrongPassword123!
server.tomcat.connection-timeout=5000
spring.mvc.servlet.load-on-startup=1
6.2 日志管理
采用Logback配置分级日志:
xml复制<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/application.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
在实际开发中,我发现记账系统最考验的不是技术实现,而是对财务业务逻辑的理解。建议开发前先梳理清楚各种记账场景,比如退款如何处理、跨月交易怎么统计等。这些业务细节往往比技术难点更影响用户体验。
