1. 程式人生 > >maven javadoc中文亂碼問題和CheckStyle編碼規範檢測

maven javadoc中文亂碼問題和CheckStyle編碼規範檢測

介紹 
CheckStyle是SourceForge下的一個專案,提供了一個幫助JAVA開發人員遵守某些編碼規範的工具。它能夠自動化程式碼規範檢查過程,從 而使得開發人員從這項重要,但是枯燥的任務中解脫出來。 
CheckStyle預設提供一下主要檢查內容: 
  •Javadoc註釋 
  •命名約定 
  •標題 
  •Import語句 
  •體積大小 
  •空白 
  •修飾符 
   •塊 
  •程式碼問題 
  •類設計 
  •混合檢查(包活一些有用的比如非必須的 System.out和printstackTrace) 
  從上面可以看出,CheckStyle提供了大部分功能都是對於程式碼規範 的檢查,而沒有提供象PMD和Jalopy那麼多的增強程式碼質量和修改程式碼的功能。但是,對於團隊開發,尤其是強調程式碼規範的公司來說,它的功能已經足夠強大。 
Eclipse外掛安裝和使用 
步驟一:http://sourceforge.net/projects/checkclipse/下載checkstyle的eclipse外掛checkclipse。下載後,將包放入eclipse的plugins資料夾下,然後重啟eclipse。在Windows—>preferences下找到checkclipse。如下圖: 

 
勾選Set Project Dir as Checkjstyle Basedir 
步驟二:右鍵選中你要進行checkstyle的專案檔案,選擇“properties”。如下圖: 
 
勾選Enable Checkstyle和Set Project ClassLoader. 
然後再Checkstyle Configuraion File中選擇專案中checkstyle的配置檔案。這裡我把配置檔案時放置在專案根目錄下,所以點選右側“Browse”按鈕,在專案根目錄下選擇該檔案。按“OK”按鈕。 
這樣整個專案的程式碼將根據配置檔案中設定的原則進行出錯提示.結果如下圖: 
 
由圖可知對不符合程式碼規範的程式碼會有錯誤提示,並且有提示資訊。 
Maven外掛安裝和使用 
首先,修改要檢查程式碼庫top級的pom.xml檔案,在build部分配置CheckStyle的Maven外掛,以便於下載安裝對應版本的外掛(Maven會自動從其映象庫中下載),方法如下: 

Java程式碼 
  1. <project>  
  2.   ...  
  3.   <build>  
  4.     <plugins>  
  5.       <plugin>  
  6.         <groupId>org.apache.maven.plugins</groupId>  
  7.         <artifactId>maven-checkstyle-plugin</artifactId>  
  8.         <version>2.3</version>  
  9.       </plugin>  
  10.     </plugins>  
  11.   </build>  
  12.   ...  
  13. </project>  

maven-checkstyle-plugin的最新版本為2.5,其對應的CheckStyle核心版本為5.0;maven-checkstyle-plugin 2.3對應的CheckStyle核心版本為4.4。檢視外掛的pom檔案,可看到如下內容,其中的版本號就為對應的CheckStyle的版本號。 
Java程式碼 
  1. <dependency>  
  2.   <groupId>checkstyle</groupId>   
  3.   <artifactId>checkstyle</artifactId>   
  4.   <version>4.4</version>   
  5.   </dependency>  

接下來,將自定義的規則配置檔案拷貝到top級目錄,在reporting部分的CheckStyle外掛配置中引用配置。 
Java程式碼 
  1. <reporting>  
  2.     <plugins>  
  3.         <plugin>  
  4.             <groupId>org.apache.maven.plugins</groupId>  
  5.             <artifactId>maven-checkstyle-plugin</artifactId>  
  6.             <configuration>  
  7.               <configLocation>my_checks.xml</configLocation>  
  8.             </configuration>  
  9.         </plugin>  
  10.     </plugins>  
  11. </reporting>  

