java-quality
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJava Quality - Quick Reference
Java 质量 - 快速参考
When NOT to Use This Skill
什么时候不要使用该技能
- SonarQube generic setup - Use skill
sonarqube - Spring Boot testing - Use Spring Boot test skills
- Security scanning - Use skill
java-security - Coverage reporting - Use skill
jacoco
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor framework-specific patterns.spring-boot
- 通用 SonarQube 配置 - 使用 技能
sonarqube - Spring Boot 测试 - 使用 Spring Boot 测试相关技能
- 安全扫描 - 使用 技能
java-security - 覆盖率报告 - 使用 技能
jacoco
深度知识: 如需框架专属模式,可调用并指定技术为mcp__documentation__fetch_docs。spring-boot
Tool Overview
工具概览
| Tool | Focus | Speed | Integration |
|---|---|---|---|
| Checkstyle | Code style, formatting | Fast | Maven/Gradle |
| SpotBugs | Bug patterns, bytecode | Medium | Maven/Gradle |
| PMD | Code smells, complexity | Fast | Maven/Gradle |
| SonarJava | All-in-one | Slow | SonarQube |
| Error Prone | Compile-time bugs | Fast | Compiler plugin |
| 工具 | 侧重方向 | 速度 | 集成方式 |
|---|---|---|---|
| Checkstyle | 代码风格、格式化 | 快 | Maven/Gradle |
| SpotBugs | Bug 模式、字节码检查 | 中等 | Maven/Gradle |
| PMD | 代码异味、复杂度 | 快 | Maven/Gradle |
| SonarJava | 全能型检查 | 慢 | SonarQube |
| Error Prone | 编译期 Bug 检查 | 快 | 编译器插件 |
Checkstyle Setup
Checkstyle 配置
Maven Configuration
Maven 配置
xml
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<violationSeverity>warning</violationSeverity>
</configuration>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.12.5</version>
</dependency>
</dependencies>
</plugin>xml
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<violationSeverity>warning</violationSeverity>
</configuration>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.12.5</version>
</dependency>
</dependencies>
</plugin>checkstyle.xml (Google Style Based)
checkstyle.xml(基于 Google 代码风格)
xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java"/>
<module name="TreeWalker">
<!-- Naming -->
<module name="ConstantName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="TypeName"/>
<!-- Imports -->
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<!-- Size -->
<module name="LineLength">
<property name="max" value="120"/>
</module>
<module name="MethodLength">
<property name="max" value="50"/>
</module>
<module name="ParameterNumber">
<property name="max" value="5"/>
</module>
<!-- Complexity -->
<module name="CyclomaticComplexity">
<property name="max" value="10"/>
</module>
<module name="NPathComplexity">
<property name="max" value="200"/>
</module>
<!-- Best Practices -->
<module name="EmptyBlock"/>
<module name="EqualsHashCode"/>
<module name="HiddenField"/>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
</module>
<!-- File-level checks -->
<module name="FileLength">
<property name="max" value="500"/>
</module>
<module name="NewlineAtEndOfFile"/>
</module>xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java"/>
<module name="TreeWalker">
<!-- 命名规范 -->
<module name="ConstantName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="TypeName"/>
<!-- 导入规范 -->
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<!-- 长度限制 -->
<module name="LineLength">
<property name="max" value="120"/>
</module>
<module name="MethodLength">
<property name="max" value="50"/>
</module>
<module name="ParameterNumber">
<property name="max" value="5"/>
</module>
<!-- 复杂度控制 -->
<module name="CyclomaticComplexity">
<property name="max" value="10"/>
</module>
<module name="NPathComplexity">
<property name="max" value="200"/>
</module>
<!-- 最佳实践 -->
<module name="EmptyBlock"/>
<module name="EqualsHashCode"/>
<module name="HiddenField"/>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
</module>
<!-- 文件级别检查 -->
<module name="FileLength">
<property name="max" value="500"/>
</module>
<module name="NewlineAtEndOfFile"/>
</module>Commands
常用命令
bash
undefinedbash
undefinedRun Checkstyle
运行 Checkstyle 检查
./mvnw checkstyle:check
./mvnw checkstyle:check
Generate report
生成报告
./mvnw checkstyle:checkstyle
undefined./mvnw checkstyle:checkstyle
undefinedSpotBugs Setup
SpotBugs 配置
Maven Configuration
Maven 配置
xml
<!-- pom.xml -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.3.0</version>
<configuration>
<effort>Max</effort>
<threshold>Medium</threshold>
<failOnError>true</failOnError>
<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>1.12.0</version>
</plugin>
</plugins>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>xml
<!-- pom.xml -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.3.0</version>
<configuration>
<effort>Max</effort>
<threshold>Medium</threshold>
<failOnError>true</failOnError>
<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>1.12.0</version>
</plugin>
</plugins>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>Exclude False Positives
排除误报
xml
<!-- spotbugs-exclude.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<!-- Exclude generated code -->
<Match>
<Package name="~.*\.generated\..*"/>
</Match>
<!-- Exclude specific patterns -->
<Match>
<Bug pattern="EI_EXPOSE_REP"/>
<Class name="~.*Dto"/>
</Match>
</FindBugsFilter>xml
<!-- spotbugs-exclude.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<!-- 排除自动生成的代码 -->
<Match>
<Package name="~.*\.generated\..*"/>
</Match>
<!-- 排除特定规则 -->
<Match>
<Bug pattern="EI_EXPOSE_REP"/>
<Class name="~.*Dto"/>
</Match>
</FindBugsFilter>Commands
常用命令
bash
undefinedbash
undefinedRun SpotBugs
运行 SpotBugs 检查
./mvnw spotbugs:check
./mvnw spotbugs:check
Generate report
生成报告
./mvnw spotbugs:spotbugs
./mvnw spotbugs:spotbugs
GUI viewer
打开 GUI 查看器
./mvnw spotbugs:gui
undefined./mvnw spotbugs:gui
undefinedCommon SpotBugs Warnings
常见 SpotBugs 警告
| Bug ID | Description | Fix |
|---|---|---|
| NP_NULL_ON_SOME_PATH | Possible null dereference | Add null check or use Optional |
| EI_EXPOSE_REP | Returns mutable object | Return defensive copy |
| MS_SHOULD_BE_FINAL | Static field should be final | Add final modifier |
| SQL_INJECTION | SQL injection risk | Use parameterized queries |
| DM_DEFAULT_ENCODING | Uses default encoding | Specify charset explicitly |
| Bug ID | 描述 | 修复方案 |
|---|---|---|
| NP_NULL_ON_SOME_PATH | 可能出现空指针引用 | 添加空值校验或使用 Optional |
| EI_EXPOSE_REP | 返回了可变对象 | 返回防御性拷贝 |
| MS_SHOULD_BE_FINAL | 静态字段应该声明为 final | 添加 final 修饰符 |
| SQL_INJECTION | 存在 SQL 注入风险 | 使用参数化查询 |
| DM_DEFAULT_ENCODING | 使用了系统默认编码 | 显式指定字符集 |
PMD Setup
PMD 配置
Maven Configuration
Maven 配置
xml
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.21.2</version>
<configuration>
<rulesets>
<ruleset>pmd-rules.xml</ruleset>
</rulesets>
<failOnViolation>true</failOnViolation>
<printFailingErrors>true</printFailingErrors>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>xml
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.21.2</version>
<configuration>
<rulesets>
<ruleset>pmd-rules.xml</ruleset>
</rulesets>
<failOnViolation>true</failOnViolation>
<printFailingErrors>true</printFailingErrors>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>pmd-rules.xml
pmd-rules.xml 规则文件
xml
<?xml version="1.0"?>
<ruleset name="Custom Rules">
<description>Custom PMD ruleset</description>
<!-- Best Practices -->
<rule ref="category/java/bestpractices.xml">
<exclude name="JUnitTestContainsTooManyAsserts"/>
</rule>
<!-- Code Style -->
<rule ref="category/java/codestyle.xml">
<exclude name="AtLeastOneConstructor"/>
<exclude name="OnlyOneReturn"/>
</rule>
<!-- Design -->
<rule ref="category/java/design.xml">
<exclude name="LawOfDemeter"/>
</rule>
<!-- Error Prone -->
<rule ref="category/java/errorprone.xml"/>
<!-- Performance -->
<rule ref="category/java/performance.xml"/>
<!-- Custom thresholds -->
<rule ref="category/java/design.xml/CyclomaticComplexity">
<properties>
<property name="methodReportLevel" value="10"/>
</properties>
</rule>
<rule ref="category/java/design.xml/CognitiveComplexity">
<properties>
<property name="reportLevel" value="15"/>
</properties>
</rule>
</ruleset>xml
<?xml version="1.0"?>
<ruleset name="Custom Rules">
<description>Custom PMD ruleset</description>
<!-- 最佳实践 -->
<rule ref="category/java/bestpractices.xml">
<exclude name="JUnitTestContainsTooManyAsserts"/>
</rule>
<!-- 代码风格 -->
<rule ref="category/java/codestyle.xml">
<exclude name="AtLeastOneConstructor"/>
<exclude name="OnlyOneReturn"/>
</rule>
<!-- 设计规范 -->
<rule ref="category/java/design.xml">
<exclude name="LawOfDemeter"/>
</rule>
<!-- 易出错场景检查 -->
<rule ref="category/java/errorprone.xml"/>
<!-- 性能优化检查 -->
<rule ref="category/java/performance.xml"/>
<!-- 自定义阈值 -->
<rule ref="category/java/design.xml/CyclomaticComplexity">
<properties>
<property name="methodReportLevel" value="10"/>
</properties>
</rule>
<rule ref="category/java/design.xml/CognitiveComplexity">
<properties>
<property name="reportLevel" value="15"/>
</properties>
</rule>
</ruleset>Commands
常用命令
bash
undefinedbash
undefinedRun PMD
运行 PMD 检查
./mvnw pmd:check
./mvnw pmd:check
Generate report
生成报告
./mvnw pmd:pmd
./mvnw pmd:pmd
Copy-paste detection
重复代码检测
./mvnw pmd:cpd
undefined./mvnw pmd:cpd
undefinedError Prone Setup
Error Prone 配置
Maven Configuration
Maven 配置
xml
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<compilerArgs>
<arg>-XDcompilePolicy=simple</arg>
<arg>-Xplugin:ErrorProne</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>2.24.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>xml
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<compilerArgs>
<arg>-XDcompilePolicy=simple</arg>
<arg>-Xplugin:ErrorProne</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>2.24.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>Combined Quality Profile
组合质量检测配置
All-in-One Maven Profile
一站式 Maven Profile
xml
<!-- pom.xml -->
<profiles>
<profile>
<id>quality</id>
<build>
<plugins>
<!-- Checkstyle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
<!-- SpotBugs -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
<!-- PMD -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>bash
undefinedxml
<!-- pom.xml -->
<profiles>
<profile>
<id>quality</id>
<build>
<plugins>
<!-- Checkstyle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
<!-- SpotBugs -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
<!-- PMD -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>bash
undefinedRun all quality checks
运行所有质量检查
./mvnw verify -Pquality
undefined./mvnw verify -Pquality
undefinedCommon Code Smells & Fixes
常见代码异味及修复方案
1. God Class
1. 上帝类(God Class)
java
// BAD - Class does too much
public class OrderService {
public Order createOrder() { ... }
public void sendEmail() { ... }
public void generatePdf() { ... }
public void calculateTax() { ... }
public void updateInventory() { ... }
}
// GOOD - Single responsibility
public class OrderService {
private final EmailService emailService;
private final PdfGenerator pdfGenerator;
private final TaxCalculator taxCalculator;
private final InventoryService inventoryService;
public Order createOrder(OrderRequest request) {
Order order = buildOrder(request);
order.setTax(taxCalculator.calculate(order));
inventoryService.reserve(order.getItems());
return orderRepository.save(order);
}
}java
// 反面示例 - 类承担了过多职责
public class OrderService {
public Order createOrder() { ... }
public void sendEmail() { ... }
public void generatePdf() { ... }
public void calculateTax() { ... }
public void updateInventory() { ... }
}
// 正面示例 - 单一职责
public class OrderService {
private final EmailService emailService;
private final PdfGenerator pdfGenerator;
private final TaxCalculator taxCalculator;
private final InventoryService inventoryService;
public Order createOrder(OrderRequest request) {
Order order = buildOrder(request);
order.setTax(taxCalculator.calculate(order));
inventoryService.reserve(order.getItems());
return orderRepository.save(order);
}
}2. Long Parameter List
2. 过长参数列表
java
// BAD
public void createUser(String name, String email, String phone,
String address, String city, String country, String zipCode) { }
// GOOD - Use builder or DTO
public void createUser(CreateUserRequest request) { }
@Builder
public record CreateUserRequest(
String name,
String email,
String phone,
Address address
) {}java
// 反面示例
public void createUser(String name, String email, String phone,
String address, String city, String country, String zipCode) { }
// 正面示例 - 使用构建器或 DTO
public void createUser(CreateUserRequest request) { }
@Builder
public record CreateUserRequest(
String name,
String email,
String phone,
Address address
) {}3. Feature Envy
3. 特性依恋(Feature Envy)
java
// BAD - Method uses another object's data excessively
public double calculateTotal(Order order) {
double total = 0;
for (OrderItem item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
if (item.getDiscount() > 0) {
total -= item.getPrice() * item.getQuantity() * item.getDiscount();
}
}
return total;
}
// GOOD - Move logic to Order
public class Order {
public double calculateTotal() {
return items.stream()
.mapToDouble(OrderItem::getSubtotal)
.sum();
}
}
public class OrderItem {
public double getSubtotal() {
double base = price * quantity;
return discount > 0 ? base * (1 - discount) : base;
}
}java
// 反面示例 - 方法过度依赖另一个对象的数据
public double calculateTotal(Order order) {
double total = 0;
for (OrderItem item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
if (item.getDiscount() > 0) {
total -= item.getPrice() * item.getQuantity() * item.getDiscount();
}
}
return total;
}
// 正面示例 - 将逻辑移到 Order 类中
public class Order {
public double calculateTotal() {
return items.stream()
.mapToDouble(OrderItem::getSubtotal)
.sum();
}
}
public class OrderItem {
public double getSubtotal() {
double base = price * quantity;
return discount > 0 ? base * (1 - discount) : base;
}
}4. Primitive Obsession
4. 基本类型偏执
java
// BAD
public void sendEmail(String email) {
if (!email.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email");
}
}
// GOOD - Value object
public record Email(String value) {
public Email {
if (!value.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email: " + value);
}
}
}
public void sendEmail(Email email) { ... }java
// 反面示例
public void sendEmail(String email) {
if (!email.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email");
}
}
// 正面示例 - 使用值对象
public record Email(String value) {
public Email {
if (!value.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email: " + value);
}
}
}
public void sendEmail(Email email) { ... }5. Deep Nesting
5. 深度嵌套
java
// BAD
public void process(Order order) {
if (order != null) {
if (order.isValid()) {
for (OrderItem item : order.getItems()) {
if (item.isAvailable()) {
if (item.getQuantity() > 0) {
// process
}
}
}
}
}
}
// GOOD - Guard clauses
public void process(Order order) {
if (order == null || !order.isValid()) {
return;
}
order.getItems().stream()
.filter(OrderItem::isAvailable)
.filter(item -> item.getQuantity() > 0)
.forEach(this::processItem);
}java
// 反面示例
public void process(Order order) {
if (order != null) {
if (order.isValid()) {
for (OrderItem item : order.getItems()) {
if (item.isAvailable()) {
if (item.getQuantity() > 0) {
// 处理逻辑
}
}
}
}
}
}
// 正面示例 - 使用卫语句
public void process(Order order) {
if (order == null || !order.isValid()) {
return;
}
order.getItems().stream()
.filter(OrderItem::isAvailable)
.filter(item -> item.getQuantity() > 0)
.forEach(this::processItem);
}Quality Metrics Targets
质量指标目标
| Metric | Target | Tool |
|---|---|---|
| Cyclomatic Complexity | < 10 | Checkstyle, PMD |
| Cognitive Complexity | < 15 | PMD, SonarQube |
| Method Length | < 50 lines | Checkstyle |
| Class Length | < 500 lines | Checkstyle |
| Parameters | < 5 | Checkstyle |
| Nesting Depth | < 4 | PMD |
| 指标 | 目标值 | 检测工具 |
|---|---|---|
| 圈复杂度 | < 10 | Checkstyle, PMD |
| 认知复杂度 | < 15 | PMD, SonarQube |
| 方法长度 | < 50 行 | Checkstyle |
| 类长度 | < 500 行 | Checkstyle |
| 参数数量 | < 5 | Checkstyle |
| 嵌套深度 | < 4 | PMD |
CI/CD Integration
CI/CD 集成
GitHub Actions
GitHub Actions 配置
yaml
name: Quality
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Run quality checks
run: ./mvnw verify -Pquality
- name: Upload reports
uses: actions/upload-artifact@v4
if: always()
with:
name: quality-reports
path: |
target/checkstyle-result.xml
target/spotbugsXml.xml
target/pmd.xmlyaml
name: Quality
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 配置 JDK
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: 运行质量检查
run: ./mvnw verify -Pquality
- name: 上传报告
uses: actions/upload-artifact@v4
if: always()
with:
name: quality-reports
path: |
target/checkstyle-result.xml
target/spotbugsXml.xml
target/pmd.xmlAnti-Patterns
反模式
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|---|---|
| Suppressing all warnings | Hides real issues | Fix or justify individually |
| No static analysis in CI | Quality degrades over time | Add to build pipeline |
| Only running Checkstyle | Misses bugs and smells | Combine with SpotBugs + PMD |
| High complexity thresholds | Allows unmaintainable code | Keep < 10 cyclomatic |
| Excluding entire packages | Ignores quality in areas | Be specific with exclusions |
| 反模式 | 危害 | 正确做法 |
|---|---|---|
| 屏蔽所有警告 | 掩盖真实问题 | 逐个修复或单独说明屏蔽理由 |
| CI 中没有配置静态分析 | 代码质量随时间逐步下降 | 加入构建流水线 |
| 只运行 Checkstyle | 遗漏 Bug 和代码异味 | 搭配 SpotBugs + PMD 一起使用 |
| 复杂度阈值设置过高 | 允许不可维护的代码存在 | 圈复杂度保持在 10 以内 |
| 排除整个包的检测 | 忽略特定区域的质量问题 | 精确指定要排除的内容 |
Quick Troubleshooting
快速问题排查
| Issue | Likely Cause | Solution |
|---|---|---|
| Checkstyle fails on generated code | No exclusion pattern | Add |
| SpotBugs false positive on DTO | EI_EXPOSE_REP on records | Exclude pattern for DTOs |
| PMD too slow | Analyzing all files | Configure incremental analysis |
| Error Prone conflicts | Version mismatch | Align with JDK version |
| Quality gate fails in CI | Different config locally | Commit config files |
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| Checkstyle 检测自动生成代码时报错 | 没有配置排除规则 | 为自动生成目录添加 |
| SpotBugs 对 DTO 出现误报 | 记录类触发 EI_EXPOSE_REP 规则 | 为 DTO 添加排除规则 |
| PMD 运行过慢 | 分析了所有文件 | 配置增量分析 |
| Error Prone 出现冲突 | 版本不匹配 | 与 JDK 版本对齐 |
| CI 中质量门禁失败 | 本地和线上配置不一致 | 提交配置文件到代码库 |
Related Skills
相关技能
- SonarQube
- JaCoCo
- Clean Code
- Java Security
- SonarQube
- JaCoCo
- Clean Code
- Java Security