IntelliJ IDEA 代码格式化深度实战:从个人快捷键到团队规范治理

代码格式化看起来是一个“小问题”,但在真实团队里,它往往会变成代码评审噪音、无意义 diff、多人协作冲突、CI 失败、甚至规范争论的来源。

这篇文章不只讲 Ctrl + Alt + L / ⌘ + ⌥ + L 怎么按,而是从 IntelliJ IDEA 本地格式化、EditorConfig 跨 IDE
统一、Maven/Gradle 自动化格式化、CI 强制校验、团队迁移策略、常见坑排查
这几层,把 IDEA 代码格式化讲透。

序言:格式化不是审美问题,而是工程治理问题

很多团队的代码规范一开始都很朴素:

“大家提交代码前记得格式化一下。”

听起来很合理,但实际落地后通常会变成这样:

  • A 同学用 IDEA 默认格式;
  • B 同学从 Eclipse 迁移过来,习惯另一套 import 顺序;
  • C 同学装了 google-java-format 插件;
  • D 同学保存时自动格式化整个文件;
  • E 同学没动逻辑,只保存了一下,结果一个 PR 里 500 行 diff;
  • Review 的人看了半天,发现真正业务改动只有 20 行。

这就是为什么代码格式化必须工程化。

格式化不应该靠“个人自觉”,而应该靠一套明确的链路:

flowchart LR
    A[IDEA 本地开发体验] --> B[项目级 Code Style]
    B --> C[.editorconfig 跨 IDE 基线]
    C --> D[Spotless / Checkstyle 构建约束]
    D --> E[Git Hook 可选前置检查]
    E --> F[CI 强制校验]
    F --> G[PR Review 专注业务逻辑]

一句话总结:

IDEA 负责让开发者写得舒服,.editorconfig 负责让不同 IDE 不跑偏,Spotless / Checkstyle / CI 负责让团队规范真正落地。

一、IDEA 代码格式化能力全景

IntelliJ IDEA 的代码格式化不是一个单点功能,而是一组相关能力:

能力 入口 作用 建议
Reformat Code Code -> Reformat Code 按当前 Code Style 重新排版 日常高频使用
Optimize Imports Code -> Optimize Imports 删除无用 import、整理 import 顺序 建议开启,但要统一规则
Rearrange Code Code -> Rearrange Code 或 Reformat 弹窗 按 Arrangement 规则重排成员顺序 谨慎使用,不建议默认全量开启
Code Cleanup Code -> Code Cleanup 根据 Inspection Profile 自动修复部分问题 不建议一上来全量自动化
Actions on Save Settings -> Tools -> Actions on Save 保存时自动格式化、优化 import 建议只作用于 Changed lines
Commit Checks Commit 窗口设置 提交前格式化、优化 import、cleanup 建议团队统一启用
Command-line Formatter idea.sh format / format.sh 用 IDEA 格式化器批量处理文件 适合一次性治理老项目

1.1 最常用快捷键

操作 macOS Windows / Linux
Reformat Code ⌘ + ⌥ + L Ctrl + Alt + L
Reformat File 弹窗 ⌘ + ⌥ + ⇧ + L Ctrl + Alt + Shift + L
Optimize Imports ⌃ + ⌥ + O Ctrl + Alt + O
Auto-indent Lines ⌃ + ⌥ + I Ctrl + Alt + I
打开 Settings ⌘ + , Ctrl + Alt + S

日常最常用的是:

1
2
macOS:           ⌘ + ⌥ + L
Windows/Linux: Ctrl + Alt + L

如果你只选中了一段代码,IDEA 只格式化选中区域;如果没有选中代码,IDEA 会格式化当前文件。

1.2 Reformat File 弹窗里几个重要选项

打开当前文件后按:

1
2
macOS:           ⌘ + ⌥ + ⇧ + L
Windows/Linux: Ctrl + Alt + Shift + L

会弹出 Reformat File 对话框,常见选项如下:

选项 作用 建议
Optimize imports 优化 import 建议开启
Rearrange entries 按 Arrangement 重排类成员 老项目慎用
Code cleanup 执行代码清理检查 慎用,建议先手动试跑
Do not keep line breaks 不保留原换行,完全按格式化规则重排 不建议默认开启

我的建议是:

日常保存或提交时,只做 Reformat Code + Optimize Imports;Rearrange 和 Code Cleanup 不要默认全项目打开,先小范围试点。

