news 2026/7/2 4:48:53

基于Java的工资管理系统毕业设计:从零实现到避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Java的工资管理系统毕业设计:从零实现到避坑指南


基于Java的工资管理系统毕业设计:从零实现到避坑指南


1. 背景痛点:为什么“能跑”≠“能毕业”?

第一次做毕业设计,大多数同学都会把“能跑起来”当成终点。可真正到了答辩现场,老师一句“如果员工并发调薪,你的事务能保证一致性吗?”就让场面瞬间凝固。下面这几个坑,90% 的 Java 项目都会踩:

  • 紧耦合:所有 SQL 直接写在 JSP 里,Service 层纯当“传话筒”,后期换个数据库差点把键盘掀了。
  • SQL 注入:用 Statement 拼接字符串,演示时把or 1=1当工号输入,全表数据秒出,老师微笑不语。
  • 事务失效:Spring 声明式事务一个@Transactional就完事,结果方法被同类内部调用,回滚直接罢工。
  • 权限裸奔:把“是否为管理员”存 Cookie,前端改 0 为 1 直接进后台,演示当场社死。
  • 代码复制:每个模块都有一段“分页+模糊查询”的重复代码,导师问“你这叫 DRY?”只能尴尬陪笑。

痛定思痛,下面给出一条“新手也能复制”的逃生路线。


2. 技术选型:Spring Boot 为什么赢?

维度Servlet + JSPSpring Boot + MyBatis
依赖管理手动导 jar,版本冲突到怀疑人生起步依赖,Maven 一行搞定
配置量web.xml、spring.xml 双份暴击约定大于配置,yml 即可
监控自己写 filter 统计 QPSactuator 端点直接看
部署打 war 丢 tomcat,本地和线上环境不一致内嵌容器,jar 包一键java -jar

JPA vs MyBatis 怎么选?毕业设计场景里,复杂报表、灵活字段是常态。JPA 的自动 SQL 在“多表+动态条件”下常常翻车,而 MyBatis 写 SQL 直观,调优空间更大,对新手调试友好。一句话:能看懂 SQL,才能睡得踏实。



3. 模块化设计:先画饼再写码

3.1 工程结构(Clean Code 版)

salary-system ├─ common // 工具、常量、全局异常 ├─ employee // 员工档案 ├─ salary // 薪资计算核心 ├─ security // 登录、鉴权、密码加密 ├─ report // 报表导出 └─ admin // 系统管理(字典、参数)

每个模块都按controller → service → mapper → entity/dto/vo四层展开,同层只依赖下层,禁止横向调用,编译期就能发现循环依赖。

3.2 数据库 ER 简图

  • 员工表 t_employee(id, name, dept_id, base_salary ...)
  • 部门表 t_department
  • 用户表 t_user(登录用)
  • 角色表 t_role & 中间表 t_user_role
  • 工资表 t_salary(月份+员工联合唯一索引,保证幂等)

3.3 关键接口设计

  • 员工调薪:PUT/employee/{id}/salary传入“新基本工资”,记录旧值→写流水→更新主表,三步一个事务。
  • 工资计算:POST/salary/calculate?month=2024-05传入月份,批量异步计算,接口只返回任务编号,避免超时。
  • 权限注解:自定义@RequiresRoles("HR"),利用 Spring AOP 拦截,比写 if-else 清爽太多。

4. 核心代码:薪资计算 Service 片段

下面给出“月薪=基本工资+绩效-社保-个税”的最小可运行示例,已填注释,可直接粘贴进 IDE 跑单测。

@Service @Slf4j @RequiredArgsConstructor public class SalaryCalculationService { private final EmployeeMapper employeeMapper; private final SalaryItemMapper itemMapper; private final SalaryMapper salaryMapper; /** * 计算指定月份工资,保证幂等:若已存在则跳过 */ @Transactional(rollbackFor = Exception.class) public void calculateMonthSalary(String month) { // 1. 查询所有在职员工 List<Employee> employees = employeeMapper.selectActive(); for (Employee e : employees) { // 2. 幂等校验 if (salaryMapper.exists(e.getId(), month)) { log.warn("salary already exists, skip empId={}", e.getId()); continue; } // 3. 组装各项 BigDecimal base = e.getBaseSalary(); BigDecimal perf = itemMapper.sumPerformance(e.getId(), month); BigDecimal social = SocialUtil.calc(base); // 社保固定比例 BigDecimal tax = TaxUtil.calc(base.add(perf).subtract(social)); // 累计预扣 BigDecimal finalAmount = base.add(perf).subtract(social).subtract(tax); // 4. 落库 Salary s = Salary.builder() .empId(e.getId()) .month(month) .baseSalary(base) .performance(perf) .social(social) .tax(tax) .finalSalary(finalAmount) .build(); salaryMapper.insertSelective(s); } } }

单元测试怎么写?用@SpringBootTest + @Transactional自动回滚,既能断言,又不污染库,毕业答辩现场演示屡试不爽。


5. 安全与性能:把“能跑”升级成“能扛”

5.1 密码加密

  • 明文存密码 = 0 分;MD5 哈希 = 50 分;BCrypt 加盐 = 100 分。
  • Spring Security 自带BCryptPasswordEncoder,encode 后长度 60 位,验证时无需自己盐值。

5.2 SQL 注入

  • MyBatis#{}占位符预编译,SQL 注入概率趋近于 0。
  • 动态排序字段不能用#{},用<choose>+白名单校验,防止 order by 后面被拼接。

5.3 并发与事务

