基于SpringBoot + Spring AI + Vue的全栈AI对话系统开发全流程解析
一、项目背景与架构设计
1.1 需求背景分析
在当今AI技术蓬勃发展的环境下,企业级应用对接多种大语言模型(LLM)已成为刚需。本系统旨在解决以下痛点:
- 多模型兼容问题:不同AI供应商(OpenAI/Ollama等)的API接口差异
- 前后端协作难题:统一通信协议与状态管理
- 企业级扩展需求:安全控制、性能优化、可维护性
- 开发效率提升:快速切换底层模型,降低对接成本
1.2 系统架构设计
采用分层架构设计,确保各模块解耦:
[前端Vue层] ←WebSocket/HTTP→ [SpringBoot API层] ←Spring AI→ [AI服务层]
↑
[安全控制层] [配置中心]
↑
[持久化存储层] ←Redis/MySQL→ [监控预警系统]
技术架构特点:
- 前端:Vue3组合式API + Pinia状态管理 + Element Plus组件库
- 网关层:Spring Cloud Gateway实现路由转发
- AI服务层:Spring AI抽象模型调用接口
- 安全体系:JWT认证 + Spring Security权限控制
二、开发环境深度配置
2.1 后端环境搭建
步骤1:创建SpringBoot项目
使用Spring Initializr生成项目,关键依赖选择:
- Spring Web
- Spring Security
- Spring AI OpenAI
- Spring AI Ollama
- Lombok
- Redis
步骤2:配置多环境参数
# application-dev.yml
spring:
ai:
openai:
api-key: ${OPENAI_KEY}
temperature: 0.7
ollama:
base-url: http://ollama:11434
model: llama2-uncensored
步骤3:配置跨域与安全策略
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081")
.allowedMethods("*")
.allowCredentials(true);
}
}
2.2 前端环境搭建
步骤1:创建Vue项目
npm create vue@latest
# 选择TypeScript + Pinia + Router
步骤2:配置全局请求拦截器
// src/utils/request.ts
const service = axios.create({
baseURL: import.meta.env.VITE_APP_API,
timeout: 30000
})
service.interceptors.request.use(config => {
config.headers.Authorization = localStorage.getItem('token')
return config
})
三、核心模块实现详解
3.1 多模型适配器实现
模型抽象接口设计
public interface ModelAdapter {
ChatResponse generate(ChatRequest request);
String getModelType();
boolean enableStream();
}
// OpenAI实现类
@Component
@RequiredArgsConstructor
public class OpenAiAdapter implements ModelAdapter {
private final OpenAiChatClient client;
@Override
public ChatResponse generate(ChatRequest request) {
return client.call(request);
}
}
// Ollama实现类
@Component
public class OllamaAdapter implements ModelAdapter {
// 实现流式响应处理
}
工厂模式动态选择
@Service
public class ModelFactory {
private final Map<String, ModelAdapter> adapterMap;
public ModelFactory(List<ModelAdapter> adapters) {
adapterMap = adapters.stream()
.collect(Collectors.toMap(ModelAdapter::getModelType, Function.identity()));
}
public ModelAdapter getAdapter(String modelType) {
return Optional.ofNullable(adapterMap.get(modelType))
.orElseThrow(() -> new ModelNotSupportedException(modelType));
}
}
3.2 对话服务核心实现
流式响应处理(SSE)
@GetMapping("/stream")
public SseEmitter streamChat(@RequestParam String message,
@RequestParam String model) {
SseEmitter emitter = new SseEmitter(180_000L);
modelFactory.getAdapter(model)
.generateStream(message)
.subscribe(
content -> emitter.send(content),
emitter::completeWithError,
emitter::complete
);
return emitter;
}
上下文管理实现
@Service
public class ContextService {
private final RedisTemplate<String, Object> redisTemplate;
public void saveContext(String sessionId, List<ChatMessage> messages) {
redisTemplate.opsForValue()
.set(buildKey(sessionId), messages, 30, TimeUnit.MINUTES);
}
}
3.3 前端交互实现
聊天组件核心逻辑
<script setup lang="ts">
const messages = ref<ChatMessage[]>([])
const sendMessage = async () => {
if (isStreamMode.value) {
const eventSource = new EventSource(`/api/stream?message=${inputText}`)
eventSource.onmessage = (e) => {
messages.value[messages.value.length-1].content += e.data
}
} else {
const res = await chatApi.postChat({
message: inputText.value,
model: selectedModel.value
})
messages.value.push(res.data)
}
}
</script>
模型切换组件
<template>
<el-select v-model="currentModel" @change="handleModelChange">
<el-option
v-for="model in modelList"
:key="model.value"
:label="model.label"
:value="model.value"
/>
</el-select>
</template>
四、企业级功能扩展
4.1 权限控制系统
JWT认证过滤器
@Component
public class JwtFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = extractToken(request);
if (token != null) {
Authentication auth = jwtUtil.parseToken(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
接口权限注解
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/model/config")
public ResponseEntity<?> updateModelConfig() {
// 管理端配置逻辑
}
4.2 监控与预警
Prometheus指标采集
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config()
.commonTags("application", "ai-chat-system");
}
@Timed(value = "chat.request.duration", description = "处理耗时")
@PostMapping
public ChatResponse handleRequest(@RequestBody ChatRequest request) {
// 业务逻辑
}
4.3 性能优化方案
连接池配置
spring:
ai:
openai:
connect-timeout: 10s
read-timeout: 30s
max-connections: 50
max-per-route: 20
缓存策略实现
@Cacheable(value = "modelResponses", key = "#request.hashCode()")
public ChatResponse getCachedResponse(ChatRequest request) {
// 实际调用逻辑
}
五、部署与运维实践
5.1 Docker容器化部署
后端Dockerfile
FROM eclipse-temurin:17-jdk
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
docker-compose编排
services:
redis:
image: redis:alpine
ports: ["6379:6379"]
ollama:
image: ollama/ollama
ports: ["11434:11434"]
volumes: ["ollama:/root/.ollama"]
backend:
build: .
environment:
SPRING_PROFILES_ACTIVE: prod
depends_on:
- redis
- ollama
5.2 压力测试方案
JMeter测试场景配置
- 并发用户数:100
- 持续时长:5分钟
- 监控指标:
- 平均响应时间 < 2s
- 错误率 < 0.5%
- CPU使用率 < 75%
5.3 日志分析系统
ELK日志收集配置
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash:5044</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
六、项目总结与展望
6.1 项目成果
- 实现多模型统一接入,支持OpenAI GPT-4/3.5、Llama2等主流模型
- 开发完整的前后端交互系统,响应时间<1.5s
- 构建企业级安全体系,通过OWASP安全测试
- 支持日均10万+次API调用
6.2 未来演进方向
- 模型微调支持:集成LoRA等微调方案
- 智能路由系统:根据query自动选择最优模型
- 多模态扩展:支持图片/语音输入输出
- 分布式部署:基于K8s的弹性伸缩方案
6.3 开发者建议
- 使用HuggingFace模型时注意内存管理
- 生产环境务必启用限流熔断机制
- 定期更新Spring AI版本以获取新特性
- 前端建议使用Web Workers处理大响应