實(shí)戰(zhàn):SpringBoot+MCP 讓你的系統(tǒng)秒變AI助手
在人工智能技術(shù)快速演進(jìn)的今天,大語言模型正在重新定義軟件與用戶的交互方式。傳統(tǒng)的圖形界面和復(fù)雜API正在被一種更加直觀的交互模式所補(bǔ)充——自然語言對話。
用戶不再需要翻閱冗長的技術(shù)文檔或在多層菜單中導(dǎo)航,只需用日常語言表達(dá)需求,比如"請幫我篩選去年出版的所有編程類書籍"或"創(chuàng)建一個新用戶,姓名為張三,郵箱為zhangsan@example.com"。
這種直觀的交互范式不僅顯著降低了用戶的學(xué)習(xí)門檻,更能為企業(yè)級系統(tǒng)節(jié)省大量培訓(xùn)資源和實(shí)施成本,讓復(fù)雜的業(yè)務(wù)應(yīng)用真正實(shí)現(xiàn)"即問即得"的智能體驗(yàn)。
這一切的背后,是模型上下文協(xié)議(Model Context Protocol,MCP)在應(yīng)用層面的創(chuàng)新實(shí)踐。
一、認(rèn)識MCP
我這里不粘貼官方的定義,用更直觀的方式理解MCP:它就像是AI生態(tài)中的"通用翻譯器"。想象你的系統(tǒng)中有各種不同的服務(wù)組件和數(shù)據(jù)庫,每個都有獨(dú)特的接口規(guī)范和通信協(xié)議。傳統(tǒng)方式下,AI要與這些服務(wù)交互,必須逐一學(xué)習(xí)各自的"方言",效率低下且難以維護(hù)。
MCP創(chuàng)新性地解決了這一痛點(diǎn)——它建立了一套標(biāo)準(zhǔn)化的通信框架,讓AI只需掌握這一套"通用語"就能與所有服務(wù)順暢對話。對開發(fā)者而言,這意味著無需為每個服務(wù)單獨(dú)構(gòu)建適配層;對AI來說,它能夠以統(tǒng)一的方式獲取和處理信息,極大提升了交互效率。
如果大家有分布式系統(tǒng)開發(fā)經(jīng)驗(yàn),應(yīng)該熟悉gRPC如何通過標(biāo)準(zhǔn)化通信實(shí)現(xiàn)跨語言服務(wù)調(diào)用。MCP可以理解為專門為AI場景設(shè)計(jì)的"智能網(wǎng)關(guān)",讓大模型能夠以標(biāo)準(zhǔn)化的方式與各類應(yīng)用系統(tǒng)和數(shù)據(jù)源進(jìn)行深度交互。
通過一個簡單的天氣查詢場景,我們可以清晰看到傳統(tǒng)API方式與MCP方式的本質(zhì)差異:
圖片
二、對現(xiàn)有SpringBoot服務(wù)改造
為了完整演示改造過程,我設(shè)計(jì)了一個圖書管理服務(wù)作為示例。首先定義核心數(shù)據(jù)模型:
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PastOrPresent;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Entity
@Table(name = "books")
@Data
@AllArgsConstructor
@NoArgsConstructor
publicclass Book{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "書名不能為空")
@Column(nullable = false)
private String title;
@NotBlank(message = "分類不能為空")
@Column(nullable = false)
private String category;
@NotBlank(message = "作者不能為空")
@Column(nullable = false)
private String author;
@NotNull(message = "出版日期不能為空")
@PastOrPresent(message = "出版日期不能是未來日期")
@Column(nullable = false)
private LocalDate publicationDate;
@NotBlank(message = "ISBN編碼不能為空")
@Column(nullable = false, unique = true)
private String isbn;
}服務(wù)接口定義基礎(chǔ)查詢能力:
import com.example.entity.Book;
import java.util.List;
public interface BookService{
// 根據(jù)作者查詢
List<Book> findBooksByAuthor(String author);
// 根據(jù)分類查詢
List<Book> findBooksByCategory(String category);
}接下來,我將詳細(xì)展示如何將這個傳統(tǒng)SpringBoot服務(wù)升級為支持自然語言交互的智能服務(wù):
2.1 導(dǎo)入依賴
在pom.xml中引入必要的AI能力依賴。需要注意的是,訪問部分AI服務(wù)可能需要配置網(wǎng)絡(luò)代理。
<!-- Spring AI 核心依賴 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
</dependency>
<!-- Anthropic 模型支持 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
</dependency>
<!-- MCP 服務(wù)器支持 - WebMVC版本 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
</dependency>由于相關(guān)組件尚處于預(yù)覽階段,需要配置特定的依賴源:
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>網(wǎng)絡(luò)訪問配置示例:
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
@Configuration
publicclass ProxyConfig{
// 代理設(shè)置
privatefinal String PROXY_HOST = "127.0.0.1";
privatefinalint PROXY_PORT = 10080;
@PostConstruct
publicvoidsetSystemProxy(){
// 設(shè)置系統(tǒng)代理屬性,這會影響Spring Boot自動配置的HTTP客戶端
System.setProperty("http.proxyHost", PROXY_HOST);
System.setProperty("http.proxyPort", String.valueOf(PROXY_PORT));
System.setProperty("https.proxyHost", PROXY_HOST);
System.setProperty("https.proxyPort", String.valueOf(PROXY_PORT));
System.out.println("System proxy configured: http://" + PROXY_HOST + ":" + PROXY_PORT);
}
}2.2 引入配置
我們的目標(biāo)是將傳統(tǒng)服務(wù)轉(zhuǎn)型為支持自然語言交互的智能端點(diǎn),相關(guān)配置如下:
# Spring AI api-key
spring.ai.anthropic.api-key=這里換成你的api-key
# MCP服務(wù)端開啟
spring.ai.mcp.server.enabled=true
# MCP服務(wù)端配置
spring.ai.mcp.server.name=book-management-server
spring.ai.mcp.server.versinotallow=1.0.0
spring.ai.mcp.server.type=SYNC
spring.ai.mcp.server.sse-message-endpoint=/mcp/message2.3 改造原服務(wù)方法
服務(wù)智能化支持兩種主要模式:注解聲明模式和函數(shù)注冊模式。
注解聲明模式
通過注解方式標(biāo)記需要暴露的智能服務(wù)方法:
import com.example.entity.Book;
import com.example.repository.BookRepository;
import com.example.service.BookService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
publicclass BookServiceImpl implements BookService{
@Resource
private BookRepository bookRepository;
@Override
@Tool(name = "findBooksByTitle", description = "根據(jù)書名模糊查詢圖書,支持部分標(biāo)題匹配")
public List<Book> findBooksByTitle(@ToolParam(description = "書名關(guān)鍵詞") String title) {
return bookRepository.findByTitleContaining(title);
}
@Override
@Tool(name = "findBooksByAuthor", description = "根據(jù)作者精確查詢圖書")
public List<Book> findBooksByAuthor(@ToolParam(description = "作者姓名") String author) {
return bookRepository.findByAuthor(author);
}
@Override
@Tool(name = "findBooksByCategory", description = "根據(jù)圖書分類精確查詢圖書")
public List<Book> findBooksByCategory(@ToolParam(description = "圖書分類")String category) {
return bookRepository.findByCategory(category);
}
}接著將這個實(shí)現(xiàn)類注冊到MCP服務(wù)器配置上即可。
import com.example.service.BookService;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MCP服務(wù)器配置類,負(fù)責(zé)注冊MCP工具
*/
@Configuration
publicclass McpServerConfig{
/**
* 注冊工具回調(diào)提供者,將BookQueryService中的@Tool方法暴露為MCP工具
* @param bookService 圖書服務(wù)
* @return 工具回調(diào)提供者
*/
@Bean
public ToolCallbackProvider bookToolCallbackProvider(BookService bookService){
return MethodToolCallbackProvider.builder()
.toolObjects(bookService)
.build();
}
}此時在聊天客戶端配置引入注冊工具即可。
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 聊天客戶端配置類
*/
@Configuration
publicclass ChatClientConfig{
@Autowired
private ToolCallbackProvider toolCallbackProvider;
/**
* 配置ChatClient,注冊系統(tǒng)指令和工具函數(shù)
*/
@Bean
public ChatClient chatClient(ChatClient.Builder builder){
return builder
.defaultSystem("你是一個圖書管理助手,可以幫助用戶查詢圖書信息。" +
"你可以根據(jù)書名模糊查詢、根據(jù)作者查詢和根據(jù)分類查詢圖書。" +
"回復(fù)時,請使用簡潔友好的語言,并將圖書信息整理為易讀的格式。")
// 注冊工具方法
.defaultTools(toolCallbackProvider)
.build();
}
}作為替代方案,可以通過函數(shù)Bean方式顯式注冊服務(wù)能力:
import com.example.entity.Book;
import com.example.service.BookService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.function.Function;
/**
* 圖書查詢服務(wù),將查詢方法作為函數(shù)Bean導(dǎo)出
*/
@Service
publicclass BookQueryService{
@Resource
private BookService bookService;
/**
* 根據(jù)書名查詢圖書的函數(shù)Bean
*/
@Bean
public Function<String, List<Book>> findBooksByTitle() {
return title -> bookService.findBooksByTitle(title);
}
/**
* 根據(jù)作者查詢圖書的函數(shù)Bean
*/
@Bean
public Function<String, List<Book>> findBooksByAuthor() {
return author -> bookService.findBooksByAuthor(author);
}
/**
* 根據(jù)分類查詢圖書的函數(shù)Bean
*/
@Bean
public Function<String, List<Book>> findBooksByCategory() {
return category -> bookService.findBooksByCategory(category);
}
}此模式下客戶端需要顯式聲明函數(shù)引用:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 聊天客戶端配置類
*/
@Configuration
publicclass ChatClientConfig{
/**
* 配置ChatClient,注冊系統(tǒng)指令和工具函數(shù)
*/
@Bean
public ChatClient chatClient(ChatClient.Builder builder){
return builder
.defaultSystem("你是一個圖書管理助手,可以幫助用戶查詢圖書信息。" +
"你可以根據(jù)書名模糊查詢、根據(jù)作者查詢和根據(jù)分類查詢圖書。" +
"回復(fù)時,請使用簡潔友好的語言,并將圖書信息整理為易讀的格式。")
// 注冊工具方法,這里使用方法名稱來引用Spring上下文中的函數(shù)Bean
.defaultTools(
"findBooksByTitle",
"findBooksByAuthor",
"findBooksByCategory"
)
.build();
}
}2.4 接口測試
服務(wù)改造完成后,創(chuàng)建統(tǒng)一的智能交互接口:
import com.example.model.ChatRequest;
import com.example.model.ChatResponse;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* 聊天控制器,處理AI聊天請求
*/
@RestController
@RequestMapping("/api/chat")
publicclass ChatController{
@Resource
private ChatClient chatClient;
/**
* 處理聊天請求,使用AI和MCP工具進(jìn)行響應(yīng)
*
* @param request 聊天請求
* @return 包含AI回復(fù)的響應(yīng)
*/
@PostMapping
public ResponseEntity<ChatResponse> chat(@RequestBody ChatRequest request){
try {
// 創(chuàng)建用戶消息
String userMessage = request.getMessage();
// 使用流式API調(diào)用聊天
String content = chatClient.prompt()
.user(userMessage)
.call()
.content();
return ResponseEntity.ok(new ChatResponse(content));
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.ok(new ChatResponse("處理請求時出錯: " + e.getMessage()));
}
}
}為了方便測試,我們開發(fā)一個數(shù)據(jù)初始化器,通過實(shí)現(xiàn)CommandLineRunner接口,它會在我們的應(yīng)用程序啟動時自動向數(shù)據(jù)庫中加載這些測試數(shù)據(jù)。
import com.example.entity.Book;
import com.example.repository.BookRepository;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
@Component
@RequiredArgsConstructor
publicclass DataInitializer implements CommandLineRunner{
@Resource
private BookRepository bookRepository;
@Override
publicvoidrun(String... args)throws Exception {
// 準(zhǔn)備示例數(shù)據(jù)
List<Book> sampleBooks = Arrays.asList(
new Book(null, "Spring實(shí)戰(zhàn)(第6版)", "編程", "Craig Walls",
LocalDate.of(2022, 1, 15), "9787115582247"),
new Book(null, "深入理解Java虛擬機(jī)", "編程", "周志明",
LocalDate.of(2019, 12, 1), "9787111641247"),
new Book(null, "Java編程思想(第4版)", "編程", "Bruce Eckel",
LocalDate.of(2007, 6, 1), "9787111213826"),
new Book(null, "算法(第4版)", "計(jì)算機(jī)科學(xué)", "Robert Sedgewick",
LocalDate.of(2012, 10, 1), "9787115293800"),
new Book(null, "云原生架構(gòu)", "架構(gòu)設(shè)計(jì)", "張三",
LocalDate.of(2023, 3, 15), "9781234567890"),
new Book(null, "微服務(wù)設(shè)計(jì)模式", "架構(gòu)設(shè)計(jì)", "張三",
LocalDate.of(2021, 8, 20), "9789876543210"),
new Book(null, "領(lǐng)域驅(qū)動設(shè)計(jì)", "架構(gòu)設(shè)計(jì)", "Eric Evans",
LocalDate.of(2010, 4, 10), "9787111214748"),
new Book(null, "高性能MySQL", "數(shù)據(jù)庫", "Baron Schwartz",
LocalDate.of(2013, 5, 25), "9787111464747"),
new Book(null, "Redis實(shí)戰(zhàn)", "數(shù)據(jù)庫", "Josiah L. Carlson",
LocalDate.of(2015, 9, 30), "9787115419378"),
new Book(null, "深入淺出Docker", "容器技術(shù)", "李四",
LocalDate.of(2022, 11, 20), "9787123456789")
);
// 保存示例數(shù)據(jù)
bookRepository.saveAll(sampleBooks);
System.out.println("數(shù)據(jù)初始化完成,共加載 " + sampleBooks.size() + " 本圖書");
}
}接下來我們通過請求接口進(jìn)行如下測試:
圖片
測試結(jié)果表明,系統(tǒng)能夠準(zhǔn)確理解自然語言查詢意圖,智能匹配并調(diào)用相應(yīng)的服務(wù)方法,返回?cái)?shù)據(jù)庫中的相關(guān)記錄。當(dāng)用戶輸入查詢問題時,大模型會自動分析語義,識別合適的MCP工具方法,并執(zhí)行對應(yīng)的數(shù)據(jù)操作。
三、MCP小結(jié)
通過Spring Boot與MCP的整合,我們輕松實(shí)現(xiàn)了傳統(tǒng)CRUD系統(tǒng)到智能AI助手的轉(zhuǎn)變。MCP作為AI與服務(wù)之間的橋梁,極大簡化了集成工作。未來隨著MCP生態(tài)發(fā)展,"對話即服務(wù)"將可能成為應(yīng)用的開發(fā)范式,讓復(fù)雜系統(tǒng)變得更加易用。
從技術(shù)演進(jìn)角度看,MCP讓開發(fā)者能夠更加專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),而不必過度關(guān)注AI集成的技術(shù)細(xì)節(jié)。這種關(guān)注點(diǎn)的分離,體現(xiàn)了現(xiàn)代軟件工程追求的高內(nèi)聚、低耦合設(shè)計(jì)原則,為構(gòu)建更加智能、靈活的業(yè)務(wù)系統(tǒng)奠定了堅(jiān)實(shí)基礎(chǔ)。


































