前言
在 Java 项目中,代码质量直接决定了项目的可维护性、运行稳定性及团队协作效率,是影响项目长期发展的核心因素。因此,建立 "代码质量评估→问题改进→二次评估" 的闭环管理机制,对项目迭代至关重要。
传统的人工代码评审虽能解决大部分显性问题,但需持续投入大量人力成本,且受评审人员经验、精力等因素影响,易遗漏隐性问题(如潜在逻辑漏洞、性能隐患)。而自动化代码质量工具可有效弥补这一短板,通过标准化检测流程实现质量管控的平滑落地,高效构建质量闭环。
本文将聚焦 Checkstyle、PMD、SpotBugs 三款主流工具,详细讲解如何在开发环境中搭建完整的代码质量管控工具链,解决开发阶段的自动化检测与问题修复需求。
自动化代码质量工具链的价值
- 统一编码规范:解决团队内编码风格混乱问题(如:缩进、大括号位置、注释等)
- 提前暴露风险:在开发阶段避免掉一些常见 bug,避免在生产环境发现问题
- 提升编码水平:通过问题解决,促使开发人员写出质量更高的代码
- 持续集成:通过 Jenkins 等流水线,自动化实现全链路代码质量管控
工具定位
工具 | 分析对象 | 核心关注点 | 场景 |
---|---|---|---|
Checkstyle | 源代码 | 编码规范、格式、命名 | 统一团队编码规范 |
PMD | 源代码 | 代码缺陷、不良实践、性能问题 | 优化代码质量和可读性 |
SpotBugs | 字节码 | 运行时错误、逻辑漏洞、安全风险 | 发现语法正确但逻辑危险的代码 |
简单来说,Checkstyle 关注 "代码写的规不规范", PMD 关注 "代码写的好不好", SpotBugs 关注 "代码跑起来会不会有问题"。
需要注意的是,这 3 个工具检测目标有部分重叠(如PMD 中也可以检测代码风格),专业的事情需要交给专业的工具去干,交叉部分需要排除掉,避免重复警告。
开发环境
- JDK版本:JDK17+
- 构建工具: Maven 3.6.3
- IDEA: IntelliJ IDEA 2024.2.4
- Checkstyle 版本:9.3
- PMD 版本:7.14.0
- SpotBugs 版本: 4.9.6
Checkstyle:统一编码规范
Checkstyle 是 Java 编码规范检测工具,支持自定义规范规则,也可以直接复用 Google、Sun 等主流规范(CheckStyle 内置这 2 个规范)。
自定义规范分为 2 种:
- 自定义规则:按照 Checkstyle 自定义规则
- 自定义 Checkstyle 扩展:当原生规则无法满足需求时(如团队特有的业务编码规范),需开发自定义 Check 类(实现 Checkstyle 提供的 Check 接口),同时配套开发对应的代码格式化扩展(确保 IDE 可自动修复违规问题)。
Maven 集成
1. 引入 Maven 插件
在 pom.xml 的 build/plugins 节点中配置 Checkstyle 插件,明确检测规则文件路径与执行时机。为确保多模块项目的规则统一性,推荐在父 pom.xml 中通过 pluginManagement 统一配置,子模块直接继承即可。
该示例配置采用 Spring 编码规范(基于 Google 规范优化,适配 Spring 生态项目), spring-javaformat 工程提供了 Checkstyle 工具扩展以及对应的格式化扩展。
xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.1</version>
<dependencies>
<!-- 指定 checkstyle 版本, 需要与 IDEA 上的版本匹配 -->
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>9.3</version>
</dependency>
<!-- 引入 Spring 规则集及其扩展, 非 Spring 规范不需要引入 -->
<dependency>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-checkstyle</artifactId>
<version>0.0.47</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<!-- 子工程继承该插件配置 -->
<inherited>true</inherited>
<configuration>
<!-- 内置的 google 编码规范 -->
<!--configLocation>google_checks.xml</configLocation -->
<!-- 默认的 Spring 规则集 -->
<!-- <configLocation>io/spring/javaformat/checkstyle/checkstyle.xml</configLocation>-->
<!-- 自定义规则集 -->
<configLocation>config/checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<!-- 是否检测测试代码-->
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!-- 引入对应的格式化扩展, 非 Spring 规范不需要引入 -->
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.47</version>
<executions>
<execution>
<phase>validate</phase>
<inherited>true</inherited>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</build>
由于示例中引入的是 Spring 的编码规范,所以额外多了 2 个插件的依赖,如果使用其他规范(如 Google 编码规范),不需要配置 io.spring.javaformat
插件及依赖。
为了在编译前发现编码问题,将检测过程绑定在 Maven 的 validate 阶段。
2. 自定义检测规则
一般内置的检测规则或多或少与团队中的编码规范有些出入,需要自定义规则。 可以在插件中 configLocation 配置规则文件的位置,定义方式如下:
- 内置规则:直接写规则的文件名称,如:google_checks.xml、sun_checks.xml
- 依赖三方扩展:需要从官方中查找对应的规则路径,如:Spring 规范路径为 io/spring/javaformat/checkstyle/checkstyle.xml
- 自定义规范:直接按照工程路径引入,如 config/checkstyle.xml
具体定义规则参见 Checkstyle官网,以下给出集成 Spring 规范的示例。
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="com.puppycrawl.tools.checkstyle.Checker">
<!-- 引入 Spring 规则集,但排除 SpringHeader 规则 -->
<module name="io.spring.javaformat.checkstyle.SpringChecks">
<!-- 排除关于版本信息的规则 -->
<property name="excludes" value="io.spring.javaformat.checkstyle.check.SpringHeaderCheck"/>
<!-- 排除关于导入顺序的规则, 当前导入的顺序和已有IDEA排序冲突,且 Spring Format 未提供导入顺序的格式化功能,故排除该规则 -->
<property name="excludes" value="io.spring.javaformat.checkstyle.check.SpringImportOrderCheck"/>
<!--
原规则中 @author 匹配的外国人的名称,需要再名字中间有空格,覆盖该规则。
checkStyle 不支持继承覆盖规则,故排除该规则,在重新实现
-->
<property name="excludes" value="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTypeCheck"/>
<!-- 排除关于 package-info.java 文件的规则 -->
<property name="excludes" value="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<module name="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTypeCheck">
<property name="scope" value="package"/>
<property name="authorFormat" value=".+"/>
</module>
</module>
</module>
3. 执行检查
上述示例将执行检测的时机绑定在编译阶段之前( Maven validation 阶段),编译时即可自动触发检测。
执行 mvn compile
, 输出日志如下:
markdown
Formatting violations found in the following files:
* D:\develop\\actuator-sample\start\src\main\java\com\sample\start\metric\TestStyle.java
Run `spring-javaformat:apply` to fix.
Spring 提供的格式化插件可以解决部分问题(如:增删空行、空格等), 执行 mvn spring-javaformat:apply
,该插件需要进行一些配置(请参考 spring-javaformat)。
IDEA 集成
IDEA 集成 Checkstyle 后,可实现代码实时检测(违规代码下方显示红色波浪线)与一键修复,大幅提升开发效率。
1. 安装插件
在 IDEA 中安装插件 CheckSyle-IDEA

