Java 代码规范检测与格式化(超详细)

前言

本文主要介绍如何检测 Java 代码规范与格式化 Java 代码,包括 IDEA 插件与 Maven 插件的使用。

代码规范检测插件

IDEA 代码规范检测插件

IDEA 可以使用 CheckStyle-IDEA 插件来检测 Java 代码的规范,它可以保证每位提交者的代码规范都保持一致。值得一提的是,CheckStyle-IDEA 插件只能检测代码的规范,并不能格式化代码。

创建规则文件

在项目中创建 checkstyle.xml 规则文件,例如路径为 config/checkstyle/checkstyle.xml

提示

  • 1、CheckStyle 的版本与 checkstyle.xml 规则文件的内容必须互相匹配,否则会影响代码规范检测插件 CheckStyle-IDEA 的正常运行。
  • 2、Alibaba Nacos 项目的 CheckStyle 规则文件可以从 GitHub 获取,详细的使用说明请看 官方文档
  • 3、Google 的 CheckStyle 规则文件可以从 GitHub 获取。
  • 4、Spring 的 CheckStyle 规则文件可以从 GitHub 获取。
  • Alibaba Nacos 的 CheckStyle 规则文件如下,要求 CheckStyle 的版本至少为 8.30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<?xml version="1.0"?>
<!--
~ Copyright 1999-2018 Alibaba Group Holding Ltd.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">

<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>

<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="150"/>
<property name="ignorePattern"
value="^implements.*|^extends.*|^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="SuppressWarningsFilter"/>

<module name="TreeWalker">
<module name="SuppressionCommentFilter"/>
<module name="SuppressWarningsHolder" />

<!-- Name Checker -->
<module name="OuterTypeFilename"/>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName"/>
<module name="MemberName"/>
<module name="ParameterName"/>
<module name="LambdaParameterName"/>
<module name="CatchParameterName"/>
<module name="LocalVariableName"/>
<module name="ClassTypeParameterName"/>
<module name="MethodTypeParameterName"/>
<module name="InterfaceTypeParameterName"/>
<module name="MethodName"/>
<module name="ConstantName"/>
<module name="StaticVariableName"/>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
<property name="allowedAbbreviations" value="VO"/>
</module>

<!-- Import Checker -->
<module name="AvoidStarImport"/>
<module name="UnusedImports"/>
<module name="RedundantImport"/>

<!-- Block Checker -->
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected|ignore(d)?"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="NeedBraces"/>

<!-- Javadoc Checker -->
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations"
value="Override, Test, Before, After, BeforeClass, AfterClass, Parameterized, Parameters, Bean"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations"
value="Override, Test, Before, After, BeforeClass, AfterClass, Parameterized, Parameters, Bean"/>
<property name="ignoreMethodNamesRegex" value="^set[A-Z].*|^get[A-Z].*|main"/>
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
<module name="InvalidJavadocPosition"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="NonEmptyAtclauseDescription"/>

<!-- Coding Checker -->
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="NoFinalizer"/>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
</module>

<!-- Miscellaneous Checker -->
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="Indentation">
<property name="arrayInitIndent" value="8"/>
<property name="lineWrappingIndentation" value="8"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<module name="ArrayTypeStyle"/>
<module name="UpperEll"/>

<!-- Design Checker -->
<module name="OneTopLevelClass"/>

<!-- Whitespace -->
<module name="NoLineWrap"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
</module>
<module name="EmptyLineSeparator">
<property name="allowMultipleEmptyLines" value="false"/>
<property name="allowMultipleEmptyLinesInsideClassMembers" value="false"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore"/>
<module name="ParenPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>

<!-- Modifier Checker -->
<module name="ModifierOrder"/>

<!-- Annotation Checker -->
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
</module>
</module>

插件安装

  • 1、打开 IDEA 插件市场的界面
  • 2、搜索 CheckStyle-IDEA,点击安装即可

插件配置

导入规则文件
  • 1、打开 CheckStyle 的配置界面(File –> Settings –> Tools –> Checkstyle)
  • 2、选择 Checkstyle 的版本为 8.39,这里的版本号必须与 checkstyle.xml 规则文件的内容相互匹配
  • 3、选择 Scan Scope 扫描范围,若 checkstyle.xml 规则文件支持检测不同类型的文件(.java.xml 等)的代码规范,则可以选择 All sources (including tests)
  • 4、在界面上点击配置文件的添加按钮,配置描述可随便填写(例如 Custom Checks),然后选中项目里的 checkstyle.xml 规则文件,点击下一步和完成
  • 5、在界面上勾选刚刚添加的配置文件

