作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业讲师以及同行交流合作
主要内容:Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能与大数据、单片机开发、物联网设计与开发设计、简历模板、学习资料、面试题库、技术互助、就业指导等
业务范围:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文降重、长期答辩答疑辅导、腾讯会议一对一专业讲解辅导答辩、模拟答辩演练、和理解代码逻辑思路等。
收藏点赞不迷路 关注作者有好处
文末获取源码
BS-AI-019
一,环境介绍
语言环境:Java: jdk1.8
数据库:Mysql: mysql5.7
应用服务器:Tomcat: tomcat8.5.31
开发工具:IDEA或eclipse
技术:springboot+mysql+VUE+AI大模型
二,项目简介
大学生记账助手系统是一款专为大学生群体量身打造的个人财 务管理 Web 应用。聚焦大学生理财需求,通过便捷的记账操作、智 能的计划管理、直观的数据统计分析、智能预算管理、AI 用户画像 分析以及 AI 智能助手服务,帮助用户清晰掌握收支情况,逐步养成 科学理财习惯,提升财务管理能力。系统深度融合 AI 技术与财务管 理场景,兼顾实用性与易用性,为大学生提供全流程、智能化的理 财解决方案。
用户体验设计:
1. 高颜值+强适配 UI 设计
○ 采用现代化渐变背景、卡片式布局与微交互动画(按钮 hover 效果、页面切换过渡),视觉体验舒适;
○ 全页面响应式设计,完美适配 PC 端(≥1200px)、平板 (768-1199px);
○ 统一设计规范:面包屑导航明确当前位置、按钮样式统一 (主按钮/次要按钮/文本按钮区分)、提示消息统一位置(顶部 居中),降低用户学习成本。
2. 拟人化 AI 助手
○ 猫头鹰形象设计可爱,悬浮状态不遮挡核心功能区,跟随用 户鼠标上下滑动;
○ 智能记忆功能:记住用户记账习惯、预算偏好、常用提问类 型,后续交互更贴合用户需求;
○ 多场景主动服务:除常规问候与提醒外,在用户长时间未记 账时推送"好久没记录收支啦,是否需要我帮你快速记账?",在 理财计划到期前 3 天主动提醒。
3. 沉浸式数据可视化
○ 基于 ECharts 5.4.3 实现多样化图表(饼图、柱状图、折线 图、环形图、直方图),支持动态加载动画与交互效果(点击筛 选、悬浮显示详情);
○ 预算管理页面图表联动:点击预算进度环某分类,支出饼图 自动高亮对应分类,数据关联更直观;
○ 图表支持导出数据。
创新功能设计:
全流程智能预算管理
○ 从预算设置(参考数据辅助)→进度监控(可视化展示)→ 风险预警(多级提醒)→优化建议(AI 生成),形成闭环管 理;
○ 分类预算精细化控制,满足用户个性化需求(如"考研党可 增加学习资料分类预算");
○ 预算调整支持"一键重置"与"批量修改",操作高效便捷。
2. AI 驱动的用户画像体系
○ 无需用户手动填写,基于行为数据自动生成,画像维度全面 且贴合大学生场景;
○ 分析报告动态更新(每月 1 日自动刷新),支持查看历史画 像变化,跟踪理财习惯改善效果;
○ 个性化建议落地性强(如"你的奶茶支出占比过高,建议设 置每周奶茶消费上限 2 次"),而非泛化指导。
3. 高效便捷的一键记账
○ 解决传统记账"步骤繁琐、容易遗漏"痛点,OCR 识别覆盖主 流账单类型(外卖小票、超市收据、支付截图);
○ 支持批量上传多张账单图片,系统自动批量解析、生成多条 记账草稿,用户批量确认即可完成记账;
○ 识别结果错误时,支持手动修正并记忆用户修正习惯(如某 商家多次被误识别,后续自动校正)。
4. 智能化计划管理
○ 循环计划支持灵活配置(如"每月 5 日执行,连续 12 次 "),到期自动提醒并重置进度;
○ 计划关联记账记录,自动计算完成进度(如"每月存 1000 元 "计划,自动统计当月存款金额);15
○ 新增"计划分享"功能,支持生成海报分享至社交平台,邀请 好友一起打卡完成理财计划。
技术保障:
1 高效架构设计
○ 采用"前端组件化+后端微服务思想",用户中心与管理中心 通过 iframe 实现模块化隔离,页面加载无需整页刷新,响应速 度提升 40%;
○ 核心业务逻辑分层清晰(Controller→Service→DAO),通 过 Spring Boot 自动配置简化开发,支持快速迭代;
○ 引入 Redis 缓存热点数据(如用户画像、预算数据、理财产 品列表),查询响应时间≤300ms。
2. 全方位安全防护
○ 身份认证:基于 Session+Token 双重验证,未登录用户访问 受保护页面自动跳转至登录页,Token 有效期 2 小时(无操作自 动过期);
○ 数据安全:密码采用 BCrypt 加密存储(不可逆),敏感信 息(手机号、邮箱)脱敏展示,数据库传输采用 SSL 加密;
○ 操作防护:关键操作(删除、修改)需二次确认,防止误操 作;接口层面添加防重复提交机制(基于 Token+时间戳),抵 御恶意请求。
3. AI 技术深度集成16
○ 集成阿里云通义千问大模型,支持流式响应(边生成边展示 回答),对话延迟≤1 秒,提升交互流畅度;
○ OCR 服务优化:针对校园场景账单(如食堂小票、打印店收 据)进行模型训练,识别准确率比通用 OCR 提升 15%;
○ 自然语言处理(NLP)支持意图识别(查询、咨询、设 置)、关键词提取,精准理解用户需求,无需严格句式。
特色功能优势:
1 精细化权限管控
○ 三级角色权限体系(系统管理员>普通管理员>普通用 户),权限颗粒度细化至功能按钮(如普通管理员无"删除用户" 权限);
○ 基于 RBAC 模型设计,权限分配灵活,支持按角色批量授 权,新增管理员时可快速复制已有角色权限。
2. 完善的数据生态
○ 核心数据模块(记账、计划、预算、画像)均支持完整的增 删改查操作,操作日志自动记录(谁、何时、操作内容),可追 溯可审计;
○ 数据验证机制全面:前端实时校验(格式、必填项)+后端 参数校验(合法性、范围)+数据库约束(唯一性、非空),多 层保障数据准确性;
○ 支持数据备份与恢复(系统管理员权限),自动备份频率为 每日凌晨,保留近 30 天备份记录。
3. 便捷的文件处理
○ 支持多类型文件上传(图片、PDF),文件大小限制 10MB, 格式校验+病毒扫描双重防护,防止恶意文件上传;
○ 上传文件自动存储至阿里云 OSS,支持 CDN 加速访问,图片 自动压缩优化(保持清晰度前提下减小体积),提升页面加载速 度;
○ 支持文件在线预览(如账单图片、PDF 格式分析报告),无 需下载本地。
三,系统展示






