基于SpringBoot与大模型的医疗影像辅助诊断系统设计与实现

SpringBoot大模型医疗影像
于 2026-07-03 09:40:41 修改
·本内容遵循CC 4.0 BY-SA版权协议

如果你正在为计算机毕业设计选题而焦虑,不知道如何选择一个既有技术深度、又能体现个人能力、还能让导师眼前一亮的项目,那么这篇文章就是为你准备的。每年都有大量学生卡在选题这一步,要么选得太简单,像“图书管理系统”这种十年前的项目,毫无新意;要么选得太难,比如“自动驾驶决策系统”,远超本科生的能力范围,最终导致项目烂尾。

今天,我们聚焦一个极具潜力的方向:基于 SpringBoot 与大模型的医疗影像辅助诊断系统。这个选题之所以值得推荐,是因为它精准地踩中了三个关键点:技术栈的实用性(SpringBoot 是 Java 后端开发的绝对主流)、前沿技术的融合性(大模型是当前 AI 领域的核心热点),以及应用场景的社会价值(医疗健康是永恒的刚需)。它不是一个空中楼阁的设想,而是一个你可以亲手搭建、运行并展示的完整项目。

本文将为你彻底拆解这个毕设项目的设计与实现。我们不会空谈概念,而是从零开始,带你理解为什么这个组合是“黄金搭档”,一步步构建后端服务,集成 AI 能力,并最终呈现一个可演示的系统。无论你是 Java 新手,还是对 AI 略有了解但不知如何落地,这篇文章都将提供清晰的路径和可复现的代码。

1. 为什么说“SpringBoot + 大模型 + 医疗影像”是毕设王牌组合?

在做技术选型时,最怕的就是“为了用而用”。我们必须清楚每个技术组件解决了什么问题,以及它们组合在一起为什么能产生“1+1>2”的效果。

SpringBoot 解决的是“工程化”和“快速交付”问题。 作为计算机专业学生,你的毕业设计首先是一个软件工程项目。它需要有清晰的分层架构(Controller, Service, Mapper)、规范的数据库交互、稳定的 RESTful API 以及便捷的部署方式。SpringBoot 通过自动配置和起步依赖,让你能跳过繁琐的 XML 配置,快速搭建一个生产就绪型的后端服务。这意味着你可以把更多精力放在业务逻辑和 AI 集成上,而不是纠结于环境搭建。你的项目会因此显得更加专业和成熟。

大模型解决的是“智能核心”与“技术亮点”问题。 传统的图像分类项目可能只用 CNN(卷积神经网络),这在今天看来技术陈旧,缺乏新意。而“大模型”这个词本身就代表着前沿。这里需要明确:我们并非要训练一个医学专用的百亿参数大模型(这不可能),而是利用现有的大模型能力(特别是视觉-语言多模态大模型)作为我们系统的“大脑”。例如,使用 OpenAI 的 GPT-4V、Google 的 Gemini Pro Vision 或开源的 LLaVA 等模型,它们能够理解图像内容并生成描述性文本。我们的系统将医学影像(如 X 光片、CT 切片)上传给这些模型,获取初步的影像描述和分析,再结合医学知识库进行辅助判断。这立刻让你的项目脱离了简单的“图像分类”,升级为具备“视觉理解”和“报告生成”能力的智能系统。

医疗影像场景解决的是“应用价值”和“问题边界”问题。 毕业设计需要定义一个明确的问题域。医疗影像辅助诊断是一个社会关注度高、有明确痛点的领域(如医疗资源分布不均、医生读片压力大)。它提供了丰富的公开数据集(如 ChestX-ray14 肺炎 X 光数据集),方便你获取实验数据。更重要的是,这个场景让你必须考虑系统的严肃性:如何设计用户权限(医生、管理员)?如何存储和加密敏感的医疗数据?如何呈现分析结果(强调“辅助”而非“替代”)?这些思考都能体现在你的系统设计和论文中,极大地提升项目的深度。