原因很简单:格式化只改变“样子”,但 Rearrange 和 Code Cleanup 可能改变代码组织结构,PR diff 会变大。格式化是扫地,Rearrange
是搬家具,别每次保存都搬一遍家具。

二、Code Style Scheme:IDEA 格式化的核心配置

IDEA 的格式化规则来自两类来源:

  1. 当前项目或 IDE 级别的 Code Style Scheme;
  2. 项目中的 .editorconfig 文件。

.editorconfig 没定义某个规则时,IDEA 会回退使用项目 Code Style 设置。

2.1 Project Scheme 与 IDE Scheme 的区别

进入:

1
2
3
Settings / Preferences
-> Editor
-> Code Style

你会看到 Scheme:

Scheme 类型 保存位置 是否适合团队共享 说明
IDE-level Scheme 当前用户 IDEA 配置目录 不适合 只对你本机生效
Project Scheme 当前项目 .idea/codeStyles 适合 可以提交到 Git
.editorconfig 项目根目录或子目录 最适合跨 IDE VS Code、Eclipse、IDEA 都可识别部分规则

团队项目建议:

1
2
优先级建议:
.editorconfig > .idea/codeStyles/Project.xml > 个人 IDE 配置

也就是说,真正应该进 Git 的通常是:

1
2
3
.editorconfig
.idea/codeStyles/Project.xml
.idea/codeStyles/codeStyleConfig.xml

不应该提交:

1
2
3
4
.idea/workspace.xml
.idea/tasks.xml
.idea/shelf/
.idea/dataSources.local.xml

2.2 Java Code Style 的核心配置项

进入:

1
2
3
4
Settings / Preferences
-> Editor
-> Code Style
-> Java

Java 下几个最重要的 Tab:

Tab 重点配置 说明
Tabs and Indents 缩进、Tab、Continuation indent 控制基础缩进
Spaces 操作符、括号、逗号前后的空格 控制细节空格
Wrapping and Braces 换行、链式调用、方法参数、builder 最容易引发争议
Blank Lines 类、方法、字段之间空行 控制代码呼吸感
JavaDoc JavaDoc 换行和对齐 公共 API 项目要关注
Imports import 顺序、通配符导入 团队必须统一
Arrangement 类成员排序 慎用,建议团队明确后再开
Code Generation getter/setter、final、注释模板 影响生成代码风格

2.3 推荐的一套 Java / Spring Boot 基线配置

下面这套配置适合大多数 Java 后端团队,尤其是 Spring Boot 项目。

缩进

配置项 推荐值
Use tab character false
Tab size 4
Indent 4
Continuation indent 8
Label indent 0
Keep indents on empty lines false

为什么 continuation indent 用 8?因为方法参数、链式调用、lambda 这些换行后,视觉层级需要比普通缩进更明显。

右边距

配置项 推荐值
Hard wrap at 120 或 140
Visual guides 120,140

如果团队业务代码里 DTO、Builder、Lambda、Stream 很多,120 有时会频繁换行,140 会更实用。

我的建议:

  • 开源库、公共组件、基础框架:偏向 100120
  • 公司业务系统、Spring Boot 单体/微服务:偏向 120140
  • 如果引入 google-java-format:接受它的风格,不再和它讨价还价。

Import 配置

路径:

1
2
3
4
5
Settings / Preferences
-> Editor
-> Code Style
-> Java
-> Imports

推荐:

配置项 推荐值
Use single class import true
Class count to use import with * 999 或 9999
Names count to use static import with * 999 或 9999
Packages to Use Import with * 清空

这样可以避免出现:

1
import java.util.*;

而是保持显式 import:

1
2
3
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

显式 import 的好处是:

  • diff 更清晰;
  • 依赖来源更明确;
  • 避免不同包下同名类冲突;
  • Checkstyle / Spotless 更容易统一。

Import Layout 推荐

可以采用:

1
2
3
4
5
6
import all other imports
<blank line>
import javax.*
import java.*
<blank line>
import static all other imports

或者更贴近国内 Java 后端习惯:

1
2
3
4
5
6
7
8
9
10
import java.*
import javax.*
import jakarta.*
<blank line>
import org.*
import com.*
<blank line>
import all other imports
<blank line>
import static all other imports

关键不在于哪一种绝对正确,而在于团队只保留一种。import 顺序这东西,吵赢了也不涨工资,统一就行。

三、Actions on Save:保存时自动格式化

进入:

1
2
3
Settings / Preferences
-> Tools
-> Actions on Save

建议开启:

1
2
[x] Reformat code
[x] Optimize imports

但是要注意作用范围。

