Spring Boot + Spring AI + Vue 3 + TypeScript + Milvus 项目实战
实现用户输入自然语言 → 后端生成嵌入向量 → 在 Milvus 中进行相似性检索 → 返回结果到前端。
·
🚀 构建 Spring AI + Milvus + Vue 全栈语义搜索 MVP
本文将引导你从零搭建一个最小可行产品(MVP):
前端使用 Vue 3 + TypeScript,后端基于 Spring Boot + Spring AI,向量数据库选用 Milvus,实现用户输入自然语言 → 后端生成嵌入向量 → 在 Milvus 中进行相似性检索 → 返回结果到前端。
🛠️ 第一步:环境准备
1. 安装 Node.js(前端依赖)
根据你的操作系统选择安装方式:
🪟 Windows
- 推荐方式:官网下载 LTS 版 .msi
- 验证安装:
node -v npm -v
🍏 macOS(推荐 Homebrew)
# 安装 Homebrew(若未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装 Node.js
brew install node
🐧 Ubuntu/Debian(使用 NodeSource)
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
✅ 建议:使用
nvm管理多版本 Node(nvm-windows / nvm)
2. 创建 Vue 3 前端项目(使用 Vite)
Vite 是现代、快速的构建工具,官方推荐用于 Vue 3。
# 创建项目(自动使用 Vite)
npm create vue@latest my-vue-app
# 按提示选择(示例):
# ✔ Add TypeScript? … Yes
# ✔ Add Vue Router? … Yes
# ✔ Add Pinia? … Yes
# ✔ Add ESLint / Prettier? … Yes
cd my-vue-app
npm install
npm run dev # 启动开发服务器(默认 http://localhost:5173)
💡 推荐 VS Code + Volar 插件 获得最佳开发体验。
🗃️ 第二步:启动 Milvus 向量数据库
使用 Docker 快速部署 Milvus Standalone:
# 下载官方 docker-compose.yml
wget https://raw.githubusercontent.com/milvus-io/milvus/master/deployments/docker/standalone/docker-compose.yml
# 启动服务(后台运行)
docker-compose up -d
✅ 默认端口:
19530(gRPC),确保该端口未被占用。
⚠️ 注意:你需要提前创建集合
demo_collection,包含字段:
vector:FLOAT_VECTOR(维度需匹配嵌入模型,如 OpenAI 的text-embedding-ada-002为 1536)text:VARCHAR(存储原始文本)
⚙️ 第三步:构建 Spring Boot 后端
项目结构
backend/
├── src/main/java/com/example/demo/
│ ├── DemoApplication.java
│ ├── controller/QueryController.java
│ ├── service/VectorSearchService.java
│ └── config/MilvusConfig.java
├── application.yml
└── pom.xml
1. pom.xml(关键依赖)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>0.8.1</version>
</dependency>
<dependency>
<groupId>io.milvus</groupId>
<artifactId>milvus-sdk-java</artifactId>
<version>2.4.5</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
2. application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
embedding:
options:
model: text-embedding-ada-002
server:
port: 8080
3. Milvus 客户端配置 (MilvusConfig.java)
@Configuration
public class MilvusConfig {
@Bean
public MilvusServiceClient milvusClient() {
return new MilvusServiceClient(
ConnectParam.newBuilder()
.withHost("localhost")
.withPort(19530)
.build()
);
}
}
4. 向量搜索服务 (VectorSearchService.java)
@Service
public class VectorSearchService {
@Autowired private EmbeddingModel embeddingModel;
@Autowired private MilvusServiceClient milvusClient;
private static final String COLLECTION_NAME = "demo_collection";
public List<String> search(String query, int topK) {
// 1. 生成嵌入向量
Embedding embedding = embeddingModel.embed(query);
List<Float> vector = embedding.getValues();
// 2. Milvus 搜索
SearchParam param = SearchParam.newBuilder()
.withCollectionName(COLLECTION_NAME)
.withMetricType(MetricType.COSINE)
.withOutFields(List.of("text"))
.withTopK(topK)
.withVectors(List.of(vector))
.withVectorFieldName("vector")
.build();
R<SearchResults> resp = milvusClient.search(param);
if (resp.getStatus() != R.Status.Success) {
throw new RuntimeException("Milvus search failed");
}
// 3. 提取文本结果
return resp.getData().getResults().stream()
.flatMap(r -> r.getFieldsDataList().stream())
.filter(f -> "text".equals(f.getFieldName()))
.map(f -> f.getScalars().getStringData().getData(0))
.collect(Collectors.toList());
}
}
5. REST 控制器 (QueryController.java)
@RestController
@RequestMapping("/api")
public class QueryController {
@Autowired private VectorSearchService searchService;
@PostMapping("/search")
public List<String> search(@RequestBody Map<String, String> payload) {
return searchService.search(payload.get("query"), 3);
}
}
启动后端
cd backend
export OPENAI_API_KEY=your_openai_api_key_here
./mvnw spring-boot:run
🌐 第四步:开发 Vue 前端(含跨域代理)
1. 安装依赖
cd frontend
npm install axios
2. 配置 Vite 代理(解决开发阶段 CORS 问题)
编辑 vite.config.ts:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
});
3. 封装 API 请求 (src/api.ts)
import axios from 'axios';
const api = axios.create({ baseURL: '/api' });
export const search = (query: string) => {
return api.post<string[]>('/search', { query });
};
4. 搜索组件 (src/components/SearchBox.vue)
<template>
<div class="search-box">
<input v-model="query" @keyup.enter="handleSearch" placeholder="Enter your query..." />
<button @click="handleSearch">Search</button>
<ul v-if="results.length">
<li v-for="(result, i) in results" :key="i">{{ result }}</li>
</ul>
<p v-else-if="loading">Searching...</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { search } from '../api';
const query = ref('');
const results = ref<string[]>([]);
const loading = ref(false);
const handleSearch = async () => {
if (!query.value.trim()) return;
loading.value = true;
try {
const res = await search(query.value);
results.value = res.data;
} catch (error) {
console.error('Search error:', error);
results.value = [];
} finally {
loading.value = false;
}
};
</script>
<style scoped>
.search-box { max-width: 600px; margin: 2rem auto; }
input, button { padding: 0.5rem; font-size: 1rem; }
ul { margin-top: 1rem; list-style: none; }
li { padding: 0.3rem 0; border-bottom: 1px solid #eee; }
</style>
5. 根组件 (src/App.vue)
<template>
<div id="app">
<h1>🔍 Spring AI + Milvus 语义搜索</h1>
<SearchBox />
</div>
</template>
<script setup lang="ts">
import SearchBox from './components/SearchBox.vue';
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
▶️ 启动整个项目
# 终端 1:启动 Milvus(已运行可跳过)
docker-compose up -d
# 终端 2:启动后端
cd backend
export OPENAI_API_KEY=sk-xxxxxx
./mvnw spring-boot:run
# 终端 3:启动前端
cd frontend
npm run dev
🔒 安全与生产注意事项
| 项目 | 建议 |
|---|---|
| OpenAI API Key | 切勿硬编码!使用环境变量或密钥管理服务 |
| CORS | 生产环境应配置 Nginx 反向代理,而非依赖 Vite 代理 |
| Milvus 集合 | 确保维度、索引类型(如 IVF_FLAT)与查询一致 |
| 错误处理 | 前后端均需完善异常捕获与用户提示 |
📦 项目结构总览
spring-ai-milvus-vue-mvp/
├── backend/ # Spring Boot + Spring AI
│ ├── src/main/java/...
│ ├── application.yml
│ └── pom.xml
│
└── frontend/ # Vue 3 + TypeScript + Vite
├── src/
│ ├── components/SearchBox.vue
│ ├── App.vue
│ ├── main.ts
│ └── api.ts
├── vite.config.ts
├── tsconfig.json
└── package.json
✅ 恭喜!你已成功构建一个现代化的 AI 语义搜索应用 MVP。
🌟 下一步建议:
- 添加文档预处理与批量插入脚本(Python/Java)
- 集成 LangChain 或 Spring AI 的
VectorStore抽象- 部署到云平台(如 AWS ECS + RDS + S3)
更多推荐



所有评论(0)