本文目录导读:

我来给你一个完整的Java静态代码分析案例,包含场景、工具配置和详细分析过程。
项目场景设定
// 待分析的示例项目:电商订单处理系统
package com.example.order;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class OrderService {
// 问题1:硬编码SQL,存在SQL注入风险
public List<Order> getOrdersByUser(String userId) {
List<Order> orders = new ArrayList<>();
String sql = "SELECT * FROM orders WHERE user_id = '" + userId + "'";
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Order order = new Order();
order.setId(rs.getLong("id"));
order.setAmount(rs.getBigDecimal("amount"));
orders.add(order);
}
} catch (SQLException e) {
e.printStackTrace(); // 问题2:打印堆栈而不是使用日志框架
}
return orders;
}
// 问题3:资源未正确关闭
public void saveOrder(Order order) {
Connection conn = null;
try {
conn = DBUtil.getConnection();
String sql = "INSERT INTO orders (id, amount, user_id) VALUES (?, ?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setLong(1, order.getId());
ps.setBigDecimal(2, order.getAmount());
ps.setString(3, order.getUserId());
ps.executeUpdate();
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage()); // 使用System.out
} finally {
// 没有关闭PreparedStatement
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("Close error"); // 忽略异常
}
}
}
}
// 问题4:空指针风险
public String getOrderStatus(Order order) {
if (order.getStatus() != null) {
return order.getStatus().toUpperCase();
}
return order.getStatus(); // 可能返回null
}
// 问题5:魔法数字和硬编码
public boolean isExpired(Order order) {
long currentTime = System.currentTimeMillis();
long expireTime = 24 * 60 * 60 * 1000; // 魔法数字
return (currentTime - order.getCreateTime()) > expireTime;
}
}
class Order {
private Long id;
private BigDecimal amount;
private String userId;
private String status;
private long createTime;
// getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public BigDecimal getAmount() { return amount; }
public void setAmount(BigDecimal amount) { this.amount = amount; }
public String getUserId() { return userId; }
public void setUserId(String userId) { this.userId = userId; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public long getCreateTime() { return createTime; }
public void setCreateTime(long createTime) { this.createTime = createTime; }
}
使用Maven配置静态分析工具
<!-- pom.xml -->
<project>
<build>
<plugins>
<!-- Checkstyle 检查代码规范 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<configLocation>google_checks.xml</configLocation>
<failOnViolation>false</failOnViolation>
</configuration>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
<!-- SpotBugs 检测Bug -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.7.3.2</version>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
</configuration>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
<!-- PMD 检查代码缺陷 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.19.0</version>
<configuration>
<rulesets>
<ruleset>rulesets/java/quickstart.xml</ruleset>
</rulesets>
<failOnViolation>false</failOnViolation>
</configuration>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
分析报告示例
1 Checkstyle 检查结果
Checkstyle violations found:
[ERROR] OrderService.java:12:9 - SQL injection vulnerability: concatenation of user input
[ERROR] OrderService.java:15:16 - Line length exceeds 120 characters
[ERROR] OrderService.java:18:13 - Variable 'ps' should be declared final
[WARN] OrderService.java:35:13 - Avoid using printStackTrace()
2 SpotBugs 检查结果
Bug Report:
[High] SQL_INJECTION: SQL statement constructed from user input
- In OrderService.getOrdersByUser(String userId)
- Repair: Use PreparedStatement with parameters
[Medium] NP_NULL_ON_SOME_PATH: Possible null pointer dereference
- In OrderService.getOrderStatus(Order order)
- When order.getStatus() returns null
[Medium] DM_EXIT: Method invokes System.exit()
- In OrderService.saveOrder(Order order)
- Avoid using System.exit() in business logic
3 PMD 检查结果
PMD Violations:
[High] AvoidUsingHardCodedIP - Hardcoded values in database connection
[Medium] AvoidInstantiatingObjectsInLoops - Objects instantiated in loops
[Low] SystemPrintln - Avoid using System.out.println for logging
[High] CloseResource - PreparedStatement not closed properly
修复后的代码
package com.example.order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class OrderServiceFixed {
private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceFixed.class);
private static final long EXPIRE_TIME_MS = 24 * 60 * 60 * 1000L; // 24小时
/** 使用参数化查询防止SQL注入 */
public List<Order> getOrdersByUser(String userId) {
List<Order> orders = new ArrayList<>();
String sql = "SELECT * FROM orders WHERE user_id = ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, userId); // 使用参数绑定
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
Order order = new Order();
order.setId(rs.getLong("id"));
order.setAmount(rs.getBigDecimal("amount"));
orders.add(order);
}
}
} catch (SQLException e) {
LOGGER.error("Failed to get orders for user: {}", userId, e); // 使用日志框架
}
return orders;
}
/** 正确关闭所有资源 */
public void saveOrder(Order order) {
String sql = "INSERT INTO orders (id, amount, user_id) VALUES (?, ?, ?)";
try (Connection conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setLong(1, order.getId());
ps.setBigDecimal(2, order.getAmount());
ps.setString(3, order.getUserId());
ps.executeUpdate();
} catch (SQLException e) {
LOGGER.error("Failed to save order: {}", order.getId(), e);
}
}
/** 处理空值情况 */
public String getOrderStatus(Order order) {
String status = order.getStatus();
return (status != null) ? status.toUpperCase() : "UNKNOWN"; // 提供默认值
}
/** 使用具名常量代替魔法数字 */
public boolean isExpired(Order order) {
long currentTime = System.currentTimeMillis();
return (currentTime - order.getCreateTime()) > EXPIRE_TIME_MS;
}
}
持续集成推荐配置
# GitLab CI/CD 配置示例
stages:
- analyze
- build
- test
# 静态代码分析阶段
analyze:
stage: analyze
script:
- mvn clean verify checkstyle:checkspotbugs:check pmd:check
artifacts:
reports:
codequality: target/reports/checkstyle-result.xml
通过这个案例,你可以:
- 看到常见的代码问题被识别和修复
- 了解不同工具的检查重点
- 建立标准化的静态分析流程
- 持续改进代码质量
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播