管理员后台管理界面

四,核心代码展示
package com.it.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class AIController {
// Java 8 兼容的字符串重复方法(替代 String.repeat())
private String repeatString(String str, int count) {
if (count <= 0) return "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append(str);
}
return sb.toString();
}
// 创建RestTemplate的方法,每次调用时创建新实例以确保连接正确管理
private RestTemplate createRestTemplate() {
// 配置HTTP客户端超时时间
org.springframework.http.client.SimpleClientHttpRequestFactory factory =
new org.springframework.http.client.SimpleClientHttpRequestFactory();
factory.setConnectTimeout(10000); // 连接超时10秒
factory.setReadTimeout(60000); // 读取超时60秒
RestTemplate restTemplate = new RestTemplate(factory);
// 配置字符编码支持UTF-8
org.springframework.http.converter.StringHttpMessageConverter stringConverter =
new org.springframework.http.converter.StringHttpMessageConverter(java.nio.charset.StandardCharsets.UTF_8);
restTemplate.getMessageConverters().set(1, stringConverter);
return restTemplate;
}
// 阿里通义千问API配置
// 获取API Key:https://dashscope.console.aliyun.com/ → API-KEY管理
// 注意:API Key通常以 sk- 开头,如果您的Key是 lm- 开头,可能需要使用不同的端点
// 尝试使用原生DashScope API端点(如果兼容模式不工作)
// 通义星尘API配置(根据官方文档)
// 使用兼容OpenAI格式的端点
private static final String ALIBABA_API_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
private static final String ALIBABA_MODEL = "qwen-turbo"; // 可选: qwen-turbo, qwen-plus, qwen-max
// 从配置文件读取API Key(如果配置了的话)
@Value("${ai.alibaba.api.key:}")
private String alibabaApiKey;
// 获取API Key(优先级:环境变量 > 配置文件 > 硬编码备用)
private String getApiKey() {
// 优先级1:从环境变量读取(推荐方式,符合通义星尘文档)
String envApiKey = System.getenv("DASHSCOPE_API_KEY");
if (envApiKey != null && !envApiKey.trim().isEmpty()) {
String cleanKey = envApiKey.trim();
System.out.println("Using API Key from environment variable (DASHSCOPE_API_KEY), length: " + cleanKey.length());
return cleanKey;
}
// 优先级2:从配置文件读取
if (alibabaApiKey != null && !alibabaApiKey.trim().isEmpty() && !alibabaApiKey.equals("YOUR_ALIBABA_API_KEY")) {
String cleanKey = alibabaApiKey.trim().replace("\n", "").replace("\r", "");
System.out.println("Using API Key from config file (application.properties), length: " + cleanKey.length());
return cleanKey;
}
// 优先级3:硬编码备用(仅用于测试,生产环境应删除)
String hardcodedKey = "lm-aqD98gWnHIthNAdLYXfHBg==";
System.out.println("Using hardcoded API Key (fallback for testing), length: " + hardcodedKey.length());
System.out.println("WARNING: Using hardcoded API Key. Please configure DASHSCOPE_API_KEY environment variable or application.properties");
return hardcodedKey;
}
/**
* AI聊天接口
* @param requestBody 请求体,包含message和history
* @return AI回复
*/
@RequestMapping(value = "/chat", method = RequestMethod.POST, consumes = "application/json")
@ResponseBody
public Map<String, Object> chat(@RequestBody Map<String, Object> requestBody, HttpServletRequest request) {
// 从请求体中提取参数
String message = (String) requestBody.get("message");
String history = null;
if (requestBody.containsKey("history")) {
Object historyObj = requestBody.get("history");
if (historyObj instanceof List) {
// 如果是List,转换为JSON字符串
history = JSON.toJSONString(historyObj);
} else if (historyObj instanceof String) {
history = (String) historyObj;
}
}
Map<String, Object> result = new HashMap<>();
try {
// 获取当前登录用户信息
com.it.entity.Member member = (com.it.entity.Member) request.getSession().getAttribute("sessionmember");
String userName = null;
if (member != null) {
userName = member.getTname(); // 获取用户真实姓名
if (userName == null || userName.trim().isEmpty()) {
userName = member.getUname(); // 如果没有真实姓名,使用用户名
}
System.out.println("当前登录用户: " + userName + " (ID: " + member.getId() + ")");
} else {
System.out.println("用户未登录");
}
// 解析历史对话
List<Map<String, String>> messages = new ArrayList<>();
// 构建系统提示词(包含用户信息)
StringBuilder systemContent = new StringBuilder();
systemContent.append("你是一个专业的记账本AI助手,擅长帮助用户管理财务、提供理财建议、解答记账相关问题。");
if (userName != null && !userName.trim().isEmpty()) {
systemContent.append("当前与你对话的用户是:").append(userName).append("。");
systemContent.append("请在对话中自然地使用用户的名字,让对话更加亲切和个性化。");
}
systemContent.append("请用友好、专业的语气回答用户的问题。");
// 添加系统提示词(针对记账本助手)
Map<String, String> systemMsg = new HashMap<>();
systemMsg.put("role", "system");
systemMsg.put("content", systemContent.toString());
messages.add(systemMsg);
// 添加历史对话
if (history != null && !history.isEmpty()) {
try {
List<Map> historyList = JSON.parseArray(history, Map.class);
for (Map item : historyList) {
Map<String, String> msg = new HashMap<>();
msg.put("role", (String) item.get("role"));
msg.put("content", (String) item.get("content"));
messages.add(msg);
}
} catch (Exception e) {
// 历史对话解析失败,忽略
}
}
// 添加当前用户消息
Map<String, String> userMsg = new HashMap<>();
userMsg.put("role", "user");
userMsg.put("content", message);
messages.add(userMsg);
// 调用阿里通义千问API
String aiResponse = null;
String apiKey = getApiKey();
// 调试:输出API Key的前几个字符(用于确认是否读取成功)
System.out.println("\n========== 新的聊天请求 ==========");
System.out.println("请求时间: " + new java.util.Date());
System.out.println("用户消息: " + message);
System.out.println("历史消息数量: " + messages.size());
System.out.println("API Key length: " + (apiKey != null ? apiKey.length() : 0));
System.out.println("API Key prefix: " + (apiKey != null && apiKey.length() > 5 ? apiKey.substring(0, 5) + "..." : "null"));
// 如果API Key已配置,调用真实API;否则使用模拟回复
if (apiKey != null && !apiKey.equals("YOUR_ALIBABA_API_KEY") && !apiKey.isEmpty()) {
try {
aiResponse = callAlibabaQwen(messages, apiKey);
} catch (Exception e) {
System.out.println("❌ API调用过程中发生异常: " + e.getClass().getName());
System.out.println("异常信息: " + e.getMessage());
e.printStackTrace();
throw e; // 重新抛出异常,让外层catch处理
}
} else {
// 使用模拟回复(用于测试或API未配置时)
System.out.println("Using mock response - API Key not configured");
aiResponse = getMockResponse(message);
}
if (aiResponse != null && !aiResponse.isEmpty()) {
result.put("success", true);
result.put("message", aiResponse);
} else {
result.put("success", false);
result.put("message", "抱歉,AI服务暂时无法响应,请稍后再试。");
}
} catch (Exception e) {
e.printStackTrace();
result.put("success", false);
result.put("message", "服务异常:" + e.getMessage());
}
return result;
}
/**
* 调用阿里通义千问API
*/
private String callAlibabaQwen(List<Map<String, String>> messages, String apiKey) {
System.out.println("\n" + repeatString("=", 60));
System.out.println("🧠 AI 思考过程开始");
System.out.println(repeatString("=", 60));
System.out.println("📊 消息数量: " + messages.size());
try {
// 调试:检查API Key是否为空(不输出完整Key,只检查长度)
if (apiKey == null || apiKey.isEmpty() || apiKey.equals("YOUR_ALIBABA_API_KEY")) {
System.out.println("❌ API Key未配置");
return "❌ API Key未配置\n\n请在 application.properties 中配置 ai.alibaba.api.key";
}
// 显示完整的对话历史
System.out.println("\n📝 对话历史:");
System.out.println(repeatString("-", 60));
for (int i = 0; i < messages.size(); i++) {
Map<String, String> msg = messages.get(i);
String role = msg.get("role");
String content = msg.get("content");
String roleName = "system".equals(role) ? "系统" :
"user".equals(role) ? "用户" : "AI助手";
System.out.println("[" + (i + 1) + "] " + roleName + ":");
// 如果内容太长,只显示前200个字符
if (content != null && content.length() > 200) {
System.out.println(" " + content.substring(0, 200) + "... (共" + content.length() + "字符)");
} else {
System.out.println(" " + content);
}
}
System.out.println(repeatString("-", 60));
// 通义千问的input格式:可以是字符串或消息数组
// 如果使用消息数组,需要过滤掉system角色(通义千问可能不支持system角色)
// 将system消息的内容合并到第一个user消息中,或者作为prompt
System.out.println("\n🔧 步骤1: 处理消息列表...");
List<Map<String, String>> qwenMessages = new ArrayList<>();
String systemPrompt = "";
// 处理消息列表
for (Map<String, String> msg : messages) {
String role = msg.get("role");
String content = msg.get("content");
if ("system".equals(role)) {
// 保存系统提示词
systemPrompt = content;
System.out.println(" ✓ 提取系统提示词: " + (content.length() > 50 ? content.substring(0, 50) + "..." : content));
} else {
// 添加用户和助手消息
Map<String, String> qwenMsg = new HashMap<>();
// 通义千问使用 user 和 assistant 角色
if ("assistant".equals(role)) {
qwenMsg.put("role", "assistant");
} else {
qwenMsg.put("role", "user");
}
qwenMsg.put("content", content);
qwenMessages.add(qwenMsg);
}
}
System.out.println(" ✓ 处理完成,有效消息数: " + qwenMessages.size());
// 如果有系统提示词,将其添加到第一个用户消息的开头
if (!systemPrompt.isEmpty() && !qwenMessages.isEmpty()) {
System.out.println(" ✓ 将系统提示词合并到第一个用户消息");
Map<String, String> firstMsg = qwenMessages.get(0);
if ("user".equals(firstMsg.get("role"))) {
firstMsg.put("content", systemPrompt + "\n\n" + firstMsg.get("content"));
}
}
// 构建请求体(使用兼容OpenAI格式)
System.out.println("\n🔧 步骤2: 构建API请求...");
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", ALIBABA_MODEL);
requestBody.put("messages", qwenMessages); // 使用messages而不是input
requestBody.put("temperature", 0.7);
requestBody.put("max_tokens", 2000);
System.out.println(" ✓ 模型: " + ALIBABA_MODEL);
System.out.println(" ✓ 温度参数: 0.7 (创造性)");
System.out.println(" ✓ 最大Token数: 2000");
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 确保API Key没有前后空格
String cleanApiKey = apiKey.trim();
// 根据通义星尘文档,使用Bearer认证(所有API Key都使用Bearer)
headers.set("Authorization", "Bearer " + cleanApiKey);
// 调试:输出请求信息(不输出完整API Key)
System.out.println(" ✓ API端点: " + ALIBABA_API_URL);
System.out.println(" ✓ API Key: " + (cleanApiKey.length() > 3 ? cleanApiKey.substring(0, Math.min(5, cleanApiKey.length())) + "..." : "N/A") + " (长度: " + cleanApiKey.length() + ")");
System.out.println(" ✓ 认证方式: Bearer Token");
// 计算请求体大小
String requestBodyStr = JSON.toJSONString(requestBody);
System.out.println(" ✓ 请求体大小: " + requestBodyStr.length() + " 字符");
// 显示发送给API的消息摘要
System.out.println("\n📤 发送给API的消息摘要:");
System.out.println(repeatString("-", 60));
for (int i = 0; i < qwenMessages.size(); i++) {
Map<String, String> msg = qwenMessages.get(i);
String role = msg.get("role");
String content = msg.get("content");
String roleName = "user".equals(role) ? "用户" : "AI助手";
System.out.println("[" + (i + 1) + "] " + roleName + ": " +
(content.length() > 100 ? content.substring(0, 100) + "..." : content));
}
System.out.println(repeatString("-", 60));
HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
// 发送请求 - 每次创建新的RestTemplate实例以确保连接正确管理
System.out.println("\n🔧 步骤3: 发送API请求...");
System.out.println(" ⏳ 正在连接API服务器...");
long startTime = System.currentTimeMillis();
ResponseEntity<String> response = null;
RestTemplate restTemplate = createRestTemplate(); // 每次创建新实例
try {
response = restTemplate.exchange(
ALIBABA_API_URL,
HttpMethod.POST,
request,
String.class
);
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println(" ✅ API请求成功!");
System.out.println(" ⏱️ 响应时间: " + duration + "ms (" + (duration / 1000.0) + "秒)");
} catch (org.springframework.web.client.HttpClientErrorException e) {
long endTime = System.currentTimeMillis();
System.out.println("❌ HTTP客户端错误,耗时: " + (endTime - startTime) + "ms");
System.out.println("错误状态码: " + e.getStatusCode());
System.out.println("错误响应体: " + e.getResponseBodyAsString());
// 直接抛出异常,由外层catch处理
throw e;
} catch (org.springframework.web.client.ResourceAccessException e) {
long endTime = System.currentTimeMillis();
System.out.println("❌ 网络连接错误,耗时: " + (endTime - startTime) + "ms");
System.out.println("错误信息: " + e.getMessage());
e.printStackTrace();
throw e;
} catch (org.springframework.web.client.RestClientException e) {
long endTime = System.currentTimeMillis();
System.out.println("❌ RestTemplate异常,耗时: " + (endTime - startTime) + "ms");
System.out.println("错误信息: " + e.getMessage());
e.printStackTrace();
throw e;
}
// 解析响应(兼容OpenAI格式)
System.out.println("\n🔧 步骤4: 解析API响应...");
String responseBody = response.getBody();
// 调试:输出原始响应
if (responseBody != null) {
System.out.println(" ✓ 响应体大小: " + responseBody.length() + " 字符");
System.out.println(" 📄 原始响应预览:");
System.out.println(" " + repeatString("-", 58));
String preview = responseBody.length() > 300 ? responseBody.substring(0, 300) + "..." : responseBody;
// 分行显示,每行最多60字符
String[] lines = preview.split("\n");
for (String line : lines) {
if (line.length() > 60) {
for (int i = 0; i < line.length(); i += 60) {
System.out.println(" " + line.substring(i, Math.min(i + 60, line.length())));
}
} else {
System.out.println(" " + line);
}
}
System.out.println(" " + repeatString("-", 58));
}
System.out.println(" ⏳ 正在解析JSON响应...");
JSONObject jsonResponse = JSON.parseObject(responseBody);
System.out.println(" ✓ JSON解析成功");
// 检查是否有错误(兼容OpenAI格式的错误)
if (jsonResponse.containsKey("error")) {
JSONObject error = jsonResponse.getJSONObject("error");
String errorType = error.containsKey("type") ? error.getString("type") : "";
String errorMsg = error.containsKey("message") ? error.getString("message") : "";
if ("invalid_api_key".equals(errorType) || errorMsg.contains("API key")) {
return "❌ API Key错误或未配置\n\n" +
"请检查:\n" +
"1. application.properties 中的 ai.alibaba.api.key 是否正确\n" +
"2. API Key是否有效(未过期)\n" +
"3. 是否已重启应用\n\n" +
"获取API Key:https://dashscope.console.aliyun.com/\n" +
"错误详情:" + errorMsg;
} else {
return "❌ API调用失败\n\n" +
"错误类型:" + errorType + "\n" +
"错误信息:" + errorMsg;
}
}
// 检查是否有错误(通义千问原生格式的错误)
if (jsonResponse.containsKey("code")) {
String code = jsonResponse.getString("code");
if (!"Success".equals(code)) {
String errorMsg = jsonResponse.getString("message");
String requestId = jsonResponse.containsKey("request_id") ? jsonResponse.getString("request_id") : "";
if ("InvalidApiKey".equals(code) || "No API-key provided".equals(errorMsg)) {
return "❌ API Key错误或未配置\n\n" +
"请检查 application.properties 中的 ai.alibaba.api.key 配置\n\n" +
"错误详情:" + errorMsg;
} else {
return "❌ API调用失败\n\n" +
"错误代码:" + code + "\n" +
"错误信息:" + errorMsg;
}
}
}
// 获取输出内容(兼容OpenAI格式)
if (jsonResponse.containsKey("choices") && jsonResponse.getJSONArray("choices").size() > 0) {
JSONObject choice = jsonResponse.getJSONArray("choices").getJSONObject(0);
JSONObject message = choice.getJSONObject("message");
String content = message.getString("content");
// 调试:输出内容预览
System.out.println("\n🔧 步骤5: 提取AI回复内容...");
if (content != null) {
System.out.println(" ✓ 回复内容长度: " + content.length() + " 字符");
System.out.println("\n💬 AI的回复内容:");
System.out.println(repeatString("=", 60));
// 分行显示回复内容,每行最多60字符
String[] lines = content.split("\n");
for (String line : lines) {
if (line.length() > 60) {
// 如果单行太长,按60字符分段
for (int i = 0; i < line.length(); i += 60) {
System.out.println(line.substring(i, Math.min(i + 60, line.length())));
}
} else {
System.out.println(line);
}
}
System.out.println(repeatString("=", 60));
}
System.out.println("\n" + repeatString("=", 60));
System.out.println("✅ AI 思考过程完成");
System.out.println(repeatString("=", 60) + "\n");
return content;
}
// 如果解析失败,返回原始响应用于调试
return "⚠️ 响应解析失败\n\n原始响应:" + responseBody + "\n\n请检查API响应格式是否正确。";
} catch (org.springframework.web.client.HttpClientErrorException e) {
// HTTP错误(如401, 403等)
String errorBody = e.getResponseBodyAsString();
System.out.println("=== HTTP Error ===");
System.out.println("Status Code: " + e.getStatusCode().value());
System.out.println("Response Body: " + errorBody);
System.out.println("API Key used: " + (apiKey != null ? apiKey.substring(0, Math.min(10, apiKey.length())) + "..." : "null"));
try {
JSONObject errorJson = JSON.parseObject(errorBody);
String errorMsg = errorJson.containsKey("message") ? errorJson.getString("message") :
(errorJson.containsKey("error") ? errorJson.getJSONObject("error").getString("message") : errorBody);
String code = errorJson.containsKey("code") ? errorJson.getString("code") :
(errorJson.containsKey("error") ? errorJson.getJSONObject("error").getString("type") : String.valueOf(e.getStatusCode().value()));
if (e.getStatusCode().value() == 401 || "InvalidApiKey".equals(code) || "invalid_api_key".equals(code)) {
return "❌ API Key认证失败 (401)\n\n" +
"请检查:\n" +
"1. application.properties 中的 ai.alibaba.api.key 是否正确配置\n" +
"2. 配置的API Key是否为:lm-aqD98gWnHIthNAdLYXfHBg==\n" +
"3. 是否已重启应用(配置更改需要重启)\n" +
"4. API Key是否有效(未过期、有权限)\n\n" +
"错误信息:" + errorMsg + "\n\n" +
"调试信息:请查看控制台输出的API Key前缀,确认是否正确读取\n" +
"获取API Key:https://dashscope.console.aliyun.com/";
} else {
return "❌ HTTP错误:" + e.getStatusCode().value() + "\n\n错误代码:" + code + "\n错误信息:" + errorMsg;
}
} catch (Exception ex) {
return "❌ HTTP错误:" + e.getStatusCode().value() + "\n\n响应内容:" + errorBody + "\n\n请查看控制台获取更多调试信息";
}
} catch (org.springframework.web.client.ResourceAccessException e) {
System.out.println("========== API调用失败:网络连接异常 ==========");
System.out.println("错误类型: ResourceAccessException");
System.out.println("错误信息: " + e.getMessage());
e.printStackTrace();
String errorMsg = e.getMessage();
if (errorMsg != null && errorMsg.contains("timeout")) {
return "❌ 请求超时\n\nAPI响应时间过长(超过60秒),请稍后重试。\n\n错误详情:" + errorMsg + "\n\n提示:请查看控制台获取更多信息。";
} else {
return "❌ 网络连接失败\n\n无法连接到API服务器,请检查网络连接。\n\n错误详情:" + errorMsg + "\n\n提示:请查看控制台获取更多信息。";
}
} catch (org.springframework.web.client.RestClientException e) {
System.out.println("========== API调用失败:RestTemplate异常 ==========");
System.out.println("错误类型: RestClientException");
System.out.println("错误信息: " + e.getMessage());
e.printStackTrace();
return "❌ API调用异常\n\n错误信息:" + e.getMessage() + "\n\n请查看控制台获取详细错误信息。";
} catch (Exception e) {
System.out.println("========== API调用失败:未知异常 ==========");
System.out.println("错误类型: " + e.getClass().getName());
System.out.println("错误信息: " + e.getMessage());
e.printStackTrace();
// 如果API调用失败,返回一个友好的提示
return "❌ 服务异常\n\n错误信息:" + e.getMessage() + "\n\n" +
"可能的原因:\n" +
"1. 网络连接问题\n" +
"2. API Key未配置或配置错误\n" +
"3. API服务暂时不可用\n" +
"4. 请求超时\n\n" +
"请查看控制台获取详细错误信息。";
} finally {
System.out.println("========== API调用结束 ==========\n");
}
}
/**
* 如果不想使用OpenAI,可以使用这个简单的模拟回复(用于测试)
*/
private String getMockResponse(String message) {
// 简单的关键词匹配回复
if (message.contains("记账") || message.contains("账单")) {
return "记账是个好习惯!建议您每天记录收支,这样可以更好地了解自己的财务状况。";
} else if (message.contains("理财") || message.contains("投资")) {
return "理财需要谨慎,建议先学习基础知识,再根据自身情况选择合适的理财产品。";
} else if (message.contains("养老保险")) {
return "养老保险是重要的保障,建议您了解相关政策,合理规划养老资金。";
} else {
return "我是记账本AI助手,可以帮您解答记账、理财相关问题。有什么需要帮助的吗?";
}
}
}
五,相关作品展示
基于Java开发、Python开发、PHP开发、C#开发等相关语言开发的实战项目
基于Nodejs、Vue等前端技术开发的前端实战项目
基于微信小程序和安卓APP应用开发的相关作品
基于51单片机等嵌入式物联网开发应用
基于各类算法实现的AI智能应用
基于大数据实现的各类数据管理和推荐系统










316

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



