使用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貌似也不難。永遠不要用做不到來限制你的未來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM