使用checkstyle来规范你的项目

简介: Checkstyle是什么自从做了程序员,关于格式化的讨论就不曾中断过,到底什么才是正确的,什么才是错误的,到现在也没有完整的定论。但随着时间发展,渐渐衍生出一套规范出来。没有什么绝对的正确和错误,关键在于规范的定义。

Checkstyle是什么

自从做了程序员,关于格式化的讨论就不曾中断过,到底什么才是正确的,什么才是错误的,到现在也没有完整的定论。但随着时间发展,渐渐衍生出一套规范出来。没有什么绝对的正确和错误,关键在于规范的定义。最出名的就是google style guide. Checkstyle就是以这种风格开发出的一个自动化插件,来辅助判断代码格式是否满足规范。

为什么要用,我们需要吗

最初,我使用checkstyle是因为公司要求,在经历过一段痛苦的格式重构阶段后,渐渐习惯了这样的格式。到后来,我新建项目就会把这个加进去,最多改几条规则。前一段时间,由于赶项目进度,其他人不熟悉,只好先关掉了。到后面发现真的每个人的风格都不一样,都看着代码怪怪的。所以,又加回来了。对于多人合作的项目,还是建议采用这样的规范,内容不必拘泥于google-checks,找出适合你们团队的风格就好。

如何使用

在gralde中使用

在gralde中用法比较简单。示例项目: https://github.com/Ryan-Miao/springboot-security-demo/blob/master/config/checkstyle/checkstyle.xml

新建一个checkstyle.gradle

/**
 * The Checkstyle Plugin
 *
 * Gradle plugin that performs quality checks on your project's Java source files using Checkstyle
 * and generates reports from these checks.
 *
 * Tasks:
 * Run Checkstyle against {rootDir}/src/main/java: ./gradlew checkstyleMain
 * Run Checkstyle against {rootDir}/src/test/java: ./gradlew checkstyleTest
 *
 * Reports:
 * Checkstyle reports can be found in {project.buildDir}/build/reports/checkstyle
 *
 * Configuration:
 * Checkstyle is very configurable. The configuration file is located at {rootDir}/config/checkstyle/checkstyle.xml
 *
 * Additional Documentation:
 * https://docs.gradle.org/current/userguide/checkstyle_plugin.html
 */

apply plugin: 'checkstyle'

checkstyle {
    // The version of the code quality tool to be used.
    // The most recent version of Checkstyle can be found at https://github.com/checkstyle/checkstyle/releases
    toolVersion = "8.8"

    // The source sets to be analyzed as part of the check and build tasks.
    // Use 'sourceSets = []' to remove Checkstyle from the check and build tasks.
//    sourceSets = [project.sourceSets.main, project.sourceSets.test]

    // Whether or not to allow the build to continue if there are warnings.
    ignoreFailures = false

    // Whether or not rule violations are to be displayed on the console.
    showViolations = true
}

然后,在build.gradle中

apply from: 'checkstyle.gradle'

应该庆幸gradle的繁荣,checkstyle都支持的到8.0以上了。后面用maven的时候遇到版本问题,完美主义追求最新版的心态会难受死。

然后,关键的地方是指定checkstyle.xml规则配置文件了。默认会读取根目录下

config/checkstyle/checkstyle.xml

文件的内容来自:https://sourceforge.net/projects/checkstyle/files/checkstyle/

即,去maven中找到对应版本的checkstyle, 然后下载jar,解压,里面有google-checks.xml, 复制里面的内容即可。

还可以直接用最新版本,参见Github

运行任务

./gradlew check

然后可以在以下目录找到检查结果

build/reports/checkstyle/main.html

更多细节,参考gradle 官网.

idea自动格式化

对于检查的结果,手动修改可能比较慢,同样有人提供了idea对应的插件来格式化。

https://github.com/google/styleguide/edit/gh-pages/intellij-java-google-style.xml

用法是,intelij idea - settting - Editor - code style - scheme, 点击旁边的齿轮设置按钮,选择import scheme, intelij idea code style xml.

导入后,使用快捷键可以快速格式化。

contrl + alt + l

在maven中使用

maven中对于单模块应用参见官网

pom中

<project>
  ...
   <reporting>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-checkstyle-plugin</artifactId>
          <version>3.0.0</version>
          <reportSets>
            <reportSet>
              <reports>
                <report>checkstyle</report>
              </reports>
            </reportSet>
          </reportSets>
        </plugin>
      </plugins>
    </reporting>
  ...
</project>

运行maven site即可在以下目录找到结果

target/site/checkstyle.html

也可以单独执行命令

mvn checkstyle:checkstyle

checkstyle plugin与checkstyle的版本对应关系

http://maven.apache.org/plugins/maven-checkstyle-plugin/history.html

Maven多模块的checkstyle配置

大多数情况下,我们会把项目的逻辑按照模块拆分出来,便于分离和解耦,项目脉络也更加清晰。在这种情况下,我们为每个模块创建checkstyle任务,需要放到parent的pom里。

示例项目: https://github.com/Ryan-Miao/springboot-starter-feign/blob/master/pom.xml

在父项目,parent pom里:


<build>

<pluginManagement>
  <plugins>

    <!--compiler在maven声明周期内置,所以后面不用声明也可使用-->
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.5.1</version>
      <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <encoding>UTF-8</encoding>
      </configuration>
    </plugin>


    <!--公共checkstyle标准配置,可以在子模块中覆盖,修改自定义选项-->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <version>3.0.0</version>
      <configuration>
        <configLocation>config/checkstyle/google-checks-6.18.xml</configLocation>
        <consoleOutput>true</consoleOutput>
        <encoding>UTF-8</encoding>
        <consoleOutput>true</consoleOutput>
        <failsOnError>true</failsOnError>
        <linkXRef>false</linkXRef>
        <skip>false</skip>
        <violationSeverity>error</violationSeverity>
      </configuration>
      <executions>
        <execution>
          <id>install</id>
          <phase>install</phase>
          <goals>
            <goal>checkstyle</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</pluginManagement>


<!--所有子模块都要执行的plugin-->
<plugins>
  <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>

这里,maven-compiler-plugin不是必须的,事实上,maven会在项目生命周期中自动执行,我添加这个插件的原因是在idea里的java编译级别需要根据这里来指定。

checkstyle plugin的配置有点多,需要仔细理解一下maven中plugin的含义。

build

在maven指令执行的时候会读取这个节点的配置,决定哪个plugin应该执行,怎么执行。

pluginManagement

这个是版本和共同配置的节点, 同dependencyManagement, 为了约束子项目使用共同的配置。不同的是,这个是指plugin。

plugin

这个表示一个插件,maven执行命令都可以用插件来理解。

plugin>configuration

对于plugin的配置,具体有哪些配置项要看具体的plugin。

executions>execution

plugin应该什么时候执行

<execution>
  <id>install</id>
  <phase>install</phase>
  <goals>
    <goal>checkstyle</goal>
  </goals>
</execution>

id可以随意,phase则是需要绑定到lifecycle的phase中的哪个命令上,这里是绑定到install上,即当执行maven install的时候会执行本plugin。

goals>goal
一个plugin有多个goals,即任务,是指绑定执行哪个任务。这里之绑定checkstyle

checkstyle的错误级别

在checkstyle.xml的配置文件中,有

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

这里是说当前这个配置是什么错误级别。如果配置的是error,那么扫描到不符合条件的,就是打印error。对于配置了

<failsOnError>true</failsOnError>

则会打断命令执行,错误的时候会停止。否则,错误会生成报告,但不会阻止命令执行。如果配置了info

[INFO] --- maven-checkstyle-plugin:3.0.0:checkstyle (install) @ j-d2-job ---
[INFO] Starting audit...
[INFO] E:\workspace\parent-demo\demo-job\src\main\java\com\demo\Service.java:147:34: WhitespaceAround: '+' is not preceded with whitespace. [WhitespaceAround]
Audit done.

会显示是info,不是error,不会阻断任务执行。最开始查了很久都没找到原因,原来在这里配置的,-_-||。

checkstyle里允许的错误级别有error, warning, info. 只有error并配置了failsOnError会打断命令的执行。打断执行后会在对应的子模块的target下生成

target/checkstyle-result.xml

但不能生成html,或者可以选择声明plain,这个更不好看。纠结了半天就妥协了,就自己看xml结果吧,知道具体的class之后再结合idea checkstyle插件来修改就行。

checkstyle遇到的错误

checkstyle缓存

修改checkstyle.xml后发现还报错,原因是没生效,过一会就好了。

