8.2 KiB
8.2 KiB
jdtls (Java Language Server) 使用指南
通过 Serena MCP 工具调用 jdtls 进行 Java 代码分析
前置条件
1. 确保 jdtls 已安装
jdtls 通常通过 VS Code 的 Java 扩展自动安装,或者手动安装:
# 检查 jdtls 路径
which jdtls
# 或
ls ~/.vscode/extensions/redhat.java-*/server/
2. 项目结构要求
jdtls 需要以下文件来识别 Java 项目:
- Maven:
pom.xml - Gradle:
build.gradle或build.gradle.kts - Eclipse:
.project和.classpath
通过 Serena 使用 jdtls
激活项目
# Step 1: 激活 Java 项目
tool: mcp__serena__activate_project
params:
project: "/path/to/java/project"
# 返回: 项目已激活,jdtls 已初始化
验证配置
# 检查当前配置
tool: mcp__serena__get_current_config
# 确认输出包含:
# - active_project: /path/to/java/project
# - language_server: jdtls
符号提取操作
获取文件符号概览
# 获取单个文件的符号列表(不含代码体)
tool: mcp__serena__get_symbols_overview
params:
relative_path: "src/main/java/com/example/OrderController.java"
depth: 1 # 0=仅顶层, 1=含直接成员, 2=含嵌套成员
# 返回示例:
# Classes:
# - OrderController (class) [59-1241]
# Methods:
# - getOrderList (method) [120-145]
# - createOrder (method) [150-180]
# - updateOrder (method) [185-210]
查找符号
# 按名称模式查找符号
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderController" # 可以是部分名称
relative_path: "src/main/java/" # 限定搜索范围
include_body: false # 是否包含代码体
include_info: true # 是否包含 hover 信息
depth: 1 # 包含成员的深度
# 名称模式规则:
# - "OrderController" -> 匹配任何包含此名称的符号
# - "controller/OrderController" -> 匹配此路径后缀
# - "/com.example.OrderController" -> 精确匹配完整路径
# - "OrderController/getOrderList" -> 匹配类中的方法
# - "OrderController[0]" -> 匹配重载方法的第一个
获取符号详情(含代码体)
# 获取完整的符号定义(含代码)
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderService/saveOrder"
relative_path: "src/main/java/com/example/service/OrderService.java"
include_body: true
depth: 0
# 返回包含:
# - 方法签名
# - Javadoc 注释
# - 完整方法体
# - 行号范围
引用分析操作
查找符号引用
# 查找某个符号被哪些地方引用
tool: mcp__serena__find_referencing_symbols
params:
name_path: "OrderService/saveOrder"
relative_path: "src/main/java/com/example/service/OrderService.java"
include_info: true
# 返回示例:
# References (5 found):
# - OrderController.createOrder [180:12-180:35]
# snippet: "orderService.saveOrder(dto)"
# - OrderController.updateOrder [210:12-210:35]
# snippet: "orderService.saveOrder(updated)"
# - OrderServiceTest.testSave [45:8-45:30]
# snippet: "service.saveOrder(testDto)"
模式搜索(补充 LSP)
# 当 LSP 无法找到时,使用模式搜索
tool: mcp__serena__search_for_pattern
params:
substring_pattern: "orderService\\.save"
paths_include_glob: "**/*.java"
restrict_search_to_code_files: true
context_lines_before: 2
context_lines_after: 2
# 适用场景:
# - 动态调用 (反射)
# - 字符串拼接的方法名
# - 注解中的引用
调用链构建
构建向下调用链 (callee)
# 伪代码: 递归构建调用链
def build_callee_chain(symbol_path, file_path, depth, max_depth):
if depth > max_depth:
return None
# Step 1: 获取方法体
symbol = find_symbol(
name_path_pattern=symbol_path,
relative_path=file_path,
include_body=True
)
# Step 2: 在方法体中查找调用
# 使用 LSP 或正则匹配
calls = extract_method_calls(symbol.body)
# Step 3: 对每个调用递归
callees = []
for call in calls:
# 尝试定位被调用方法
target = find_symbol(
name_path_pattern=call.method_name,
relative_path=call.potential_file
)
if target:
callees.append({
'symbol': target,
'evidence': call.location,
'children': build_callee_chain(
target.path, target.file, depth + 1, max_depth
)
})
return {
'symbol': symbol,
'callees': callees
}
实际操作步骤
# 1. 获取入口方法
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderController/createOrder"
relative_path: "src/main/java/com/example/controller/"
include_body: true
depth: 0
# 2. 分析方法体中的调用
# 从返回的 body 中提取: orderService.saveOrder(dto)
# 3. 定位被调用方法
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderService/saveOrder"
relative_path: "src/main/java/"
include_body: true
# 4. 查找该方法的引用(验证调用关系)
tool: mcp__serena__find_referencing_symbols
params:
name_path: "OrderService/saveOrder"
relative_path: "src/main/java/com/example/service/OrderService.java"
# 5. 递归处理下一层
Java 特有处理
注解识别
# 常见注解及其语义含义
API 入口点注解:
- "@RestController": REST API 控制器
- "@Controller": MVC 控制器
- "@RequestMapping": 请求映射
- "@GetMapping": GET 请求
- "@PostMapping": POST 请求
- "@PutMapping": PUT 请求
- "@DeleteMapping": DELETE 请求
服务层注解:
- "@Service": 业务服务
- "@Component": 通用组件
- "@Transactional": 事务方法
数据层注解:
- "@Repository": 数据访问
- "@Mapper": MyBatis Mapper
- "@Table": JPA 表映射
- "@Entity": JPA 实体
数据对象注解:
- "@Data": Lombok 数据类
- "@Getter/@Setter": Lombok 访问器
- "@Builder": Lombok 构建器
MyBatis Mapper 处理
# MyBatis Mapper 接口无法通过 LSP 追踪到 SQL
# 需要关联 XML 文件
# 1. 找到 Mapper 接口
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderMapper"
relative_path: "src/main/java/"
# 2. 查找对应的 XML
tool: mcp__serena__search_for_pattern
params:
substring_pattern: "OrderMapper"
paths_include_glob: "**/*.xml"
# 3. 读取 XML 获取 SQL 定义
tool: mcp__serena__list_dir
params:
relative_path: "src/main/resources/mapper/"
LSP SymbolKind 映射
# jdtls 返回的 SymbolKind 数值对照
1: File
2: Module
3: Namespace
4: Package
5: Class # 类
6: Method # 方法
7: Property
8: Field # 字段
9: Constructor # 构造函数
10: Enum # 枚举
11: Interface # 接口
12: Function # 函数
13: Variable # 变量
14: Constant # 常量
15: String
16: Number
17: Boolean
18: Array
19: Object
20: Key
21: Null
22: EnumMember # 枚举值
23: Struct
24: Event
25: Operator
26: TypeParameter # 泛型参数
常见问题
Q: jdtls 启动慢
A: 首次打开项目时,jdtls 需要构建索引。
- Maven 项目: 会下载依赖
- 大项目: 索引可能需要几分钟
建议: 等待 Serena 报告项目就绪
Q: 找不到符号
A: 可能原因:
1. 项目未正确识别 (缺少 pom.xml 或 build.gradle)
2. 编译错误导致索引不完整
3. 符号在排除目录中
解决:
1. 确保项目根目录正确
2. 先执行 mvn compile 或 gradle build
3. 使用 search_for_pattern 作为备选
Q: 引用结果不完整
A: jdtls 的 references 可能遗漏:
1. 反射调用
2. 字符串拼接的方法名
3. 动态代理
解决:
使用 search_for_pattern 补充搜索
最佳实践
- 先概览后详细 - 用
get_symbols_overview了解文件结构,再用find_symbol获取详情 - 限定搜索范围 - 总是传入
relative_path以提高效率 - 分批处理 - 大项目分模块处理,避免一次性加载全部
- 缓存结果 - 符号信息变化不频繁,可以缓存复用
- 结合搜索 - LSP 不足时用
search_for_pattern补充