首页 / 资讯中心 / 文章详情

基于Java Web的动物疾病诊断系统设计与实现:从规则匹配到加权评分

基于Java Web的动物疾病诊断系统设计与实现:从规则匹配到加权评分 ★ FEATURED ARTICLE
做毕业设计或者课程设计的时候最怕碰到哪种题目不是那种框架一搭就结束的管理系统也不是纯算法能蒙混过关的“数据挖掘类”。最怕的是那种“看着像管理系统但仔细一想里面还藏着一条业务逻辑线”的题目。“基于Java Web的动物疾病诊断系统设计与实现”就属于这一类。这个系统表面上是把动物疾病信息做成增删改查但实际上核心价值在“诊断推理”那部分——用户选完症状系统要能给出可能性最高的一批疾病还要附带预防措施和治疗建议。做得好它就是一个靠谱的兽医辅助问诊工具做得糙它就是一个带搜索框的疾病词条库。区别就在设计思路上。这篇文章我从头到尾把这个项目的设计、建库、算法实现、页面交互、常见坑都过一遍适合正在搞Java Web课程设计、毕业设计或者想自己练手做一个“规则判断型”业务系统的同学参考。不管你是刚学完Servlet和JSP还是已经用过Spring Boot这篇内容都能给你一些可以直接落地的思路。1. 系统定位与核心需求拆解1.1 这个系统到底在解决什么问题先说痛点。宠物主人遇到动物生病第一反应是上网搜症状“狗狗呕吐”“猫咪精神不振”这种关键词搜出来结果五花八门甚至能给你带到“犬瘟”“猫瘟”这种吓人的方向上越搜越焦虑。系统的定位就是把“症状—疾病”之间的对应关系结构化让用户按照实际情况选择症状系统基于预设的知识库去匹配可能的疾病再给出概率排序。这里的“诊断”不是替代兽医而是做初步筛查和科普减少信息不对等。所以整个系统要服务两类人普通用户选症状看结果了解疾病知识。管理员维护疾病库、症状库、疾病与症状的关联关系、病例记录。清楚了这两类角色功能边界就出来了。普通用户不需要看到管理后台管理员也不需要天天走诊断流程。登录、角色权限、功能菜单的划分全部围绕这个来。1.2 核心功能模块怎么划分功能模块按角色拆不要混在一起。我当时画功能结构图的时候是这么分的用户端用户注册与登录症状选择按动物类型分组如犬、猫、家禽、反刍动物诊断结果显示匹配疾病列表按匹配度排序疾病详情浏览病因、症状、治疗建议、预防措施诊断历史记录登录用户可查历史诊断记录管理端管理员登录疾病信息管理增删改查症状信息管理疾病—症状关联关系配置病例记录管理可按疾病、动物类型筛选用户管理可选简单系统可跳过这里特别提醒一点很多人拿到题目就直接建五张表开始写代码结果做到一半发现“疾病症状关联”这个关系没有单独建模只能靠字符串拼接存储诊断逻辑根本写不下去。这个模块是系统的数据核心必须单独设计一张关联表。1.3 用户流程和业务闭环用户的完整操作流程应该是登录系统游客可以只浏览疾病库但不能用诊断功能避免无脑刷接口选择动物类型犬、猫、鸟类、兔等勾选当前出现的症状支持多选建议限制在1~10个提交诊断系统返回匹配疾病列表点击疾病名称查看详情包括治疗建议和预防措施如果用户已登录这次诊断记录自动存入历史用户可以在“我的诊断记录”里回头看把这个流程理顺了再去做页面跳转设计和接口设计就很简单。页面之间的参数传递也不容易乱。2. 技术选型与方案取舍2.1 Java Web技术路线怎么选这个题目没有限定框架所以选型空间比较大。不同的选型对应不同的开发成本和学习收益可以根据自己的基础来定。方案技术栈适合场景难度传统JSPServletServlet JSP JDBC MySQL Tomcat学校要求用纯JSP做课设考察基础中SSM整合Spring SpringMVC MyBatis经典企业级组合适合巩固框架知识中高Spring Boot ThymeleafSpring Boot MyBatis/JPA Thymeleaf Bootstrap快速开发适合毕设和实操项目中我个人推荐Spring Boot Thymeleaf这套组合。为什么第一Spring Boot内嵌Tomcat开发环境不用单独配置服务器省事。第二Thymeleaf是服务端渲染模板写页面可以沿用传统思路不需要前后端分离对课设类项目来说心智负担最低。第三简历上写Spring Boot比写Servlet好看而且这套技术的资料最多卡住了搜得到解决方案。如果学校明确要求必须用JSP那也别慌下面的表结构设计和诊断逻辑完全可以复用只是Controller层换成ServletORM换成JDBC或者DbUtils就行。核心业务逻辑不受框架影响。2.2 诊断推理怎么实现很多人一看到“疾病诊断”四个字就想去搞人工智能想着用神经网络训练症状与疾病的映射模型或者是引入贝叶斯网络、决策树之类的东西。这属于过度设计。课设和毕设场景用“规则匹配 加权评分”就够了。思路跟学习通上做试卷一样每一种疾病对应若干条“典型症状”用户选择一系列症状遍历疾病库计算“选中症状中该疾病典型症状的数量”用匹配度和覆盖率两个指标排序得出诊断结果这种方案的好处很直接不需要训练集不需要标注数据逻辑完全可解释。演示答辩的时候老师问你“这个结果怎么算出来的”你能把评分公式写在黑板上每一步都说得清楚比丢个黑盒模型强多了。2.3 数据库MySQL版本和字符集数据库首选MySQL课设和毕设基本默认。需要注意的是两个点一是版本5.7和8.0都行。建议直接用8.0连接驱动用8.x对应的com.mysql.cj.jdbc.DriverURL要带上serverTimezoneAsia/Shanghai和useSSLfalse否则连数据库容易报时区错误和SSL警告。二是字符集建库的时候统一用utf8mb4。不要用utf8因为MySQL的utf8是阉割版不支持四字节的emoji和特殊符号。虽然这个系统不太可能存emoji但数据导入导出的时候字符集问题很折磨人用utf8mb4一劳永逸。CREATE DATABASE animal_diag DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;3. 数据库设计这个系统的地基3.1 五张核心表怎么建模这个系统最少需要五张表用户表、疾病表、症状表、疾病症状关联表、诊断记录表。表结构我直接给出设计你可以根据自己的需求做增减。用户表t_userCREATE TABLE t_user ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码MD5加密存储, real_name varchar(50) DEFAULT NULL COMMENT 姓名, phone varchar(20) DEFAULT NULL COMMENT 联系电话, role tinyint(1) NOT NULL DEFAULT 1 COMMENT 角色1普通用户 2管理员, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4;疾病表t_diseaseCREATE TABLE t_disease ( id int(11) NOT NULL AUTO_INCREMENT, disease_name varchar(50) NOT NULL COMMENT 疾病名称, animal_type varchar(20) NOT NULL COMMENT 动物类型犬、猫、鸟等, pathogen varchar(255) DEFAULT NULL COMMENT 病原体/病因, symptom_desc text COMMENT 典型症状描述, treatment text COMMENT 治疗方案, prevention text COMMENT 预防措施, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4;症状表t_symptomCREATE TABLE t_symptom ( id int(11) NOT NULL AUTO_INCREMENT, symptom_name varchar(50) NOT NULL COMMENT 症状名称, animal_type varchar(20) NOT NULL COMMENT 适用动物类型, sort_order int(11) DEFAULT 0 COMMENT 展示排序小值在前, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;疾病症状关联表t_disease_symptomCREATE TABLE t_disease_symptom ( id int(11) NOT NULL AUTO_INCREMENT, disease_id int(11) NOT NULL, symptom_id int(11) NOT NULL, weight int(11) DEFAULT 1 COMMENT 症状权重1一般 2典型 3高特异性, PRIMARY KEY (id), UNIQUE KEY uk_disease_symptom (disease_id, symptom_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;诊断记录表t_diag_recordCREATE TABLE t_diag_record ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL COMMENT 诊断用户ID, animal_type varchar(20) DEFAULT NULL, selected_symptoms varchar(500) NOT NULL COMMENT 选择的症状ID集合逗号分隔, result_content text COMMENT 诊断结果JSON格式保存, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里重点聊一下t_disease_symptom这张表。它是整个诊断系统的知识库核心。疾病与症状是多对多的关系一条病可能有十个典型症状一个症状也可能出现在五种疾病里。如果不建这张中间表只在t_disease表里放一个symptoms字段存字符串“1,2,3,4”那你做匹配的时候就只能用FIND_IN_SET和LIKE这种土办法写出来的SQL又丑又慢而且扩展性极差。多建一张表前期看着多写几行代码后期诊断算法写起来能省一半力气。3.2 初始化数据怎么准备数据是这类系统的灵魂。很多学生做完系统里面有表但没数据演示效果很差。建议至少为常见动物疾病准备10条以上的数据例如犬瘟热、细小病毒病、犬传染性肝炎、猫瘟、猫鼻支、犬肠胃炎、皮肤真菌感染等。每一条疾病数据都要认真填写症状关联。比如“犬瘟热”的典型症状是发热、咳嗽、眼鼻分泌物增多、呕吐、腹泻、抽搐、食欲下降。其中“抽搐”神经症状特异性很高权重可以设为3“发热”是常见症状权重设为1。这样诊断结果才有区分度。初始化SQL我一般是写成独立脚本比如data.sql和建表脚本分开存放。这样如果调试时数据乱了重新执行一遍脚本就行不用手动一条条敲。4. 诊断算法的实现逻辑4.1 规则匹配和评分公式前面说了我们不用机器学习用加权评分。这个公式要提前设计好再写代码实现。假设用户选中的症状集合为 S某个疾病 D 对应的典型症状集合为 C(D)那么匹配数M |S ∩ C(D)|即用户选中且属于该疾病的症状数量待匹配数N |C(D)|即该疾病在知识库中登记的症状总数匹配度 M / N表示该疾病的症状被用户覆盖的比例值越大越像命中数 M值越大说明用户症状和该疾病重合越多排序的时候以“命中数”为主要指标以“匹配度”为次要指标。为什么两个都要比如用户选了5个症状“犬瘟热”命中4个但疾病症状共10条匹配度只有0.4“急性肠胃炎”命中3个但疾病症状共4条匹配度0.75。前者更可能是方向后者更精准。所以输出的时候两个指标都要展示排序逻辑建议先比命中数再比匹配度不然会出现疾病A有20条症状被命中9条却排到有5条症状全部命中的疾病B后面这不符合直觉。另外可以引入“特异性”。“抽搐”出现在犬瘟热里其他病很少见一旦用户选了它犬瘟热的排名应该大幅提前。实现方式就是在t_disease_symptom表里加一个weight字段计算时对命中集合内的症状权重求和。评分公式调整为score ∑(命中症状的weight) 匹配度 × 2也就是“加权命中权重和”叠加一个“覆盖率奖励”。代码里把两部分算清楚就可以这种可解释性强的算法答辩的时候老师随便问怎么计算都能答得清清楚楚。4.2 Java代码实现诊断逻辑写在Service层我给出一个核心伪代码示例public ListDiagnosisResult matchDisease(Integer animalType, ListInteger symptomIds) { // 1. 查询该动物类型下的所有疾病 ListDisease diseaseList diseaseMapper.selectByAnimalType(animalType); // 2. 查询用户选中症状对应的症状信息 ListSymptom selectedSymptoms symptomMapper.selectBatchIds(symptomIds); // 3. 查询所有疾病-症状关联关系构建Map结构 MapInteger, ListDiseaseSymptom dsMap diseaseSymptomMapper.selectAll() .stream() .collect(Collectors.groupingBy(DiseaseSymptom::getDiseaseId)); // 4. 逐疾病计算匹配度 ListDiagnosisResult results new ArrayList(); for (Disease disease : diseaseList) { ListDiseaseSymptom diseaseSymptoms dsMap.getOrDefault(disease.getId(), Collections.emptyList()); // 计算该疾病的症状总数 int totalSymptomCount diseaseSymptoms.size(); // 计算命中数量及权重和 int hitCount 0; int score 0; for (DiseaseSymptom ds : diseaseSymptoms) { if (symptomIds.contains(ds.getSymptomId())) { hitCount; score ds.getWeight(); } } if (hitCount 0) { continue; // 一个症状都没命中直接丢弃 } // 匹配度命中数 / 疾病总症状数 double matchRate (double) hitCount / totalSymptomCount; // 综合评分加权命中权重和 覆盖率奖励 double finalScore score matchRate * 2; results.add(new DiagnosisResult(disease, hitCount, matchRate, finalScore)); } // 排序综合评分降序命中数降序 results.sort((r1, r2) - { int cmp Double.compare(r2.getFinalScore(), r1.getFinalScore()); return cmp ! 0 ? cmp : Integer.compare(r2.getHitCount(), r1.getHitCount()); }); // 5. 截取前10个返回 return results.stream().limit(10).collect(Collectors.toList()); }这段逻辑的核心就是把“知识”和“推理”分离。疾病、症状、权重都是数据推理算法只做遍历和评分。将来想换更高级的算法比如贝叶斯打分只需要改这一段数据表不用动。4.3 一个推理实例看效果举个例子。用户选了“犬”类型症状勾选了“发热”“咳嗽”“眼鼻分泌物增多”“抽搐”四项。“犬瘟热”在知识库中登记了9个症状发热、咳嗽、眼鼻分泌物增多、抽搐、呕吐、腹泻、食欲下降、精神沉郁、脚垫增厚。命中4个权重分别是1、1、2、3合计7分匹配度4/9≈0.44。综合评分70.887.88。“犬窝咳”登记4个症状咳嗽、流鼻涕、发热、食欲下降。命中3个咳嗽、发热但注意“眼鼻分泌物增多”和“抽搐”不在里面。命中2个权重112匹配度2/40.5。综合评分21.03.0。很明显犬瘟热排最前面而且因为“抽搐”这个高特异权重症状评分拉得很高。这里就是权重设计的价值所在。// 犬瘟热的症状关联示例 INSERT INTO t_disease_symptom(disease_id, symptom_id, weight) VALUES (1, 1, 1), -- 发热 - 权重1 (1, 2, 1), -- 咳嗽 - 权重1 (1, 3, 2), -- 眼鼻分泌物增多 - 权重2 (1, 4, 3), -- 抽搐 - 权重3强特异性 (1, 5, 1), (1, 6, 1), (1, 7, 1), (1, 8, 1), (1, 9, 2);5. 前后端实现与页面设计5.1 页面结构和路由设计页面不用搞得太复杂一个清爽的四层结构就够用了首页用户登录注册页症状选择与诊断页疾病列表与详情页我的诊断记录页管理后台疾病管理、症状管理、关联关系管理由于用的是Thymeleaf服务端渲染路由设计就是Controller直接返回视图名称没有前后端分离的跨域问题。目录结构建议这样src/main/java/com/example/animaldiag/ ├── controller/ # Controller层 ├── service/ # 业务逻辑层 ├── mapper/ # MyBatis Mapper接口 ├── entity/ # 实体类 └── config/ # 配置类拦截器、登录校验等 src/main/resources/ ├── mapper/ # MyBatis XML文件 ├── static/ # CSS、JS、图片 └── templates/ # Thymeleaf模板5.2 症状选择页的多选交互症状选择页是整个系统的门面用户体验好不好就看这一页。建议按动物类型先用下拉框分类比如用户选“犬”下方展示犬类常见症状列表。每个症状做成一个可点击的卡片样式点击高亮选中再次点击取消。卡片上用文字描述症状不用图片加载快。多选状态用原生JavaScript控制即可不用引入Vue。核心代码很简单function toggleSymptom(el, symptomId) { el.classList.toggle(active); var hiddenInput document.getElementById(selectedSymptoms); var ids hiddenInput.value ? hiddenInput.value.split(,) : []; var index ids.indexOf(String(symptomId)); if (index 0) { ids.splice(index, 1); } else { ids.push(String(symptomId)); } hiddenInput.value ids.join(,); // 实时更新已选标签数量 document.getElementById(countText).innerText 已选 ids.length 项; }这里有一个细节坑表单用隐藏域存症状ID集合时一定要在提交前处理好字符串格式去掉首尾逗号。如果用户一个症状都没选就提交后端要友好提示“请至少选择一项症状”不要直接报空指针。5.3 诊断结果页的数据展示诊断结果页直接展示匹配列表按综合评分从高到低排列。每一行显示疾病名称命中症状数例如“命中 4 / 9”匹配度进度条简要的病因描述“查看详情”按钮匹配度用进度条可视化会很直观用Bootstrap的progress组件就够了不需要写图表库。div classprogress div classprogress-bar th:stylewidth: ${item.matchRatePercent} % span th:text${item.matchRatePercent} %/span /div /div疾病详情页再展示完整的治疗建议和预防措施。注意治疗建议的文案一定要加免责声明提示“如症状严重请及时就医本系统结果仅供参考”。这个不光是负责任也是答辩时老师会注意到的细节。5.4 管理后台的关联配置管理后台最容易被忽略的是“疾病症状关联管理”。很多同学做成疾病管理、症状管理两块就完事了结果发现疾病和症状之间建不了关系那诊断功能就没有数据可用。正确的做法是做一个独立页面选择一个疾病然后显示当前已关联的症状列表同时列出未关联症状通过勾选和设置权重来更新关联关系。PostMapping(/admin/disease/{diseaseId}/symptoms) public String updateRelation(PathVariable Integer diseaseId, RequestParam(required false) ListInteger symptomIds, RequestParam(required false) ListInteger weights) { // 先删除该疾病的全部关联再重新插入简单粗暴但有效 diseaseSymptomMapper.deleteByDiseaseId(diseaseId); if (symptomIds ! null) { for (int i 0; i symptomIds.size(); i) { DiseaseSymptom ds new DiseaseSymptom(); ds.setDiseaseId(diseaseId); ds.setSymptomId(symptomIds.get(i)); ds.setWeight(weights.get(i)); diseaseSymptomMapper.insert(ds); } } return redirect:/admin/disease/detail/ diseaseId; }这种“先删后插”的方式在管理配置类功能里很常用数据量不大时性能完全没问题而且逻辑简单不会出现残留数据。6. 环境搭建与项目落地的关键步骤6.1 开发环境清单做这个项目前先把环境准备齐全省得写代码时被工具折腾JDK 1.8或更高版本推荐JDK 8稳定资料多Maven 3.6MySQL 5.7/8.0IntelliJ IDEA或EclipseSpring Boot 2.x不要追新到3.xSpring Boot 3要求JDK17有些学校电脑没装Navicat或MySQL Workbench做数据库可视化如果是用Spring Boot 2.xpom.xml里依赖用spring-boot-starter-web、mybatis-spring-boot-starter、thymeleaf和mysql-connector-java即可。6.2 项目初始化步骤第一步创建Spring Boot项目可以用IDEA自带的Spring Initializr也可以去网站生成。注意Group和Artifact名称取简单的比如com.example.animaldiag。第二步配置文件application.ymlserver: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/animal_diag?serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingutf8useSSLfalseallowPublicKeyRetrievaltrue username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver thymeleaf: cache: false mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.animaldiag.entity第三步编写数据库脚本并用Navicat执行。第四步写实体类、Mapper接口、XML文件、Service、Controller一步步来。6.3 登录校验和会话管理系统既然区分普通用户和管理员那登录校验不能只靠前端隐藏按钮。后端必须做统一拦截。用拦截器方案Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { User user (User) request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(/login?redirect request.getRequestURI()); return false; } return true; } }然后在配置类里注册拦截规则Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/**) .excludePathPatterns(/login, /loginSubmit, /register, /registerSubmit, /css/**, /js/**, /images/**, /disease/list, /disease/detail/**); } }管理员接口单独校验user.getRole()2用另一个拦截器或直接在Controller里判断。不要在每一个Controller方法里手写判断代码会重复到让你想哭而且一旦漏判就会被绕过。6.4 密码加密不能偷懒用户表里的密码不能存明文。至少要加一层MD5有条件就加盐。虽然这个系统没有别的高价值数据但毕业设计答辩时老师看到明文密码印象分会大打折扣。用Spring自带的DigestUtils.md5DigestAsHex就够String encodePwd DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));登录时同样把用户输入的密码做MD5再比对。如果觉得MD5不安全换成BCrypt也行spring-security-crypto包里自带BCryptPasswordEncoder使用时注意每次加密结果不同比对要用matches()方法而不是直接equals。7. 测试场景设计与常见问题排查7.1 测试用例怎么设计功能做完要跑一遍完整的测试流程。至少覆盖这几个场景新用户注册用户名重复时要有错误提示普通用户登录看到用户端菜单不能进入管理后台管理员登录能正常管理疾病和症状关联不选任何症状直接提交系统友好报错选择某一个疾病的所有典型症状该疾病排名第一删除一个疾病后关联关系表中的数据级联删除诊断结果中不再出现该病连续两次诊断历史记录能正确显示这些用例不用写成自动化测试手工过一遍就行。但每一条都要记录结果发现问题立刻修。7.2 高频报错速查表以下是我实际开发中统计到的高频问题每个都踩过坑直接列给大家保平安。现象原因解决办法Tomcat启动失败报端口被占用8080端口被其他进程占用改配置端口为8081或用netstat -ano查占用进程结束掉连接MySQL报Communications link failure数据库服务没启动或者URL时区参数缺失确认MySQL服务启动URL加serverTimezoneAsia/Shanghai中文乱码存进去是问号连接URL没有characterEncoding或库不是utf8mb4URL加characterEncodingutf8重建库用utf8mb4页面加载不出CSS样式静态资源被拦截器挡掉或Thymeleaf路径写错拦截器放行/css/**/js/**模板里用th:href{/css/style.css}MyBatis报Invalid bound statementMapper接口和XML文件的namespace不对或XML没编译到classes目录检查namespace和接口全限定名一致pom里resources把mapper目录包含进去宝塔/Navicat导入SQL数据时报错SQL语句中用了utf8mb4_0900_ai_ci排序规则MySQL5.7不支持把排序规则改成utf8mb4_general_ciSession里取不到用户登录时没有存Session或跳转是重定向导致Session变化确认request.getSession().setAttribute存在拦截器里再set一次诊断结果为空疾病数据没有关联症状记录或者动物类型没对上查t_disease_symptom表确认关联数据里disease_id对应正确7.3 诊断结果不准怎么调系统交付后如果发现某些病完全识别不出来八成不是代码问题而是知识库数据不完善。比如“猫鼻支”如果只在关联表里登记了“打喷嚏”“流泪”而用户选的是“发热”“食欲下降”那就匹配不上。这时候需要回数据脚本把疾病的典型症状补全。建议每种疾病至少关联6个症状覆盖常见表现不要只关联两三条。权重上也要有意识的区分。共性的症状发热、食欲下降权重给1高鉴别度的症状抽搐、皮肤溃烂、眼部分泌物权重给2~3这样诊断结果的区分度自然就上来了。8. 项目扩展方向和实操心得8.1 可以继续加的功能如果这个项目的时间充足或者你想让它在简历上更好看可以从这几个方向扩展。第一增加图片上传功能。疾病详情页允许管理员上传病理图片用户诊断后看到的不只是文字还能有视觉参考。这个用Spring Boot的MultipartFile就能实现保存到本地目录再映射成静态资源即可。第二诊断记录导出为PDF。用户历史记录支持导出检查报告方便带去宠物医院给医生看。用iText或POI可以做到但注意字体问题中文渲染要引入中文字体文件。第三增加搜索关键词联想。在症状选择框里支持输入文字模糊搜索用前端JS实现本地过滤就行不需要Elasticsearch。大数据量才有必要上检索框架这个规模的数据用索引内存匹配就够了。第四接入疫苗提醒功能。用户给自己宠物建档后记录疫苗接种日期系统提前推送提醒。这个就涉及定时任务和通知可以学习Quartz或Spring自带的Scheduled。8.2 实际开发中容易踩的隐形坑有些坑不是一次踩完就记住的我吃了亏之后才总结出几条经验这里分享给大家。Thymeleaf模板中如果某个字段为null渲染会直接报错。比如疾病库里有条数据的prevention字段是空的你写th:text${disease.prevention}页面直接500。解决办法是在实体类给默认空字符串或者用th:text${disease.prevention ?: 暂无}。MyBatis的XML中写SQL时和要用转义否则XML解析直接报错。SQL里凡是出现小于号的地方都要写成lt;。这个报错信息看着像SQL语法错其实是XML没解析排查思路完全不同。管理员“先删后插”更新关联时如果前端忘记传权重后端可能存0诊断逻辑里权重为0相当于没加分。所以前端表单里权重默认选1后端也要判空处理。8.3 答辩和演示时的加分建议如果这个项目是用来答辩或者项目评审的我有几个亲测有效的演示技巧。准备一份初始化数据脚本里面包含10种以上疾病和40条以上症状演示时现场执行导入展示数据真实感。不要只在本地库看得到数据换台电脑就崩了。演示诊断功能时选一个知识库里记录比较完整的疾病故意勾选它的3个高权重典型症状让结果第一就是这个病。这样老师一看就能理解“诊断”不是瞎猜是基于权重规则匹配的。讲解的时候重点说清楚两张图一张是功能结构图一张是诊断算法流程图。用文字把“选症状→查关联→算权重→排序→展示”这条链路讲透比堆代码强得多。老师最怕听到“这个模块就是增删改查”最想听到的是“这里的核心难点在于关联关系的引入和权重评分的量化设计”。做这个项目给我最大的体会是看似是管理系统但真正拉开差距的地方是知识库的建模和推理逻辑的设计。很多同学把大量时间花在堆页面上结果诊断功能只是一个简单的数据库模糊查询失去了“诊断系统”的灵魂。先把疾病-症状-权重这套数据模型想清楚系统的品质自然就有保障了。
阅读完成 · 觉得有帮助?
咨询建站