如启用 Spring 代码格式化需要离线安装Spring JavaFormat插件
2. 配置插件
在安装完插件后,在 工具 -> Checkstyle 配置:
- 指定 Checkstyle 版本,需要与 Maven 配置一致
- 指定检测规则路径
- 如 Spring 规范,需要下载 spring-javaformat-checkstyle 和 spring-javaformat-config 并配置到 Third-Party Checks 中
3. 执行检测
-
手动执行检测
该插件配合 Spring 规范执行过程中的几个问题:
- 重复执行检测可能无结果,需在 Checkstyle 配置页面点击「Refresh」刷新规则后重试;
- Spring 格式化相关的规则(如:空格问题)不会执行检测
-
实时检测效果: 编写代码时,若存在违规(如命名不规范、缺少注释),代码下方会显示红色波浪线,鼠标悬停可查看违规原因与改进建议,部分问题可点击「Fix」一键修复。
-
代码格式化: 通过 IDEA 自带的格式化功能(快捷键:CTRL + ALT + L),即可快速输出符合规范的代码格式。
PMD: 代码逻辑缺陷检测
PMD 的核心能力是 "静态代码分析",能检测未使用变量、冗余条件、循环复杂度过高等问题。与 Checkstyle 不同,PMD 更关注 "代码逻辑质量" 而非 "格式"。
Maven 集成
1. 引入 Maven 插件
在 pom.xml 的 build/plugins 中添加 PMD 插件,配置检查规则文件和执行时机。 推荐在父 pom.xml 中进行配置,以使所有的工程共享一套配置。
xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.27.0</version>
<configuration>
<failOnViolation>true</failOnViolation>
<printFailingErrors>true</printFailingErrors>
<!-- 最低优先级的问题也会导致构建失败 -->
<failurePriority>5</failurePriority>
<!-- 规则集路径 -->
<rulesets>
<!-- 易错:用于检测有缺陷、极其令人困惑或容易导致运行时错误的结构的规则。 -->
<ruleset>category/java/errorprone.xml</ruleset>
<!-- 设计想挂面 -->
<ruleset>category/java/design.xml</ruleset>
<!-- 性能相关 -->
<ruleset>category/java/performance.xml</ruleset>
<!-- 安全相关 -->
<ruleset>category/java/security.xml</ruleset>
<!-- 最佳实践 -->
<ruleset>category/java/bestpractices.xml</ruleset>
<!-- 并发相关 -->
<ruleset>category/java/multithreading.xml</ruleset>
<!-- 代码风格相关,交由 Checkstyle -->
<!-- <ruleset>category/java/codestyle.xml</ruleset>-->
<!-- 文档相关,交由 Checkstyle -->
<!-- <ruleset>category/java/documentation.xml</ruleset>-->
</rulesets>
</configuration>
<executions>
<execution>
<inherited>true</inherited>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
</plugin>
</plugins>
</build>
2. 配置检测规则
插件配置中的 rulesets 用于定义引入的规则,目前官方 内置了 8 套规则,也提供一些 三方规则。
国内主要使用阿里 P3C, 但目前 P3C 很长时间未更新,提供的 P3C-PMD 版本也比较低,有兼容问题。
3. 执行检测
上述示例将执行检测的时机绑定在编译阶段之前( Maven validation 阶段),编译时即可自动触发检测。
执行 mvn compile
, 输出日志如下:
ruby
PMD 7.14.0 has found 10 violations
PMD Failure: com.song.sample.start.SimulationRequest:29 Rule:LawOfDemeter Priority:3 Access to field `map` on foreign value `this.demoMetric` (degree 1).
PMD Failure: com.song.sample.start.SimulationRequest:30 Rule:SystemPrintln Priority:2 Usage of System.out/err.
PMD Failure: com.song.sample.start.SimulationRequest:31 Rule:UnusedLocalVariable Priority:3 Avoid unused local variables such as 'a'..
IDEA 集成
1. 安装插件
在 IDEA 中安装插件 CheckSyle-IDEA