EmptyCatchBlockCheck

如果try-catch捕获了异常但却没有任何操作,则会报警。当然,你确实认为不需要任何操作,可以忽略,忽略配置方案

 <module name="EmptyCatchBlock">
    <property name="exceptionVariableName" value="ignore|expected;/>
 </module>

此时,只要把捕获的excavation变量名称修改为ignore或者expected就可以避免审查。

比如

try {
     throw new RuntimeException();
 } catch (RuntimeException expected) {
 }
 
 
 try {
     throw new RuntimeException();
 } catch (RuntimeException ignore) {
 }

还可以配置注释,只要添加注释即可忽略

<module name="EmptyCatchBlock">
    <property name="exceptionVariableName" value="ignore|expected"/>
    <property name="commentFormat" value="ignore"/>
</module>

比如

try {
     throw new RuntimeException();
 } catch (RuntimeException ex) {
     //ignore
 }

AbbreviationAsWordInName

变量名称不允许连续大写,遵循驼峰命名规范。

<module name="AbbreviationAsWordInName">
   <property name="tokens" value="VARIABLE_DEF,CLASS_DEF"/>
   <property name="ignoreStatic" value="false"/>
   <property name="allowedAbbreviationLength" value="1"/>
   <property name="allowedAbbreviations" value="XML,URL"/>
 </module>

结语

没有尝试和努力解决之前,总是以为很难不可能做到。等像打怪升级一样把项目过一遍之后,你发现checkstyle貌似也不难。永远不要用做不到来限制你的未来。

    关注我的公众号

img_acfe50023e4718b33064273d65e4cd67.jpe
唯有不断学习方能改变! -- Ryan Miao
目录
相关文章
|
6月前
|
存储 Java Apache
Maven - 统一构建规范:Maven 插件管理最佳实践
Maven - 统一构建规范:Maven 插件管理最佳实践
256 0
|
JavaScript Java Maven
|
2月前
|
Java 测试技术 Maven
单元测试添加运行参数的maven插件
单元测试添加运行参数的maven插件
19 0
|
12月前
|
消息中间件 JavaScript 小程序
自从用了CheckStyle插件,代码写的越来越规范了....
自从用了CheckStyle插件,代码写的越来越规范了....
|
存储 前端开发 Java
【Maven项目】在项目开发中对于NAPSHOT、Maven依赖关系管理以及三个标准生命周期
【Maven项目】在项目开发中对于NAPSHOT、Maven依赖关系管理以及三个标准生命周期
113 0
|
NoSQL Java Maven
【巧立名目】利用IDEA工具修改Maven多模块项目标识包名全过程
【巧立名目】利用IDEA工具修改Maven多模块项目标识包名全过程
975 0
【巧立名目】利用IDEA工具修改Maven多模块项目标识包名全过程
|
缓存 IDE Java
已经使用ant的项目如何利用maven来管理依赖
已经使用ant的项目如何利用maven来管理依赖
|
XML IDE Java
【Groovy】Gradle 构建工具 ( 自动下载并配置构建环境 | 提供 API 扩展与开发工具集成 | 内置 Maven 和 Ivy 依赖管理 | 使用 Groovy 编写构建脚本 )
【Groovy】Gradle 构建工具 ( 自动下载并配置构建环境 | 提供 API 扩展与开发工具集成 | 内置 Maven 和 Ivy 依赖管理 | 使用 Groovy 编写构建脚本 )
239 0
【Groovy】Gradle 构建工具 ( 自动下载并配置构建环境 | 提供 API 扩展与开发工具集成 | 内置 Maven 和 Ivy 依赖管理 | 使用 Groovy 编写构建脚本 )
|
XML Java Maven
【Groovy】构建工具 ( 构建工具引入 | Gradle 构建工具作用 | 传统的依赖管理 )
【Groovy】构建工具 ( 构建工具引入 | Gradle 构建工具作用 | 传统的依赖管理 )
126 0
|
存储 Java Android开发
Gradle 使用技巧(六) - 使用统一的Gradle管理
1. 前言 大多数情况下我们依赖第三方库都是直接在dependencies中直接引用,在引入少量且不是多个地方引用是没有问题的,但是一旦某一个开源库在多个地方引用,且每个地方引用的版本都不一致的时候,就只在是难以维护了。
1267 0