版权归属于 LangChat Team
官网:https://langchat.cn
23 - Spring Boot 集成
版本说明
本文档基于 LangChain4j 1.10.0 版本编写。学习目标
通过本章节学习,你将能够:- 理解 LangChain4j 与 Spring Boot 的集成方式
- 掌握 LangChain4j Spring Boot Starter 的使用
- 学会创建基于 Spring Boot 的 LLM 应用
- 理解依赖注入和配置管理
- 掌握 REST API 的创建
- 实现一个完整的 Spring Boot + LangChain4j 应用
前置知识
- 完成《01 - LangChain4j 简介》章节
- Spring Boot 基础知识
- Maven/Gradle 构建工具基础
核心概念
Spring Boot Starter
LangChain4j Spring Boot Starter 是官方提供的 Spring Boot 集成模块,提供:-
自动配置
- 自动配置 ChatModel
- 自动配置 EmbeddingModel
- 自动配置 TokenStream
-
依赖注入
- 通过 @Autowired 注入模型
- 通过 @Bean 自定义配置
-
属性配置
- application.yml/application.properties 配置
- 环境变量和配置文件支持
-
Starter 优势
- 简化集成
- 统一配置管理
- 自动依赖管理
- Spring 生态系统集成
项目结构
Copy
langchat-demo/
├── src/main/java/
│ └── com/example/langchat/
│ ├── LangchatDemoApplication.java # 主应用类
│ ├── config/
│ │ ├── ModelConfig.java # 模型配置
│ │ └── ChatConfig.java # 聊天配置
│ ├── controller/
│ │ ├── ChatController.java # 聊天控制器
│ │ └── ChatWebSocketHandler.java # WebSocket 处理器
│ ├── service/
│ │ ├── ChatService.java # 聊天服务
│ │ └── StreamingChatService.java # 流式聊天服务
│ └── dto/
│ ├── ChatRequest.java # 聊天请求 DTO
│ └── ChatResponse.java # 聊天响应 DTO
├── src/main/resources/
│ ├── application.yml # 配置文件
│ └── static/ # 静态资源
└── pom.xml # Maven 配置
项目配置
pom.xml 依赖
Copy
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>langchat-demo</artifactId>
<version>1.0.0</version>
<name>LangChat Demo</name>
<description>LangChain4j Spring Boot 集成示例</description>
<properties>
<java.version>17</java.version>
<langchain4j.version>1.10.0</langchain4j.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- LangChain4j Spring Boot Starter -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- Spring Boot WebSocket (可选)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Lombok (可选)-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml 配置
Copy
server:
port: 8080
servlet:
context-path: /api
spring:
application:
name: langchat-demo
# OpenAI 配置
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-4o-mini
temperature: 0.7
max-tokens: 1000
timeout: 60s
max-retries: 3
log-requests: true
log-responses: true
streaming-chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-4o-mini
temperature: 0.7
max-tokens: 1000
timeout: 60s
embedding-model:
api-key: ${OPENAI_API_KEY}
model-name: text-embedding-3-small
timeout: 60s
# 日志配置
logging:
level:
root: INFO
dev.langchain4j: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/langchat-demo.log
核心代码实现
主应用类
Copy
package com.example.langchat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot 主应用类
*/
@SpringBootApplication
public class LangchatDemoApplication {
public static void main(String[] args) {
SpringApplication.run(LangchatDemoApplication.class, args);
}
}
模型配置类
Copy
package com.example.langchat.config;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
/**
* 模型配置
*/
@Configuration
public class ModelConfig {
@Value("${langchain4j.open-ai.chat-model.api-key}")
private String chatApiKey;
@Value("${langchain4j.open-ai.chat-model.model-name}")
private String chatModelName;
@Value("${langchain4j.open-ai.chat-model.temperature}")
private Double temperature;
@Value("${langchain4j.open-ai.chat-model.max-tokens}")
private Integer maxTokens;
@Value("${langchain4j.open-ai.chat-model.timeout}")
private Duration timeout;
/**
* ChatModel Bean
*/
@Bean
public ChatModel chatModel() {
return OpenAiChatModel.builder()
.apiKey(chatApiKey)
.modelName(chatModelName)
.temperature(temperature)
.maxTokens(maxTokens)
.timeout(timeout)
.build();
}
/**
* StreamingChatModel Bean
*/
@Bean
public StreamingChatModel streamingChatModel() {
return OpenAiStreamingChatModel.builder()
.apiKey(chatApiKey)
.modelName(chatModelName)
.temperature(temperature)
.maxTokens(maxTokens)
.timeout(timeout)
.build();
}
/**
* EmbeddingModel Bean
*/
@Bean
public EmbeddingModel embeddingModel() {
return OpenAiEmbeddingModel.builder()
.apiKey(chatApiKey)
.modelName("text-embedding-3-small")
.build();
}
/**
* 聊天模型接口
*/
public interface StreamingChatModel extends dev.langchain4j.model.chat.StreamingChatModel {
}
}
聊天服务
Copy
package com.example.langchat.service;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 聊天服务
*/
@Service
public class ChatService {
private static final Logger logger = LoggerFactory.getLogger(ChatService.class);
private final ChatModel chatModel;
/**
* AI 服务接口
*/
@AiService
public interface Assistant {
String chat(@UserMessage String message);
}
/**
* AI 助手实例
*/
private Assistant assistant;
/**
* 构造函数
*/
@Autowired
public ChatService(ChatModel chatModel) {
this.chatModel = chatModel;
// 创建 AI 助手
this.assistant = AiServices.builder(Assistant.class)
.chatModel(chatModel)
.systemMessageProvider(chatMemoryId ->
"你是一个专业、友好且乐于助人的 AI 助手。" +
"你的任务是回答用户的问题,提供准确、有用的信息。" +
"请保持回答简洁明了,避免冗长的解释。" +
"如果不确定答案,请诚实告知用户。" +
"请使用自然的语言风格,避免过于正式或生硬的表达。"
)
.build();
}
/**
* 发送消息
*/
public String sendMessage(String message) {
logger.info("收到消息: {}", message);
return assistant.chat(message);
}
}
聊天控制器
Copy
package com.example.langchat.controller;
import com.example.langchat.dto.ChatRequest;
import com.example.langchat.dto.ChatResponse;
import com.example.langchat.service.ChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.validation.Valid;
/**
* 聊天控制器
*/
@RestController
@RequestMapping("/chat")
@CrossOrigin(origins = "*") // 生产环境应该指定具体域名
public class ChatController {
private static final Logger logger = LoggerFactory.getLogger(ChatController.class);
private final ChatService chatService;
/**
* 构造函数
*/
@Autowired
public ChatController(ChatService chatService) {
this.chatService = chatService;
}
/**
* 发送聊天消息
*
* @param request 聊天请求
* @return 聊天响应
*/
@PostMapping("/message")
public ResponseEntity<ChatResponse> sendMessage(@Valid @RequestBody ChatRequest request) {
logger.info("收到聊天请求: {}", request.getMessage());
try {
String response = chatService.sendMessage(request.getMessage());
ChatResponse chatResponse = new ChatResponse();
chatResponse.setMessage(response);
chatResponse.setTimestamp(System.currentTimeMillis());
return ResponseEntity.ok(chatResponse);
} catch (Exception e) {
logger.error("处理聊天请求失败", e);
ChatResponse errorResponse = new ChatResponse();
errorResponse.setMessage("处理失败: " + e.getMessage());
errorResponse.setTimestamp(System.currentTimeMillis());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(errorResponse);
}
}
/**
* 健康检查
*/
@GetMapping("/health")
public ResponseEntity<String> health() {
return ResponseEntity.ok("Chat 服务正常运行");
}
/**
* 获取服务信息
*/
@GetMapping("/info")
public ResponseEntity<ChatServiceInfo> getInfo() {
ChatServiceInfo info = new ChatServiceInfo();
info.setName("Chat Service");
info.setVersion("1.0.0");
info.setUptime(System.currentTimeMillis());
return ResponseEntity.ok(info);
}
/**
* 聊天服务信息
*/
private static class ChatServiceInfo {
private String name;
private String version;
private long uptime;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public long getUptime() { return uptime; }
public void setUptime(long uptime) { this.uptime = uptime; }
}
}
流式聊天控制器
Copy
package com.example.langchat.controller;
import com.example.langchat.service.StreamingChatService;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.model.chat.StreamingChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
/**
* 流式聊天控制器
*/
@RestController
@RequestMapping("/chat/stream")
public class StreamingChatController {
private static final Logger logger = LoggerFactory.getLogger(StreamingChatController.class);
private final StreamingChatModel streamingChatModel;
/**
* 构造函数
*/
@Autowired
public StreamingChatController(StreamingChatService streamingChatService) {
this.streamingChatModel = streamingChatService.getModel();
}
/**
* 流式发送消息
*/
@GetMapping(value = "/message", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public void streamMessage(@RequestParam("message") String message,
@RequestParam(value = "temperature", defaultValue = "0.7") double temperature,
@RequestParam(value = "maxTokens", defaultValue = "1000") int maxTokens) throws IOException {
logger.info("收到流式聊天请求: {}", message);
// 设置响应
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
try (java.io.PrintWriter writer = response.getWriter()) {
// 发送开始事件
writer.write("event: start\n");
writer.write("data: {}\n\n");
writer.flush();
// 流式生成
AtomicReference<StringBuilder> fullResponse = new AtomicReference<>(new StringBuilder());
streamingchatModel.chat(message, nextToken -> {
// 发送 Token 事件
try {
writer.write("event: token\n");
writer.write("data: ");
writer.write(nextToken);
writer.write("\n\n");
writer.flush();
fullResponse.get().append(nextToken);
} catch (IOException e) {
logger.error("发送流数据失败", e);
}
});
// 发送完成事件
writer.write("event: end\n");
writer.write("data: ");
writer.write(fullResponse.get().toString());
writer.write("\n\n");
writer.flush();
} catch (Exception e) {
logger.error("流式聊天处理失败", e);
// 发送错误事件
response.sendError(500, "处理失败: " + e.getMessage());
}
}
/**
* 获取 HttpServletResponse
*/
private jakarta.servlet.http.HttpServletResponse response;
/**
* 注入 HttpServletResponse
*/
@Autowired
public void setResponse(jakarta.servlet.http.HttpServletResponse response) {
this.response = response;
}
}
DTO 类
Copy
package com.example.langchat.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
/**
* 聊天请求
*/
public class ChatRequest {
@NotBlank(message = "消息不能为空")
@Size(min = 1, max = 2000, message = "消息长度必须在 1-2000 字符之间")
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
* 聊天响应
*/
public class ChatResponse {
private String message;
private long timestamp;
private String error;
// Getters and Setters
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
}
REST API 示例
创建完整 API
Copy
package com.example.langchat.controller;
import com.example.langchat.dto.ChatRequest;
import com.example.langchat.dto.ChatResponse;
import com.example.langchat.service.ChatService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 高级聊天 API
*/
@RestController
@RequestMapping("/api/v1/chat")
public class AdvancedChatController {
private final ChatService chatService;
@Autowired
public AdvancedChatController(ChatService chatService) {
this.chatService = chatService;
}
/**
* 批量聊天
*/
@PostMapping("/batch")
public ResponseEntity<List<ChatResponse>> batchChat(@RequestBody List<ChatRequest> requests) {
List<ChatResponse> responses = new java.util.ArrayList<>();
for (ChatRequest request : requests) {
try {
String responseMessage = chatService.sendMessage(request.getMessage());
ChatResponse response = new ChatResponse();
response.setMessage(responseMessage);
response.setTimestamp(System.currentTimeMillis());
responses.add(response);
} catch (Exception e) {
ChatResponse errorResponse = new ChatResponse();
errorResponse.setMessage("失败: " + e.getMessage());
errorResponse.setTimestamp(System.currentTimeMillis());
responses.add(errorResponse);
}
}
return ResponseEntity.ok(responses);
}
/**
* 带上下文的聊天
*/
@PostMapping("/context")
public ResponseEntity<ChatResponse> chatWithContext(@RequestBody ChatContextRequest request) {
String fullMessage = request.getContext() + "\n" + request.getMessage();
String response = chatService.sendMessage(fullMessage);
ChatResponse chatResponse = new ChatResponse();
chatResponse.setMessage(response);
chatResponse.setTimestamp(System.currentTimeMillis());
return ResponseEntity.ok(chatResponse);
}
/**
* 多轮对话
*/
@PostMapping("/conversation")
public ResponseEntity<ChatResponse> conversation(@RequestBody ConversationRequest request) {
StringBuilder context = new StringBuilder();
// 处理历史消息
for (String message : request.getHistory()) {
context.append(message).append("\n");
}
// 添加当前消息
context.append(request.getMessage());
// 发送
String response = chatService.sendMessage(context.toString());
ChatResponse chatResponse = new ChatResponse();
chatResponse.setMessage(response);
chatResponse.setTimestamp(System.currentTimeMillis());
return ResponseEntity.ok(chatResponse);
}
/**
* 带系统提示的聊天
*/
@PostMapping("/custom-system")
public ResponseEntity<ChatResponse> chatWithSystemMessage(@RequestBody SystemMessageRequest request) {
// 使用自定义系统提示发送
// 这里可以创建一个专门的服务方法
ChatResponse chatResponse = new ChatResponse();
chatResponse.setMessage("自定义系统提示功能");
chatResponse.setTimestamp(System.currentTimeMillis());
return ResponseEntity.ok(chatResponse);
}
/**
* 聊天上下文请求
*/
private static class ChatContextRequest {
private String context;
private String message;
// Getters and Setters
public String getContext() { return context; }
public void setContext(String context) { this.context = context; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
/**
* 对话请求
*/
private static class ConversationRequest {
private List<String> history;
private String message;
// Getters and Setters
public List<String> getHistory() { return history; }
public void setHistory(List<String> history) { this.history = history; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
/**
* 系统消息请求
*/
private static class SystemMessageRequest {
private String systemMessage;
private String userMessage;
// Getters and Setters
public String getSystemMessage() { return systemMessage; }
public void setSystemMessage(String systemMessage) { this.systemMessage = systemMessage; }
public String getUserMessage() { return userMessage; }
public void setUserMessage(String userMessage) { this.userMessage = userMessage; }
}
}
测试代码
Spring Boot 测试
Copy
package com.example.langchat;
import com.example.langchat.dto.ChatRequest;
import com.example.langchat.dto.ChatResponse;
import com.example.langchat.service.ChatService;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.MockitoBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import dev.langchain4j.data.message.AiMessage;
/**
* 聊天服务测试
*/
@SpringBootTest
@TestPropertySource(properties = {
"langchain4j.open-ai.chat-model.api-key=test-key",
"langchain4j.open-ai.chat-model.model-name=gpt-4o-mini",
"langchain4j.open-ai.chat-model.temperature=0.7",
"langchain4j.open-ai.chat-model.max-tokens=1000"
})
class ChatControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ChatService chatService;
@Test
void should_send_message_successfully() throws Exception {
// 准备测试数据
ChatRequest request = new ChatRequest();
request.setMessage("你好");
// Mock 服务
when(chatService.sendMessage(anyString())).thenReturn("你好!有什么可以帮助你的?");
// 执行请求
mockMvc.perform(MockMvcRequestBuilders.post("/api/chat/message")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"message\":\"你好\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.message").value("你好!有什么可以帮助你的?"))
.andExpect(jsonPath("$.timestamp").exists());
}
@Test
void should_validate_empty_message() throws Exception {
ChatRequest request = new ChatRequest();
request.setMessage("");
mockMvc.perform(MockMvcRequestBuilders.post("/api/chat/message")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"message\":\"\"}"))
.andExpect(status().isBadRequest());
}
@Test
void should_validate_long_message() throws Exception {
ChatRequest request = new ChatRequest();
request.setMessage("a".repeat(2001)); // 超过 2000 字符限制
mockMvc.perform(MockMvcRequestBuilders.post("/api/chat/message")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"message\":\"" + "a".repeat(2001) + "\"}"))
.andExpect(status().isBadRequest());
}
@Test
void should_handle_service_error() throws Exception {
ChatRequest request = new ChatRequest();
request.setMessage("测试");
// Mock 服务异常
when(chatService.sendMessage(anyString()))
.thenThrow(new RuntimeException("服务错误"));
mockMvc.perform(MockMvcRequestBuilders.post("/api/chat/message")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"message\":\"测试\"}"))
.andExpect(status().isInternalServerError())
.andExpect(jsonPath("$.error").exists());
}
@Test
void should_return_health_check() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/chat/health"))
.andExpect(status().isOk())
.andExpect(content().string("Chat 服务正常运行"));
}
@Test
void should_return_service_info() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/chat/info"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Chat Service"))
.andExpect(jsonPath("$.version").value("1.0.0"))
.andExpect(jsonPath("$.uptime").exists());
}
}
实践练习
练习 1:实现完整的聊天应用
Copy
package com.example.langchat;
import com.example.langchat.dto.ChatRequest;
import com.example.langchat.dto.ChatResponse;
import com.example.langchat.service.ChatService;
import org.springframework.web.bind.annotation.*;
/**
* 完整的聊天应用
*/
@RestController
@RequestMapping("/api/v2/chat")
public class CompleteChatController {
private final ChatService chatService;
public CompleteChatController(ChatService chatService) {
this.chatService = chatService;
}
/**
* 发送消息
*/
@PostMapping("/send")
public ResponseEntity<ChatResponse> sendMessage(@RequestBody ChatRequest request) {
String response = chatService.sendMessage(request.getMessage());
ChatResponse chatResponse = new ChatResponse();
chatResponse.setMessage(response);
chatResponse.setTimestamp(System.currentTimeMillis());
return ResponseEntity.ok(chatResponse);
}
/**
* 批量处理消息
*/
@PostMapping("/batch")
public ResponseEntity<List<ChatResponse>> batchProcess(@RequestBody List<ChatRequest> requests) {
// 实现批量处理逻辑
return ResponseEntity.ok(new java.util.ArrayList<>());
}
/**
* 清除会话
*/
@Delete("/session")
public ResponseEntity<String> clearSession() {
// 实现会话清除逻辑
return ResponseEntity.ok("会话已清除");
}
/**
* 获取会话历史
*/
@GetMapping("/history")
public ResponseEntity<List<String>> getSessionHistory() {
// 实现历史记录逻辑
return ResponseEntity.ok(new java.util.ArrayList<>());
}
/**
* 设置参数
*/
@PostMapping("/settings")
public ResponseEntity<String> updateSettings(@RequestBody ChatSettings settings) {
// 实现参数更新逻辑
return ResponseEntity.ok("设置已更新");
}
/**
* 获取参数
*/
@GetMapping("/settings")
public ResponseEntity<ChatSettings> getSettings() {
return ResponseEntity.ok(new ChatSettings());
}
/**
* 聊天设置
*/
private static class ChatSettings {
private double temperature;
private int maxTokens;
private String modelName;
// Getters and Setters
public double getTemperature() { return temperature; }
public void setTemperature(double temperature) { this.temperature = temperature; }
public int getMaxTokens() { return maxTokens; }
public void setMaxTokens(int maxTokens) { this.maxTokens = maxTokens; }
public String getModelName() { return modelName; }
public void setModelName(String modelName) { this.modelName = modelName; }
}
}
总结
本章要点
-
Spring Boot Starter
- 简化 LangChain4j 集成
- 自动配置模型
- 统一依赖管理
-
配置管理
- application.yml 配置
- @Value 属性注入
- @Bean 模型定义
-
服务层
- ChatService 封装
- AI 服务使用
- 业务逻辑分离
-
REST API
- 控制器设计
- 请求验证
- 错误处理
-
测试策略
- 单元测试
- 集成测试
- Mock 测试
下一步
在下一章节中,我们将学习:- WebSocket 实时通信
- 高级流式处理
- 安全和认证
- 性能优化
- 部署和运维
常见问题
Q1:如何配置不同的模型? A:配置方法:- 在 application.yml 中指定不同的模型名称
- 为不同模型创建不同的 Bean
- 使用 @Profile 区分环境
- 动态切换模型
- 使用线程池配置
- 设置连接池大小
- 使用异步处理
- 实现请求队列
- 限流和熔断
- 为每个租户配置不同的 API Key
- 动态创建模型 Bean
- 租户级别的限流
- 租户配置隔离
- 使用 AOP 实现租户拦截
- Spring Boot Actuator
- 自定义健康检查
- Prometheus 指标暴露
- 日志聚合
- APM 工具集成
- 打包为 JAR 或 WAR
- Docker 容器化
- Kubernetes 部署
- 环境变量配置
- 反向代理配置
参考资料
版权归属于 LangChat Team
官网:https://langchat.cn