2. 配置插件 在安装完插件后,在 工具 -> PMD 指定规则集:

使用内置的规则集,需要在选项中选取生效,选择的规则集会作用在违规代码下方,出现警告波浪线。

3. 执行检测
-
手动执行: 右键点击待检测的工程,选择使用的规则集。
这个 PMD 插件有个不友好的地方:不能批量选择规则集,只能全部选择或者一次执行一个。
执行效果如下:
-
实时检测: 在编写代码时,实时提示违规问题
SpotsBug: 字节码级缺陷检测配置
SpotBugs 是 FindBugs(已经不再维护) 的继任者,通过分析 Java 字节码检测运行时潜在缺陷,如空指针异常、资源未关闭、线程安全问题等。它的优势是能发现 "语法正确但逻辑危险" 的代码。
Maven 集成
1. 引入 Maven 插件
在 pom.xml 的 build/plugins 中添加 SpotsBug 插件,配置检查规则文件和执行时机。 推荐在父 pom.xml 中进行配置,以使所有的工程共享一套配置。
xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.9.6.0</version>
<configuration>
<!-- 分析程度 (min, default, max) -->
<effort>max</effort>
<!-- 报告级别 (low, medium, high) -->
<threshold>medium</threshold>
<!-- 生成 XML 报告 -->
<xmlOutput>true</xmlOutput>
<!-- 生成 HTML 报告 -->
<htmlOutput>true</htmlOutput>
<!-- 发现错误时是否使构建失败 -->
<failOnError>true</failOnError>
</configuration>
<executions>
<execution>
<id>spotbugs-check</id>
<inherited>true</inherited>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2. 自定义检测规则
Spotbugs 支持引入额外的检测,请参考官网进行配置
3. 执行检测
上述示例将执行检测的时机绑定在编译阶段之前( Maven validation 阶段),编译时即可自动触发检测。
执行 mvn compile
, 输出日志如下:
vbnet
[INFO] Total bugs: 2
[ERROR] Medium: Dead store to a in com.song.sample.start.SimulationRequest.increment() [com.song.sample.start.SimulationRequest] At SimulationRequest.java:[line 31] DLS_DEAD_LOCAL_STORE
[ERROR] Medium: Primitive field com.song.sample.start.metric.DemoMetric.counter is public and set from inside the class, which makes it too exposed. Consider making it private to limit external accessibility. [com.song.sample.start.SimulationRequest] At SimulationRequest.java:[line 28] PA_PUBLIC_PRIMITIVE_ATTRIBUTE
IDEA 集成
1. 安装插件
在 IDEA 中安装插件 SpotBugs-idea

2. 配置插件 在安装完插件后,在 工具 -> SpotsBugs 配置:

在开发环境中,可以按需要过滤一些问题
3. 执行检测
-
手动检测
-
实时检测
SpotsBug 作用于字节码,没有提供实时的检测功能。
总结
本文介绍的 3 个工具链对于保障代码质量的作用性显而易见,可以在开发阶段发现大部分问题。 本文只是简单介绍这些工具在开发环境的集成方法。 还有其他比较重要的点:
- 各个工具的规则集自定义方法
- 持续集成流水线上配置工具
- 如何沉淀出符合自己团队的规范