Spring AI Hands‑On Introduction: Build AI‑Powered Apps with the Spring Ecosystem
This guide walks you through setting up Spring AI, configuring OpenAI credentials, using ChatClient for basic and advanced interactions, enabling function calling, managing conversation memory, and building real‑world projects such as a smart customer‑service bot, document summarizer, and code assistant, while also comparing Spring AI with LangChain4j and addressing common setup issues.
1. Quick Start
Spring AI is an official Spring framework for building AI applications using familiar Spring programming models. Add the required Maven dependencies and the Spring Milestones repository to your pom.xml:
<dependencies>
<!-- Spring Boot base -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI support -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-M4</version>
</dependency>
<!-- Optional: domestic large‑model support -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
<version>1.0.0-M4</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>Configure the OpenAI key and chat options in application.yml (or application.properties):
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY} # read from environment variable
chat:
options:
model: gpt-4o
temperature: 0.7Run a minimal Spring AI application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class AiApplication {
public static void main(String[] args) {
SpringApplication.run(AiApplication.class, args);
}
}
@RestController
public class AiController {
private final ChatClient chatClient;
public AiController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/ai/chat")
public String chat(@RequestParam(value = "message", defaultValue = "你好") String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}2. Core Components
2.1 ChatClient – Conversation Client
Basic usage shows a simple REST controller that forwards the user message to the model and returns the response.
@RestController
public class ChatController {
@Autowired
private ChatClient chatClient;
@GetMapping("/chat")
public String chat(String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}Advanced usage demonstrates adding a system prompt and session‑level parameters:
public class ChatService {
@Autowired
private ChatClient.Builder chatClientBuilder;
public String chatWithSystemPrompt(String userMessage) {
return chatClientBuilder.build()
.prompt()
.system("你是一位专业的 Java 开发顾问")
.user(userMessage)
.call()
.content();
}
public String chatWithHistory(String sessionId, String userMessage) {
return chatClientBuilder.build()
.prompt()
.system("你是一位友好的助手")
.user(userMessage)
.advisors(a -> a.param("sessionId", sessionId))
.call()
.content();
}
}A bean can set default system messages and advisors:
@Configuration
public class ChatConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.defaultSystem("你是一位专业的 AI 助手")
.defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory()))
.build();
}
}2.2 Structured Output
Define a POJO to receive structured AI responses:
public class ProductReview {
private String summary;
private int rating;
private List<String> pros;
private List<String> cons;
private boolean recommend;
// getters and setters omitted
}Use .entity(ProductReview.class) to map the model output:
@RestController
public class ReviewController {
@Autowired
private ChatClient chatClient;
@PostMapping("/review")
public ProductReview analyzeReview(@RequestBody String reviewText) {
return chatClient.prompt()
.user("请分析以下产品评价:" + reviewText)
.call()
.entity(ProductReview.class);
}
}2.3 Function Calling
Expose Java methods as AI‑callable tools:
@Service
public class WeatherService {
@Tool("查询指定城市的天气信息")
public String getWeather(@ToolParam(description = "城市名称") String city) {
return city + ":晴,25°C,湿度 60%";
}
@Tool("计算两个数的和")
public double add(@ToolParam(description = "第一个数") double a,
@ToolParam(description = "第二个数") double b) {
return a + b;
}
}Register the tool callbacks:
@Configuration
public class AiToolConfig {
@Autowired
private WeatherService weatherService;
@Bean
public ToolCallbackProvider toolCallbackProvider() {
return new SimpleToolCallbackProvider(
ToolCallbackBuilder.from(weatherService).build()
);
}
}Invoke the tool from a controller:
@RestController
public class AiToolController {
@Autowired
private ChatClient chatClient;
@GetMapping("/ai/weather")
public String askWeather(String city) {
return chatClient.prompt()
.user(city + "今天天气怎么样?")
.call()
.content(); // AI will call getWeather automatically
}
}2.4 Conversation Memory
Configure a window‑based memory that keeps the last 10 messages:
@Configuration
public class ChatMemoryConfig {
@Bean
public ChatMemory chatMemory() {
return new MessageWindowChatMemory(10);
}
@Bean
public ConversationAdvisor conversationAdvisor(ChatMemory chatMemory) {
return new MessageChatMemoryAdvisor(chatMemory);
}
}Use the memory in a chat endpoint:
@RestController
public class ChatWithMemoryController {
@Autowired
private ChatClient.Builder chatClientBuilder;
@Autowired
private ConversationAdvisor conversationAdvisor;
@PostMapping("/chat")
public String chat(@RequestBody ChatRequest request) {
return chatClientBuilder.build()
.prompt()
.user(request.getMessage())
.advisors(conversationAdvisor)
.advisors(a -> a.param("sessionId", request.getSessionId()))
.call()
.content();
}
}3. Hands‑On Projects
3.1 Smart Customer Service
Goal: answer product‑related questions using a knowledge base.
@SpringBootApplication
public class CustomerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerServiceApplication.class, args);
}
}
@Service
public class KnowledgeBaseService {
public String getProductInfo(String productName) {
return switch (productName.toLowerCase()) {
case "手机" -> "XX 手机,售价 2999 元,配置:8GB+256GB";
case "电脑" -> "XX 笔记本,售价 5999 元,配置:16GB+512GB SSD";
default -> "暂未找到该产品信息";
};
}
}
@RestController
@RequestMapping("/api/customer-service")
public class CustomerServiceController {
@Autowired
private ChatClient.Builder chatClientBuilder;
@Autowired
private KnowledgeBaseService knowledgeBase;
@PostMapping("/chat")
public ChatResponse chat(@RequestBody ChatRequest request) {
String systemPrompt = """
你是一位专业的客服助手,负责回答产品相关问题。
如果用户询问产品信息,请先查询知识库。
回答要友好、专业、简洁。
""";
String response = chatClientBuilder.build()
.prompt()
.system(systemPrompt)
.user(request.getMessage())
.call()
.content();
return new ChatResponse(response);
}
}
public class ChatRequest {
private String message;
private String sessionId;
// getters and setters omitted
}
public class ChatResponse {
private String reply;
public ChatResponse(String reply) { this.reply = reply; }
// getter and setter omitted
}3.2 Document Summarization Service
Goal: generate concise summaries for long documents.
@RestController
@RequestMapping("/api/summary")
public class DocumentSummaryController {
@Autowired
private ChatClient.Builder chatClientBuilder;
@PostMapping("/generate")
public SummaryResponse generateSummary(@RequestBody SummaryRequest request) {
String prompt = """
请总结以下文档内容:
%s
要求:
1. 用一句话概括核心内容
2. 列出 3-5 个关键点
3. 总结不超过 200 字
""".formatted(request.getContent());
String summary = chatClientBuilder.build()
.prompt()
.user(prompt)
.call()
.content();
return new SummaryResponse(summary);
}
}3.3 Code Assistant
Goal: generate and explain code snippets on demand.
@RestController
@RequestMapping("/api/code-assistant")
public class CodeAssistantController {
@Autowired
private ChatClient.Builder chatClientBuilder;
@PostMapping("/generate")
public CodeGenerationResponse generateCode(@RequestBody CodeGenerationRequest request) {
String prompt = """
请生成%s代码,实现以下功能:%s
要求:
1. 代码规范、可运行
2. 添加必要注释
3. 提供使用示例
""".formatted(request.getLanguage(), request.getDescription());
String code = chatClientBuilder.build()
.prompt()
.user(prompt)
.call()
.content();
return new CodeGenerationResponse(code);
}
@PostMapping("/explain")
public CodeExplanationResponse explainCode(@RequestBody CodeExplanationRequest request) {
String prompt = """
请解释以下代码的功能和工作原理:
```%s
%s
```
要求:
1. 说明代码的主要功能
2. 解释关键逻辑
3. 指出可能的优化点
""".formatted(request.getLanguage(), request.getCode());
String explanation = chatClientBuilder.build()
.prompt()
.user(prompt)
.call()
.content();
return new CodeExplanationResponse(explanation);
}
}4. Spring AI vs LangChain4j
Ecosystem Integration: Spring AI – native Spring support (★★★★★); LangChain4j – manual integration (★★★).
Learning Curve: Spring AI – low for Spring developers (★★★★); LangChain4j – moderate (★★★).
Feature Completeness: Spring AI – continuously improving (★★★★); LangChain4j – mature and stable (★★★★★).
Community Support: Spring AI – official Spring backing (★★★★★); LangChain4j – active community (★★★★).
Enterprise Support: Spring AI – official enterprise support (★★★★★); LangChain4j – community support (★★★).
4.2 Selection Advice
Choose Spring AI when:
You already have a Spring Boot project.
Your team is familiar with the Spring ecosystem.
You need enterprise‑grade support and long‑term stability.
Choose LangChain4j when:
You are building a standalone AI application.
You require a broader set of AI features.
You want rapid prototyping without depending on Spring.
5. Frequently Asked Questions
5.1 Dependency Download Failure
Problem: Maven cannot resolve Spring AI artifacts.
<!-- Ensure the Milestones repository is added -->
<repositories>
<repository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>5.2 API Key Configuration
Recommended ways:
# Use environment variable
export OPENAI_API_KEY=your_key
# Or use a configuration server
spring.ai.openai.api-key=${AI_API_KEY:default_key}5.3 Response Timeout
Adjust the chat options to limit token count and set a timeout:
spring:
ai:
openai:
chat:
options:
max-tokens: 1000 # limit output length
timeout: 30s # set timeout6. Learning Resources
Spring AI official site – https://spring.io/projects/spring-ai
GitHub repository – https://github.com/spring-projects/spring-ai
Reference documentation – https://docs.spring.io/spring-ai/reference
Community tutorials on B‑Station and Zhihu
Conclusion
The guide covered environment setup, core Spring AI components (ChatClient, structured output, function calling, conversation memory), three practical applications, a feature comparison with LangChain4j, and solutions to common issues, providing a solid foundation for building enterprise‑grade AI services on the Spring platform.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