配置编辑器的代码检测规范
  • 1、打开 IDEA 编辑器的配置界面(File –> Settings –> Editor –> Code Style –> Schema –> Import Schema –> CheckStyle Configuration)
  • 2、导入项目中的 checkstyle.xml 规则文件,如下图所示:

配置编辑器的代码实时检测
  • 1、打开 IDEA 编辑器的配置界面(File –> Settings –> Editor –> Inspections)
  • 2、勾选 Checkstyle real-time scan 选项,如下图所示:

配置编辑器提示信息的颜色

在 IDEA 的编辑器内,默认的 CheckStyle 提示样式跟 IDEA 默认的差不多,两者并不好区分。若希望更改 CheckStyle 提示信息的颜色,可以按照以下步骤操作:

  • 1、打开 CheckStyle 的颜色设置窗口(File –> Settings –> Editor –> Inspections –> CheckStyle –> Severity –> Edit severities)
  • 2、更改不同类型的提示信息的颜色

插件使用

  • 1、在 IDEA 界面内打开任意一个 Java 源文件
  • 2、打开 IDEA 界面底部的 CheckStyle 操作面板,点击左侧的 绿色三角形 按钮,这样就可以检查单个 Java 源文件的代码规范

提示

CheckStyle 除了可以检测单个 Java 源文件的代码规范,还支持检测整个 Maven 模块(Check Module)或者整个项目(Check Project)的 Java 代码规范。

Maven 代码规范检测插件

Maven Checkstyle Plugin 插件可用于检测 Java 代码规范,更详细的使用教程可看 官方文档

创建规则文件

在项目中创建 checkstyle.xml 规则文件,例如路径为 config/checkstyle/checkstyle.xml。Checkstyle 8.39 版本可使用的规则文件请参考 这里

提示

  • 1、Maven Checkstyle Plugin 与 Checkstyle 的版本对应关系请看 官方文档
  • 2、若不指定 checkstyle.xml 规则文件的路径,Maven Checkstyle Plugin 默认会从项目的根目录下搜索规则文件。
  • 3、当 Maven Checkstyle Plugin 找不到对应的 checkstyle.xml 规则文件时,默认会使用内置的 sun_checks.xml 或者 google_checks.xml 规则文件。

配置插件

Maven Checkstyle Plugin 3.2.0 默认使用的 Checkstyle 版本是 9.3,由于 Checkstyle 的版本必须与 checkstyle.xml 规则文件的内容互相匹配,因此需要引入 checkstyle 来指定 Checkstyle 的版本号,这样就可以很方便地兼容不同的规则文件了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<properties>
<!-- 指定项目中自定义的 CheckStyle 规则文件 -->
<checkstyle.config.location>config/checkstyle/checkstyle.xml</checkstyle.config.location>
</properties>

<build>
<plugins>
<!-- 代码规范检测插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.39</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<inherited>true</inherited>
<configuration>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

现在切换到项目所在的目录下,就可以使用 mvn checkstyle:check 命令执行代码规范检测了,或者直接执行 mvn compile 命令。Maven Checkstyle Plugin 插件除了会在控制台打印代码规范的检测结果,还会将检测结果输出到项目的 target/checkstyle-result.xml 文件中。

1
2
3
4
5
6
7
8
9
 <executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>

上述的 id 可以随意填写,phase 表示将插件绑定到 Maven Lifecycle 的 phase 中的哪个命令上。指定 phasevalidate 后,当执行 mvn compile 命令时会执行 Maven CheckStyle Plugin 插件。若指定 phaseinstall,则表示绑定到 install 命令上,即当执行 maven install 命令的时候才会执行插件。

生成报告

若希望 Maven Checkstyle Plugin 将代码规范的检测结果生成 HTML 报告,可以参考以下写法,详情可参考 官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<project>
<properties>
<!-- 指定项目中自定义的 CheckStyle 规则文件 -->
<checkstyle.config.location>config/checkstyle/checkstyle.xml</checkstyle.config.location>
</properties>

<build>
<plugins>
<!-- 站点生成插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<!-- 代码规范检测插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.39</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<inherited>true</inherited>
<configuration>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<!-- 生成的报告 -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</project>

现在切换到项目所在的目录下,就可以使用 mvn checkstyle:checkstyle 命令生成代码规范检测结果的 HTML 报告了,或者使用 mvn site 命令(速度较慢,会生成多种类型的站点报告),默认会将检测报告输出到项目的 target/site/checkstyle.html 文件中。