  • 批量更新工资时,在 t_salary 建唯一索引(emp_id, month),利用数据库抛DuplicateKeyException实现幂等。
  • 事务方法一定要 public,同类自调用请用 AopContext 或拆到新 Bean,否则 Spring 无法代理。

5.4 简单压测

  • 本地笔记本 4C8G,连接池默认 10 线程,2000 员工 * 12 月历史回算,平均 RT 1.3s,CPU 峰值 60%,无 FullGC。
  • 把 Druid 连接池调到 maxActive=30,RT 降到 0.7s,足够毕设答辩“性能”章节交差。


6. 生产环境避坑指南

  1. 数据库连接池
    阿里云 MySQL 5.7 默认 max_connections=200,毕设演示时把连接池 maxActive 设 100,结果老师同时开 5 台手机热点刷新,直接把库打挂。调回 30 并加等待超时,世界瞬间安静。

  2. 事务回滚失效
    捕获异常后 log 一把,又 throw 出去,事务正常回滚;若 catch 后吞掉异常,Spring 以为你“已处理”,不回滚,数据当场裂开。

  3. 前端 Mock
    本地没网?用 Mock.js 拦截 Ajax,返回随机工资条,演示流畅不掉链。记得上线前把 mock 开关干掉,否则真发钱时发现数字全是假的,HR 要来砍人。

  4. 日志级别
    生产环境 root 级别 INFO 足够,把 SQL 日志调成 DEBUG 会刷屏,磁盘 1 天 3G,云盘报警比工资条先到。

  5. 端口与防火墙
    云服务器 3306 只对 Web 机开放,后台管理端口 8080 走 Nginx 反向代理,再配 HTTPS,答辩老师问“安全怎么做”时,直接把锁形图标甩给他看。


7. 留给你的思考题

单公司场景跑通后,只要再加一个company_id字段,所有表按租户隔离,登录时把公司编码塞进 JWT,就能升级成 SaaS 多租户。或者把“导出工资 Excel”功能排进日程:用阿里巴巴 EasyExcel,2 行代码把 2 万条数据流式写出,内存稳在 50M 以内,老师看了都说“像商业软件”。

毕业设计不是句号,而是把“写能跑的代码”练成“写能用的系统”。下一步,你会把多租户、分布式锁、微服务都安排上吗?评论区聊聊你的计划,我们下篇再见。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 18:00:36

基于Dify和知识库构建高可用AI智能体客服系统的实战指南

基于Dify和知识库构建高可用AI智能体客服系统的实战指南 摘要&#xff1a;本文针对企业搭建智能客服系统时面临的知识更新滞后、意图识别不准等痛点&#xff0c;详细介绍如何利用Dify平台结合私有知识库构建高可用的AI智能体客服系统。通过知识库实时更新、多轮对话设计、意图识…

作者头像 李华
网站建设 2026/7/1 22:19:54

Hunyuan-MT-7B效果展示:瑶语→汉语传统医药典籍翻译专业性与古汉语对应

Hunyuan-MT-7B效果展示&#xff1a;瑶语→汉语传统医药典籍翻译专业性与古汉语对应 1. 为什么传统医药典籍翻译需要专用模型 你有没有想过&#xff0c;当一份记载着千年瑶族草药用法的竹简手稿摆在面前&#xff0c;上面密密麻麻写着“岜山藤、金丝吊葫芦、七叶一枝花”这类名…

作者头像 李华
网站建设 2026/7/1 23:40:54

从0开始学人像抠图,BSHM镜像让AI更简单

从0开始学人像抠图&#xff0c;BSHM镜像让AI更简单 你是不是也遇到过这些场景&#xff1a; 想给朋友圈照片换个星空背景&#xff0c;但PS抠图半小时还毛边明显&#xff1b;做电商详情页要批量处理模特图&#xff0c;手动抠图一天只能做20张&#xff1b;直播带货需要实时换背景…

作者头像 李华
网站建设 2026/7/1 7:45:17

LightOnOCR-2-1B效果展示:实测11种语言识别准确率

LightOnOCR-2-1B效果展示&#xff1a;实测11种语言识别准确率 导语&#xff1a;我们实测了LightOnOCR-2-1B在真实文档场景下的表现——不是跑分榜上的理论值&#xff0c;而是从超市小票、学术论文、多栏新闻到手写笔记的11类原生图像。它不只“认识”11种语言&#xff0c;更在…

作者头像 李华
网站建设 2026/7/1 22:36:11

Qwen3-TTS-Tokenizer-12Hz开箱即用:一键部署高保真音频编解码器

Qwen3-TTS-Tokenizer-12Hz开箱即用&#xff1a;一键部署高保真音频编解码器 Qwen3-TTS-Tokenizer-12Hz 是阿里巴巴Qwen团队推出的轻量级、高保真音频编解码核心组件。它不生成语音&#xff0c;也不理解文字&#xff0c;而是专注做一件事&#xff1a;把声音“翻译”成紧凑的数字…

作者头像 李华
网站建设 2026/7/1 22:36:59

CLAP-htsat-fused部署详解:/root/ai-models挂载路径权限与缓存策略

CLAP-htsat-fused部署详解&#xff1a;/root/ai-models挂载路径权限与缓存策略 1. 为什么需要特别关注 /root/ai-models 挂载路径&#xff1f; 你可能已经试过直接运行 python /root/clap-htsat-fused/app.py&#xff0c;界面也顺利打开了&#xff0c;但上传音频后却卡在“Lo…

作者头像 李华