也可以將配置檔案放在子資料夾下,配置中帶上相對路徑即可。 
Java程式碼 
  1. <reporting>  
  2.     <plugins>  
  3.         <plugin>  
  4.             <groupId>org.apache.maven.plugins</groupId>  
  5.             <artifactId>maven-checkstyle-plugin</artifactId>  
  6.             <configuration>  
  7.               <configLocation>build-tools/src/main/resources/xx/my_checks.xml</configLocation>  
  8.             </configuration>  
  9.         </plugin>  
  10.     </plugins>  
  11. </reporting>  

如果使用外掛自帶的規則檔案,可以作如下配置。maven-checkstyle-plugin外掛自帶的規則有sun_checks.xml、maven_checks.xml等,可檢視外掛包。 
Java程式碼 
  1. <reporting>  
  2.     <plugins>  
  3.                <plugin>  
  4.                  <groupId>org.apache.maven.plugins</groupId>  
  5.                  <artifactId>maven-checkstyle-plugin</artifactId>  
  6.                  <configuration>  
  7.                             <configLocation>config/maven_checks.xml</configLocation>  
  8.                 </configuration>  
  9.                  <version>2.3</version>         
  10.                </plugin>  
  11.     </plugins>  
  12. </reporting>  

在reporting部分增加jxr外掛,生成程式碼報告,這樣在CheckStyle報告 中點選問題對應的連結就可以直接看到出錯的程式碼。 
      Java程式碼 
  1. <reporting>  
  2.           <plugins>  
  3.             <plugin>  
  4.               <groupId>org.apache.maven.plugins</groupId>  
  5.               <artifactId>maven-checkstyle-plugin</artifactId>  
  6.               <configuration>  
  7.                          <configLocation>my_checks.xml</configLocation>                              
  8.           </configuration>  
  9.               <version>2.3</version>         
  10.             </plugin>  
  11.             <plugin>  
  12.                    <groupId>org.apache.maven.plugins</groupId>  
  13.                  <artifactId>maven-jxr-plugin</artifactId>  
  14.             </plugin>                
  15.           </plugins>  
  16.     </reporting>   
           
在build和reporting部分增加javadoc外掛,如果pom檔案中已經配置,則只需作相應修改。charset、encoding、docencoding配置用於解決生成的javadoc檔案中文亂碼問題;aggregate配置為true則javadoc報告會集中顯示所有子模組的javadoc。 
        Java程式碼 
  1. <reporting>  
  2.             <plugins>  
  3.               <plugin>  
  4.                           <groupId>org.apache.maven.plugins</groupId>  
  5.                           <artifactId>maven-javadoc-plugin</artifactId>  
  6.                           <version>2.4</version>  
  7.                           <configuration>  
  8.                              <aggregate>true</aggregate>  
  9.                         <charset>UTF-8</charset>  
  10.                                       <encoding>UTF-8</encoding>  
  11.                                       <docencoding>UTF-8</docencoding>  
  12.                         </configuration>  
  13.               </plugin>              
  14.               <plugin>  
  15.                 <groupId>org.apache.maven.plugins</groupId>  
  16.                 <artifactId>maven-checkstyle-plugin</artifactId>  
  17.                 <configuration>  
  18.                            <configLocation>my_checks.xml</configLocation>                              
  19.             </configuration>  
  20.                 <version>2.3</version>         
  21.               </plugin>  
  22.               <plugin>  
  23.                      <groupId>org.apache.maven.plugins</groupId>  
  24.                    <artifactId>maven-jxr-plugin</artifactId>  
  25.               </plugin>                
  26.             </plugins>  
  27.       </reporting>  

在maven外掛中使用 install命令將pom檔案中配置的外掛下載安裝到本地,然後使用checkstyle:checkstyle命令進行檢查並生成報告,執行完畢,各專案目錄下會生成target目錄,target/site/checkstyle.html即為該專案的問題報告。 
需要注意的是checkstyle:checkstyle僅生成CheckStyle相關報告,因此不能從報告中直接連結到錯誤程式碼;需要同時生成jxr原始碼,使用site。 
如果執行checkstyle:checkstyle或site過程中出現如下錯誤,則應該修改CheckStyle規 則配置檔案,去除其中的中文字元。 
Java程式碼 
  1. “[ERROR] BUILD ERROR  
  2. [INFO] ------------------------------------------------------------------------  
  3. [INFO] An error has occurred in Checkstyle report generation.  
  4. Embedded error: Failed during checkstyle configuration  
  5. Invalid byte1 of 1-byte UTF-8 sequence.  
  6. ”  

