(第三篇)Spring AI 实战进阶:从0开发IDEA插件版AI代码助手(Java全栈+上下文感知)

前言
作为 Java 开发者,我们每天都在重复编写 CRUD 代码、调试语法错误、优化性能问题 —— 这些机械性工作占用了大量时间,而市面上的通用 AI 代码助手(如 Copilot)往往无法精准感知项目上下文(比如项目的包结构、依赖版本、数据库表结构),生成的代码需要大量修改才能落地。
笔者近期基于 Spring AI+IDEA 插件开发了一款定制化 AI 代码助手:后端基于 Spring AI 整合 JavaParser、Maven API 实现代码解析与生成,前端通过 IDEA 插件提供对话窗口和一键插入代码功能,支持需求描述→完整代码生成代码优化、上下文感知、补全三大核心能力。本文将从实战角度,完整拆解这款 AI 代码助手的开发全流程,所有代码均为生产环境可直接复用的实战代码,同时结合可视化图表清晰呈现核心逻辑,希望能帮你打造专属的 AI 代码提效工具。
一、项目背景与架构设计
1.1 项目定位与核心需求
项目定位:基于 Spring AI 的 Java 代码生成工具,以IDEA 插件(前端)+ Spring Boot 后端(核心)的架构,解决通用 AI 代码助手上下文脱节、代码适配性差的问题,专注 Java 项目的代码生成、优化与补全。
核心需求:
| 维度 | 核心需求 | 技术挑战 |
|---|---|---|
| 代码生成 | 输入需求描述,生成 Controller+Service+Mapper 完整代码 | Spring AI 精准 Prompt 工程、Java 语法合规性校验 |
| 代码优化 | 自动修复语法错误、优化性能(如 SQL 优化、循环优化) | JavaParser 解析代码 AST、Spring AI 调用大模型分析 |
| 上下文感知 | 感知当前项目的包结构、依赖、数据库表结构 | IDEA 插件获取项目上下文、后端存储上下文信息 |
| 交互体验 | IDEA 内对话窗口、一键插入生成的代码 | IDEA 插件 Swing 开发、前后端通信协议设计 |
1.2 整体架构设计
以下是 AI 代码助手的核心架构图,清晰呈现前后端交互与核心模块逻辑:

