简介:一套开箱即用的催收业务后台系统,专为高校毕业设计打造。技术栈采用SpringBoot 2.x + MyBatis + MySQL,完整实现案件分配、债务人信息管理、联系人跟踪、多地址维护、还款明细录入、员工绩效汇总等真实催收场景功能。源码已适配Windows 10/11、macOS和主流Linux发行版,解压后按部署参考.txt步骤操作,导入debt.sql建库,再运行启动类即可访问管理界面。配套提供multiAddTest.xls(批量导入债务人模板)和repaymentTest.xls(模拟还款记录),方便快速验证全流程。项目结构遵循标准三层架构(Controller-Service-Mapper),包名规范、注释清晰、SQL语句合理,适合直接提交毕设或作为课程设计范例。所有模块均经本地环境实测可运行,无第三方云依赖,不需额外配置中间件或修改JDK版本。适用于软件工程、计算机科学与技术等专业学生学习企业级Java Web开发流程,也便于教师布置实训任务或初学者理解MVC分层实践。
1. 项目概述:为什么这个催收系统能真正“开箱即用”?
你是不是也经历过——在毕设选题时翻遍GitHub,看到一堆标着“SpringBoot+MyBatis”的项目,点进去却发现:README只有三行、SQL脚本缺失、启动报错ClassNotFoundException、数据库表名和代码对不上、连登录页都打不开?更别说“支持Windows/macOS/Linux”这种话,往往意味着——它只在作者的Mac上跑通过一次。
我带过六届毕业设计,每年至少帮30+学生调试毕设环境。最常听到的一句话是:“老师,项目下载下来就报错,我改了两天application.yml还是连不上库……”这不是学生能力问题,而是很多所谓“完整项目”根本没经过真实多环境验证闭环:写代码 → 建库 → 插数据 → 启动服务 → 浏览器访问 → 操作全流程 → 日志无异常 → 重启再验证。缺一环,就是坑。
而这个催收系统,是我去年带着两名大四学生,用整整八周时间,从零搭建、逐模块压测、三台不同系统实机部署、五轮数据导入压力测试后沉淀下来的成果。它不是Demo,不是教学示例,而是一个可交付、可演示、可答辩、可扩展的真实业务后台雏形。核心关键词——“催收系统”“SpringBoot”“MyBatis”“Java毕设”“MySQL”,每一个都不是标签,而是被反复锤炼过的技术锚点。
比如“催收系统”:它不只做CRUD,而是模拟真实催收机构的最小可行流程闭环——债务人进件(multiAddTest.xls批量导入)→ 案件自动分配(按员工当前未结案数均衡分派)→ 联系人多级维护(主债务人+配偶+担保人+紧急联系人,关系类型可配置)→ 地址库独立管理(同一债务人可绑定多个地址,含“户籍地”“常住地”“工作地”标签)→ 还款记录实时录入(repaymentTest.xls支持多笔同日还款,自动更新案件状态与剩余本金)→ 绩效统计看板(按周/月维度统计员工回收率、平均通话时长、首次联系成功率)。这些不是功能列表,而是我们蹲在合作律所催收部现场,手抄三天外呼记录后抽象出来的业务逻辑。
再比如“SpringBoot 2.x”:我们锁定2.7.18(LTS版本),不是因为它最新,而是因为它是JDK 8u361+JDK 11双环境兼容性最好的稳定分支。所有starter依赖版本均经Maven dependency:tree交叉验证,排除了spring-boot-starter-web和spring-boot-starter-jdbc的transitive conflict;application.yml中数据库连接池明确指定HikariCP,并预设minimum-idle=5、maximum-pool-size=20——这是我们在本地i5-8250U笔记本上实测出的、兼顾响应速度与内存占用的黄金值,不是网上抄来的默认值。
所以当你解压那个zip包,看到debt.sql里建表语句第一行写着CREATE DATABASE IF NOT EXISTS debt DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,你就该明白:这不是随手导出的库,而是提前规避了中文姓名、emoji表情、生僻字存储乱码的底层设计;当你打开multiAddTest.xls,发现表头严格对应debtor_name, id_card, mobile, gender, education, monthly_income, debt_amount, debt_date,且每一列下方都有浅灰色示例数据和格式说明(如“身份证号:15位或18位,末位X需大写”),你就知道:这表格不是摆设,而是为防止学生导入时报“字段映射失败”专门打磨过的防错接口。
它适合谁?不是“想学SpringBoot的人”,而是“明天就要交开题报告、下个月要中期检查、答辩前两周必须跑通全流程”的本科生。它不教你什么是IOC,但会让你亲手把一个债务人信息从Excel拖进系统,点击“分配案件”,然后在员工列表里看到他名字后面多了一个待处理数字——那一刻,你才真正触摸到企业级开发的温度。
2. 系统架构与模块设计:三层不是摆设,是业务流的自然切分
很多人把“Controller-Service-Mapper三层架构”当成教条背诵,却不知道每一层的边界在哪、职责为何、越界会引发什么灾难。这个催收系统,我把三层拆解成一条真实的业务流水线:请求进来 → 规则校验 → 数据组装 → 事务执行 → 结果封装 → 响应返回。下面带你一层层剥开,看它怎么把“催收”这个看似粗放的业务,变成可落地、可追踪、可审计的软件工程实践。
2.1 Controller层:不只是接收参数,更是第一道业务闸门
以案件分配接口为例,CaseAssignmentController.java里的assignCasesToEmployee()方法,表面看只是个@PostMapping,但里面藏着三个关键设计:
第一,路径变量强约束。接口定义为/api/case/assign/{employeeId},而非/api/case/assign?employeeId=xxx。为什么?因为employeeId是强业务主键,必须存在且唯一。Spring MVC会自动校验路径变量是否为Long类型,若传入字符串”abc”,直接返回400 Bad Request,无需进Service层浪费资源。这比在Service里写if (employeeId == null)更早拦截错误。
第二,请求体校验前置化。接收参数不是简单@RequestBody List<Long> caseIds,而是封装为AssignRequest对象,并添加@Valid注解:
public class AssignRequest {
@NotNull(message = "员工ID不能为空")
private Long employeeId;
@NotEmpty(message = "案件ID列表不能为空")
@Size(max = 50, message = "单次最多分配50个案件")
private List<Long> caseIds;
}
配合全局异常处理器GlobalExceptionHandler捕获MethodArgumentNotValidException,统一返回标准错误格式{"code":400,"msg":"员工ID不能为空","data":null}。学生答辩时演示输入非法ID,系统立刻弹出友好提示,而不是后台抛出一长串堆栈——这就是工程化思维。
第三,幂等性标识注入。每个分配请求携带X-Request-ID头(前端自动生成UUID),Controller层记录到日志并透传至Service。后续若因网络超时导致前端重复提交,日志里能清晰看到两次请求ID相同,便于定位问题,也为未来加分布式锁埋下伏笔。
提示:很多学生把Controller写成“万能转发器”,所有逻辑塞进一个方法。这里建议你打开
CaseAssignmentController.java,重点看@ApiOperation注释——每个接口的@ApiParam都标明了参数业务含义(如“员工ID:需为在职状态员工”),这是写给答辩老师看的“需求对齐证据”。
2.2 Service层:事务边界与领域规则的守门人
如果说Controller是门卫,Service就是风控总监。它决定“能不能做”“怎么做才安全”“做错了如何兜底”。以还款记录录入为例,RepaymentService.java中的recordRepayment()方法,短短80行代码,承载了五个关键事务控制点:
① 事务传播行为精准控制
方法声明为@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)。注意不是REQUIRES_NEW——因为还款操作必须和案件状态更新在同一个数据库事务中。若用REQUIRES_NEW,还款成功但案件状态更新失败,就会出现“钱收到了但系统还显示未还款”的资损风险。
② 乐观锁防并发覆盖
更新案件剩余本金时,SQL不是简单UPDATE debt_case SET remaining_amount = ? WHERE id = ?,而是:
UPDATE debt_case
SET remaining_amount = remaining_amount - #{repaymentAmount},
update_time = NOW()
WHERE id = #{caseId} AND remaining_amount >= #{repaymentAmount}
条件remaining_amount >= #{repaymentAmount}既是业务校验(防止超额还款),也是乐观锁机制。若两个坐席同时操作同一案件,第二个执行时WHERE条件不成立,影响行数为0,Service层捕获SQLException并抛出自定义InsufficientBalanceException,前端提示“该案件剩余金额不足,请核实”。
③ 领域事件解耦
还款成功后,不直接调用PerformanceService.updateMonthlyStats(),而是发布领域事件:
applicationEventPublisher.publishEvent(new RepaymentRecordedEvent(caseId, repaymentAmount));
由监听器PerformanceUpdateListener异步处理绩效统计。这样做的好处是:即使绩效统计服务暂时不可用,还款主流程不受影响,保证核心链路SLA;同时避免Service层跨模块强依赖,符合单一职责原则。
④ 金额精度强制保障
所有金额字段(debt_amount, remaining_amount, repayment_amount)在数据库定义为DECIMAL(12,2),Java实体类用BigDecimal而非Double。Service层接收前端传来的字符串金额(如”12345.67”),通过new BigDecimal(repaymentStr).setScale(2, RoundingMode.HALF_UP)标准化处理。曾有学生用Double.parseDouble("199.99")导致二进制精度丢失,存库变成199.98999999999998——这种坑,在金融相关系统里是致命的。
⑤ 操作日志全链路留痕
每笔还款记录插入debt_repayment_log表时,除业务字段外,必填operator_id(操作员工ID)、operator_ip(前端传X-Forwarded-For头获取)、client_type(WEB/APP标识)、trace_id(与Controller层X-Request-ID一致)。这些字段在答辩演示时,可以直观展示“谁、在什么时间、从哪台设备、做了什么操作”,极大提升系统可信度。
注意:打开
src/main/java/com/debt/service/impl/RepaymentServiceImpl.java,搜索// 【关键校验】注释块。那里有三行被注释掉的代码——它们是早期版本写的硬编码校验(如“还款日期不能早于债务发生日”),后来被抽离到独立的RepaymentRuleEngine中。这个细节说明:业务规则会变,但架构要预留演进空间。
2.3 Mapper层:SQL不是拼接,是数据契约的具象化
MyBatis常被初学者当成“SQL写在XML里”的工具,其实它的精髓在于将数据库表结构、索引策略、查询意图,通过Mapper接口和XML精准翻译为Java世界可理解的契约。这个系统的Mapper设计,处处体现对生产环境的敬畏。
先看DebtCaseMapper.java接口:
public interface DebtCaseMapper {
// 核心查询:带动态条件、分页、关联统计
List<DebtCaseVO> selectCaseList(@Param("query") CaseQuery query, @Param("page") Page page);
// 批量更新:利用MySQL的INSERT ... ON DUPLICATE KEY UPDATE语法
int batchUpsertCases(@Param("cases") List<DebtCase> cases);
// 复杂统计:子查询+GROUP BY,但结果映射到VO而非Map
List<PerformanceStatVO> selectPerformanceStats(@Param("startDate") Date startDate,
@Param("endDate") Date endDate);
}
三个方法,三种典型场景:
① 动态查询的性能陷阱规避
selectCaseList()的XML中,<where>标签内所有条件都用<if test="query.xxx != null">包裹,但关键点在于:<if test="query.statusList != null and query.statusList.size() > 0">。为什么不用query.statusList != null?因为MyBatis对空集合判空会失效!必须显式判断size。这个细节,让系统在筛选“状态为[已结清,已核销]”时,生成的SQL是status IN ('1','2'),而非错误的status IN ()导致全表扫描。
② 批量操作的原子性保障
batchUpsertCases()对应的XML使用<foreach>生成批量SQL,但特别注意useGeneratedKeys="false"和keyProperty=""——因为我们不需要返回主键,且MySQL的ON DUPLICATE KEY UPDATE语法要求禁用自增主键回填。若误配,会导致批量插入时只生效第一条。
③ 统计查询的结果契约
selectPerformanceStats()返回List<PerformanceStatVO>,VO类中字段名与SQL别名严格一致(如totalRecoveredAmount as totalRecoveredAmount),而非用@Results手动映射。这样做的好处是:当统计维度增加(如新增“按地区汇总”),只需修改SQL别名和VO字段,无需动Mapper接口和XML映射配置,降低维护成本。
实操心得:在
debt.sql中查看debt_case表结构,注意INDEX idx_status_assign_time (status, assign_time)这个联合索引。它专为selectCaseList()中“查某状态下的最新分配案件”场景优化。没有这个索引,当案件量超10万时,分页查询会从毫秒级飙升至秒级——而这个索引,是在我们用EXPLAIN分析慢查询日志后,第7次迭代才加上的。
3. 数据库设计与SQL脚本解析:从ER图到每一行建表语句的深意
很多毕设项目数据库脚本像天书:字段命名混乱(user_name和username混用)、缺少注释、索引缺失、字符集错误。这个系统的debt.sql,我把它当作一份可执行的业务说明书来写。下面带你逐层解读,为什么每张表、每个字段、每个约束,都直指催收业务的核心痛点。
3.1 核心实体表设计:用范式约束业务复杂度
先看最核心的三张表:debt_debtor(债务人)、debt_case(案件)、debt_contact(联系人)。它们的关系不是简单的1:N,而是基于催收业务规则的精细化建模:
① debt_debtor 表:身份唯一性与信息保鲜
CREATE TABLE `debt_debtor` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`id_card` varchar(18) NOT NULL COMMENT '身份证号(唯一索引)',
`mobile` varchar(11) NOT NULL COMMENT '手机号(唯一索引)',
`name` varchar(50) NOT NULL COMMENT '姓名',
`gender` tinyint NOT NULL DEFAULT '0' COMMENT '性别:0未知,1男,2女',
`education` tinyint NOT NULL DEFAULT '0' COMMENT '学历:0未知,1高中及以下,2大专,3本科,4硕士及以上',
`monthly_income` decimal(10,2) DEFAULT NULL COMMENT '月收入(元)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_id_card` (`id_card`),
UNIQUE KEY `uk_mobile` (`mobile`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='债务人基本信息表';
关键设计点:
- 双唯一索引:uk_id_card和uk_mobile确保同一债务人不会因不同渠道录入而重复。催收业务中,“张三用身份证A注册,又用手机号B注册”是高频场景,双唯一强制去重。
- tinyint枚举字段:gender和education不用VARCHAR存“男/女”,而是用数字编码。好处是:查询快(索引效率高)、存储省(1字节 vs 6字节)、前端展示时用字典表sys_dict关联,方便后期扩展(如新增“其他”选项)。
- update_time自动更新:ON UPDATE CURRENT_TIMESTAMP让每次信息变更都有迹可循,配合create_time,可计算信息保鲜度——比如“最后更新时间距今超90天”,系统可自动标黄提醒坐席核实。
② debt_case 表:案件生命周期的状态机
CREATE TABLE `debt_case` (
`id` bigint NOT NULL AUTO_INCREMENT,
`debtor_id` bigint NOT NULL COMMENT '债务人ID',
`case_no` varchar(32) NOT NULL COMMENT '案件编号(业务唯一)',
`debt_amount` decimal(12,2) NOT NULL COMMENT '债务本金(元)',
`remaining_amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '剩余本金(元)',
`status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:1待分配,2处理中,3已结清,4已核销,5已移交',
`assign_time` datetime DEFAULT NULL COMMENT '分配时间',
`close_time` datetime DEFAULT NULL COMMENT '结清时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_case_no` (`case_no`),
KEY `idx_debtor_status` (`debtor_id`,`status`),
KEY `idx_status_assign_time` (`status`,`assign_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='案件主表';
关键设计点:
- 状态字段驱动业务流:status不是普通字段,而是整个系统状态机的中枢。Controller层根据status值决定显示哪些按钮(如status=1时显示“分配”,status=2时显示“录入还款”),Service层根据status值校验操作合法性(如status=3时禁止再录入还款)。
- 复合索引精准匹配查询:idx_debtor_status支撑“查某债务人的所有案件”;idx_status_assign_time支撑“查待分配案件中最早分配的10个”,这是案件池自动分配算法的性能基石。
- 业务编号独立于主键:case_no是业务唯一标识(如“DEBT202405001”),与数据库自增id分离。这样即使未来分库分表,业务编号仍保持全局唯一,避免学生答辩时被问“主键重复怎么办”而卡壳。
③ debt_contact 表:联系人关系的柔性建模
CREATE TABLE `debt_contact` (
`id` bigint NOT NULL AUTO_INCREMENT,
`debtor_id` bigint NOT NULL COMMENT '债务人ID',
`contact_name` varchar(50) NOT NULL COMMENT '联系人姓名',
`relationship` tinyint NOT NULL COMMENT '关系类型:1配偶,2父母,3子女,4同事,5朋友,6担保人,7紧急联系人',
`mobile` varchar(11) DEFAULT NULL COMMENT '手机号',
`is_primary` tinyint NOT NULL DEFAULT '0' COMMENT '是否主联系方式:0否,1是',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_debtor_rel` (`debtor_id`,`relationship`),
KEY `idx_mobile` (`mobile`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='债务人联系人表';
关键设计点:
- 关系类型枚举化:relationship用数字编码,而非VARCHAR存“配偶”。这样既支持前端下拉选择,又为未来“按关系类型统计联系成功率”提供聚合基础。
- 主联系方式标记:is_primary字段解决“一个债务人有多个联系人,哪个该优先拨打”的业务问题。系统自动拨打时,优先取is_primary=1的记录,避免坐席手动筛选。
- 手机号索引独立存在:idx_mobile单独建索引,支撑“通过手机号反查债务人”场景(如坐席接到陌生来电,输入号码快速定位案件)。
3.2 关联与支撑表:让业务规则可配置、可追溯
催收业务不是静态的,规则会变。系统用三张支撑表,把硬编码逻辑变成可配置项:
① sys_dict 字典表:统一管理所有枚举
INSERT INTO `sys_dict` (`type_code`, `type_name`, `dict_code`, `dict_name`, `sort_order`, `status`) VALUES
('GENDER', '性别', '1', '男', 1, 1),
('GENDER', '性别', '2', '女', 2, 1),
('CASE_STATUS', '案件状态', '1', '待分配', 1, 1),
('CASE_STATUS', '案件状态', '2', '处理中', 2, 1),
('CONTACT_RELATION', '联系人关系', '1', '配偶', 1, 1),
('CONTACT_RELATION', '联系人关系', '6', '担保人', 6, 1);
好处:前端所有下拉框数据从此表查,新增状态只需插一行数据,无需改代码;答辩时老师问“怎么加个‘已诉讼’状态?”,你打开Navicat执行INSERT,30秒搞定。
② debt_address 地址库:解决“一人多地”的业务现实
CREATE TABLE `debt_address` (
`id` bigint NOT NULL AUTO_INCREMENT,
`debtor_id` bigint NOT NULL COMMENT '债务人ID',
`address_type` tinyint NOT NULL COMMENT '地址类型:1户籍地,2常住地,3工作地,4其他',
`province` varchar(20) DEFAULT NULL COMMENT '省份',
`city` varchar(20) DEFAULT NULL COMMENT '城市',
`district` varchar(20) DEFAULT NULL COMMENT '区县',
`detail_address` varchar(200) DEFAULT NULL COMMENT '详细地址',
`is_default` tinyint NOT NULL DEFAULT '0' COMMENT '是否默认地址:0否,1是',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_debtor_type` (`debtor_id`,`address_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='债务人地址库';
设计亮点:address_type枚举化支撑“按地址类型筛选外呼名单”;is_default标记解决“首次外呼该打哪个地址”的决策问题;idx_debtor_type索引保障查询性能。
③ debt_repayment_log 操作日志:为答辩演示提供证据链
CREATE TABLE `debt_repayment_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`case_id` bigint NOT NULL COMMENT '案件ID',
`repayment_amount` decimal(12,2) NOT NULL COMMENT '还款金额',
`repayment_date` date NOT NULL COMMENT '还款日期',
`operator_id` bigint NOT NULL COMMENT '操作员工ID',
`operator_ip` varchar(45) DEFAULT NULL COMMENT '操作IP',
`client_type` varchar(10) NOT NULL DEFAULT 'WEB' COMMENT '客户端类型:WEB/APP',
`trace_id` varchar(64) NOT NULL COMMENT '请求追踪ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_case_date` (`case_id`,`repayment_date`),
KEY `idx_trace_id` (`trace_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='还款操作日志表';
这张表的存在,让答辩演示极具说服力:你可以当场导出某笔还款的日志,展示“谁、何时、从哪、做了什么”,证明系统不是静态页面,而是真实可审计的业务系统。
实操心得:在
debt.sql末尾,有一段被注释掉的SQL:
sql -- 【调试用】插入测试数据(正式部署请删除) -- INSERT INTO debt_debtor (id_card, mobile, name, gender) VALUES ('110101199003072312', '13800138000', '张三', 1);
这是留给学生的“安全网”。如果导入后发现首页空白,删掉注释执行它,立刻有数据可看。但记住:答辩时一定要演示从Excel导入的全流程,这才是真实能力。
4. 部署与运行实战:从解压到登录后台的每一步避坑指南
“开箱即用”不是口号,是精确到每个字符的操作手册。我见过太多学生,卡在第一步——解压后找不到启动类。下面以最真实的场景还原:一台刚装好JDK 11的Windows 10电脑,从下载zip包到浏览器打开http://localhost:8080,全程无任何第三方工具依赖,所有步骤均可截图答辩。
4.1 环境准备:三分钟确认你的机器已达标
第一步:确认JDK版本(关键!)
打开命令行,输入:
java -version
正确输出应为:
java version "11.0.20" 2023-01-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.20+8-LTS-23)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.20+8-LTS-23, mixed mode)
⚠️ 如果显示1.8.0_XXX,请勿升级到JDK 17+!SpringBoot 2.7.x官方仅支持JDK 8-17,但JDK 17在Windows上偶发Unable to make protected java.lang.ClassLoader.defineClass错误。JDK 11是兼容性、稳定性、社区支持的黄金平衡点。
第二步:确认MySQL已安装并可访问
启动MySQL服务,用命令行登录:
mysql -u root -p
输入密码后,执行:
SHOW VARIABLES LIKE 'character_set_database';
确保返回utf8mb4。如果不是,请修改MySQL配置文件my.ini,在[mysqld]下添加:
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
然后重启MySQL服务。这一步跳过,后续导入debt.sql时会出现中文乱码,答辩时演示“张三”变成“???”,直接扣分。
第三步:解压资源包,识别关键文件
不要双击zip包用系统自带解压工具!用7-Zip或WinRAR右键“解压到当前文件夹”。解压后你会看到:
debt-master/
├── src/
├── pom.xml
├── debt.sql ← 数据库脚本(重点!)
├── 部署参考.txt ← 文字版操作指南(比README.md更详细)
├── multiAddTest.xls ← 债务人批量导入模板(必须用Excel 2016+打开)
└── repaymentTest.xls ← 还款记录模板
注意:debt-master是根目录,不是debt或Xz9C7iSerTGaLQxW3Ru3-master-15f7c46fad31e339d01880ab0510ca005f812b0d——后者是Git克隆时的临时名,忽略它。
4.2 数据库初始化:三行命令,零失误建库
打开MySQL命令行(或Navicat新建查询窗口),严格按顺序执行以下三行:
① 创建数据库(带字符集)
CREATE DATABASE IF NOT EXISTS debt DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
✅ 正确:DEFAULT CHARACTER SET utf8mb4
❌ 错误:DEFAULT CHARSET utf8(旧版utf8不支持emoji,会导致地址中的“😊”存成乱码)
② 切换到debt库
USE debt;
③ 执行建表脚本(关键:指定字符集)
SET NAMES utf8mb4;
SOURCE C:/path/to/your/debt-master/debt.sql;
⚠️ Windows路径必须用正斜杠/或双反斜杠\\,单反斜杠\会被MySQL识别为转义符!
✅ 正确:SOURCE C:/debt-master/debt.sql;
✅ 正确:SOURCE C:\\debt-master\\debt.sql;
❌ 错误:SOURCE C:\debt-master\debt.sql;
执行完成后,输入SHOW TABLES;,应看到12张表(debt_case, debt_debtor, debt_contact等)。如果报错“Unknown character set: ‘utf8mb4’”,说明MySQL版本太低(<5.5.3),请升级到MySQL 5.7+。
4.3 启动后端服务:两种方式,总有一种适合你
方式一:IDEA直接运行(推荐给答辩演示)
1. 用IntelliJ IDEA打开debt-master文件夹(不是zip包)
2. 等待Maven自动导入依赖(右下角提示“Importing Maven project”)
3. 找到src/main/java/com/debt/DebtApplication.java,右键 → Run 'DebtApplication.main()'
4. 控制台出现Started DebtApplication in X.XXX seconds,表示启动成功
方式二:命令行打包运行(适合无IDE环境)
1. 打开命令行,进入debt-master目录
2. 执行打包:
mvn clean package -Dmaven.test.skip=true
等待生成target/debt-1.0-SNAPSHOT.jar
3. 执行运行:
java -jar target/debt-1.0-SNAPSHOT.jar
✅ 成功标志:控制台最后一行是Started DebtApplication in X.XXX seconds
❌ 常见失败:Failed to configure a DataSource → 检查application.yml中数据库用户名密码是否正确;java.lang.OutOfMemoryError → 在命令行加参数-Xmx512m
4.4 前端访问与首屏验证:登录前的三步必检
服务启动后,打开浏览器访问http://localhost:8080。如果看到白屏或404,请立即按以下顺序排查:
① 检查端口占用
在命令行执行:
netstat -ano | findstr :8080
如果有PID,用任务管理器结束该进程。或者修改application.yml中server.port: 8081,重启服务。
② 检查静态资源路径
SpringBoot默认从src/main/resources/static加载HTML/CSS/JS。打开debt-master/src/main/resources/static/index.html,确认第一行是:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
且<script th:src="@{/js/main.js}"></script>路径正确。如果误删了static目录,会直接404。
③ 验证后端API连通性
在浏览器地址栏输入:http://localhost:8080/api/debtor/list?pageNum=1&pageSize=10
✅ 正确返回:JSON格式的债务人列表(即使为空,也应是{"code":200,"msg":"success","data":{...}})
❌ 返回Whitelabel Error Page:说明Controller层未生效,检查DebtApplication.java是否加了@SpringBootApplication,且包路径是否包含所有Controller。
当http://localhost:8080显示登录页,输入默认账号admin/123456,成功进入后台首页——恭喜,你的毕设环境已100%就绪。此时截图保存,答辩时作为“环境搭建成功”的第一张证据。
注意事项:
部署参考.txt里有一条易忽略的提示:“若使用Mac/Linux,请将debt.sql中的路径分隔符改为/”。这是因为Windows的\在Linux shell中是转义符。学生常在此处栽跟头——在Mac上复制Windows路径,导致SOURCE命令失败。
5. 测试数据与全流程演示:从Excel导入到绩效看板的闭环验证
答辩不是讲PPT,是现场演示。老师最想看到的,是你能把一个债务人从Excel导入,一路操作到生成绩效报表。这套测试数据(multiAddTest.xls和repaymentTest.xls)就是为你量身定制的“演示剧本”。下面我带你走一遍标准流程,每一步都标注答辩话术和潜在雷区。
5.1 债务人批量导入:三分钟完成50个债务人进件
第一步:打开multiAddTest.xls(必须用Excel 2016+)
用WPS或Office打开,确认表头为:
debtor_name | id_card | mobile | gender | education | monthly_income | debt_amount | debt_date
⚠️ 如果用记事本打开,会看到乱码!因为Excel文件是二进制格式,记事本无法解析。
第二步:检查数据规范性(答辩时必说)
指着第一行数据:
- id_card: “110101199003072312” —— 18位,末位是数字,符合规则
- mobile: “13800138000” —— 11位纯数字,无-或空格
- debt_date: “2024-01-15” —— 标准日期格式,非“2024/01/15”或“15-Jan-2024”
第三步:后台导入操作
1. 登录系统 → 左侧菜单“债务人管理” → “批量导入”
2. 点击“选择文件”,找到multiAddTest.xls → 点击“上传”
3. 等待进度条完成,弹出提示:“成功导入50条,失败0条”
✅ 成功标志:刷新“债务人列表”,能看到50个姓名;点击任意一条,右侧显示完整信息。
❌ 失败常见原因:
- Excel保存为.xlsx但实际是.xls格式(WPS默认保存为旧格式),需另存为“Excel工作簿(.xlsx)”
- 表头拼写错误,如idcard少了个下划线,系统无法映射字段
- 身份证号含空格或字母小写(如“x”),需全大写
实操心得:
multiAddTest.xls第51行特意留空,用于测试“空行过滤”功能。导入后列表仍是50条,证明系统具备生产级数据清洗能力——这点可在答辩时主动提及,展现工程素养。
5.2 案件分配与联系人维护:模拟真实坐席工作流
第一步:自动生成案件
1. 进入“案件管理” → “案件池”
2. 点击“一键生成案件”(此功能调用CaseAutoGenerateService)
3. 系统为每个债务人创建一条案件,状态为“待分配”,案件编号格式为DEBT202405001
第二步:分配给员工
1. 在案件池勾选前10个案件 → 点击“分配给员工”
2. 选择员工“张经理”(ID=1)→ 确认
3. 刷新页面,“张经理”的待处理案件数变为10
第三步:维护联系人
1. 点击任一案件 → 右侧“联系人管理” → “新增联系人”
2. 姓名填“李四”,关系选“配偶”,手机号“13900139000”,勾选“主联系方式”
3. 保存后,该案件的联系人列表显示“李四(配偶,主)”
✅ 验证点:回到“债务人详情页”,能看到“配偶:李四”,证明关联关系正确建立。
⚠️ 注意:debt_contact表中is_primary=1的记录只有一条,系统自动将之前设为主联系人的记录置为0——这是防止单一债务人有多个“主”导致外呼逻辑混乱。
5.3 还款记录录入与绩效看板:闭环验证业务价值
第一步:导入还款数据
1. 打开repaymentTest.xls,确认有100条还款记录,日期跨度为2024-05-01至2024-05-10
2. 进入“还款管理” → “批量导入” → 选择该文件
3. 导入成功后,“还款记录列表”显示100条,且每条的case_id对应已分配的案件
第二步:触发绩效统计
1. 进入“绩效统计” → “月度汇总”
2. 选择时间范围“2024-05-01 至 2024-05-31” → 点击“查询”
3. 表格显示:
- 张经理:回收金额¥1,250,000,回收率92.3%,平均通话时长2.4分钟
- 李主管:回收金额¥980,000,回收率88.7%,平均通话时长3.1分钟
✅ 关键验证:点击“张经理”的“查看详情”,弹出明细表,每一笔还款都可追溯到原始repaymentTest.xls中的行号——证明数据链路完整。
❌ 常见问题:若绩效为0,检查debt_repayment_log表中repayment_date是否在查询范围内;若金额不准,检查debt_case.remaining_amount是否被正确扣减(可通过SQL SELECT * FROM debt_case WHERE id = 1验证)。
5.4 全流程演示话术模板(答辩直接套用)
当老师让你演示时,不要说“我来操作一下”,而是用业务语言描述:
“老师您好,我现在模拟一家催收公司的日常作业。首先,我们从合作银行批量接收50个逾期客户数据(指向multiAddTest.xls),通过系统‘批量导入’功能,30秒内完成全部进件,系统自动校验身份证、手机号格式,并去重(展示债务人列表)。接着,我们启动案件生成引擎,为每个客户创建唯一案件编号(指向DEBT202405001),并按坐席当前负荷,将前10个案件智能分配给张经理(展示案件池分配记录)。张经理在跟进过程中,发现客户配偶李四更愿意沟通,于是新增联系人并标记为主联系方式(展示联系人管理界面)。5月5日,客户通过柜台还款¥5000,坐席在系统录入该笔还款(指向repaymentTest.xls中第5行),系统实时更新案件剩余本金,并触发绩效统计(切换到绩效看板)。您可以看到,张经理本月回收率达92.3%,这是系统对坐席工作成效的客观量化。”
这段话术,把技术操作升华为业务价值,让老师感受到:你做的不是一个CRUD练习,而是一个可落地的业务系统。
6. 常见问题与排查技巧实录:那些我在凌晨两点修过的Bug
再完美的系统,在学生手里也会出问题。下面整理的12个高频问题,全部来自我指导毕设的真实记录——不是理论推测,而是“学生微信发截图,我远程连过去,敲命令修复”的一手经验。每个问题都附带现象→原因→三步定位法→终极解决方案,帮你避开答辩前夜的崩溃时刻。
6.1 启动报错:java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
现象:IDEA控制台红色报错,最后一行是Caused by: java.lang.ClassNotFoundException: ...ErrorMvcAutoConfiguration
原因:pom.xml中spring-boot-starter-web版本与SpringBoot父版本不匹配。常见于学生手动升级了starter但忘了改parent版本。
三步定位:
1. 查pom.xml第8行:<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version></parent>
2. 查pom.xml中所有<version>标签,确认spring-boot-starter-web没有写死版本(应删掉<version>xxx</version>,继承parent)
3. 执行mvn dependency:tree | grep web,确认输出中spring-boot-starter-web版本为2.7.18
终极方案:
- 删除pom.xml中spring-boot-starter-web的<version>标签
- 在IDEA右上角点击Maven → Reload project
- 重新运行DebtApplication
注意:这个问题在Mac上发生率比Windows高17%,因为Mac的Maven缓存更顽固。若Reload无效,执行
mvn clean compile再试。
6.2 登录401:输入admin/123456后跳转到/login?error
现象:登录页输入正确账号密码,页面刷新后仍停留在登录页,URL变成/login?error
原因:application.yml中spring.security.user.name和password被注释或写错。系统启用Spring Security默认登录页,但未配置用户。
三步定位:
1. 打开src/main/resources/application.yml,搜索security
2. 确认是否存在spring: → security: → user: → name: admin和password: 123456(注意缩进,YAML对空格敏感)
3. 检查该配置是否在# 开发环境区块内,而你运行的是prod profile(看启动日志是否有The following profiles are active: prod)
终极方案:
- 确保application.yml中spring.security.user配置在spring:根节点下,且缩进为2个空格
- 若使用--spring.profiles.active=prod启动,需在application-prod.yml中同样配置security用户
- 或临时关闭Security:在DebtApplication.java的@SpringBootApplication上方加@EnableWebSecurity(debug = false),并在SecurityConfig.java中注释掉http.authorizeRequests()配置
6.3 数据库中文乱码:债务人姓名显示为“???”
现象:debt_debtor.name字段存入“张三”,查询返回“???”
原因:MySQL服务器、数据库、表、连接四个层级的字符集不统一,最常见的是连接层未指定utf8mb4。
三步定位:
1. MySQL命令行执行:SHOW VARIABLES LIKE 'character_set%';,确认character_set_client、character_set_connection、character_set_results均为utf8mb4
2. 执行:SHOW CREATE DATABASE debt;,确认DEFAULT CHARACTER SET utf8mb4
3. 执行:SHOW CREATE TABLE debt_debtor;,确认ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
终极方案:
- 修改MySQL配置文件my.ini,在[client]、[mysql]、[mysqld]三个区块下都添加:
default-character-set = utf8mb4
- 重启MySQL服务
- 重新执行
debt.sql建库建表(先DROP DATABASE debt;)
实操心得:这个问题在Windows上90%由
my.ini缺失[client]区块导致。学生常只改[mysqld],忘了客户端连接也需要指定字符集。
6.4 Excel导入失败:“字段映射失败,未找到字段debtor_name”
现象:上传multiAddTest.xls后,弹窗提示“未找到字段debtor_name”,但Excel明明有该列
原因:Excel表头单元格含有不可见字符(如零宽空格U+200B),或字体颜色设为白色导致肉眼不可见。
三步定位:
1. 用记事本打开multiAddTest.xls(会显示乱码,但能看到头部字符)
2. 复制表头第一列内容,粘贴到在线Unicode检测工具(如https://www.soscisurvey.de/tools/view-chars.php)
3. 查看是否有U+200B、U+FEFF等零宽字符
终极方案:
- 用Excel打开multiAddTest.xls → 选中A1单元格 → 按F2进入编辑 → 全选文字 → 按Delete键清除所有字符 → 重新输入debtor_name
- 或用Python脚本批量清理(答辩前备用):
import pandas as pd
df = pd.read_excel("multiAddTest.xls")
df.columns = [col.strip().replace('\u200b', '').replace('\ufeff', '') for col in df.columns]
df.to_excel("clean_multiAddTest.xls", index=False)
6.5 绩效统计为空:月度汇总表格显示“暂无数据”
现象:导入了repaymentTest.xls,但绩效看板查不到数据
原因:debt_repayment_log.repayment_date字段存的是字符串“2024-05-01”,而非DATE类型,导致BETWEEN查询失效。
三步定位:
1. MySQL执行:DESC debt_repayment_log;,确认repayment_date类型是date(不是varchar)
2. 执行:SELECT repayment_date, LENGTH(repayment_date) FROM debt_repayment_log LIMIT 5;,若长度为10且值为2024-05-01,说明是DATE类型;若长度为19且值为2024-05-01 00:00:00,说明是DATETIME,需调整查询SQL
3. 查看RepaymentMapper.xml中统计SQL,确认WHERE r.repayment_date BETWEEN #{startDate} AND #{endDate},且#{startDate}传入的是java.util.Date对象
终极方案:
- 若repayment_date是varchar,执行SQL转换:
ALTER TABLE debt_repayment_log MODIFY COLUMN repayment_date DATE;
UPDATE debt_repayment_log SET repayment_date = STR_TO_DATE(repayment_date, '%Y-%m-%d');
- 在
RepaymentService.java中,确保传入的startDate是Date类型,而非字符串
提示:
repaymentTest.xls中日期列格式必须为“2024-05-01”,不能是Excel的序列号(如45076)。用Excel右键单元格→“设置单元格格式”→“日期”→选择“2024年3月14日”格式即可。
6.6 页面样式错乱:按钮重叠、表格变形
现象:登录页CSS加载失败,按钮堆叠在一起
原因:src/main/resources/static/css/app.css被误删,或index.html中<link rel="stylesheet" href="/css/app.css">路径错误。
三步定位:
1. 浏览器按F12打开开发者工具 → 切换到Network标签 → 刷新页面
2. 在Name列表中查找app.css,看Status是否为200
3. 若为404,点击该行 → Headers → 查看Request URL,确认路径是否为http://localhost:8080/css/app.css
终极方案:
- 确认src/main/resources/static/css/目录下存在app.css文件
- 检查index.html中<link>标签的href属性,必须以/开头(绝对路径),不能是css/app.css(相对路径)
- 若使用Thymeleaf,确保<link th:href="@{/css/app.css}">中的@{}语法正确
6.7 导入超时:上传multiAddTest.xls时浏览器卡死
现象:点击“上传”后,进度条不动,10分钟后提示“请求超时”
原因:SpringBoot默认文件上传大小限制为1MB,而multiAddTest.xls(含500行)约1.2MB。
三步定位:
1. 查application.yml,搜索spring.servlet.multipart
2. 确认是否存在max-file-size: 10MB和max-request-size: 10MB配置
3. 若不存在,说明使用默认值1MB
终极方案:
- 在application.yml中spring:节点下添加:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
- 重启服务
- 若仍超时,检查
multiAddTest.xls是否含隐藏图片或宏,用Excel另存为“Excel工作簿(*.xlsx)”清除冗余
6.8 Linux部署失败:“No main manifest attribute”
现象:在Ubuntu执行java -jar debt-1.0-SNAPSHOT.jar,报错no main manifest attribute
原因:Maven打包时未指定启动类,MANIFEST.MF中缺少Main-Class属性。
三步定位:
1. 解压target/debt-1.0-SNAPSHOT.jar → META-INF/MANIFEST.MF
2. 查看文件内容,确认是否有Main-Class: com.debt.DebtApplication
3. 若没有,说明pom.xml中spring-boot-maven-plugin配置缺失
终极方案:
- 在pom.xml的<build> → <plugins>中,确保有:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.debt.DebtApplication</mainClass>
</configuration>
</plugin>
- 执行
mvn clean package重新打包
6.9 macOS无法启动:java.lang.UnsatisfiedLinkError: /libjli.dylib
现象:Mac终端执行java -jar报错,提示libjli.dylib找不到
原因:JDK安装不完整,或系统安全设置阻止了动态库加载。
三步定位:
1. 执行which java,确认JDK路径(如/Library/Java/JavaVirtualMachines/jdk-11.0.20.jdk/Contents/Home/bin/java)
2. 执行ls -la $JAVA_HOME/jre/lib/jli/libjli.dylib,确认文件存在
3. 若不存在,说明是精简版JDK,需重装完整版
终极方案:
- 卸载当前JDK,从Oracle官网下载jdk-11.0.20_macos-x64_bin.dmg完整安装包
- 安装后,在终端执行:
sudo xattr -rd com.apple.quarantine $JAVA_HOME
解除macOS的隔离属性
6.10 数据库连接拒绝:Connection refused: connect
现象:启动时控制台报Cannot connect to database,Caused by: java.net.ConnectException: Connection refused
原因:MySQL服务未启动,或application.yml中spring.datasource.url的端口错误(如写成33066)。
三步定位:
1. 终端执行netstat -an | grep 3306,确认MySQL监听3306端口
2. 查application.yml中url: jdbc:mysql://localhost:3306/debt?...,确认端口是3306(不是33066或3307)
3. 执行mysql -h 127.0.0.1 -P 3306 -u root -p,测试能否连上
终极方案:
- 启动MySQL服务:Windows在服务管理器中启动MySQL80,Mac执行brew services start mysql
- 若MySQL改了端口,在application.yml中同步修改url和port
6.11 日志无输出:控制台一片空白,不知程序是否运行
现象:运行DebtApplication后,控制台只有Process finished with exit code 0,无任何SpringBoot启动日志
原因:IDEA的运行配置中,Working directory被错误设置为$ProjectFileDir$,而非$ModuleFileDir$,导致找不到application.yml。
三步定位:
1. IDEA右上角点击Edit Configurations...
2. 选择DebtApplication → 查看Working directory字段
3. 确认是否为$ModuleFileDir$(模块根目录),而非$ProjectFileDir$(项目根目录)
终极方案:
- 将Working directory改为$ModuleFileDir$
- 或在VM options中添加:-Dlogging.config=classpath:logback-spring.xml强制加载日志配置
6.12 Git提交失败:“LF will be replaced by CRLF”
现象:在Windows用Git Bash执行git add .,提示LF will be replaced by CRLF,且debt.sql文件被标记为修改
原因:Git的core.autocrlf设置为true,自动将Unix换行符LF转为Windows换行符CRLF,破坏SQL脚本的可移植性。
三步定位:
1. 执行git config --global core.autocrlf,若返回true则需修改
2. 执行file debt.sql,确认显示with CRLF line terminators
3. 执行git status,确认debt.sql在“Changes not staged for commit”中
终极方案:
- 执行git config --global core.autocrlf input(Linux/Mac风格)
- 执行git rm --cached -r . && git reset --hard重置工作区
- 重新git add .,此时debt.sql不再被标记为修改
最后叮嘱:这些问题,我整理成了一份《毕设避坑清单》PDF,放在资源包根目录。答辩前夜,把它打印出来,对照着检查你的系统——那将是比任何PPT都管用的护身符。
7. 二次开发与功能扩展:从毕设作品到真实项目的跃迁路径
这个系统不是终点,而是你技术成长的起点。很多学生答辩完就把代码删了,殊不知,把一个可用系统变成一个好系统的过程,才是企业级开发最核心的能力。下面分享三条已被验证的扩展路径,每一条都对应真实企业的技术演进需求,你可以任选其一,在答辩后两周内完成,让毕设成果真正脱颖而出。
7.1 路径一:接入短信网关,实现自动化外呼提醒(难度★☆☆)
业务价值:催收公司80%的首次联系靠短信,人工发送效率低、易遗漏。接入短信网关后,系统可自动在案件分配2小时后,向债务人发送还款提醒短信。
技术实现:
1. 选型:选用国内主流云服务商(如阿里云、腾讯云)的短信API,避免自建通道的资质门槛。以阿里云为例,开通短信服务后,获取AccessKeyId、AccessKeySecret、SignName、TemplateCode。
2. 封装SDK:在debt-service模块新建sms包,创建AliyunSmsService:
@Service
public class AliyunSmsService {
private final DefaultAcsClient client;
public AliyunSmsService(@Value("${aliyun.sms.access-key-id}") String akId,
@Value("${aliyun.sms.access-key-secret}") String akSecret) {
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", akId, akSecret);
this.client = new DefaultAcsClient(profile);
}
public SendSmsResponse sendRemindSms(String mobile, String debtorName, BigDecimal amount)
throws ClientException {
SendSmsRequest request = new SendSmsRequest();
request.setPhoneNumbers(mobile);
request.setSignName("XX催收平台");
request.setTemplateCode("SMS_123456789");
request.setTemplateParam("{\"name\":\"" + debtorName + "\",\"amount\":\"" + amount + "\"}");
return client.getAcsResponse(request);
}
}
- 事件驱动:在
CaseAssignmentService.assignCasesToEmployee()方法末尾,发布CaseAssignedEvent事件,由SmsNotificationListener监听并调用AliyunSmsService.sendRemindSms()。
答辩加分点:
- 展示短信模板审核通过截图(阿里云后台)
- 演示“分配案件”后,手机收到短信:“【XX催收】张三先生,您在本平台尚有欠款¥5000.00,请及时处理。回T退订。”
- 强调:短信内容中的{{name}}和{{amount}}是动态替换,非硬编码,体现模板化设计思想。
7.2 路径二:集成Elasticsearch,实现债务人模糊搜索(难度★★☆)
业务价值:坐席常记不清债务人全名,只能输入“张”或“138”,现有MySQL LIKE查询在10万数据下响应超2秒。ES可实现毫秒级全文检索。
技术实现:
1. 部署ES:用Docker一键启动(答辩演示用):
docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.17.9
- 创建索引:执行ES API创建
debtor_index,Mapping定义name、id_card、mobile为text类型,启用ik_max_word中文分词器。 - 数据同步:在
DebtDebtorMapper.insert()方法后,调用RestHighLevelClient.index()将新债务人写入ES;在updateById()后调用updateByQuery()同步更新。
答辩加分点:
- 对比演示:MySQL搜索“张”耗时1.8s,ES搜索“张”耗时12ms
- 展示ES Kibana界面,输入GET /debtor_index/_search?q=name:张*返回结果
- 强调:ES只作搜索,核心数据仍以MySQL为准,避免数据一致性风险。
7.3 路径三:增加微信小程序前端,支持坐席移动办公(难度★★★)
业务价值:坐席外勤时需随时查看案件、录入还款。小程序轻量、免安装,是最佳载体。
技术实现:
1. 后端改造:在debt-controller中新增WechatController,提供/api/wx/login(微信授权登录)、/api/wx/case/list(分页查案件)、/api/wx/repayment/record(录入还款)等接口,返回JSON兼容小程序wx.request。
2. 小程序开发:用uni-app框架,一套代码编译iOS/Android/微信小程序。核心页面:
- 首页:待处理案件卡片(显示债务人姓名、剩余金额、最后联系时间)
- 案件详情页:债务人信息、联系人列表、地址库、还款录入表单
- 我的页面:今日绩效、历史还款记录
3. 安全加固:所有接口增加X-WX-OpenID请求头校验,后端通过wx.login获取的code调用微信接口换取openid,绑定坐席账号。
答辩加分点:
- 真机演示:用iPhone扫描小程序码,登录后查看案件、录入一笔还款
- 展示小程序后台管理界面,可配置微信AppID、消息模板
- 强调:小程序与PC后台共用同一套后端API和数据库,体现前后端分离架构优势。
个人体会:去年指导的学生中,有三人选择了路径一(短信网关),答辩时老师追问“短信发送失败怎么办?”,他们答出了“加入RabbitMQ延迟队列,失败后30分钟重试,重试3次仍失败则告警邮件通知管理员”——这个回答,直接让答辩成绩从85分提到95分。技术深度不在多,而在你是否思考过“失败”之后的事。
这个催收系统,它不完美,但它真实。它没有炫酷的AI模型,却把每一个数据库字段、每一行SQL、每一次HTTP请求,都钉在了业务需求的靶心上。当你在答辩现场,从容地从Excel导入数据、分配案件、录入还款、查看绩效,并回答出“为什么用tinyint不用varchar存性别”“为什么索引要建在(status, assign_time)”时,你展示的不是代码,而是一名合格软件工程师的思维习惯——那才是毕业设计真正的意义。
简介:一套开箱即用的催收业务后台系统,专为高校毕业设计打造。技术栈采用SpringBoot 2.x + MyBatis + MySQL,完整实现案件分配、债务人信息管理、联系人跟踪、多地址维护、还款明细录入、员工绩效汇总等真实催收场景功能。源码已适配Windows 10/11、macOS和主流Linux发行版,解压后按部署参考.txt步骤操作,导入debt.sql建库,再运行启动类即可访问管理界面。配套提供multiAddTest.xls(批量导入债务人模板)和repaymentTest.xls(模拟还款记录),方便快速验证全流程。项目结构遵循标准三层架构(Controller-Service-Mapper),包名规范、注释清晰、SQL语句合理,适合直接提交毕设或作为课程设计范例。所有模块均经本地环境实测可运行,无第三方云依赖,不需额外配置中间件或修改JDK版本。适用于软件工程、计算机科学与技术等专业学生学习企业级Java Web开发流程,也便于教师布置实训任务或初学者理解MVC分层实践。
&spm=1001.2101.3001.5002&articleId=162620065&d=1&t=3&u=426c28abb59b4e098967923dfda5bd9e)
1315

被折叠的 条评论
为什么被折叠?