3.1 Whole file 还是 Changed lines?

IDEA 的 Actions on Save 可以选择:

选项 含义 建议
Whole file 保存时格式化整个文件 新项目可以,老项目慎用
Changed lines 只格式化本地修改过的行 老项目强烈推荐

老项目一定优先选择:

1
Changed lines

原因是老项目通常历史格式不统一,如果保存时格式化整个文件,很容易制造巨大 diff。

3.2 推荐配置

1
2
3
4
5
6
Tools -> Actions on Save
[x] Reformat code
Scope: Changed lines
File types: Java, XML, YAML, JSON, Markdown 根据项目选择
[x] Optimize imports
File types: Java

不建议一开始就开启:

1
2
[ ] Rearrange code
[ ] Run code cleanup

特别是 Run code cleanup,它可能自动套用 inspection quick-fix,比如删除看似无用的代码、替换写法、调整声明。这个功能很好,但不要让它在没有团队共识时“偷偷改代码”。

四、Commit Checks:提交前兜底

在 Commit 工具窗口:

1
2
3
Commit Tool Window
-> Show Commit Options
-> Commit Checks

建议开启:

1
2
[x] Reformat code
[x] Optimize imports

可选开启:

1
[x] Cleanup

但 Cleanup 仍然建议谨慎。

4.1 为什么提交前检查比保存时更重要?

保存时格式化属于个人开发习惯;提交前检查属于团队协作边界。

保存时你可以忘,提交时不能漏。

建议团队约定:

1
2
3
本地保存:Changed lines 自动格式化
提交前:Reformat code + Optimize imports
CI:Spotless / Checkstyle 强制校验

这三层刚好形成闭环。

五、.editorconfig:跨 IDE 的最低规范

.editorconfig 是一套跨编辑器/IDE 的配置文件约定,目标是让团队成员即使使用不同工具,也能保持基础代码风格一致。

它适合放在项目根目录,提交到 Git。

5.1 推荐的基础 .editorconfig

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
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

[*.java]
indent_style = space
indent_size = 4
continuation_indent_size = 8
max_line_length = 140

[*.{xml,properties}]
indent_style = space
indent_size = 4

[*.{yml,yaml,json,js,ts,tsx,jsx,css,scss,html}]
indent_style = space
indent_size = 2

[*.md]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false

为什么 Markdown 里 trim_trailing_whitespace = false

因为 Markdown 中两个尾随空格有时表示强制换行。如果统一删除,可能会破坏文章排版。

5.2 IDEA 中导出 .editorconfig

IDEA 支持从当前 Code Style Scheme 导出 .editorconfig

1
2
3
4
5
6
Settings / Preferences
-> Editor
-> Code Style
-> Scheme Actions
-> Export
-> EditorConfig File

这比手写大量 ij_java_xxx 配置更靠谱。

推荐流程:

flowchart TD
    A[在 IDEA 中调整 Java Code Style] --> B[确认 Reformat 效果]
    B --> C[Export as .editorconfig]
    C --> D[提交 .editorconfig]
    D --> E[团队成员拉取后自动生效]
    E --> F[Spotless / Checkstyle 在 CI 校验]

5.3 .editorconfig 与 IDEA Code Style 谁优先?

在 IDEA 中,.editorconfig 会覆盖对应范围内的 Code Style 设置;如果某个规则没有在 .editorconfig 中定义,则回退使用项目
Code Style。

所以建议:

1
2
3
.editorconfig:放跨 IDE、跨平台、通用规则
.idea/codeStyles:放 IDEA 专属、细粒度规则
Spotless/Checkstyle:放构建和 CI 强约束规则

不要试图把所有东西都塞进 .editorconfig。它适合做“地基”,不是把整栋楼都塞进地基里。

六、google-java-format:要么接受,要么别用

google-java-format 是 Google Java Style 的自动格式化工具。它的最大特点是:

算法几乎不可配置,目标是让所有代码统一成一种格式。

这既是优点,也是缺点。

6.1 适合使用 google-java-format 的场景

场景 是否推荐
新项目,团队不想争论格式 推荐
开源项目,希望贡献者风格统一 推荐
团队能接受 2 空格或 AOSP 4 空格风格 推荐
业务老项目,已有大量自定义风格 谨慎
团队非常在意链式调用、Builder、Lambda 换行 谨慎
想细调每一个换行规则 不推荐

6.2 IDEA 安装 google-java-format 插件

路径:

1
2
3
4
Settings / Preferences
-> Plugins
-> Marketplace
-> 搜索 google-java-format