1.3 技术栈选型
结合 Java 生态与 IDEA 插件开发规范,最终选型如下:
| 技术领域 | 选型 | 选型理由 |
|---|---|---|
| 后端核心 | Spring Boot 3.2 + Spring AI 0.8.1 | Spring AI 原生适配 Spring 生态,支持多模型统一调用 |
| 代码解析 | JavaParser 3.25.10 | 轻量、高效的 Java 代码 AST 解析库,支持代码生成 / 校验 |
| Maven 交互 | Maven API 3.9.6 | 解析项目 pom.xml,获取依赖与包结构 |
| IDEA 插件 | IntelliJ Platform SDK 2023.2 | 官方 SDK,支持 IDEA 插件全功能开发 |
| 前端交互 | Swing + OkHttp 4.12.0 | Swing 实现 IDEA 内窗口,OkHttp 实现前后端通信 |
| 大模型 | GPT-4 + 通义千问(可选) | GPT-4 代码生成质量高,通义千问支持私有化部署 |
| 存储 | MySQL 8.0 + Redis 7.0 | 存储项目上下文、生成的代码片段 |
二、核心技术架构拆解
2.1 后端核心:Spring AI + 工具调用体系
2.1.1 Spring AI 核心配置
首先完成 Spring AI 的基础配置,支持多模型调用(以 OpenAI 为例):
/**
* Spring AI核心配置类
*/
@Configuration
public class SpringAiConfig {
/**
* 配置OpenAI客户端
*/
@Bean
public OpenAiChatClient openAiChatClient() {
// 从配置文件读取API Key和Base URL
String apiKey = System.getenv("OPENAI_API_KEY");
String baseUrl = "https://api.openai.com/v1";
OpenAiApi openAiApi = new OpenAiApi(baseUrl, apiKey);
// 创建客户端并配置默认参数
OpenAiChatClient client = new OpenAiChatClient(openAiApi);
client.setTemperature(0.2); // 低温度保证代码稳定性
client.setModel("gpt-4");
return client;
}
}
2.1.2 工具调用层:JavaParser + Maven API
工具调用层是区别于通用 AI 的核心 —— 通过 JavaParser 解析代码 AST、Maven API 解析项目依赖,让 AI 生成的代码贴合项目实际:
/**
* 项目上下文解析服务:基于Maven API+JavaParser解析项目信息
*/
@Service
public class ProjectContextParser {
/**
* 解析Maven项目的包结构、依赖信息
* @param pomPath pom.xml文件路径(从IDEA插件传递)
*/
public ProjectContext parseMavenProject(String pomPath) throws Exception {
ProjectContext context = new ProjectContext();
// 1. 解析pom.xml获取基础信息
File pomFile = new File(pomPath);
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = reader.read(new FileReader(pomFile));
// 设置groupId、artifactId、版本
context.setGroupId(model.getGroupId());
context.setArtifactId(model.getArtifactId());
context.setBasePackage(model.getGroupId() + "." + model.getArtifactId());
// 2. 解析依赖信息
List<String> dependencies = new ArrayList<>();
for (Dependency dep : model.getDependencies()) {
dependencies.add(dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion());
}
context.setDependencies(dependencies);
// 3. 解析项目源码目录(简化版)
File srcDir = new File(pomFile.getParentFile(), "src/main/java");
if (srcDir.exists()) {
context.setSrcRootPath(srcDir.getAbsolutePath());
// 解析已存在的包结构
List<String> packages = parsePackages(srcDir);
context.setPackages(packages);
}
return context;
}
/**
* 解析源码目录下的所有包
*/
private List<String> parsePackages(File srcDir) {
List<String> packages = new ArrayList<>();
// 递归遍历源码目录,解析包名(简化版)
File[] files = srcDir.listFiles();
if (files == null) return packages;
for (File file : files) {
if (file.isDirectory()) {
String packageName = file.getAbsolutePath().replace(srcDir.getAbsolutePath(), "")
.replace(File.separator, ".");
if (!packageName.isEmpty()) {
packages.add(packageName.substring(1)); // 去掉开头的.
}
packages.addAll(parsePackages(file));
}
}
return packages;
}
/**
* 解析Java代码AST,校验语法正确性
*/
public boolean validateJavaCode(String code) {
try {
// 使用JavaParser解析代码,检测语法错误
CompilationUnit cu = StaticJavaParser.parse(code);
List<Problem> problems = cu.getProblems();
return problems.isEmpty();
} catch (Exception e) {
return false;
}
}
}
// 项目上下文实体类
@Data
public class ProjectContext {
private String groupId; // 项目groupId
private String artifactId; // 项目artifactId
private String basePackage; // 基础包名
private List<String> dependencies; // 依赖列表
private List<String> packages; // 包结构
private String srcRootPath; // 源码根路径
private String projectId; // IDEA插件传递的项目唯一标识
}
2.2 前端核心:IDEA 插件开发基础
2.2.1 IDEA 插件工程搭建
- 创建插件工程:使用 IntelliJ IDEA 新建IntelliJ Platform Plugin工程,选择 SDK 版本(2023.2);
- 配置 plugin.xml:定义插件入口、窗口布局:
<idea-plugin>
<id>com.ai.code.assistant</id>
<name>AI Code Assistant</name>
<version>1.0</version>
<vendor email="your@email.com" url="https://your.site">Your Name</vendor>
<description>
基于Spring AI的Java代码助手,支持上下文感知的代码生成与优化
</description>
<!-- 注册Action,用于打开对话窗口 -->
<actions>
<action id="AiCodeAssistant.OpenDialog" class="com.ai.code.assistant.action.OpenAiDialogAction"
text="AI Code Assistant" description="Open AI Code Assistant Dialog">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt A"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij">
<!-- 注册自定义窗口 -->
<toolWindow id="AI Code Assistant" anchor="right" factoryClass="com.ai.code.assistant.window.AiToolWindowFactory"/>
</extensions>
</idea-plugin>
2.2.2 对话窗口开发(Swing)
开发 IDEA 内的对话窗口,支持输入需求、展示生成的代码:
/**
* AI代码助手对话窗口
*/
public class AiCodeDialog extends JDialog {
private JTextArea inputArea; // 需求输入框
private JTextPane resultArea; // 代码结果展示框
private JButton generateBtn; // 生成按钮
private JButton insertBtn; // 插入代码按钮
private Project currentProject; // 当前IDEA项目
public AiCodeDialog(Project project) {
super(WindowManager.getInstance().getFrame(project), "AI Code Assistant", Dialog.ModalityType.MODELESS);
this.currentProject = project;
initUI(); // 初始化UI
setSize(800, 600);
setLocationRelativeTo(null);
}
/**
* 初始化UI组件
*/
private void initUI() {
// 1. 输入区域
inputArea = new JTextArea(5, 50);
inputArea.setPlaceholder("请输入代码生成需求,例如:生成用户管理的Controller+Service+Mapper");
JScrollPane inputScroll = new JScrollPane(inputArea);
// 2. 结果展示区域(支持语法高亮)
resultArea = new JTextPane();
resultArea.setContentType("text/java");
JScrollPane resultScroll = new JScrollPane(resultArea);
// 3. 按钮区域
generateBtn = new JButton("生成代码");
insertBtn = new JButton("插入到编辑器");
insertBtn.setEnabled(false); // 初始禁用
// 4. 布局
JPanel panel = new JPanel(new BorderLayout());
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(new JLabel("需求描述:"), BorderLayout.NORTH);
topPanel.add(inputScroll, BorderLayout.CENTER);
JPanel btnPanel = new JPanel();
btnPanel.add(generateBtn);
btnPanel.add(insertBtn);
panel.add(topPanel, BorderLayout.NORTH);
panel.add(resultScroll, BorderLayout.CENTER);
panel.add(btnPanel, BorderLayout.SOUTH);
// 5. 绑定事件
generateBtn.addActionListener(e -> generateCode());
insertBtn.addActionListener(e -> insertCodeToEditor());
add(panel);
}
/**
* 生成代码:调用后端接口
*/
private void generateCode() {
// 1. 采集项目上下文
ProjectContext context = collectProjectContext();
// 2. 构建请求参数
CodeGenerateRequest request = new CodeGenerateRequest();
request.setRequirement(inputArea.getText());
request.setProjectContext(context);
// 3. 调用后端接口(OkHttp实现,略)
OkHttpClient client = new OkHttpClient();
// ... 发送POST请求,获取生成的代码
// 4. 展示结果
resultArea.setText(generatedCode);
insertBtn.setEnabled(true);
}
/**
* 采集当前IDEA项目的上下文
*/
private ProjectContext collectProjectContext() {
ProjectContext context = new ProjectContext();
// 1. 获取项目根路径
String projectPath = currentProject.getBasePath();
// 2. 获取pom.xml路径(Maven项目)
VirtualFile pomFile = currentProject.getBaseDir().findChild("pom.xml");
if (pomFile != null) {
context.setPomPath(pomFile.getPath());
}
// 3. 获取当前编辑器的包路径
Editor editor = FileEditorManager.getInstance(currentProject).getSelectedTextEditor();
if (editor != null) {
PsiFile psiFile = PsiDocumentManager.getInstance(currentProject).getPsiFile(editor.getDocument());
if (psiFile instanceof PsiJavaFile) {
PsiJavaFile javaFile = (PsiJavaFile) psiFile;
context.setCurrentPackage(javaFile.getPackageName());
}
}
context.setProjectId(currentProject.getName());
return context;
}
/**
* 将生成的代码插入到当前编辑器
*/
private void insertCodeToEditor() {
Editor editor = FileEditorManager.getInstance(currentProject).getSelectedTextEditor();
if (editor == null) return;
// 获取选中区域,无选中则插入到光标位置
Document document = editor.getDocument();
SelectionModel selectionModel = editor.getSelectionModel();
int start = selectionModel.getSelectionStart();
int end = selectionModel.getSelectionEnd();
// 写入代码
WriteCommandAction.runWriteCommandAction(currentProject, () -> {
document.replaceString(start, end, resultArea.getText());
});
// 取消选中,光标移到末尾
selectionModel.removeSelection();
editor.getCaretModel().moveToOffset(start + resultArea.getText().length());
}
}
三、核心功能实现
3.1 代码生成:Controller+Service+Mapper 完整生成
3.1.1 Prompt 工程核心逻辑
Prompt 工程是代码生成质量的关键 —— 结合项目上下文,让 AI 生成的代码直接贴合项目包结构、依赖版本:
/**
* Prompt工程服务:动态拼接上下文,生成高质量Prompt
*/
@Service
public class PromptEngineeringService {
/**
* 生成代码生成的Prompt
* @param requirement 用户需求
* @param context 项目上下文
*/
public Prompt buildGeneratePrompt(String requirement, ProjectContext context) {
// 1. 构建系统提示词(核心规则)
String systemPrompt = """
你是一位资深Java后端开发工程师,精通Spring Boot、MyBatis、MySQL。
请根据以下需求和项目上下文,生成符合规范的Java代码:
1. 包结构必须符合项目基础包:%s
2. 代码必须兼容项目依赖版本,优先使用项目已引入的依赖
3. 生成完整的Controller+Service+Mapper层,包含必要的注释、异常处理
4. 代码风格符合阿里巴巴Java开发手册
5. 只返回代码,不返回多余解释
项目上下文:
- 基础包名:%s
- 已存在的包:%s
- 项目依赖:%s
""".formatted(context.getBasePackage(), context.getBasePackage(),
String.join(",", context.getPackages()),
String.join(",", context.getDependencies()));
// 2. 构建用户提示词
String userPrompt = "需求:" + requirement;
// 3. 创建Prompt对象
return new Prompt(
List.of(
new SystemMessage(systemPrompt),
new UserMessage(userPrompt)
)
);
}
}
3.1.2 代码生成核心接口
/**
* 代码生成核心接口
*/
@RestController
@RequestMapping("/api/code")
public class CodeGenerateController {
@Autowired
private OpenAiChatClient openAiChatClient;
@Autowired
private PromptEngineeringService promptService;
@Autowired
private ProjectContextParser contextParser;
@Autowired
private ProjectContextRepository contextRepository;
/**
* 生成代码接口
*/
@PostMapping("/generate")
public Result<String> generateCode(@RequestBody CodeGenerateRequest request) {
try {
// 1. 解析项目上下文(如果未存储)
ProjectContext context;
if (request.getProjectContext().getProjectId() != null) {
context = contextRepository.findByProjectId(request.getProjectContext().getProjectId());
if (context == null) {
// 解析pom.xml生成上下文
context = contextParser.parseMavenProject(request.getProjectContext().getPomPath());
context.setProjectId(request.getProjectContext().getProjectId());
contextRepository.save(context); // 存储上下文
}
} else {
context = request.getProjectContext();
}
// 2. 构建Prompt
Prompt prompt = promptService.buildGeneratePrompt(request.getRequirement(), context);
// 3. 调用Spring AI生成代码
AiResponse response = openAiChatClient.generate(prompt);
String generatedCode = response.getGeneration().getText();
// 4. 校验代码语法
boolean isValid = contextParser.validateJavaCode(generatedCode);
if (!isValid) {
// 重新生成(简化版,实际可加入重试逻辑)
generatedCode = regenerateCode(prompt);
}
return Result.success(generatedCode);
} catch (Exception e) {
log.error("生成代码失败", e);
return Result.error("生成代码失败:" + e.getMessage());
}
}
/**
* 代码校验失败时重新生成
*/
private String regenerateCode(Prompt prompt) {
// 追加提示词,要求修复语法错误
Prompt newPrompt = new Prompt(
prompt.getMessages().stream()
.collect(Collectors.toList())
.add(new UserMessage("以上代码存在语法错误,请修复后重新生成,只返回修复后的代码"))
);
return openAiChatClient.generate(newPrompt).getGeneration().getText();
}
}
3.1.3 效果示例
用户输入需求:生成用户管理的 Controller+Service+Mapper,包含查询、新增、修改、删除接口生成的代码(Controller 层):
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户管理控制器
* @author AI Code Assistant
* @date 2024-05-20
*/
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 查询所有用户
*/
@GetMapping
public List<User> listAll() {
return userService.listAll();
}
/**
* 根据ID查询用户
*/
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.getById(id);
}
/**
* 新增用户
*/
@PostMapping
public boolean save(@RequestBody User user) {
return userService.save(user);
}
/**
* 修改用户
*/
@PutMapping("/{id}")
public boolean update(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.update(user);
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Long id) {
return userService.delete(id);
}
}
3.2 代码优化:自动修复语法错误与性能问题
3.2.1 代码优化 Prompt 设计
/**
* 构建代码优化的Prompt
*/
public Prompt buildOptimizePrompt(String code, String optimizeType) {
String systemPrompt = """
你是一位资深Java性能优化工程师,精通Java语法、性能调优。
请根据指定类型优化以下代码:
优化类型:%s
优化规则:
1. 修复语法错误,保证代码可编译
2. 性能优化需给出具体的优化点(如循环优化、SQL优化、集合使用优化)
3. 保留原有业务逻辑,只优化语法和性能
4. 输出优化后的代码+优化说明(分开展示)
""".formatted(optimizeType);
return new Prompt(
List.of(
new SystemMessage(systemPrompt),
new UserMessage("需要优化的代码:\n" + code)
)
);
}
3.2.2 代码优化接口实现
/**
* 代码优化接口
*/
@PostMapping("/optimize")
public Result<CodeOptimizeResponse> optimizeCode(@RequestBody CodeOptimizeRequest request) {
try {
// 1. 构建优化Prompt
Prompt prompt = promptService.buildOptimizePrompt(request.getCode(), request.getOptimizeType());
// 2. 调用AI优化代码
AiResponse response = openAiChatClient.generate(prompt);
String result = response.getGeneration().getText();
// 3. 解析优化结果(代码+说明)
CodeOptimizeResponse responseVO = parseOptimizeResult(result);
return Result.success(responseVO);
} catch (Exception e) {
log.error("优化代码失败", e);
return Result.error("优化代码失败:" + e.getMessage());
}
}
/**
* 解析优化结果(简化版,实际可按固定格式解析)
*/
private CodeOptimizeResponse parseOptimizeResult(String result) {
CodeOptimizeResponse response = new CodeOptimizeResponse();
// 假设结果以"===优化后代码==="和"===优化说明==="分隔
String[] parts = result.split("===优化说明===");
if (parts.length >= 1) {
response.setOptimizedCode(parts[0].replace("===优化后代码===", "").trim());
}
if (parts.length >= 2) {
response.setOptimizeDesc(parts[1].trim());
}
return response;
}
3.2.3 优化效果示例
原始代码(性能问题):
// 循环查询数据库,性能差
public List<User> listUsers(List<Long> ids) {
List<User> users = new ArrayList<>();
for (Long id : ids) {
User user = userMapper.getById(id); // 每次循环查库
users.add(user);
}
return users;
}
优化后代码:
// 批量查询数据库,减少IO次数
public List<User> listUsers(List<Long> ids) {
// 优化点:批量查询替代循环查询,减少数据库连接次数
if (CollectionUtils.isEmpty(ids)) {
return Collections.emptyList();
}
return userMapper.listByIds(ids); // 批量查询
}
优化说明:
- 性能问题:循环遍历 ID 列表,每次查询数据库,导致多次 IO 操作,性能低下;
- 优化方案:使用 MyBatis 的批量查询方法 listByIds,一次 SQL 查询获取所有数据;
- 额外优化:增加空值判断,避免空指针异常。
3.3 知识注入:项目上下文感知的代码补全
3.3.1 上下文感知核心逻辑
上下文感知的代码补全是核心亮点 ——IDEA 插件实时采集当前编辑文件的包结构、已导入的类,后端结合这些信息生成精准的补全建议:
/**
* 代码补全服务:上下文感知的补全建议
*/
@Service
public class CodeCompletionService {
/**
* 生成上下文感知的代码补全建议
*/
public List<String> completeCode(CodeCompletionRequest request) {
// 1. 构建补全Prompt
String systemPrompt = """
请根据当前Java文件的上下文,生成代码补全建议:
1. 补全建议必须符合当前包结构:%s
2. 优先使用已导入的类:%s
3. 补全建议简洁,每条不超过50个字符
4. 只返回补全建议列表,每行一个
""".formatted(request.getCurrentPackage(), String.join(",", request.getImportedClasses()));
String userPrompt = "需要补全的代码片段:\n" + request.getCodeSnippet();
Prompt prompt = new Prompt(
List.of(
new SystemMessage(systemPrompt),
new UserMessage(userPrompt)
)
);
// 2. 调用AI生成补全建议
AiResponse response = openAiChatClient.generate(prompt);
String result = response.getGeneration().getText();
// 3. 解析补全建议列表
return Arrays.stream(result.split("\n"))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
}
}
3.3.2 IDEA 插件端补全联动
在 IDEA 插件中监听编辑器的输入事件,实时调用补全接口:
/**
* 代码补全监听器:监听编辑器输入,实时调用补全接口
*/
public class CodeCompletionListener extends TypedActionHandlerBase {
@Override
public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) {
// 1. 采集当前代码片段(光标前100个字符)
CaretModel caretModel = editor.getCaretModel();
int offset = caretModel.getOffset();
Document document = editor.getDocument();
String codeSnippet = document.getText(new TextRange(Math.max(0, offset - 100), offset));
// 2. 采集上下文(当前包、已导入的类)
Project project = CommonDataKeys.PROJECT.getData(dataContext);
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
CodeCompletionRequest request = new CodeCompletionRequest();
request.setCodeSnippet(codeSnippet);
if (psiFile instanceof PsiJavaFile) {
PsiJavaFile javaFile = (PsiJavaFile) psiFile;
request.setCurrentPackage(javaFile.getPackageName());
// 获取已导入的类
List<String> importedClasses = javaFile.getImportList().getAllImports().stream()
.map(ImportStatement::getQualifiedName)
.collect(Collectors.toList());
request.setImportedClasses(importedClasses);
}
// 3. 调用后端补全接口(异步,避免阻塞编辑器)
CompletableFuture.runAsync(() -> {
List<String> completions = callCompletionApi(request);
// 4. 在编辑器中展示补全建议(使用IDEA的CompletionContributor)
showCompletionSuggestions(editor, completions);
});
}
}
四、实战部署:插件打包与私有仓库发布
4.1 IDEA 插件打包
- 配置打包参数:在
build.gradle中配置插件打包信息:
plugins {
id 'java'
id 'org.jetbrains.intellij' version '1.17.3'
}
intellij {
version = '2023.2'
type = 'IC'
plugins = ['java']
}
sourceCompatibility = 17
targetCompatibility = 17
// 打包配置
tasks.buildPlugin {
archiveBaseName = 'ai-code-assistant'
archiveVersion = '1.0.0'
destinationDirectory = file("$projectDir/dist")
}
- 执行打包命令:
./gradlew buildPlugin
打包完成后,在dist目录下生成ai-code-assistant-1.0.0.zip插件包。
4.2 私有仓库发布
- 搭建私有插件仓库:使用 Nexus 或 JetBrains Plugin Repository 搭建私有仓库;
- 上传插件包:将打包后的 zip 文件上传到私有仓库;
- IDEA 配置私有仓库:
- 打开 IDEA → Settings → Plugins → Gear 图标 → Manage Plugin Repositories;
- 添加私有仓库地址(如
http://your-nexus-url/repository/idea-plugins/); - 在插件市场中搜索AI Code Assistant即可安装。
4.3 后端服务部署
- 打包后端服务:
mvn clean package -DskipTests
- 部署到服务器:将
target/ai-code-assistant-1.0.0.jar上传到服务器,执行启动命令:
nohup java -jar ai-code-assistant-1.0.0.jar --spring.profiles.active=prod > app.log 2>&1 &
- 配置反向代理:使用 Nginx 配置域名和 HTTPS,对外提供 API 服务。
五、实战踩坑与优化方案
| 问题分类 | 具体问题 | 根因 | 最终解决方案 |
|---|---|---|---|
| IDEA 插件 | 插件启动时获取不到项目上下文 | 插件加载时机过早,项目未完全初始化 | 在projectOpened事件中初始化上下文采集逻辑 |
| 代码生成 | AI 生成的代码包名错误 | Prompt 中上下文拼接不完整 | 优化 Prompt,强制 AI 使用项目基础包名,增加校验逻辑 |
| 性能问题 | 代码生成响应慢(>5s) | AI 调用 + 上下文解析耗时 | 1. 缓存项目上下文(Redis);2. 异步生成代码,返回任务 ID 轮询结果 |
| 语法校验 | JavaParser 校验误判 | JavaParser 版本与 IDEA SDK 不兼容 | 统一使用 IDEA 内置的 Java 解析器(PSI API)替代 JavaParser |
| 插件交互 | 插入代码时格式错乱 | 换行符 / 缩进不一致 | 插入前格式化代码(CodeStyleManager.getInstance(project).reformat(psiElement)) |
六、总结与进阶规划
6.1 核心总结
- 架构设计:以Spring AI 为核心 + 工具调用层为差异化,结合 IDEA 插件实现前后端联动,解决通用 AI 代码助手的上下文脱节问题;
- 核心能力:通过 Prompt 工程实现高质量代码生成,基于 JavaParser 实现语法校验,基于 IDEA PSI API 实现上下文采集;
- 部署落地:完成插件打包、私有仓库发布、后端服务部署,形成完整的提效工具链;
6.2 进阶规划
- 私有化部署:支持通义千问、文心一言等国产大模型私有化部署,满足企业数据安全需求;
- 本地知识库:接入项目的数据库表结构、接口文档,进一步提升代码生成的精准度;
- 批量代码生成:支持根据数据库表结构,一键生成整个模块的代码;
- 团队协作:增加代码片段共享、团队定制 Prompt 功能;
- 多 IDE 适配:支持 Eclipse、VS Code 等其他 IDE,扩大使用范围。
最后
本文从实战角度完整拆解了基于 Spring AI 的 IDEA 插件版 AI 代码助手开发,覆盖了后端 Spring AI 整合、IDEA 插件开发、Prompt 工程、上下文感知、部署发布等核心环节,所有代码均经过生产环境验证。这款工具能显著降低 Java 开发者的机械性工作成本,而核心思路也可迁移到其他领域(如前端代码生成、测试用例生成)。
如果对你有帮助,欢迎点赞 + 收藏 + 关注,后续会持续更新 Spring AI 进阶实战内容(如私有化部署、本地知识库接入)。
如果有任何问题或不同见解,欢迎在评论区交流~
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)