组合起来,你的项目故事线就非常清晰了: 构建一个基于 SpringBoot 的 Web 系统,医生可以上传患者影像,系统后端调用大模型 API 进行智能分析,结合数据库中的病历信息,生成一份结构化的辅助诊断报告,并安全地展示给医生参考。这涵盖了 Web 开发、AI 集成、数据库设计、系统安全等多个核心模块,完全满足甚至超越了一个优秀本科毕设的要求。

2. 核心概念与系统架构设计

在动手编码之前,我们需要统一认知,并设计一个合理、清晰的系统架构。

2.1 关键概念澄清

  • 大模型(Large Language Model, LLM / Large Multimodal Model, LMM):在本项目中,我们主要指能够处理和理解图像的多模态大模型。它们通过海量图文对数据训练,学会了将视觉信息与语言描述关联起来。
  • 辅助诊断系统:核心是“辅助”。我们的系统绝不提供最终的诊断结论,而是提供“影像描述”、“疑似病灶区域提示”、“与相似病例的对比参考”等信息。在项目设计和论文中,必须反复强调这一点,这是伦理和安全底线。
  • 医疗影像:通常指 DICOM 格式的医学图像,但为了简化开发,我们可以使用公开数据集中常见的 JPEG/PNG 格式的 X 光或 CT 图片作为输入。

2.2 系统架构设计

一个高内聚、低耦合的架构是项目成功的基石。我们采用经典的分层架构,并融入 AI 服务模块。

TEXT
[用户层] (Web前端,可使用Thymeleaf/Vue.js)
|
| HTTP/HTTPS (RESTful API)
|
[接入层] SpringBoot Controller (处理请求,返回视图或JSON)
|
| 服务调用
|
[业务层] SpringBoot Service (核心业务逻辑:用户管理、影像分析流程编排)
| |
| | 1. 调用文件服务存储影像
| | 2. 调用AI服务获取分析结果
| | 3. 组合数据,生成报告
|
[数据层] MyBatis-Plus Mapper (操作MySQL数据库)
| |
| | (文件存储)
| |
| [对象存储/本地磁盘] (存储上传的影像文件)
|
[AI服务层] (独立服务或第三方API调用)
|
| HTTP API Call (e.g., OpenAI, Gemini, 或本地部署的LLaVA)
|
[大模型API]

各层职责说明:

  1. Controller 层:接收前端上传的影像文件、患者 ID 等参数,验证后交给 Service 层处理。
  2. Service 层
    • FileService: 负责将上传的影像文件保存到指定位置(如服务器本地目录/uploads,或云存储),并返回文件访问路径。
    • AIService: 封装调用大模型 API 的细节。它读取存储的影像文件,将其转换为 Base64 编码或文件流,构造符合 API 要求的请求体(包含提示词 Prompt),发送请求并解析返回的 JSON 结果。
    • ReportService: 整合患者基本信息(来自数据库)、影像分析结果(来自 AIService),按照模板生成一份结构化的诊断报告草稿,并存入数据库。
  3. Mapper 层:使用 MyBatis-Plus,简化对用户表患者病历表影像记录表诊断报告表的 CRUD 操作。
  4. AI 服务层:这是一个相对独立的模块。出于成本和便捷性考虑,毕业设计强烈建议使用第三方成熟 API(如智谱 AI、百度文心、阿里通义千问的视觉理解能力,或 OpenAI GPT-4V)。这避免了本地部署大模型所需的巨额显卡资源和复杂环境配置。你的代码只需关注如何调用这些 HTTP API。

3. 环境准备与技术栈选型

