这个基于Spring Boot的个人财务收支管理系统是一个专为大学生毕业设计开发的实战项目。作为一名有10年Java开发经验的工程师,我深知学生在毕业设计阶段面临的挑战——既要掌握技术栈,又要完成一个功能完整的系统。这个项目就是为了解决这个问题而设计的。
系统采用Spring Boot+Vue+MySQL的主流技术栈,实现了完整的财务收支管理功能。从我的实际开发经验来看,这种技术组合既保证了系统的稳定性,又降低了学习曲线,非常适合毕业设计场景。
系统采用标准的MVC设计模式,这是我推荐给所有Java开发者的基础架构方案。在实际项目中,清晰的层次划分能大幅提升代码可维护性。
视图层(View):使用Vue.js构建响应式前端界面。我特别推荐Vue的组件化开发方式,它能让前端代码像积木一样灵活组合。在项目中,每个功能模块都封装成独立组件,比如收支记录表单、统计图表等。
控制层(Controller):Spring Boot的@RestController注解简化了API开发。我在项目中采用了RESTful风格设计接口,这样前后端分离更彻底。例如:
java复制@RestController
@RequestMapping("/api/transactions")
public class TransactionController {
@Autowired
private TransactionService transactionService;
@GetMapping
public List<Transaction> list() {
return transactionService.getAll();
}
@PostMapping
public Transaction create(@RequestBody Transaction transaction) {
return transactionService.save(transaction);
}
}
服务层(Service):这里封装核心业务逻辑。我建议将复杂的业务规则放在这一层,保持Controller的简洁。例如记账时的金额校验逻辑:
java复制@Service
public class TransactionServiceImpl implements TransactionService {
@Override
public Transaction save(Transaction transaction) {
if(transaction.getAmount() <= 0) {
throw new IllegalArgumentException("金额必须大于0");
}
// 其他业务逻辑...
return transactionRepository.save(transaction);
}
}
数据访问层(DAO):使用MyBatis Plus实现,它提供了强大的CRUD封装。我特别喜欢它的Wrapper查询构造器,可以这样使用:
java复制QueryWrapper<Transaction> query = new QueryWrapper<>();
query.eq("user_id", userId)
.between("create_time", startDate, endDate)
.orderByDesc("create_time");
return transactionMapper.selectList(query);
选择Spring Boot是因为它"约定优于配置"的理念大幅简化了项目搭建。我在项目中特别利用了这些特性:
Vue.js的选择基于:
MySQL作为关系型数据库,提供了ACID事务支持,这对财务系统至关重要。我建议使用5.7以上版本,它支持JSON数据类型和更好的性能。
安全是财务系统的首要考虑。我采用JWT(JSON Web Token)实现认证,这是目前最流行的无状态认证方案。
关键实现步骤:
java复制public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
java复制@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = getTokenFromRequest(request);
if(token != null && validateToken(token)) {
String username = getUsernameFromToken(token);
UserDetails userDetails = userService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null,
userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
安全提示:务必使用HTTPS传输Token,防止中间人攻击。SECRET密钥要足够复杂,建议长度至少256位。
这是系统的核心功能模块,我设计了以下数据结构:
java复制@Entity
@Table(name = "transactions")
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private TransactionType type; // 收入/支出
private BigDecimal amount;
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
private String remark;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
private LocalDateTime createTime;
// getters/setters...
}
关键业务逻辑:
java复制@PrePersist
public void prePersist() {
this.createTime = LocalDateTime.now();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if(auth != null) {
this.user = ((UserDetailsImpl)auth.getPrincipal()).getUser();
}
}
java复制public BigDecimal getBalance(Long userId) {
List<Transaction> transactions = transactionRepository.findByUserId(userId);
return transactions.stream()
.map(t -> t.getType() == TransactionType.INCOME ?
t.getAmount() : t.getAmount().negate())
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
我实现了多种统计视图,这是毕业设计中的亮点部分:
java复制@Query("SELECT t.category.name, SUM(t.amount) FROM Transaction t " +
"WHERE t.user.id = :userId AND t.type = 'EXPENSE' " +
"GROUP BY t.category.name")
List<Object[]> getCategoryStats(@Param("userId") Long userId);
java复制@Query("SELECT FUNCTION('DATE_FORMAT', t.createTime, '%Y-%m'), SUM(t.amount) " +
"FROM Transaction t WHERE t.user.id = :userId AND t.type = 'INCOME' " +
"GROUP BY FUNCTION('DATE_FORMAT', t.createTime, '%Y-%m')")
List<Object[]> getMonthlyIncome(@Param("userId") Long userId);
前端使用ECharts展示这些数据,创建了直观的饼图和折线图。
经过多年实践,我总结出高效的开发环境配置:
IDE选择:IntelliJ IDEA Ultimate版(学生可免费申请)
本地开发配置:
yaml复制# application-dev.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/finance?useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
hibernate:
ddl-auto: update
问题1:Vue前端跨域访问
java复制@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("*");
}
};
}
问题2:MyBatis Plus分页失效
java复制@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
问题3:日期时间处理
java复制@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
java复制@Table(name = "transactions", indexes = {
@Index(name = "idx_user_type", columnList = "user_id,type"),
@Index(name = "idx_create_time", columnList = "createTime")
})
java复制@Cacheable(value = "categories", key = "#userId")
public List<Category> getUserCategories(Long userId) {
return categoryRepository.findByUserId(userId);
}
java复制transactionService.saveBatch(transactions);
根据我指导数百名学生的经验,优秀毕业论文应包含:
系统架构图:使用StarUML或Draw.io绘制
数据库ER图:展示主要实体关系
核心算法伪代码:如统计分析的实现逻辑
测试用例设计:包括功能测试和性能测试
演示准备:
常见问题准备:
PPT制作技巧:
服务器要求:
数据库配置:
sql复制CREATE DATABASE finance CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'finance'@'%' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON finance.* TO 'finance'@'%';
FLUSH PRIVILEGES;
bash复制mvn clean package -DskipTests
bash复制nohup java -jar finance-system.jar --spring.profiles.active=prod > app.log 2>&1 &
健康检查:Spring Boot Actuator端点
日志管理:
yaml复制logging:
file:
name: finance.log
level:
root: info
org.springframework.web: debug
bash复制mysqldump -u finance -p finance > backup_$(date +%F).sql
这个基础系统可以进一步扩展:
我在实际项目中发现,添加预算功能特别受用户欢迎。实现思路是:
java复制@Entity
public class Budget {
@Id
@GeneratedValue
private Long id;
@ManyToOne
private User user;
@ManyToOne
private Category category;
private BigDecimal amount;
private YearMonth month;
public boolean isExceeded(List<Transaction> transactions) {
BigDecimal spent = transactions.stream()
.filter(t -> t.getCategory().equals(category))
.map(Transaction::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
return spent.compareTo(amount) > 0;
}
}
这个毕业设计项目采用了企业级开发标准和最佳实践,代码结构清晰,文档完整,非常适合作为学习Spring Boot和Vue的实战案例。我在开发过程中特别注意了代码的可读性和可维护性,每个关键类和方法都有详细注释,方便理解和扩展。