最佳實踐 
自定義的checkstyle配置檔案 
  以下程式碼是自定義的checkstyle配置檔案內容,相關說明都已經用註釋形式寫在檔案中。程式碼如下: 
Java程式碼 
  1. <!DOCTYPE module PUBLIC  
  2.     "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
  3.     "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">  
  4. <module name="Checker">  
  5.     <!--  
  6.         重複程式碼的檢查,超過8行就認為重複,UTF-8格式 本檢查一定要放在"TreeWalker"節點前,否則在  
  7.         Checkclipse中會無法使用。(在ant下可以)  
  8.     -->  
  9.     <module name="StrictDuplicateCode">  
  10.         <property name="min" value="8" />  
  11.         <property name="charset" value="UTF-8" />  
  12.     </module>  
  13.     <module name="TreeWalker">  
  14.         <!-- javadoc的檢查 -->  
  15.         <!-- 檢查所有的interfaceclass -->  
  16.         <module name="JavadocType" />  
  17.         <!-- 命名方面的檢查,它們都使用了Sun官方定的規則。 -->  
  18.         <!-- 區域性的final變數,包括catch中的引數的檢查 -->  
  19.         <module name="LocalFinalVariableName" />  
  20.         <!-- 區域性的非final型的變數,包括catch中的引數的檢查 -->  
  21.         <module name="LocalVariableName" />  
  22.         <!-- 包名的檢查(只允許小寫字母) -->  
  23.         <module name="PackageName">  
  24.             <property name="format" value="^[a-z]+(/.[a-z][a-z0-9]*)*$" />  
  25.         </module>  
  26.         <!-- 僅僅是static型的變數(不包括staticfinal型)的檢查 -->  
  27.         <module name="StaticVariableName" />  
  28.         <!-- 型別(Class或Interface)名的檢查 -->  
  29.         <module name="TypeName" />  
  30.         <!-- 非static型變數的檢查 -->  
  31.         <module name="MemberName" />  
  32.         <!-- 方法名的檢查 -->  
  33.         <module name="MethodName" />  
  34.         <!-- 方法的引數名 -->  
  35.         <module name="ParameterName " />  
  36.         <!-- 常量名的檢查 -->  
  37.         <module name="ConstantName" />  
  38.         <!-- import方面的檢查 -->  
  39.         <!-- import中避免星號"*" -->  
  40.         <module name="AvoidStarImport" />  
  41.         <!--  
  42.             沒用的import檢查,比如:1.沒有被用到2.重複的3.import java.lang的4.import
  43.             與該類在同一個package的  
  44.         -->  
  45.         <module name="UnusedImports" />  
  46.         <!-- 長度方面的檢查 -->  
  47.         <!-- 檔案長度不超過1500行 -->  
  48.         <module name="FileLength">  
  49.             <property name="max" value="1500" />  
  50.         </module>  
  51.         <!-- 每行不超過120個字-->  
  52.         <module name="LineLength">  
  53.             <property name="max" value="120" />  
  54.         </module>  
  55.         <!-- 方法不超過30行 -->  
  56.         <module name="MethodLength">  
  57.             <property name="tokens" value="METHOD_DEF" />  
  58.             <property name="max" value="30" />  
  59.         </module>  
  60.         <!-- 方法的引數個數不超過3個。 並且不對構造方法進行檢查-->  
  61.         <module name="ParameterNumber">  
  62.             <property name="max" value="3" />  
  63.             <property name="tokens" value="METHOD_DEF" />  
  64.         </module>  
  65.         <!-- 空格檢查  -->  
  66.         <!-- 允許方法名後緊跟左邊圓括號"(" -->  
  67.         <module name="MethodParamPad" />  
  68.         <!-- 在型別轉換時,不允許左圓括號右邊有空格,也不允許與右圓括號左邊有空格 -->  
  69.         <module name="TypecastParenPad" />  
  70.         <!-- 不允許使用"tab"鍵  -->  
  71.         <module name="TabCharacter" />  
  72.         <!-- 關鍵字 -->  
  73.         <!--  
  74.             每個關鍵字都有正確的出現順序。比如 publicstaticfinal XXX 是對一個常量的宣告。如果使用 static
  75.             publicfinal 就是錯誤的  
  76.         -->  
  77.         <module name="ModifierOrder" />  
  78.         <!-- 多餘的關鍵字 -->  
  79.         <module name="RedundantModifier" />  
  80.         <!-- 對區域的檢查 -->  
  81.         <!-- 不能出現空白區域 -->  
  82.         <module name="EmptyBlock" />  
  83.         <!-- 所有區域都要使用大括號。 -->  
  84.         <module name="NeedBraces" />  
  85.         <!-- 多餘的括號 -->  
  86.         <module name="AvoidNestedBlocks">  
  87.             <property name="allowInSwitchCase" value="true" />  
  88.         </module>  
  89.         <!-- 編碼方面的檢查 -->  
  90.         <!-- 不許出現空語句 -->  
  91.         <module name="EmptyStatement" />  
  92.         <!-- 每個類都實現了equals()和hashCode() -->  
  93.         <module name="EqualsHashCode" />  
  94.         <!-- 不許使用switch,"a++"這樣可讀性很差的程式碼 -->  
  95.         <module name="IllegalToken" />  
  96.         <!-- 不許內部賦值 -->  
  97.         <module name="InnerAssignment" />  
  98.         <!-- 絕對不能容忍魔法數 -->  
  99.         <module name="MagicNumber">  
  100.             <property name="tokens" value="NUM_DOUBLE, NUM_INT" />  
  101.         </module>  
  102.         <!-- 迴圈控制變數不能被修改 -->  
  103.         <module name="ModifiedControlVariable" />  
  104.         <!-- 多餘的throw -->  
  105.         <module name="RedundantThrows" />  
  106.         <!-- 不許使用未被簡化的條件表示式 -->  
  107.         <module name="SimplifyBooleanExpression" />  
  108.         <!-- 不許使用未被簡化的布林返回值 -->  
  109.         <module name="SimplifyBooleanReturn" />  
  110.         <!-- String的比較不能用!= 和 == -->  
  111.         <module name="StringLiteralEquality" />  
  112.         <!-- if最多巢狀3層 -->  
  113.         <module name="NestedIfDepth">  
  114.             <property name="max" value="3" />  
  115.         </module>  
  116.         <!-- try最多被巢狀2層 -->  
  117.         <module name="NestedTryDepth">  
  118.             <property name="max" value="2" />  
  119.         </module>  
  120.         <!-- clone方法必須呼叫了super.clone() -->  
  121.         <module name="SuperClone" />  
  122.         <!-- finalize 必須呼叫了super.finalize() -->  
  123.         <module name="SuperFinalize" />  
  124.         <!-- 不能catch java.lang.Exception -->  
  125.         <module name="IllegalCatch">  
  126.             <property name="illegalClassNames" value="java.lang.Exception" />  
  127.         </module>  
  128.         <!-- 確保一個類有package宣告 -->  
  129.         <module name="PackageDeclaration" />  
  130.         <!-- 一個方法中最多有3return -->  
  131.         <module name="ReturnCount">  
  132.             <property name="max" value="3" />  
  133.             <property name="format" value="^$" />  
  134.         </module>  
  135.         <!--  
  136.             根據 Sun 編碼規範, class 或 interface 中的順序如下: 1.class 宣告。首先是 public,  
  137.             然後是protected , 然後是 package level (不包括access modifier ) 最後是private .  
  138.             (多個class放在一個java檔案中的情況) 2.變數宣告。 首先是 public, 然後是protected然後是 package
  139.             level (不包括access modifier ) 最後是private . (多個class放在一個java檔案中的情況)  
  140.             3.建構函式 4.方法  
  141.         -->  
  142.         <module name="DeclarationOrder" />  
  143.         <!-- 不許對方法的引數賦值 -->  
  144.         <module name="ParameterAssignment" />  
  145.         <!-- 確保某個class 在被使用時都已經被初始化成預設值(物件是null,數字和字元是0,boolean 變數是false.) -->  
  146.         <module name="ExplicitInitialization" />  
  147.         <!-- 不許有同樣內容的String -->  
  148.         <module name="MultipleStringLiterals" />  
  149.         <!-- 同一行不能有多個宣告 -->  
  150.         <module name="MultipleVariableDeclarations" />  
  151.         <!-- 不必要的圓括號 -->  
  152.         <module name="UnnecessaryParentheses" />  
  153.         <!-- 各種量度 -->  
  154.         <!-- 布林表示式的複雜度,不超過3 -->  
  155.         <module name="BooleanExpressionComplexity" />  
  156.         <!-- 類資料的抽象耦合,不超過7 -->  
  157.         <module name="ClassDataAbstractionCoupling" />  
  158.         <!-- 類的分散複雜度,不超過20 -->  
  159.         <module name="ClassFanOutComplexity" />  
  160.         <!-- 函式的分支複雜度,不超過10 -->  
  161.         <module name="CyclomaticComplexity" />  
  162.         <!-- NPath複雜度,不超過200 -->  
  163.         <module name="NPathComplexity" />  
  164.         <!-- 雜項 -->  
  165.         <!-- 禁止使用System.out.println -->  
  166.         <module name="GenericIllegalRegexp">  
  167.             <property name="format" value="System/.out/.println" />  
  168.             <property name="ignoreComments" value="true" />  
  169.         </module>  
  170.         <!-- 不許使用main方法 -->  
  171.         <module name="UncommentedMain" />  
  172.         <!-- 檢查並確保所有的常量中的L都是大寫的。因為小寫的字母l跟數字1太象了 -->  
  173.         <module name="UpperEll" />  
  174.         <!-- 檢查陣列型別的定義是String[] args,而不是String args[] -->  
  175.         <module name="ArrayTypeStyle" />  
  176.         <!--  
  177.             檢查java程式碼的縮排 預設配置:基本縮排 4個空格,新行的大括號:0。新行的case4個空格。  
  178.         -->  
  179.         <module name="Indentation" />  
  180.     </module>  
  181.     <!-- 檢查翻譯檔案     -->  
  182.     <module name="Translation" />  
  183. </module>  