安装后还要启用:

1
2
3
Settings / Preferences
-> google-java-format Settings
-> Enable google-java-format

注意:插件启用后,会替换 IDEA 默认的 Reformat CodeOptimize Imports 行为。

6.3 JDK 16+ / JDK 21 下的 VM Options

如果 google-java-format 插件因为 JDK 模块封装问题不可用,需要在:

1
2
Help
-> Edit Custom VM Options

加入类似配置:

1
2
3
4
5
6
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

然后重启 IDEA。

6.4 google-java-format 的现实提醒

如果你不喜欢它的换行风格,不要硬上。

尤其是下面这种代码:

1
UserDTO result = userService.queryUser(userId, tenantId, includeDeleted, includeRoles, includePermissions);

可能会被格式化成你不喜欢的样子。google-java-format 的思想是“统一大于个性化”,不是“给你一个可调到满意的格式器”。

所以团队要先做选择:

1
2
想要极致统一:google-java-format / Palantir Java Format / Spotless
想要符合团队审美:IDEA Built-in Formatter + .editorconfig + Checkstyle

七、Spotless:把格式化放进 Maven / Gradle

IDEA 只能管开发者本地,管不了 CI,也管不了没装同样插件的人。

所以工程化项目一定要把格式化放进构建工具。

Spotless 的定位是:

1
格式化工具聚合器 + 构建期格式校验器

它可以接入:

  • google-java-format;
  • Eclipse JDT Formatter;
  • Palantir Java Format;
  • Prettier;
  • ktlint;
  • license header;
  • import order;
  • trim trailing whitespace;
  • end with newline。

7.1 Maven 项目接入 Spotless

父 POM 中加入:

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

<properties>
<spotless.maven.plugin.version>3.6.0</spotless.maven.plugin.version>
<google.java.format.version>1.35.0</google.java.format.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.maven.plugin.version}</version>
<configuration>
<java>
<target>
<include>src/main/java/**/*.java</include>
<include>src/test/java/**/*.java</include>
</target>

<googleJavaFormat>
<version>${google.java.format.version}</version>
<!-- Google: 2 空格;AOSP: 4 空格。Java 后端团队通常更能接受 AOSP。 -->
<style>AOSP</style>
</googleJavaFormat>

<removeUnusedImports/>
<formatAnnotations/>
</java>

<formats>
<format>
<includes>
<include>*.md</include>
<include>.gitignore</include>
<include>src/**/*.yml</include>
<include>src/**/*.yaml</include>
<include>src/**/*.properties</include>
</includes>
<trimTrailingWhitespace/>
<endWithNewline/>
</format>
</formats>
</configuration>
<executions>
<execution>
<id>spotless-check</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

常用命令:

1
2
3
4
5
6
7
8
# 检查格式,不修改文件。适合 CI。
mvn spotless:check

# 自动修复格式。适合本地开发。
mvn spotless:apply

# 跳过测试,只检查格式。
mvn -DskipTests spotless:check

7.2 Gradle 项目接入 Spotless

build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
plugins {
id 'java'
id 'com.diffplug.spotless' version '8.6.0'
}

spotless {
java {
target 'src/main/java/**/*.java', 'src/test/java/**/*.java'

googleJavaFormat('1.35.0').aosp()
removeUnusedImports()
formatAnnotations()

trimTrailingWhitespace()
endWithNewline()
}

format 'misc', {
target '*.md', '.gitignore', 'src/**/*.yml', 'src/**/*.yaml', 'src/**/*.properties'
trimTrailingWhitespace()
endWithNewline()
}
}

常用命令:

1
2
3
4
5
# 检查格式
./gradlew spotlessCheck

# 自动修复格式
./gradlew spotlessApply

7.3 Spotless 与 IDEA 的关系

不要把 IDEA 和 Spotless 当成两个互相替代的东西。

正确关系是:

1
2
IDEA:写代码时实时舒服
Spotless:提交前和 CI 兜底

如果使用 google-java-format,最好让 IDEA 插件和 Spotless 使用同一个版本:

1
2
IDEA google-java-format plugin
Spotless googleJavaFormat('1.35.0')

否则就可能出现:

1
2
本地 IDEA 格式化通过
mvn spotless:check 失败

这类问题最烦,因为它不是代码问题,是工具链内耗。

八、Checkstyle:格式化之外的规范检查

Spotless 主要解决“怎么自动格式化”;Checkstyle 主要解决“代码是否符合规范”。