错误级别

checkstyle.xml 规则文件中,有以下的配置内容,表示当扫描到代码有不符合规范的地方时,指定错误级别为 error

1
<property name="severity" value="error"/>

Maven CheckStyle Plugin 有以下的配置内容,表示如果在扫描代码时遇到 error 级别的错误,就直接中断命令的执行;否则,只会生成检测结果文件,但不会中断命令的执行。

1
<failsOnError>true</failsOnError>

CheckStyle 允许的错误级别有 errorwarninginfo,只有指定错误级别为 error,并配置了 failsOnError 才会中断命令的执行。命令中断执行后,会在对应的模块下生成 target/checkstyle-result.xml 检测结果文件。

多模块配置

在企业开发中,一般会把项目的逻辑按照模块拆分出来,这样便于分离和解耦,项目脉络也更加清晰。在这种情况下,要为每个 Maven 模块创建 CheckStyle 任务,也就是需要放到 Parent 的 pom.xml 配置文件里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<project>
<properties>
<!-- 指定项目中自定义的 CheckStyle 规则文件 -->
<checkstyle.config.location>config/checkstyle/checkstyle.xml</checkstyle.config.location>
</properties>

<build>
<!-- 公共的 CheckStyle 插件标准配置,可以在子模块中覆盖,并修改自定义选项 -->
<pluginManagement>
<plugins>
<!-- 站点生成 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<!-- 代码检测 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.39</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<inherited>true</inherited>
<configuration>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>

<!-- 所有子模块都要执行的插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</build>

<reporting>
<plugins>
<!-- 所有子模块都要生成的报告 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</project>

常见问题汇总

无法打印检测结果

首先,执行 Maven 代码规范检测插件的常用命令有两种:

  • mvn checkstyle:check
  • mvn checkstyle:checkstyle

特别注意的是,上述两个命令的执行效果是不一样的:

  • 执行 mvn checkstyle:check 命令,控制台会显示 BUILD FAILURE,会打印详细的代码规范检测结果(警告或错误信息),会将检测结果记录在 target/checkstyle-result.xml 文件里,不会生成 HTML 检测报告
  • 执行 mvn checkstyle:checkstyle 命令,控制台会显示 BUILD SUCCESS,不会打印详细的代码规范检测结果(警告或错误信息),会将检测结果记录在 target/checkstyle-result.xml 文件里,会生成 HTML 检测报告

提示

值得一提的是,mvn checkstyle:check 命令默认会绑定到 validate 阶段(phase),它将在编译代码之前检测代码的规范,详细说明请看 官方文档

无法定位 XRef 资源

若执行 mvn checkstyle:check 命令后,Maven 打印 Unable to locate Source XRef to link 这样的警告信息,可以在 pom.xml 配置文件中加入以下内容来解决:

1
2
3
4
5
6
7
8
9
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.3</version>
</plugin>
</plugins>
</reporting>

代码格式化插件

Maven 代码格式化插件

Spring Java Format 插件集提供了一款格式化 Java 代码的 Maven 插件,默认使用 Spring 的代码规范,插件的运行依赖于 JDK 11+。在项目里配置好代码格式化的 Maven 插件后,可直接运行命令格式化项目代码: mvn spring-javaformat:apply 或者 ./mvnw spring-javaformat:apply

基础配置

在项目中的 pom.xml 配置文件中添加以下内容:

1
2
3
4
5
6
7
8
9
<build>
<plugins>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.35</version>
</plugin>
</plugins>
</build>

现在切换到项目所在的目录下,就可以使用 mvn spring-javaformat:apply 或者 ./mvnw spring-javaformat:apply 命令批量格式化 Java 代码了。

强制格式化

若希望强制所有代码都符合所需的规范,可以使用以下的插件配置内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<build>
<plugins>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.35</version>
<executions>
<execution>
<phase>validate</phase>
<inherited>true</inherited>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

提示

配置强制格式化代码后,如果 Maven 在编译项目时发现有代码的风格不符合 Spring 规范,会自动终止编译,直至所有代码的风格都符合 Spring 规范才会让项目正常编译。

强制检测特定的代码规范

若希望在 Maven 编译之前,强制检测特定的代码规范,则可以在上述配置内容的基础上(如果只是想让 Maven 插件检测特定的代码规范,而不需要执行代码格式化,则可以不引入上述的配置内容),额外引入 CheckStyle 的 Maven 插件,并包含 spring-javaformat-checkstyle 依赖,然后指定 CheckStyle 的规则文件即可,具体的配置内容如下:

