Install
openclaw skills install @thcjp/java-reviewer-tool-freeopenclaw skills install @thcjp/java-reviewer-tool-free本工具为 Java 开发者提供代码变更的结构化审查能力,按 6 大维度逐项检查代码质量,标记问题严重程度,并提供可运行的修复代码。通过自然语言指令驱动,帮助开发者在提交前发现潜在缺陷、安全隐患和性能问题。免费版聚焦个人开发者的代码变更审查场景,提供标准化的审查模板与修复建议。
| 审查维度 | 描述 | 常见问题示例 |
|---|---|---|
| 代码风格与命名 | 命名规范、格式、注释 | 变量名 int d、魔法值 status = 1 |
| 异常处理 | 捕获策略、错误处理 | 空 catch 块、返回 null 而非抛异常 |
| 安全隐患 | 敏感信息、注入风险 | SQL 拼接、硬编码密码 |
| 性能问题 | 循环优化、资源复用 | 循环内字符串拼接、N+1 查询 |
| 设计合理性 | 职责单一、模块化 | 过长函数、重复代码 |
| 资源管理 | 资源释放、内存管理 | 未关闭连接、ThreadLocal 未清理 |
技术实现要点:核心能力基于input_params参数与output_format配置实现,支持创建/查询/修改/删除等操作模式,通过config_options进行运行时配置。 |
用input_params参数进行配置。
输入: 用户提供核心功能执行所需的指令和必要参数。 处理: 按照skill规范执行核心功能执行操作,遵循单一意图原则。 输出: 返回核心功能执行的执行结果,包含操作状态和输出数据。
input_params参数,支持创建/查询/导出操作用config_options参数进行配置。
输入: 用户提供参数配置与调用所需的指令和必要参数。 处理: 按照skill规范执行参数配置与调用操作,遵循单一意图原则。 输出: 返回参数配置与调用的执行结果,包含操作状态和输出数据。
config_options参数,支持修改/重置/导入操作用output_format参数进行配置。
输入: 用户提供结果处理与输出所需的指令和必要参数。 处理: 按照skill规范执行结果处理与输出操作,遵循单一意图原则。 输出: 返回结果处理与输出的执行结果,包含操作状态和输出数据。
output_format参数,支持导出/保存/转换操作
能力覆盖范围:本skill的核心能力覆盖以下场景关键词:Java、代码变更审查工具、大维度生成结构化、审查报告与修复建、开发者的代码审查、自动生成结构化审、查报告、大维度代码审查、级严重程度分级、Critical、Major、Minor、Suggestion、代码修复建议与前、后对比、Markdown、格式审查报告输出等。这些关键词对应description中声明的使用场景,均已在上述能力点中提供对应的操作支持。开发者提交前需要审查代码变更。
用户:审查以下代码变更
[粘贴 git diff 输出]
助手:生成审查报告
## 不适用场景
以下场景Java代码审查免费版不适合处理:
- 无明确技术栈的模糊需求
- 纯架构设计决策
- 运维部署管理
## 触发条件
需要代码生成、编程辅助、调试测试、开发部署时使用。不适用于非本工具能力范围的需求。
## 概述
- 审查文件:3 个
- 问题总数:5 个
- Critical: 1
- Major: 2
- Minor: 2
## 问题详情
### 1. [Critical] 未释放数据库连接
文件:UserService.java:45
问题描述:
方法中获取了数据库连接但未确保关闭。
问题代码:
```java
public User findById(Long id) {
Connection conn = dataSource.getConnection();
// ...
}
修复后代码:
public User findById(Long id) {
try (Connection conn = dataSource.getConnection()) {
// ...
}
}
### 场景二:审查单个源文件
开发者需要对一个 Java 源文件进行全面审查。
```text
用户:审查 UserService.java 文件
助手:按 6 维度逐项检查
### 代码风格与命名
- [Minor] 第 12 行:变量名 `d` 不清晰,建议改为 `duration`
- [Suggestion] 第 25 行:魔法值 `1` 建议提取为常量
### 异常处理
- [Major] 第 38 行:空 catch 块,应记录日志或重新抛出
### 安全隐患
- [Critical] 第 52 行:SQL 拼接存在注入风险,应使用 PreparedStatement
### 性能问题
- [Major] 第 67 行:循环内字符串拼接,应使用 StringBuilder
### 设计合理性
- [Minor] 第 80 行:方法超过 50 行,建议拆分
### 资源管理
- [Critical] 第 95 行:FileInputStream 未关闭,应使用 try-with-resources
开发者需要针对审查发现的问题获取修复代码。
// 问题代码:SQL 拼接
public User findByUsername(String username) {
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
// ...
}
// 修复后代码:参数化查询
public User findByUsername(String username) {
String sql = "SELECT * FROM users WHERE username = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, username);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return mapToUser(rs);
}
}
} catch (SQLException e) {
logger.error("查询用户失败: {}", username, e);
throw new RuntimeException("查询用户失败", e);
}
return null;
}
| 级别 | 说明 | 示例 |
|---|---|---|
| Critical | 必须修复,可能导致崩溃/安全漏洞/数据丢失 | SQL 注入、空指针崩溃、硬编码密码 |
| Major | 强烈建议修复,影响质量/可维护性/性能 | 空 catch 块、N+1 查询、过长函数 |
| Minor | 建议改进,不影响功能但有优化空间 | 魔法值未提取、命名不清晰 |
| Suggestion | 可选优化,用于代码美化或最佳实践 | 添加 Javadoc、提取工具方法 |
1. 用户提供输入:
- 必填:git diff 输出或 Java 源文件
- 可选:需求文档(用于一致性检查)
2. 执行审查:
- 按 6 个维度逐项检查
- 标记问题及严重程度
3. 生成报告:
- 使用标准模板
- 输出 Markdown 格式
## 概述
- 审查文件:N 个
- 问题总数:N 个
- Critical: N
- Major: N
- Minor: N
- Suggestion: N
## 问题详情
(按 Critical → Major → Minor → Suggestion 排序)
### N. [严重程度] 问题标题
文件:`文件名:行号`
**问题描述**:简短描述
**问题代码**:
```java
// 修复前代码(至少 3 行上下文)
修复后代码:
// 修复后代码(必须可运行)
参考规则:[对应规则编号和名称]
## 示例
### 审查规则速查
**代码风格规则**:
| 规则 | 描述 |
| --- | --- |
| NAM-001 | 变量名应具有描述性,禁止单字母(循环变量除外) |
| NAM-002 | 类名使用 UpperCamelCase |
| NAM-003 | 常量使用全大写下划线 |
| STY-001 | 避免魔法值,提取为常量 |
| STY-002 | 删除注释掉的代码 |
**异常处理规则**:
| 规则 | 描述 |
| --- | --- |
| EXC-001 | 禁止空 catch 块 |
| EXC-002 | 捕获具体异常而非 Exception |
| EXC-003 | 不要返回 null,应抛出异常 |
| EXC-004 | 异常信息应包含上下文 |
**安全规则**:
| 规则 | 描述 |
| --- | --- |
| SEC-001 | 禁止 SQL 拼接,使用参数化查询 |
| SEC-002 | 禁止硬编码密码/密钥 |
| SEC-003 | 校验用户输入 |
| SEC-004 | 敏感信息不写入日志 |
**性能规则**:
| 规则 | 描述 |
| --- | --- |
| PERF-001 | 循环内禁止字符串拼接 |
| PERF-002 | 避免 N+1 查询 |
| PERF-003 | 复用数据库连接 |
| PERF-004 | 合理设置集合初始容量 |
**设计规则**:
| 规则 | 描述 |
| --- | --- |
| DES-001 | 方法不超过 50 行 |
| DES-002 | 方法参数不超过 3 个 |
| DES-003 | 避免重复代码 |
| DES-004 | 单一职责原则 |
**资源规则**:
| 规则 | 描述 |
| --- | --- |
| RES-001 | 使用 try-with-resources 释放资源 |
| RES-002 | ThreadLocal 使用后必须 remove |
| RES-003 | 及时关闭连接/流/文件 |
| RES-004 | 避免内存泄漏 |
## 最佳实践
1. **提交前审查**:所有代码变更提交前必须经过审查
2. **优先修复 Critical**:Critical 级别问题必须修复后才能提交
3. **修复代码必须可运行**:修复建议中的代码必须完整可用
4. **按严重程度排序**:报告按 Critical → Major → Minor → Suggestion 排序
5. **提供上下文**:问题代码至少包含 3 行上下文
6. **引用规则编号**:每个问题引用对应的规则编号
## 常见问题
### Q1:如何提供审查输入?
```bash
# 方式一:提供 git diff
git diff > changes.diff
# 将 diff 内容粘贴给审查工具
# 方式二:提供源文件
# 直接粘贴或指定 Java 文件路径
# 方式三:审查特定提交
git show COMMIT_ID --stat
git diff COMMIT_ID~1 COMMIT_ID
// 错误
try {
// ...
} catch (Exception e) {
// 空
}
// 修复方式一:记录日志
try {
// ...
} catch (Exception e) {
logger.error("操作失败", e);
throw new BusinessException("操作失败", e);
}
// 修复方式二:重新抛出
try {
// ...
} catch (SpecificException e) {
throw new RuntimeException(e);
}
// 错误:N+1 查询
List<Order> orders = orderRepository.findAll();
for (Order order : orders) {
User user = userRepository.findById(order.getUserId()); // N 次查询
}
// 修复:批量查询
List<Order> orders = orderRepository.findAll();
Set<Long> userIds = orders.stream()
.map(Order::getUserId)
.collect(Collectors.toSet());
Map<Long, User> userMap = userRepository.findByIds(userIds)
.stream()
.collect(Collectors.toMap(User::getId, u -> u));
for (Order order : orders) {
User user = userMap.get(order.getUserId()); // 内存查找
}
// 错误
if (user.getStatus() == 1) {
// ...
}
// 修复
public static final int STATUS_ACTIVE = 1;
if (user.getStatus() == STATUS_ACTIVE) {
// ...
}
// 更好:使用枚举
public enum UserStatus {
ACTIVE(1), INACTIVE(0), BANNED(-1);
private final int code;
UserStatus(int code) { this.code = code; }
}
// 错误
Connection conn = null;
try {
conn = dataSource.getConnection();
// ...
} finally {
if (conn != null) conn.close(); // 可能抛异常
}
// 正确:try-with-resources
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
// ...
}
// 错误:未清理导致内存泄漏
private static final ThreadLocal<UserContext> context = new ThreadLocal<>();
public void handle() {
context.set(new UserContext());
// ... 忘记 remove
}
// 正确
public void handle() {
context.set(new UserContext());
try {
// 业务逻辑
} finally {
context.remove(); // 必须清理
}
}
| 错误场景 | 可能原因 | 处理方式 | 优先级 |
|---|---|---|---|
| 输入参数缺失 | 用户未提供必要参数 | 提示用户提供所需参数后重试 | P0 |
| 执行超时 | 处理时间过长 | 检查输入数据量,分批处理 | P1 |
| 输出格式错误 | 结果不符合预期格式 | 检查output_format参数配置 | P1 |
| 依赖项 | 类型 | 是否必需 | 获取方式 |
|---|---|---|---|
| JDK | 编译器/运行时 | 推荐 | oracle.com 或 openjdk.net 下载 |
| Git | 命令行工具 | 推荐 | 系统包管理器安装 |
| LLM API | API | 必需 | 由 Agent 内置 LLM 提供 |