Checkstyle 可以检查:

  • 是否存在通配符 import;
  • 行长度是否超限;
  • 类名、方法名、常量名是否符合命名规范;
  • 是否缺少 JavaDoc;
  • 是否有多余空格;
  • 方法复杂度、参数数量、嵌套深度等。

8.1 Maven 接入 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
38

<properties>
<maven.checkstyle.plugin.version>3.6.0</maven.checkstyle.plugin.version>
<checkstyle.version>13.5.0</checkstyle.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven.checkstyle.plugin.version}</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>${checkstyle.version}</version>
</dependency>
</dependencies>
<configuration>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<executions>
<execution>
<id>checkstyle</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

8.2 一个基础 checkstyle.xml

文件位置:

1
config/checkstyle/checkstyle.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
<?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="charset" value="UTF-8"/>

<module name="TreeWalker">
<!-- 禁止通配符 import -->
<module name="AvoidStarImport"/>

<!-- 命名规范 -->
<module name="TypeName"/>
<module name="MethodName"/>
<module name="MemberName"/>
<module name="ParameterName"/>
<module name="LocalVariableName"/>
<module name="ConstantName"/>

<!-- 基础代码风格 -->
<module name="NeedBraces"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
</module>

<!-- 行长度:忽略 import、package、URL -->
<module name="LineLength">
<property name="max" value="140"/>
<property name="ignorePattern" value="^(package|import) .*|https?://.*"/>
</module>

<!-- 文件末尾必须有换行 -->
<module name="NewlineAtEndOfFile"/>
</module>

8.3 Spotless 与 Checkstyle 的分工

工具 负责什么 是否自动修复
IDEA Formatter 本地开发时格式化
EditorConfig 跨 IDE 基础风格 部分 IDE 支持自动应用
Spotless 构建阶段格式化/检查
Checkstyle 代码规范静态检查 大多数不自动修复
PMD / SpotBugs 潜在缺陷和坏味道

建议顺序:

1
2
3
先上 EditorConfig
再上 Spotless
最后再逐步收紧 Checkstyle

千万别第一天就把 Checkstyle 规则拉满。这样很容易导致团队第一反应不是“规范真好”,而是“谁把构建搞挂了”。

九、前端、配置文件与 Prettier

如果你的 Spring Boot 项目里也包含前端,比如:

1
2
3
4
src/main/frontend
src/main/resources/static
web
ui

那么不要用 IDEA Java Formatter 去格式化 JS / TS / Vue / React 文件。

前端文件建议交给 Prettier。

9.1 安装 Prettier

1
npm install --save-dev prettier

.prettierrc 示例:

1
2
3
4
5
6
7
8
9
10
11
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
}

package.json

1
2
3
4
5
6
{
"scripts": {
"format": "prettier --write .",
"format:check": "prettier --check ."
}
}

9.2 IDEA 中使用 Prettier

路径:

1
2
3
4
Settings / Preferences
-> Languages & Frameworks
-> JavaScript
-> Prettier

建议:

1
2
[x] On save
[x] On Reformat Code action

但要注意:

同一种文件类型只交给一个格式化器。

例如:

1
2
3
Java -> IDEA Formatter / google-java-format / Spotless
JS/TS/Vue/React -> Prettier
XML/YAML/Properties -> IDEA Formatter + EditorConfig

不要让 IDEA Formatter 和 Prettier 同时抢同一个文件,否则保存一次像两个人同时开车,一个往左一个往右。

十、命令行格式化:批量治理老项目

IDEA 提供命令行格式化能力,可以用当前 Code Style 批量格式化指定文件。

macOS 默认脚本位置类似:

1
/Applications/IntelliJ\ IDEA.app/Contents/bin/format.sh

示例:

1
2
3
4
5
6
7
# 使用默认 Code Style 格式化两个文件
/Applications/IntelliJ\ IDEA.app/Contents/bin/format.sh -allowDefaults \
src/main/java/com/example/UserService.java \
src/main/java/com/example/UserController.java

# 递归格式化整个 src 目录
/Applications/IntelliJ\ IDEA.app/Contents/bin/format.sh -allowDefaults -r src

如果你已经配置了 IDEA 命令行启动器,也可以用:

1
idea.sh format -allowDefaults -r src

不过老项目批量格式化要非常谨慎。

推荐做法:

1
2
3
4
5
1. 新建单独分支:chore/reformat-code
2. 只做格式化,不改业务逻辑
3. 一次性提交格式化结果
4. 后续所有业务分支基于格式化后的主干 rebase
5. CI 开启格式化检查

