🎓 一、 选题背景:为什么选这个题?
在毕设选题中,“管理系统”(如图书管理、宿舍管理)已经烂大街了,只拿及格分很难。而**“深度学习”**(如人脸识别、自动驾驶)门槛太高,代码跑不通容易挂科。
“基于知识图谱的推荐系统”是完美的中间地带:
- 听起来高端:涉及“知识图谱”、“自然语言处理 (NLP)”、“智能推荐”。
- 做起来简单:本质还是 CRUD,算法部分可以直接调用现成的 Java 库 (HanLP)。
- 可视化强:ECharts 的力引导图(关系图)一动起来,视觉冲击力满分。
🏗️ 二、 系统架构设计
我们在论文中必须展示清晰的架构。本系统采用经典的B/S 架构,前后端分离。
1. 技术栈选型
- 后端:Spring Boot 2.x、MyBatis Plus、HanLP (核心算法库)
- 前端:Vue 2/3、Element UI、ECharts 5.0 (核心图谱库)
- 数据库:MySQL 8.0 (业务数据)、Redis (缓存)
2. 系统逻辑架构图 (Mermaid图)
这张图展示了数据是如何从用户端流向数据库,又是如何通过算法处理返回给用户的。
🛠️ 三、 环境搭建与基座选择
为了不造轮子,我们选用国产最流行的后台管理框架RuoYi-Vue作为底座。它帮我们解决了登录、权限、日志、代码生成等 80% 的脏活累活。
1. 下载与运行基座
- GitHub/Gitee: 搜索
RuoYi-Vue下载。 - 环境要求: JDK 1.8+, MySQL 5.7+, Redis, Node.js。
- 启动步骤:
- 导入
ry_202x.sql到 MySQL。 - 修改
application.yml里的数据库连接。 - 启动
RuoYiApplication。 - 前端运行
npm install && npm run dev。
此时,你已经拥有了一个功能完备的后台管理系统。接下来,我们要开始**“注入灵魂”**。
💻 四、 核心功能实现(保姆级代码)
我们需要新增三个核心业务表:tb_job(岗位)、tb_resume(简历)、tb_job_skill(知识图谱关系)。
1. 数据库设计
-- 1. 岗位表CREATETABLE`tb_job`(`job_id`bigint(20)NOTNULLAUTO_INCREMENT,`job_name`varchar(100)DEFAULTNULLCOMMENT'岗位名称',`salary`varchar(50)DEFAULTNULLCOMMENT'薪资范围',`requirement`textCOMMENT'岗位职责与要求(核心字段)',`city`varchar(50)DEFAULTNULLCOMMENT'工作城市',PRIMARYKEY(`job_id`))ENGINE=InnoDBCOMMENT='招聘岗位表';-- 2. 简历表CREATETABLE`tb_resume`(`resume_id`bigint(20)NOTNULLAUTO_INCREMENT,`user_id`bigint(20)DEFAULTNULL,`name`varchar(50)DEFAULTNULL,`skill_text`textCOMMENT'个人技能描述(核心字段)',PRIMARYKEY(`resume_id`))ENGINE=InnoDBCOMMENT='学生简历表';2. 核心算法 A:基于 NLP 的智能推荐
这是系统的“大脑”。原理是将简历和岗位描述都切割成“关键词”,然后计算重合度。
第一步:引入 HanLP 依赖 (pom.xml)
<dependency><groupId>com.hankcs</groupId><artifactId>hanlp</artifactId><version>portable-1.8.4</version></dependency>第二步:编写推荐算法工具类 (RecommendationUtils.java)
packagecom.ruoyi.common.utils;importcom.hankcs.hanlp.HanLP;importcom.hankcs.hanlp.seg.common.Term;importjava.util.*;importjava.util.stream.Collectors;/** * 智能推荐核心算法工具类 */publicclassRecommendationUtils{/** * 计算文本相似度 (Jaccard系数) * @param text1 学生简历文本 * @param text2 岗位要求文本 * @return 0.0 ~ 1.0 的相似度得分 */publicstaticdoublegetSimilarity(Stringtext1,Stringtext2){// 1. 提取关键词 (去除停用词,只保留名词和动词)List<String>keywords1=extractKeywords(text1);List<String>keywords2=extractKeywords(text2);// 2. 转换为 Set 集合Set<String>set1=newHashSet<>(keywords1);Set<String>set2=newHashSet<>(keywords2);// 3. 计算交集 (Intersection)Set<String>intersection=newHashSet<>(set1);intersection.retainAll(set2);// 4. 计算并集 (Union)Set<String>union=newHashSet<>(set1);union.addAll(set2);if(union.isEmpty())return0.0;// 5. 计算得分: 交集大小 / 并集大小return(double)intersection.size()/union.size();}// 辅助方法:利用 HanLP 提取关键词privatestaticList<String>extractKeywords(Stringcontent){List<Term>termList=HanLP.segment(content);returntermList.stream()// 过滤掉标点符号和长度为1的词.filter(term->term.word.length()>1).map(term->term.word).collect(Collectors.toList());}}第三步:在 Service 中调用
// JobService.javapublicList<Job>recommendJobs(StringresumeContent){List<Job>allJobs=jobMapper.selectJobList(newJob());for(Jobjob:allJobs){// 计算匹配分doublescore=RecommendationUtils.getSimilarity(resumeContent,job.getRequirement());// 将分数存入临时字段job.setMatchScore(score);}// 按分数倒序排序,取前 10 名returnallJobs.stream().sorted(Comparator.comparing(Job::getMatchScore).reversed()).limit(10).collect(Collectors.toList());}3. 核心功能 B:知识图谱可视化
这是系统的“脸面”。我们在前端使用 ECharts 的 Graph 图表。
后端数据接口 (KnowledgeGraphController.java)
我们不需要真的图数据库,用代码模拟出节点和线即可。
@GetMapping("/graph/data")publicAjaxResultgetGraph(){// 模拟数据:实际开发中应该从数据库统计// 节点:岗位 + 技能List<Map>nodes=newArrayList<>();nodes.add(createNode("Java开发",50,0));// 中心节点nodes.add(createNode("Spring Boot",30,1));nodes.add(createNode("MySQL",30,1));nodes.add(createNode("微服务",30,1));// 连线List<Map>links=newArrayList<>();links.add(createLink("Java开发","Spring Boot"));links.add(createLink("Java开发","MySQL"));links.add(createLink("Java开发","微服务"));Map<String,Object>res=newHashMap<>();res.put("nodes",nodes);res.put("links",links);returnAjaxResult.success(res);}前端 Vue 组件 (KnowledgeGraph.vue)
<template><divid="chart"style="width:100%;height:600px;"></div></template><script>import*asechartsfrom'echarts';import{getGraphData}from"@/api/system/job";exportdefault{mounted(){this.initChart();},methods:{initChart(){constmyChart=echarts.init(document.getElementById('chart'));getGraphData().then(response=>{constoption={title:{text:'岗位技能图谱'},tooltip:{},series:[{type:'graph',layout:'force',// 力引导布局data:response.data.nodes,links:response.data.links,roam:true,label:{show:true},force:{repulsion:1000}// 节点之间的斥力}]};myChart.setOption(option);});}}}</script>📸 五、 运行效果展示 (答辩 PPT 素材)
在答辩 PPT 中,你要展示以下几个关键界面:
- 系统首页(数据大屏):展示“热门技能词云”、“各城市岗位数量”、“平均薪资走势”。
- 推荐列表页:展示算法计算出的“匹配度”,例如:Java后端工程师 (匹配度: 92%)。
- 知识图谱页:展示上述 ECharts 动图。
🗣️ 六、 答辩高分话术
老师可能会问的问题,我帮你准备好了:
Q1: 你的“知识图谱”是用什么存的?
A (稳妥版):“老师,本系统采用了关系型数据库 MySQL 模拟图结构存储。为了降低系统复杂度,我设计了点表和边表,通过后端算法转换为 JSON 格式,最后由前端 ECharts 进行力引导布局渲染。这在中小规模数据量下是性价比最高的方案。”
Q2: 你的推荐算法原理是什么?
A (专业版):“我采用了基于内容的推荐算法 (Content-Based)。首先利用HanLP 自然语言处理库对简历和岗位描述进行分词和去停用词处理,构建词向量空间;然后利用Jaccard 相似系数计算两者的语义重合度,从而实现精准匹配。”