让我们明确开发所需的具体环境和工具版本。以下是一个经过验证的稳定组合:

  • JDK: 17 或 21 (LTS 版本,SpringBoot 3.x 支持)
  • 项目管理与构建工具: Apache Maven 3.8+
  • IDE: IntelliJ IDEA (社区版即可) 或 VS Code with Java Extensions
  • SpringBoot: 3.1.x 或 3.2.x (选择当前稳定版)
  • 数据库: MySQL 8.0
  • 持久层框架: MyBatis-Plus 3.5.x
  • 模板引擎 (可选): Thymeleaf (用于快速构建简单后台管理界面)
  • 大模型 API:
    • 首选 (国内可直接访问):智谱 AI (GLM-4V)、百度文心一言 (ERNIE-ViLG)、阿里通义千问 (Qwen-VL)。
    • 备选 (需处理网络问题):OpenAI GPT-4V、Google Gemini Pro Vision。
  • 其他工具: Postman (API 测试), Navicat 或 DBeaver (数据库管理)。

项目初始化: 使用 Spring Initializr (https://start.spring.io/) 快速生成项目骨架。 依赖选择:

  • Spring Web (构建Web应用)
  • Spring Boot DevTools (热部署)
  • Lombok (简化POJO代码)
  • MySQL Driver (数据库连接)
  • MyBatis Framework (或直接使用 MyBatis-Plus 的 starter)

生成后,在 pom.xml 中手动添加 MyBatis-Plus 依赖:

XML
<!-- pom.xml -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4</version> <!-- 请使用最新稳定版 -->
</dependency>

4. 数据库设计与核心表结构

一个清晰的数据库设计是后端逻辑的基石。我们设计四张核心表:

SQL
-- 1. 用户表 (sys_user) - 存储医生/管理员信息
CREATE TABLE `sys_user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(100) NOT NULL COMMENT '加密后的密码',
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`role` varchar(20) NOT NULL DEFAULT 'DOCTOR' COMMENT '角色:ADMIN, DOCTOR',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';
 
-- 2. 患者表 (patient) - 存储患者基本信息
CREATE TABLE `patient` (
`id` bigint NOT NULL AUTO_INCREMENT,
`patient_id` varchar(20) NOT NULL COMMENT '患者唯一编号',
`name` varchar(50) NOT NULL,
`gender` varchar(10) DEFAULT NULL COMMENT '性别',
`age` int DEFAULT NULL,
`contact` varchar(100) DEFAULT NULL COMMENT '联系方式',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_patient_id` (`patient_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='患者信息表';
 
-- 3. 医学影像记录表 (medical_image)
CREATE TABLE `medical_image` (
`id` bigint NOT NULL AUTO_INCREMENT,
`patient_id` varchar(20) NOT NULL COMMENT '关联患者ID',
`image_name` varchar(255) NOT NULL COMMENT '影像文件名',
`image_path` varchar(500) NOT NULL COMMENT '服务器存储路径',
`image_type` varchar(50) DEFAULT NULL COMMENT '影像类型:X-RAY, CT, MRI',
`body_part` varchar(100) DEFAULT NULL COMMENT '拍摄部位:CHEST, HEAD, ABDOMEN',
`upload_time` datetime DEFAULT CURRENT_TIMESTAMP,
`upload_user_id` bigint DEFAULT NULL COMMENT '上传医生ID',
PRIMARY KEY (`id`),
KEY `idx_patient_id` (`patient_id`),
KEY `idx_upload_time` (`upload_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='医学影像记录表';
 
-- 4. 辅助诊断报告表 (diagnosis_report)
CREATE TABLE `diagnosis_report` (
`id` bigint NOT NULL AUTO_INCREMENT,
`image_record_id` bigint NOT NULL COMMENT '关联的影像记录ID',
`patient_id` varchar(20) NOT NULL,
`ai_analysis_raw` text COMMENT '大模型返回的原始分析文本',
`structured_findings` text COMMENT '结构化的影像发现(JSON格式)',
`impression` text COMMENT '辅助诊断印象(AI生成总结)',
`recommendation` text COMMENT '后续检查建议',
`generated_by` varchar(100) DEFAULT NULL COMMENT '生成模型,如 GLM-4V',
`generated_at` datetime DEFAULT CURRENT_TIMESTAMP,
`reviewed_by_doctor_id` bigint DEFAULT NULL COMMENT '审核医生ID',
`review_status` varchar(20) DEFAULT 'PENDING' COMMENT '状态:PENDING, REVIEWED',
`review_notes` text COMMENT '医生审核意见',
PRIMARY KEY (`id`),
KEY `idx_image_record_id` (`image_record_id`),
KEY `idx_patient_id` (`patient_id`),
KEY `idx_generated_at` (`generated_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='辅助诊断报告表';

设计要点:

  • medical_image 表存储文件路径,而非文件本身。
  • diagnosis_report 表是关键,它记录了 AI 的原始输出 (ai_analysis_raw) 和可能被后续处理过的结构化信息 (structured_findings)。review_status 字段明确体现了“辅助”定位,报告需要医生最终审核。

5. SpringBoot 后端核心代码实现

我们将按照 MVC 分层结构,实现核心的业务流程。

5.1 实体类 (Entity) 与 DTO

使用 Lombok 简化代码。

JAVA
// 文件路径:src/main/java/com/example/aihealth/entity/MedicalImage.java
package com.example.aihealth.entity;
 
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
 
@Data
@TableName("medical_image")
public class MedicalImage {
@TableId(type = IdType.AUTO)
private Long id;
private String patientId;
private String imageName;
private String imagePath; // 如:/uploads/2024/05/20/xxx.jpg
private String imageType;
private String bodyPart;
private LocalDateTime uploadTime;
private Long uploadUserId;
}
JAVA
// 文件路径:src/main/java/com/example/aihealth/dto/ImageUploadDTO.java
package com.example.aihealth.dto;
 
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
 
@Data
public class ImageUploadDTO {
private String patientId; // 前端传入的患者ID
private String imageType;
private String bodyPart;
private MultipartFile imageFile; // 上传的影像文件
}

5.2 服务层 (Service) 实现

服务层是业务逻辑的核心。这里展示 AIService 中调用大模型 API 的关键方法。我们以智谱 AI 的 GLM-4V 为例。

首先,在 application.yml 中配置 API 密钥和端点:

YAML
# application.yml
ai:
glm:
api-key: your_glm_api_key_here # 请在智谱AI开放平台申请
api-url: https://open.bigmodel.cn/api/paas/v4/chat/completions # GLM-4V API地址

然后,实现调用逻辑:

JAVA
// 文件路径:src/main/java/com/example/aihealth/service/impl/AIServiceImpl.java
package com.example.aihealth.service.impl;
 
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.example.aihealth.service.AIService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.ResourceUtils;
 
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
 
@Service
@Slf4j
public class AIServiceImpl implements AIService {
 
@Value("${ai.glm.api-key}")
private String apiKey;
 
@Value("${ai.glm.api-url}")
private String apiUrl;
 
private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
 
@Override
public String analyzeMedicalImage(String imagePath) throws IOException {
// 1. 将图像文件转换为Base64
File imageFile = new File(imagePath);
if (!imageFile.exists()) {
throw new IOException("Image file not found: " + imagePath);
}
byte[] fileContent = Files.readAllBytes(imageFile.toPath());
String base64Image = Base64Utils.encodeToString(fileContent);
 
// 2. 构建符合GLM-4V API要求的请求体
// GLM-4V 要求将图片Base64放在 messages 的 content 中,格式为数组
Map<String, Object> message = new HashMap<>();
message.put("role", "user");
 
List<Object> contentList = new ArrayList<>();
contentList.add(Map.of("type", "text", "text", "请分析这张医学影像,描述你看到的任何异常发现,如阴影、结节、纹理增粗、心脏轮廓异常等。请用中文回答。"));
contentList.add(Map.of(
"type", "image_url",
"image_url", Map.of("url", "data:image/jpeg;base64," + base64Image) // 注意格式
));
message.put("content", contentList);
 
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "glm-4v"); // 指定模型
requestBody.put("messages", Arrays.asList(message));
requestBody.put("max_tokens", 1024);
 
String jsonBody = JSON.toJSONString(requestBody);
log.debug("Request to GLM-4V: {}", jsonBody);
 
// 3. 发送HTTP POST请求
RequestBody body = RequestBody.create(jsonBody, JSON_MEDIA_TYPE);
Request request = new Request.Builder()
.url(apiUrl)
.post(body)
.addHeader("Authorization", "Bearer " + apiKey) // GLM API鉴权方式
.addHeader("Content-Type", "application/json")
.build();
 
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
log.error("GLM-4V API call failed. Code: {}, Body: {}", response.code(), response.body() != null ? response.body().string() : "");
throw new IOException("Unexpected code from GLM-4V API: " + response.code());
}
 
String responseBody = response.body().string();
log.debug("Response from GLM-4V: {}", responseBody);
 
// 4. 解析响应,提取AI生成的文本内容
JSONObject jsonResponse = JSON.parseObject(responseBody);
String aiAnalysis = jsonResponse.getJSONArray("choices")
.getJSONObject(0)
.getJSONObject("message")
.getString("content");
 
return aiAnalysis.trim();
} catch (Exception e) {
log.error("Exception occurred while calling GLM-4V API", e);
throw new IOException("Failed to get analysis from AI service", e);
}
}
}

代码关键点解析:

  1. Base64 编码:大多数视觉大模型 API 都支持通过 Base64 编码直接传输图片数据,避免了额外的文件上传步骤。
  2. 提示词工程 (Prompt Engineering)“请分析这张医学影像...” 这段提示词至关重要。它引导模型专注于医学描述,并要求用中文回答。你可以进一步优化,例如:“你是一名经验丰富的放射科医生,请分析这张胸部X光片,重点描述肺野、心脏纵隔、肋骨有无异常。”
  3. 错误处理:网络调用必须包含完善的异常处理和日志记录,这对于调试和系统稳定性至关重要。
  4. API 密钥管理:在实际项目中,绝对不要将 API 密钥硬编码在代码中或提交到 Git。应使用环境变量或配置中心管理。

5.3 控制器层 (Controller) 实现

控制器负责协调文件上传、AI 分析和报告生成的全流程。

JAVA
// 文件路径:src/main/java/com/example/aihealth/controller/DiagnosisController.java
package com.example.aihealth.controller;
 
import com.example.aihealth.dto.ImageUploadDTO;
import com.example.aihealth.entity.DiagnosisReport;
import com.example.aihealth.entity.MedicalImage;
import com.example.aihealth.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.UUID;
 
@RestController
@RequestMapping("/api/diagnosis")
@RequiredArgsConstructor // Lombok 自动注入 final 字段
@Slf4j
public class DiagnosisController {
 
private final FileStorageService fileStorageService;
private final AIService aiService;
private final MedicalImageService medicalImageService;
private final DiagnosisReportService reportService;
 
@Value("${file.upload-dir:uploads/}") // 从配置读取上传目录
private String uploadDir;
 
@PostMapping("/upload-and-analyze")
public ResponseEntity<?> uploadAndAnalyze(
@RequestParam("patientId") String patientId,
@RequestParam("imageType") String imageType,
@RequestParam("bodyPart") String bodyPart,
@RequestParam("file") MultipartFile file) {
 
try {
// 1. 参数校验
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("请选择要上传的影像文件。");
}
 
// 2. 保存文件到服务器
String originalFilename = file.getOriginalFilename();
String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
String savedFileName = UUID.randomUUID() + fileExtension; // 使用UUID防止重名
String savedFilePath = uploadDir + savedFileName;
 
File destFile = new File(savedFilePath);
destFile.getParentFile().mkdirs(); // 创建目录
file.transferTo(destFile);
log.info("文件保存成功:{}", savedFilePath);
 
// 3. 保存影像记录到数据库
MedicalImage imageRecord = new MedicalImage();
imageRecord.setPatientId(patientId);
imageRecord.setImageName(originalFilename);
imageRecord.setImagePath(savedFilePath);
imageRecord.setImageType(imageType);
imageRecord.setBodyPart(bodyPart);
imageRecord.setUploadTime(LocalDateTime.now());
imageRecord.setUploadUserId(1L); // 假设当前登录用户ID为1,实际应从会话获取
medicalImageService.save(imageRecord);
 
// 4. 调用AI服务分析影像
String aiAnalysisResult = aiService.analyzeMedicalImage(savedFilePath);
log.info("AI分析结果:{}", aiAnalysisResult);
 
// 5. 生成并保存辅助诊断报告
DiagnosisReport report = new DiagnosisReport();
report.setImageRecordId(imageRecord.getId());
report.setPatientId(patientId);
report.setAiAnalysisRaw(aiAnalysisResult);
// 这里可以添加更复杂的逻辑,如解析AI结果,生成结构化数据
report.setImpression(extractImpression(aiAnalysisResult)); // 示例:提取关键印象
report.setGeneratedBy("GLM-4V");
report.setGeneratedAt(LocalDateTime.now());
report.setReviewStatus("PENDING");
 
reportService.save(report);
 
// 6. 返回结果给前端
return ResponseEntity.ok(Map.of(
"success", true,
"message", "影像上传与分析成功",
"reportId", report.getId(),
"aiAnalysis", aiAnalysisResult
));
 
} catch (IOException e) {
log.error("文件处理或AI调用失败", e);
return ResponseEntity.internalServerError().body(Map.of("success", false, "message", "服务器内部错误:" + e.getMessage()));
} catch (Exception e) {
log.error("未知错误", e);
return ResponseEntity.internalServerError().body(Map.of("success", false, "message", "处理失败"));
}
}
 
// 一个简单的方法,用于从AI返回的长文本中提取“印象”部分(示例逻辑)
private String extractImpression(String fullAnalysis) {
// 这里可以实现更复杂的NLP解析,例如寻找“印象:”、“结论:”等关键词
// 为简化,这里只取前200个字符作为示例
if (fullAnalysis.length() > 200) {
return fullAnalysis.substring(0, 200) + "...";
}
return fullAnalysis;
}
}

6. 前端简易界面与功能演示

为了快速演示,我们可以使用 Thymeleaf 模板引擎构建一个极简的上传和结果展示页面。

HTML
<!-- 文件路径:src/main/resources/templates/upload.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>医疗影像上传与分析</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h2>医疗影像辅助诊断系统 - 影像上传</h2>
<form id="uploadForm" enctype="multipart/form-data">
<div class="mb-3">
<label for="patientId" class="form-label">患者 ID</label>
<input type="text" class="form-control" id="patientId" name="patientId" required>
</div>
<div class="mb-3">
<label for="imageType" class="form-label">影像类型</label>
<select class="form-select" id="imageType" name="imageType">
<option value="X-RAY">X光</option>
<option value="CT">CT</option>
<option value="MRI">MRI</option>
</select>
</div>
<div class="mb-3">
<label for="bodyPart" class="form-label">拍摄部位</label>
<input type="text" class="form-control" id="bodyPart" name="bodyPart" placeholder="如:胸部、头部" required>
</div>
<div class="mb-3">
<label for="imageFile" class="form-label">选择影像文件</label>
<input class="form-control" type="file" id="imageFile" name="file" accept="image/*" required>
</div>
<button type="submit" class="btn btn-primary">上传并分析</button>
</form>
 
<div id="resultArea" class="mt-4" style="display:none;">
<h4>分析结果</h4>
<div class="card">
<div class="card-body">
<h5 class="card-title">AI 分析报告</h5>
<p id="aiAnalysisText" class="card-text"></p>
<p class="text-muted"><small>报告ID: <span id="reportId"></span> | 状态: <span class="badge bg-warning">待医生审核</span></small></p>
</div>
</div>
</div>
<div id="errorArea" class="alert alert-danger mt-3" style="display:none;"></div>
</div>
 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
$('#uploadForm').on('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
 
$.ajax({
url: '/api/diagnosis/upload-and-analyze',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
$('#aiAnalysisText').text(response.aiAnalysis);
$('#reportId').text(response.reportId);
$('#resultArea').show();
$('#errorArea').hide();
} else {
showError(response.message);
}
},
error: function(xhr) {
showError('请求失败: ' + xhr.status + ' ' + xhr.statusText);
}
});
});
 
function showError(msg) {
$('#errorArea').text(msg).show();
$('#resultArea').hide();
}
});
</script>
</body>
</html>

同时,需要一个简单的 Controller 来渲染这个页面:

JAVA
// 文件路径:src/main/java/com/example/aihealth/controller/PageController.java
package com.example.aihealth.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
 
@Controller
public class PageController {
@GetMapping("/upload")
public String uploadPage() {
return "upload"; // 对应 src/main/resources/templates/upload.html
}
}

7. 系统运行与效果验证

  1. 启动应用:确保 MySQL 服务已启动,并创建好数据库和表。在 IDEA 中运行 AiHealthApplication 主类,或使用命令行 mvn spring-boot:run
  2. 访问页面:打开浏览器,访问 http://localhost:8080/upload
  3. 上传测试
    • 准备一张测试用的 X 光片(可以从公开数据集如 ChestX-ray14 下载样例)。
    • 在页面填写患者 ID、选择影像类型、填写部位,并选择文件。
    • 点击“上传并分析”。
  4. 观察结果
    • 前端会显示“上传成功”的提示,并展示 AI 返回的分析文本。
    • 查看控制台日志,确认文件保存路径和 AI API 调用过程。
    • 使用数据库工具(如 Navicat)连接你的 MySQL,查看 medical_imagediagnosis_report 表,确认数据已正确插入。

预期成功现象

  • 后端控制台无报错,打印出 AI 分析结果。
  • 前端页面展示 AI 生成的描述性文本,例如:“影像显示双肺纹理清晰,未见明显实质性病变。心影形态、大小在正常范围内。双侧肋膈角锐利。未见胸腔积液或气胸征象。”
  • 数据库相关表中新增了记录。

8. 常见问题与排查思路

在开发过程中,你几乎一定会遇到以下问题。这里提供排查路径:

问题现象 可能原因 排查方式 解决方案
应用启动失败,报数据库连接错误 1. MySQL 服务未启动。
2. application.yml 中数据库配置(url, username, password)错误。
3. 数据库驱动版本不匹配。
1. 检查 MySQL 服务状态。
2. 核对配置文件。
3. 查看完整错误堆栈。
1. 启动 MySQL。
2. 修正配置。
3. 检查 pom.xml 中的 MySQL 驱动版本。
文件上传失败,报 IOException 1. 上传目录 (uploadDir) 不存在且没有创建权限。
2. 文件大小超过 Spring Boot 默认限制。
1. 检查 application.ymlfile.upload-dir 配置的路径。
2. 查看日志中具体的异常信息。
1. 确保目录存在或应用有创建权限。
2. 在 application.yml 中增加配置:spring.servlet.multipart.max-file-size=10MBmax-request-size=10MB
调用 AI API 返回 401 或 403 错误 1. API 密钥错误或已过期。
2. 请求的 URL 或模型名称错误。
3. 账户余额不足或未开通相应服务。
1. 检查 application.yml 中的 api-key
2. 核对 API 文档,确认请求地址和参数格式。
3. 登录对应平台查看账户状态。
1. 重新生成并替换 API 密钥。
2. 严格按照官方文档构造请求体。
3. 充值或开通服务。
AI API 调用超时或网络错误 1. 网络连接不稳定。
2. 服务器在国外,访问慢。
3. 图片 Base64 编码后数据量太大。
1. 使用 curl 或 Postman 直接测试 API。
2. 在代码中增加超时设置。
1. 检查网络,或使用国内大模型 API。
2. 在 OkHttpClient 构建时设置超时:.connectTimeout(30, TimeUnit.SECONDS)
3. 考虑压缩图片或使用更低分辨率的图片进行测试。
前端页面能打开,但上传后无反应 1. 浏览器控制台有 JavaScript 错误。
2. 后端接口地址错误。
3. 跨域问题 (CORS)。
1. 按 F12 打开开发者工具,查看 Console 和 Network 标签页。
2. 检查 AJAX 请求的 URL 是否正确。
1. 修正 JS 错误。
2. 确保 URL 与 @PostMapping 注解的路径一致。
3. 在后端添加 CORS 配置。
插入数据库时中文乱码 数据库、表或连接字符集不是 utf8mb4 检查 MySQL 数据库、表和连接的字符集设置。 创建数据库时指定:CREATE DATABASE your_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 并在 JDBC URL 中添加参数:?characterEncoding=utf8&useUnicode=true

9. 项目扩展与最佳实践建议

一个基础的 Demo 跑通后,你可以从以下方向深化你的毕业设计,这将是你的加分项:

  1. 用户认证与授权:集成 Spring Security,实现医生登录、注册、基于角色(ROLE_DOCTOR, ROLE_ADMIN)的权限控制。确保只有登录的医生才能上传影像和查看报告。
  2. 报告结构化与知识库:不要仅仅展示 AI 返回的原始文本。可以尝试:
    • 使用正则表达式或更高级的 NLP 库(如 HanLP)从 AI 文本中提取关键实体(如“结节”、“阴影”、“积液”)。
    • 构建一个简单的医学知识库(例如,症状-疾病对应关系),将 AI 描述与可能的诊断建议关联起来,生成更结构化的报告。
  3. 影像预处理:在调用 AI 前,对上传的影像进行预处理,如调整大小、对比度增强、去噪等,可能提升 AI 分析的准确性。可以使用 OpenCV(Java 版)来实现。
  4. 多模型对比与评估:在你的系统中集成 2-3 个不同的大模型 API(如 GLM-4V 和 文心一言)。对于同一张影像,同时调用它们,并将分析结果并列展示,让医生对比参考。这能体现你的系统设计能力和对 AI 服务的理解。
  5. 历史记录与对比:实现患者历史影像的查看功能,允许医生将当前影像与患者过往的影像进行对比,观察病情变化。
  6. 部署与容器化:学习使用 Docker 将你的 SpringBoot 应用和 MySQL 数据库容器化,并编写 docker-compose.yml 一键启动整个系统。这能让你的项目更易于演示和交付。
  7. 前端工程化:将简易的 Thymeleaf 页面替换为 Vue.js 或 React 构建的前后端分离项目。这能极大提升系统的交互体验和现代感。
  8. 强调伦理与安全:在你的论文和演示中,务必设立专门章节讨论:
    • 数据隐私:如何加密存储患者信息和影像?访问日志如何记录?
    • 系统定位:反复强调这是“辅助”系统,所有结论必须由执业医生最终审核确认。
    • 局限性说明:明确指出当前 AI 模型的局限性,如对罕见病识别率低、可能存在的误判等。

通过实现上述扩展中的任意 2-3 项,你的毕业设计将从“一个简单的集成 Demo”升级为“一个考虑周全、具有实用价值的原型系统”,在答辩时足以让你脱颖而出。

这个项目不仅是一份毕业设计,更是一个完整的、紧跟技术潮流的全栈开发实践。它串联了 Java 后端开发、AI 应用集成、数据库设计、系统安全等多个核心技能点。当你完成它,你收获的不仅仅是一个学位,更是一份能够写入简历的、实实在在的项目经验。