不要把“大格式化”和“业务需求”混在一个 PR 里。那不是代码评审,那是大家一起找茬版连连看。

十一、Git Hook:提交前本地拦截

CI 是最后防线,但等 CI 失败再回来改,会打断节奏。

可以加一个本地 pre-commit hook。

11.1 Maven 版本

.git/hooks/pre-commit

1
2
3
4
5
6
7
8
#!/usr/bin/env bash
set -e

echo "[pre-commit] running spotless check..."
mvn -q -DskipTests spotless:check

echo "[pre-commit] running checkstyle..."
mvn -q -DskipTests checkstyle:check

赋权:

1
chmod +x .git/hooks/pre-commit

11.2 Gradle 版本

1
2
3
4
5
#!/usr/bin/env bash
set -e

echo "[pre-commit] running spotlessCheck..."
./gradlew spotlessCheck

11.3 团队共享 Hook 的方式

Git 默认不会提交 .git/hooks 目录。

推荐方式:

1
scripts/git-hooks/pre-commit

然后提供安装脚本:

1
2
3
4
5
6
7
8
#!/usr/bin/env bash
set -e

mkdir -p .git/hooks
cp scripts/git-hooks/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

echo "Git hooks installed."

也可以使用 huskylefthookpre-commit 等工具统一管理。

注意:Git Hook 是本地体验优化,不是安全边界。真正的强约束必须放在 CI。

十二、CI 集成:格式不对就不让合并

12.1 GitHub Actions 示例

.github/workflows/code-style.yml

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
name: Code Style

on:
pull_request:
push:
branches:
- main
- master
- develop

jobs:
code-style:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven

- name: Spotless check
run: mvn -B -DskipTests spotless:check

- name: Checkstyle
run: mvn -B -DskipTests checkstyle:check

12.2 GitLab CI 示例

.gitlab-ci.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
stages:
- verify

code-style:
stage: verify
image: maven:3.9.9-eclipse-temurin-21
script:
- mvn -B -DskipTests spotless:check
- mvn -B -DskipTests checkstyle:check
only:
- merge_requests
- main
- master
- develop

12.3 CI 中是否应该自动修复?

一般不建议 CI 自动提交格式化结果。

推荐:

1
2
本地执行 spotless:apply 修复
CI 执行 spotless:check 校验

CI 自动改代码容易引入权限、分支保护、循环触发、责任归属等问题。CI 应该像裁判,不应该亲自下场踢球。

十三、Spring Boot 多模块项目实战方案

假设项目结构如下:

1
2
3
4
5
6
7
8
9
10
11
finance-system/
├── pom.xml
├── .editorconfig
├── config/
│ └── checkstyle/
│ └── checkstyle.xml
├── finance-api/
├── finance-domain/
├── finance-application/
├── finance-infrastructure/
└── finance-bootstrap/

13.1 根目录放 .editorconfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

[*.java]
indent_size = 4
continuation_indent_size = 8
max_line_length = 140

[*.{yml,yaml,json,md}]
indent_size = 2

[*.md]
trim_trailing_whitespace = false

13.2 父 POM 统一插件

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

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.maven.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven.checkstyle.plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<configuration>
<java>
<target>
<include>**/src/main/java/**/*.java</include>
<include>**/src/test/java/**/*.java</include>
</target>
<googleJavaFormat>
<version>${google.java.format.version}</version>
<style>AOSP</style>
</googleJavaFormat>
<removeUnusedImports/>
<formatAnnotations/>
</java>
<formats>
<format>
<includes>
<include>*.md</include>
<include>**/*.yml</include>
<include>**/*.yaml</include>
<include>**/*.properties</include>
</includes>
<excludes>
<exclude>**/target/**</exclude>
<exclude>**/build/**</exclude>
</excludes>
<trimTrailingWhitespace/>
<endWithNewline/>
</format>
</formats>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>${checkstyle.version}</version>
</dependency>
</dependencies>
<configuration>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
</plugin>
</plugins>
</build>

13.3 本地开发命令

1
2
3
4
5
6
7
8
9
10
11
# 自动修复格式
mvn spotless:apply

# 检查格式
mvn spotless:check

# 检查代码规范
mvn checkstyle:check

# 完整校验
mvn clean verify

13.4 IDEA 配置

团队成员拉项目后建议统一设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. Settings -> Editor -> Code Style
确认 Enable EditorConfig support 开启

2. Settings -> Tools -> Actions on Save
开启 Reformat code
开启 Optimize imports
Reformat 范围选择 Changed lines

3. Settings -> Editor -> Code Style -> Java -> Imports
Use single class import = true
Class count to use import with '*' = 999
Names count to use static import with '*' = 999
Packages to Use Import with '*' 清空

4. Commit Tool Window -> Commit Checks
开启 Reformat code
开启 Optimize imports

13.5 推荐团队约定

CONTRIBUTING.md 里写清楚:

1
2
3
4
5
6
7
8
9
10
## Code Style

本项目使用 `.editorconfig` 统一基础格式,使用 Spotless 做格式化检查,使用 Checkstyle 做代码规范检查。

本地开发前建议执行:

```bash
mvn spotless:apply
mvn spotless:check
mvn checkstyle:check

提交 PR 前必须保证:

1
mvn clean verify

请不要在业务 PR 中混入大规模格式化修改。如需全量格式化,请单独提交 chore: reformat code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
```

## 十四、老项目迁移策略:不要一口吃成胖子

老项目最大的问题不是“没有规范”,而是“历史代码已经不统一”。

如果你一上来全项目格式化,会产生巨大 diff,影响所有正在开发的分支。

推荐分四步走。

### 14.1 第一阶段:只加配置,不强制失败

提交:

```text
.editorconfig
.idea/codeStyles/Project.xml
config/checkstyle/checkstyle.xml
pom.xml 中的 Spotless/Checkstyle 配置

但 CI 暂时只提示,不阻塞合并。

14.2 第二阶段:只格式化新增和修改代码

IDEA Actions on Save 设置:

1
Changed lines

Spotless 可以先不绑定 verify,让开发者本地手动执行。

14.3 第三阶段:单独做一次全量格式化

新建分支:

1
2
3
4
git checkout -b chore/reformat-code
mvn spotless:apply
git add .
git commit -m "chore: reformat code"

这个 PR 只做格式化,不改业务逻辑。

合并后通知所有业务分支 rebase。

14.4 第四阶段:CI 强制校验

最后再打开:

1
2
mvn spotless:check
mvn checkstyle:check

并将其纳入:

1
mvn clean verify

这样团队阻力最小。

十五、常见坑排查

15.1 我按了格式化,代码没变化

排查顺序:

  1. 当前文件是否被 .editorconfig 覆盖?
  2. 当前文件类型是否被 IDEA 识别?
  3. Settings -> Editor -> Code Style -> Formatter -> Do not format 是否排除了该文件?
  4. 是否启用了 @formatter:off
  5. 是否安装并启用了 google-java-format,导致 IDEA 内置规则不生效?
  6. 是否是生成代码目录,比如 target/generated-sources

15.2 保存时没有自动格式化

排查:

1
Settings -> Tools -> Actions on Save

确认:

  • Reformat code 已勾选;
  • 文件类型包含 Java;
  • 范围不是误配置;
  • 如果选择 Changed lines,当前文件必须在 Git 下有本地修改;
  • 当前文件没有被 Do not format 排除。

15.3 IDEA 格式化通过,但 CI 的 Spotless 失败

常见原因:

原因 解决
IDEA 使用内置 Formatter,CI 使用 google-java-format 统一格式器
IDEA google-java-format 插件版本与 Spotless 中版本不同 锁定同一版本
IDEA import 顺序和 Spotless importOrder 不一致 统一 import 规则
.editorconfig 与 Spotless 规则不一致 以 Spotless 为 CI 真相
CI JDK 版本过低,不支持当前 Java 语法 统一 JDK 版本

15.4 import 总是被改来改去

重点检查:

1
Settings -> Editor -> Code Style -> Java -> Imports

建议:

1
2
3
4
Use single class import = true
Class count to use import with '*' = 999
Names count to use static import with '*' = 999
Packages to Use Import with '*' = empty

并检查 Spotless / Checkstyle 是否也禁止 wildcard import。

15.5 换行符反复变化

.editorconfig 加:

1
2
[*]
end_of_line = lf

同时建议加 .gitattributes

1
2
3
* text=auto eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf

然后执行一次:

1
2
git add --renormalize .
git commit -m "chore: normalize line endings"

15.6 Lombok / MapStruct / Protobuf 生成代码要不要格式化?

不要。

这些目录建议排除:

1
2
3
**/target/generated-sources/**
**/build/generated/**
**/generated/**

Spotless 中也要排除:

1
2
3
4
5
<excludes>
<exclude>**/target/**</exclude>
<exclude>**/build/**</exclude>
<exclude>**/generated/**</exclude>
</excludes>

生成代码的原则是:

源头生成器负责它的风格,业务项目不要手动改生成产物。

15.7 @formatter:off 怎么用?

IDEA 支持用注释关闭局部格式化。

先开启:

1
2
Settings -> Editor -> Code Style -> Formatter
[x] Turn formatter on/off with markers in code comments

代码中使用:

1
2
3
4
5
6
7
8
9
10
11
// @formatter:off
private static final String SQL = """
SELECT
t.id,
t.name,
t.amount
FROM finance_bill t
WHERE t.deleted = 0
ORDER BY t.create_time DESC
""";
// @formatter:on

适合场景:

  • 多行 SQL;
  • ASCII 表格;
  • 特殊对齐的数据结构;
  • DSL 配置。

不要滥用。否则格式化器就变成摆设了。

十六、不同方案怎么选?

16.1 方案对比

方案 优点 缺点 适合场景
IDEA Built-in Formatter 灵活、可调、适合团队审美 不同 IDE 难完全统一 公司业务项目
.editorconfig 跨 IDE、轻量、可进 Git 无法覆盖所有 Java 细节 所有项目必备
google-java-format 极致统一、争议少 几乎不可配置,换行风格可能不喜欢 新项目、开源项目
Spotless 可集成 CI,可自动修复 需要维护构建配置 中大型团队必备
Checkstyle 规范检查强 规则过多容易打击开发体验 稳定团队逐步引入
Prettier 前端格式化事实标准 不管 Java 前端/全栈项目

16.2 我的推荐组合

Java 后端业务项目

1
2
3
4
5
IDEA Built-in Formatter
+ .editorconfig
+ Spotless
+ Checkstyle 基础规则
+ CI spotless:check / checkstyle:check

新 Java 项目,想减少争论

1
2
3
4
google-java-format
+ IDEA google-java-format plugin
+ Spotless googleJavaFormat 同版本
+ CI spotless:check

老项目渐进治理

1
2
3
4
5
.editorconfig
+ IDEA Actions on Save Changed lines
+ Spotless 手动 apply
+ 单独 reformat PR
+ CI 后置开启

Spring Boot + React/Vue 项目

1
2
3
4
Java: IDEA Formatter / Spotless
Frontend: Prettier / ESLint
Config: EditorConfig
CI: Maven/Gradle + npm format:check

十七、推荐落地清单

团队落地时可以直接按这个清单执行。

17.1 项目文件

1
2
3
4
5
6
[x] .editorconfig
[x] .gitattributes
[x] config/checkstyle/checkstyle.xml
[x] pom.xml / build.gradle 中配置 Spotless
[x] CI 中执行 spotless:check
[x] CONTRIBUTING.md 写明规范

17.2 IDEA 设置

1
2
3
4
5
6
7
8
[x] Enable EditorConfig support
[x] Project Code Style 使用项目级 Scheme
[x] Java import 禁止 wildcard
[x] Actions on Save 开启 Reformat code
[x] Actions on Save 开启 Optimize imports
[x] 老项目选择 Changed lines
[x] Commit Checks 开启 Reformat code
[x] Commit Checks 开启 Optimize imports

17.3 团队约定

1
2
3
4
5
[x] 不在业务 PR 中混入全量格式化
[x] 大格式化单独 chore commit
[x] CI 失败先本地 spotless:apply
[x] generated sources 不手动格式化
[x] Java / JS / YAML / Markdown 各自明确格式化器

十八、结语

IDEA 的代码格式化如果只停留在快捷键层面,它只是个人习惯;一旦结合 .editorconfig、Spotless、Checkstyle、Git Hook 和
CI,它就变成了团队工程规范。

成熟的格式化体系应该满足三个目标:

1
2
3
本地写得舒服
团队风格一致
CI 能够兜底

真正推荐的做法不是“大家都记得格式化”,而是让工具链保证:

你写代码时它自动整理,你提交前它自动提醒,你忘了也有 CI 帮团队守门。

代码格式化不应该成为 Review 的主角。Review 应该关注业务、设计、边界、性能和稳定性。至于空格、换行、import
顺序这些事,就交给工具吧。工具不嫌烦,人嫌。

参考资料


IntelliJ IDEA 代码格式化深度实战:从个人快捷键到团队规范治理
https://allendericdalexander.github.io/2026/06/12/devTools/idea-code-formatting-deep-practice/
作者
AtLuoFu
发布于
2026年6月12日
许可协议