尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

30分钟用SpringBoot集成DeepSeek API构建AI聊天机器人

30分钟用SpringBoot集成DeepSeek API构建AI聊天机器人 1. 项目概述为什么选择SpringBoot和DeepSeek最近DeepSeek的API火得一塌糊涂身边不少朋友都在问怎么快速搭个自己的AI聊天机器人玩玩。说实话现在大模型API的选择确实多但DeepSeek V4 Flash这个模型性价比是真的高响应速度也快对于想快速验证想法或者做个个人小工具的开发者来说是个绝佳的选择。而SpringBoot作为Java生态里最主流的Web应用框架它的“约定大于配置”理念能让我们把精力集中在业务逻辑上而不是繁琐的XML配置里。把这两者结合起来30分钟搞出一个能对话的AI应用听起来有点夸张但只要你跟着我的步骤走真不是什么难事。这个项目适合谁呢首先如果你是个Java开发者想给自己的项目加个AI对话的“智能大脑”那这篇就是为你量身定做的。其次即便你SpringBoot刚入门只要会写基本的Controller和Service也能轻松跟上。最后对于那些想了解如何调用第三方RESTful API特别是AI模型API的开发者这个过程也是一个非常标准的范例。你不用去研究复杂的AI算法只需要知道怎么发请求、收响应就能让应用“聪明”起来。整个过程我们只关注三件事拿到DeepSeek的API Key、用SpringBoot写个接口去调用它、最后做个简单的网页能输入和显示对话。工具就用你最熟悉的IDEA或者VSCode连数据库都不需要主打一个轻快。2. 核心思路与架构设计2.1 技术选型背后的考量为什么是SpringBoot DeepSeek API这个组合这得从实际需求说起。我们的目标是“快速实现”这意味着技术栈要成熟、文档要齐全、踩坑要少。SpringBoot的自动配置和内置Tomcat让我们省去了搭建Web服务器和配置DispatcherServlet的麻烦一个main方法就能跑起来。而DeepSeek API相比其他一些大模型接口它的认证方式简单Bearer Token请求响应格式标准JSON并且提供了非常清晰的官方文档对于集成来说障碍最小。这里有个关键点DeepSeek API目前主要支持deepseek-v4-pro和deepseek-v4-flash这两个模型名。根据网络上的反馈deepseek-v4-flash在速度和成本上更有优势非常适合我们这种对实时性有要求的聊天场景。所以我们的模型参数就锁定它了。整个架构极其简单用户在前端页面输入问题请求发到我们的SpringBoot后端后端组装成符合DeepSeek API要求的JSON格式附上API Key转发请求拿到DeepSeek的回复后再返回给前端展示。这就是一个典型的代理转发模式我们的SpringBoot服务充当了一个安全、可控的中间层。2.2 项目结构规划为了清晰和可维护我们不能把所有代码都堆在一个类里。一个简单合理的Maven项目结构应该是这样的src/main/java/com/yourdomain/ai/ ├── AiChatApplication.java // SpringBoot主启动类 ├── config/ │ └── RestTemplateConfig.java // 配置HTTP客户端 ├── controller/ │ └── ChatController.java // 接收前端请求的入口 ├── service/ │ └── DeepSeekService.java // 封装调用DeepSeek API的核心逻辑 ├── dto/ │ ├── ChatRequest.java // 前端-后端的请求体 │ └── DeepSeekApiRequest.java // 后端-DeepSeek的请求体 └── dto/ └── DeepSeekApiResponse.java // DeepSeek-后端的响应体DeepSeekService是这个项目的核心它负责与远程API通信。使用Spring提供的RestTemplate或者更现代的WebClient来发送HTTP请求。这里我推荐用RestTemplate因为它更简单直观对于这个简单场景完全够用。我们会在配置类里把它初始化为一个单例Bean。ChatController只负责接收HTTP请求、调用Service、返回结果保持职责单一。DTOData Transfer Object对象则用来规范数据的格式确保我们发送和接收的JSON能被正确序列化和反序列化。这种结构哪怕以后你想增加对话历史、流式输出SSE或者切换其他模型扩展起来也非常方便。3. 环境准备与依赖配置3.1 初始化SpringBoot项目首先打开你的IDEA选择Spring Initializr来创建项目。如果你用VSCode也可以使用Spring Initializr扩展或者直接去 start.spring.io 网站生成项目再导入。关键依赖选择这几个就够了Spring Web: 提供构建Web应用的能力包含内嵌的Tomcat。Lombok: 通过注解自动生成Getter、Setter、构造函数等代码让DTO类非常简洁。Spring Boot DevTools: 可选但强烈建议。它支持热加载修改代码后无需重启应用能极大提升开发效率。项目元数据里Group填你的域名倒序比如com.exampleArtifact填ai-chatbot。打包方式选JarJava版本根据你的环境选择11或17推荐17。生成项目后用IDEA打开等待Maven下载完所有依赖。这个过程取决于你的网速通常一两分钟就好。3.2 获取DeepSeek API密钥这是调用API的通行证。你需要去DeepSeek的官方平台注册账号并创建API Key。通常流程是登录控制台找到“API Keys”或类似的管理页面点击“Create new API key”。创建时你可以给它起个名字比如“MySpringBootChat”。创建成功后会生成一串以sk-开头的密钥字符串。这个密钥只会显示一次务必立即复制并妥善保存到安全的地方比如本地的密码管理器或者一个临时文本文件但记得事后清理。如果丢失只能重新生成。注意千万不要把API Key直接硬编码在代码里更不要提交到GitHub等公开代码仓库。一旦泄露别人就可以用你的密钥疯狂调用API产生的费用都得你承担。我们下一步就要解决如何安全地配置它。3.3 安全配置API密钥在SpringBoot中管理敏感配置的最佳实践是使用application.properties或application.yml文件并结合环境变量。我们在src/main/resources/application.yml文件中添加配置deepseek: api: key: ${DEEPSEEK_API_KEY:your-default-key-here} # 优先从环境变量读取 url: https://api.deepseek.com/v1/chat/completions model: deepseek-v4-flash这里用了一个小技巧${DEEPSEEK_API_KEY:your-default-key-here}。它的意思是SpringBoot会首先查找系统环境变量中名为DEEPSEEK_API_KEY的值。如果找到了就使用它如果没找到则使用冒号后面的默认值your-default-key-here。这样在本地开发时你可以在IDEA的Run Configuration里设置环境变量或者直接在终端导出export DEEPSEEK_API_KEYsk-xxx。而在部署到服务器时比如用Jenkins或Docker也只需要在服务器环境或容器启动命令中设置这个环境变量即可代码本身无需改动非常安全。4. 核心代码实现与解析4.1 定义数据模型DTODTO是系统各层之间数据传输的载体定义好它们后面的代码写起来就清晰多了。我们先定义前端传给我们的请求格式。在dto包下创建ChatRequest.javaimport lombok.Data; Data public class ChatRequest { private String message; // 用户发送的消息内容 }一个Data注解来自Lombok相当于自动生成了getter、setter、toString()等方法。接着定义我们发给DeepSeek API的请求体。根据官方文档一个最简单的聊天完成请求需要model,messages两个必填字段。messages是一个数组每个元素包含role角色如user或assistant和content内容。我们暂时只实现单轮对话所以messages里只放用户当前的问题。创建DeepSeekApiRequest.javaimport lombok.Data; import java.util.ArrayList; import java.util.List; Data public class DeepSeekApiRequest { private String model; private ListMessage messages new ArrayList(); private double temperature 0.7; // 控制回复随机性0-2之间默认0.7 Data public static class Message { private String role; private String content; } }这里我添加了一个temperature参数默认值设为0.7。这个参数很有意思它决定了AI回复的“创造性”。值越低如0.2回复越确定、保守值越高如1.2回复越随机、有创意。对于一般的问答0.7是个不错的平衡点。最后定义DeepSeek API返回的响应体。我们最关心的是回复文本它藏在嵌套的JSON结构里。创建DeepSeekApiResponse.javaimport lombok.Data; import java.util.List; Data public class DeepSeekApiResponse { private ListChoice choices; Data public static class Choice { private Message message; } Data public static class Message { private String content; } }这样当我们收到API响应后就可以通过response.getChoices().get(0).getMessage().getContent()来获取AI的回复文本。4.2 配置HTTP客户端RestTemplate我们需要一个工具来发送HTTP请求。在config包下创建RestTemplateConfig.javaimport org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; Configuration public class RestTemplateConfig { Bean public RestTemplate restTemplate() { return new RestTemplate(); } }这是一个非常基础的配置创建了一个RestTemplate实例并交给Spring容器管理。RestTemplate是线程安全的所以配置成单例Bean完全没问题。在实际生产环境中你可能需要配置连接超时、读取超时、请求拦截器比如统一加日志等但对我们这个30分钟快速上手的项目基础配置足矣。4.3 实现核心服务层DeepSeekService服务层是业务逻辑的核心。在service包下创建DeepSeekService.javaimport com.example.ai.dto.DeepSeekApiRequest; import com.example.ai.dto.DeepSeekApiResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; Service Slf4j public class DeepSeekService { Value(${deepseek.api.url}) private String apiUrl; Value(${deepseek.api.key}) private String apiKey; Value(${deepseek.api.model}) private String model; private final RestTemplate restTemplate; public DeepSeekService(RestTemplate restTemplate) { this.restTemplate restTemplate; } public String chatWithDeepSeek(String userMessage) { // 1. 构造请求体 DeepSeekApiRequest request new DeepSeekApiRequest(); request.setModel(model); DeepSeekApiRequest.Message message new DeepSeekApiRequest.Message(); message.setRole(user); message.setContent(userMessage); request.getMessages().add(message); // 2. 设置请求头 HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(apiKey); // 关键设置Authorization头为Bearer Token HttpEntityDeepSeekApiRequest entity new HttpEntity(request, headers); // 3. 发送POST请求 log.info(正在向DeepSeek API发送请求模型{}, model); ResponseEntityDeepSeekApiResponse response restTemplate.exchange( apiUrl, HttpMethod.POST, entity, DeepSeekApiResponse.class ); // 4. 处理响应 if (response.getStatusCode() HttpStatus.OK response.getBody() ! null) { DeepSeekApiResponse apiResponse response.getBody(); if (apiResponse.getChoices() ! null !apiResponse.getChoices().isEmpty()) { String reply apiResponse.getChoices().get(0).getMessage().getContent(); log.info(收到DeepSeek回复长度{}, reply.length()); return reply; } } log.error(调用DeepSeek API失败状态码{}, response.getStatusCode()); return 抱歉AI助手暂时无法响应请稍后再试。; } }这段代码有几个关键点Value注解自动从application.yml中注入我们配置的URL、Key和模型名。构造请求体严格按照DeepSeek API的格式要求创建包含角色和内容的Message对象。设置认证头headers.setBearerAuth(apiKey)这一行是核心它自动生成Authorization: Bearer sk-xxx的请求头。这是调用绝大多数云API的标准认证方式。发送请求使用restTemplate.exchange方法指定URL、方法、请求实体和期望的响应类型。这里我们期望的响应体类型就是我们定义的DeepSeekApiResponse.classSpring会自动帮我们把JSON反序列化成这个Java对象。异常处理目前我们做了最简单的处理如果响应状态不是200 OK或者响应体为空就返回一个友好的错误提示。在实际项目中这里需要更精细的错误处理和重试机制。4.4 实现控制器层ChatController控制器是面向HTTP的入口。在controller包下创建ChatController.javaimport com.example.ai.dto.ChatRequest; import com.example.ai.service.DeepSeekService; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/chat) Slf4j public class ChatController { private final DeepSeekService deepSeekService; public ChatController(DeepSeekService deepSeekService) { this.deepSeekService deepSeekService; } PostMapping public String chat(RequestBody ChatRequest chatRequest) { log.info(收到用户消息{}, chatRequest.getMessage()); if (chatRequest.getMessage() null || chatRequest.getMessage().trim().isEmpty()) { return 请输入有效的问题。; } return deepSeekService.chatWithDeepSeek(chatRequest.getMessage().trim()); } }这个控制器极其简洁。RestController表明这是一个RESTful风格的控制器它的方法返回值会自动被序列化成JSON。RequestMapping(“/api/chat”)定义了该控制器下所有接口的基础路径。我们只定义了一个PostMapping方法它接收一个JSON格式的ChatRequest对象Spring会自动绑定然后调用Service层的方法最后将AI的回复直接返回。这里也做了一个简单的非空校验。4.5 创建前端测试页面为了快速测试我们不需要搞复杂的前端框架。SpringBoot默认从src/main/resources/static目录提供静态资源。我们就在这个目录下创建一个简单的index.html!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title我的AI聊天助手/title style body { font-family: sans-serif; max-width: 800px; margin: 40px auto; padding: 20px; } #chatBox { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 10px; margin-bottom: 10px; } .user-msg { text-align: right; color: blue; margin: 5px 0; } .ai-msg { text-align: left; color: green; margin: 5px 0; } #inputArea { display: flex; } #userInput { flex-grow: 1; padding: 10px; } button { padding: 10px 20px; margin-left: 10px; } /style /head body h2 我的AI聊天助手 (基于DeepSeek)/h2 div idchatBox/div div idinputArea input typetext iduserInput placeholder输入你的问题... / button onclicksendMessage()发送/button /div script const chatBox document.getElementById(chatBox); const userInput document.getElementById(userInput); function addMessage(sender, text) { const msgDiv document.createElement(div); msgDiv.className sender user ? user-msg : ai-msg; msgDiv.innerHTML strong${sender user ? 你 : AI}:/strong ${text}; chatBox.appendChild(msgDiv); chatBox.scrollTop chatBox.scrollHeight; // 滚动到底部 } async function sendMessage() { const message userInput.value.trim(); if (!message) return; addMessage(user, message); userInput.value ; userInput.disabled true; try { const response await fetch(/api/chat, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ message: message }) }); const aiReply await response.text(); addMessage(ai, aiReply); } catch (error) { console.error(请求失败:, error); addMessage(ai, 网络请求失败请检查控制台。); } finally { userInput.disabled false; userInput.focus(); } } // 支持回车键发送 userInput.addEventListener(keypress, function(e) { if (e.key Enter) { sendMessage(); } }); /script /body /html这个页面功能很简单一个显示对话的区域一个输入框一个发送按钮。用JavaScript的fetchAPI向我们的后端接口POST /api/chat发送请求然后把回复展示出来。注意我们的后端接口地址是/api/chat而前端页面和后台服务在同一个域名/端口下所以这里用了相对路径避免了跨域问题。5. 运行、测试与问题排查5.1 启动应用与功能测试一切就绪现在可以启动了。找到主启动类AiChatApplication运行它的main方法。看到控制台输出类似Tomcat started on port(s): 8080的信息就说明启动成功了。首先我们直接用浏览器测试API。打开Postman或者任何你喜欢的API测试工具新建一个POST请求地址填http://localhost:8080/api/chat。在Body里选择raw和JSON输入{ message: 你好请用Java写一个Hello World程序。 }点击发送。你应该能收到一个状态码为200的响应并且响应体就是AI生成的Java代码。如果这一步成功了说明后端逻辑完全正确。然后打开浏览器访问http://localhost:8080因为我们把index.html放在了static根目录所以直接访问根路径即可。你应该能看到我们刚写的聊天界面。在输入框里问个问题比如“介绍一下SpringBoot”点击发送。稍等片刻AI的回复就应该会显示在聊天框里。恭喜你你的第一个AI聊天机器人已经跑起来了5.2 常见错误与解决方案实录在实际操作中你可能会遇到一些错误。下面是我在调试过程中遇到过的几个典型问题及其解决方法希望能帮你快速排雷。问题1API Error: 400 ‘type’ must be in [“enabled”, “disabled”, “auto”]现象调用接口返回400错误提示上述信息。排查这个错误通常是因为你的请求体中包含了API不支持的字段。仔细检查DeepSeekApiRequest对象确保它的字段名和官方文档完全一致。有时候某些教程或旧代码可能会包含stream是否流式输出、max_tokens最大生成长度等字段。对于DeepSeek V4 Flash这些字段可能不是必填或者名字有变化。最稳妥的办法是只发送model和messages这两个必填字段等通了之后再尝试添加其他可选参数。解决简化你的请求DTO暂时移除temperature以外的所有可选字段再次测试。问题2API Error: 400 This model’s maximum context length is 1048576 tokens…现象提示上下文长度超限。排查这个错误在你尝试进行多轮对话并把历史消息都塞进messages数组时可能出现。虽然DeepSeek V4 Flash支持很长的上下文约100万tokens但如果你累计的消息内容太长还是会触发这个错误。另外这个错误信息里的具体数字1048565或1048576可能因模型版本略有差异。解决对于快速演示项目我们只做单轮对话所以不会遇到。如果你后续要实现多轮对话就需要设计一个策略来管理历史消息比如只保留最近10轮对话或者当总token数估计超过某个阈值时丢弃最早的一些对话。问题3API Error: Connection closed mid-response.现象连接中途被重置响应不完整。排查这通常是网络问题或者服务器端出现了临时中断。也可能是你的请求时间太长而RestTemplate的默认超时设置较短。解决首先重试一下。如果频繁出现可以考虑在RestTemplateConfig中配置更长的读写超时时间。Bean public RestTemplate restTemplate() { RestTemplate restTemplate new RestTemplate(); SimpleClientHttpRequestFactory factory new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(10000); // 连接超时10秒 factory.setReadTimeout(60000); // 读取超时60秒 restTemplate.setRequestFactory(factory); return restTemplate; }问题4控制台打印Invalid character found in the request target或返回400状态码。现象前端发送的消息包含特殊字符如中文、空格、问号时请求失败。排查这可能是URL编码问题。但请注意我们用的是POST请求参数在请求体JSON中而不是URL里所以通常不会出现这个问题。如果出现检查前端fetch请求的headers是否正确设置了‘Content-Type’: ‘application/json’。另外确保你的ChatController方法参数使用了RequestBody注解这样Spring才能正确解析JSON请求体。问题5无法加载静态页面index.html显示404或空白页。排查检查index.html是否确实放在了src/main/resources/static/目录下。SpringBoot的静态资源默认映射规则是/static,/public,/resources,/META-INF/resources。访问http://localhost:8080默认会寻找index.html。如果还不行尝试清理一下项目并重新编译Maven - Clean, then Compile。5.3 性能与体验优化点基础功能跑通后我们可以做一些小优化让体验更好。流式输出SSE目前我们是等AI完全生成完所有文本后才一次性返回用户需要等待较长时间。更好的体验是像ChatGPT那样一个字一个字地实时显示。这可以通过Server-Sent Events (SSE) 技术实现。DeepSeek API支持设置stream: true参数返回一个数据流。后端需要将流式数据块实时推送给前端。这需要改造Controller的返回类型为SseEmitter并调整Service层的解析逻辑。虽然稍复杂但能极大提升用户体验。对话历史管理现在的Service每次只发送当前消息AI没有上下文记忆。要实现多轮对话需要在后端比如用HttpSession或数据库里保存一个会话的历史消息列表每次请求都把整个列表发给AI。注意要控制列表长度避免超出上下文限制。前端加载状态在前端发送请求后、收到响应前可以禁用发送按钮并在输入框旁边显示一个“思考中…”的动画给用户明确的反馈。错误友好提示目前Service里只返回了简单的错误字符串。可以定义更丰富的错误码和消息让前端能根据不同的错误类型如网络超时、API额度不足、内容违规等展示不同的提示。6. 项目部署与后续扩展6.1 打包与部署开发测试完成后你可以把它打包成可执行的JAR文件部署到任何有Java环境的服务器上。在项目根目录下运行Maven命令mvn clean package命令执行成功后会在target目录下生成一个ai-chatbot-0.0.1-SNAPSHOT.jar文件名字取决于你的pom.xml中的设置。这个JAR包是“可执行”的因为它内嵌了Tomcat服务器。部署到服务器只需将JAR文件上传到你的Linux服务器然后在终端运行export DEEPSEEK_API_KEY你的真实API密钥 java -jar ai-chatbot-0.0.1-SNAPSHOT.jar应用就会在后台启动监听8080端口默认。你可以使用nohup或systemd来让它持续运行。再次强调API密钥通过环境变量传入安全又灵活。使用Docker部署如果你熟悉Docker可以创建一个简单的DockerfileFROM openjdk:17-jdk-slim COPY target/ai-chatbot-*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app.jar]然后构建镜像并运行容器同样通过-e DEEPSEEK_API_KEYxxx来传递环境变量。用Docker部署能更好地解决环境依赖问题。6.2 可能的扩展方向这个30分钟完成的项目是一个完美的起点你可以基于它扩展出很多有趣的功能增加身份验证使用Spring Security为你的聊天机器人加上登录功能区分不同用户的对话历史。接入更多模型抽象一个AIService接口然后实现DeepSeekService、OpenAIService、ZhipuService等。在配置文件中指定当前使用的模型甚至可以做一个模型切换功能。实现工具调用Function Calling让AI不仅能聊天还能根据你的指令执行操作比如查询天气、发送邮件。这需要按照模型的Function Calling规范来定义工具和解析响应。构建知识库问答结合向量数据库如Milvus, Pinecone和Embedding模型先让你的文档生成向量并存储。用户提问时先检索相关文档片段再连同问题和文档一起发给AI实现基于私有知识的精准问答。设计更美观的前端用Vue.js或React重写前端界面加入消息气泡、头像、Markdown渲染用于显示AI返回的代码块等特性。这个小小的项目就像一颗种子涵盖了现代AI应用开发的核心流程获取凭证、封装API、处理数据、提供服务。理解了它你就掌握了接入任何大模型API的通用方法。剩下的就是发挥你的想象力去创造更有价值的应用了。
返回列表