CheckStyle應用的最佳實踐 
  採用CheckStyle以後,編碼規範的檢查就變得及其簡單,可以作為一項切實可行的實踐加以執行。 
  一般情況下,在專案小組中引入CheckStyle可以按照下面的步驟進行: 
  1. 強調Code Review與Code Conventions的重要作用; 
  2. 介紹CheckStyle; 
    3. 初步應用CheckStyle:參照CheckStyle附帶的配置檔案,酌情加以剪裁,在專案的Maven配置檔案中,新增CheckStyle任務,可以 單獨執行; 
  4. 修改、定型CheckStyle的配置檔案:按照基本配置檔案執行一段時間(2~3周),聽取開發人員的反饋意見,修改配置資訊; 
  5. 作為開發過程的日常實踐,強制執行CheckStyle:穩定CheckStyle的配置資訊,同時將CheckStyle任務作為Build的依賴任務 或者配置SCM(目前,CheckStyle可以與SVN有效整合),使得程式碼在加入系統 之前必須通過檢查。 
  同時需要指出的是,CheckStyle的有效執行需要依賴的條件: 
    •IDE Format Code的強大功能:由於CheckStyle本身並沒有提供很強大的Code Format等功能,因此,需要藉助IDE的幫助,從而使得在發生錯誤的時候,可以很容易的進行修復。 
IDE格式配置使用介紹 
在eclipse中的windowpreferencesjavacode style中可以匯入自定義的java編碼風格檔案。如下圖: 
 
點選“Clean Up”,在右側可以看見一個Import按鈕,匯入自定義的cleanup檔案,點選“OK”即可。左側的“Formatter”也是如法炮製。具體自定義的checkstyle,cleanup,formatter檔案可參考壓縮包檔案中的公司程式碼規範檔案夾。