特别注意

  • 1、配置了强制检测特定的代码规范之后,如果 Maven 在编译项目时发现有代码的风格不符合特定的代码规范,会自动终止编译,直至所有代码的风格都符合特定的代码规范才会让项目正常编译。
  • 2、在下述的 Maven 配置内容中,checkstyle 依赖的版本必须与指定的 checkstyle.xml 规则文件的内容互相匹配,否则会影响 Maven 代码规范检测插件的运行。
  • 3、下述的 Maven 配置内容,只是让 Maven 插件在编译代码之前强制检测特定的代码规范,而不是让 Maven 插件按照 CheckStyle 的规则文件来格式化代码,也就是说 Maven 插件最终还是会使用 Spring 的代码规范来进行格式化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<properties>
<!-- 指定项目中自定义的 CheckStyle 规则文件 -->
<checkstyle.config.location>config/checkstyle/checkstyle.xml</checkstyle.config.location>
</properties>

<build>
<plugins>
<!-- 代码格式化插件 -->
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.35</version>
<executions>
<execution>
<phase>validate</phase>
<inherited>true</inherited>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>

<!-- 代码规范检测插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.39</version>
</dependency>
<dependency>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-checkstyle</artifactId>
<version>0.0.35</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<inherited>true</inherited>
<configuration>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

现在切换到项目所在的目录下,就可以使用 mvn checkstyle:check 命令执行代码规范检测了,或者直接执行 mvn compile 命令。

配合 CheckStyle-IDEA 插件使用

在 IDEA 里配置 CheckStyle-IDEA 代码规范检测插件,让 CheckStyle 默认使用 Spring 的代码规范来检测。

创建规则文件

在项目中创建 checkstyle.xml 规则文件,并写入如下内容:

1
2
3
4
5
6
7
8
<?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">
<module name="io.spring.javaformat.checkstyle.SpringChecks" />
</module>
配置 CheckStyle-IDEA 插件
  • 1、打开 CheckStyle 的配置界面(File –> Settings –> Tools –> Checkstyle)
  • 2、选择 Checkstyle 的版本,例如 8.39
  • 3、在界面上点击配置文件的添加按钮,配置描述可随便填写(例如 Custom Checks),然后选中项目里的 checkstyle.xml 规则文件,点击下一步和完成
  • 4、在界面上勾选刚刚添加的配置文件
  • 5、下载 spring-javaformat-checkstyle-0.0.35.jarspring-javaformat-config-0.0.35.jar 文件,并将它们添加到 Third-Party Checks

IDEA 代码格式化插件

IDEA 内置的格式化工具

IDEA 可以使用内置工具格式化 Java 代码,格式化代码的快捷键是 CTRL + ALT + L

代码风格配置

若希望让 IDEA 默认使用特定的代码风格来格式化代码,可以参考以下配置步骤:

  • 1、从 Nacos GitHub 下载 IDEA 的代码风格 XML 文件,这里使用 Alibaba Nacos 的代码风格(附上官方教程),也可以选择 Google GitHub 的代码风格
  • 2、打开 IDEA 编辑器的配置界面(File –> Settings –> Editor –> Code Style –> Schema –> Import Schema –> IntelliJ IDEA code style XML)
  • 3、导入 IDEA 的代码风格 XML 文件

单个格式化

打开任意一个 Java 源文件,使用快捷键 CTRL + ALT + L 即可按照特定的代码风格来格式化单个源文件了。

批量格式化

IDEA 支持代码批量格式化的功能,这样就不用手动使用快捷键格式化每个 Java 源文件了,而且基于上面 IDEA 代码格式化风格的配置,可以让 IDEA 按照特定的代码风格批量格式化,具体的操作步骤如下:

  • 打开 IDEA 批量格式化代码的界面(右键项目 / 模块 –> Reformat Code)
  • 配置批量格式化的参数(如下图所示)
  • 最后点击 Run 按钮

Spring Java Format 格式化插件

Spring Java Format 提供了一款可以格式化 Java 代码的 IDEA 插件,可以从 Maven Central 下载,详细的使用教程请看官方文档

最佳实践

在企业项目开发中,推荐使用以下的技术组合来约束项目的代码风格。

推荐方案一

推荐方案二

资源文件

CheckStyle 规则文件

IDEA 代码风格 XML 文件

参考资料