上一节使用checkstyle来规范你的项目主要解决了代码编码规范问题,比如缩进换行等。这次继续代码健康工具类PMD。

什么是PMD

PMD真的不像checkstyle这样的东西所见即所得啊,去官网找了半天也没有找到解释。官网都直接说是PMD。

We've been trying to find the meaning of the letters PMD - because frankly, we don't really know. We just think the letters sound good together.

简单来说,PMD是一个代号,是一个静态代码检测工具。它可以用来检查

  • 潜在的bug:空的try/catch/finally/switch语句
  • 未使用的代码:未使用的局部变量、参数、私有方法等
  • 可选的代码:String/StringBuffer的滥用
  • 复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
  • 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs

总之,这是一个辅助我们检测潜在bug的工具,大大减少了人工审查成本,提高编码效率。

在gradle中使用

gradle还是一贯的简单,新建pmd.gradle

/**
* The PMD Plugin
*
* Gradle plugin that performs quality checks on your project’s Java source files using PMD
* and generates reports from these checks.
*
* Tasks:
* Run PMD against {rootDir}/src/main/java: ./gradlew pmdMain
* Run PMD against {rootDir}/src/test/java: ./gradlew pmdTest
*
* Reports:
* PMD reports can be found in {project.buildDir}/build/reports/pmd
*
* Configuration:
* PMD is very configurable. The configuration file is located at {rootDir}/config/pmd/pmd-ruleset.xml
*
* Additional Documentation:
* https://docs.gradle.org/current/userguide/pmd_plugin.html
*/ apply plugin: 'pmd' pmd {
// The version of the code quality tool to be used.
// The most recent version of PMD can be found at https://pmd.github.io
toolVersion = "5.8.1" // The source sets to be analyzed as part of the check and build tasks.
// Use 'sourceSets = []' to remove PMD from the check and build tasks.
sourceSets = [project.sourceSets.main] // The directory where reports will be generated.
reportsDir = file("$project.buildDir/reports/pmd") // Whether to allow the build to continue if there are warnings.
ignoreFailures = false // Whether or not rule violations are to be displayed on the console.
consoleOutput = true // The custom rule set files to be used.
ruleSetConfig = resources.text.fromFile("$rootProject.projectDir/config/pmd/pmd-ruleset.xml")
}

添加我们的pmd-ruleset.xml配置文件, 这个ruleset有很多种,我们可以先把所有的加上,然后在开发中调整,直到找到最合适的配置方案。因为全部的规则太多,会导致你花费大量的时间解决PMD问题。

ruleset内容可以在https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html 这里找到

然后在build.gradle中添加

apply from: 'pmd.gradle'

执行

./gradlew check  或者 ./gradlew build

报告位置:

build/reports/pmd/main.html

在maven中使用

maven需要把ruleset放到resources下读取,如果是单moudle项目,直接就可以。如果是多模块项目,需要额外做一些工作。

我们来新建一个项目来单独存储配置文件,build-tools. 在resources下放置ruleset。名字叫做pmd-ruleset.xml, 内容见https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

然后maven install把这个子模块给安装到本地仓库。

接着修改parent pom

<build>

    <pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.10.0</version>
<dependencies>
<dependency>
<groupId>com.shuwei</groupId>
<artifactId>build-tools</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
<configuration>
<sourceEncoding>utf-8</sourceEncoding>
<minimumTokens>100</minimumTokens>
<targetJdk>${java.version}</targetJdk>
<excludes>
<exclude>**/message/*.java</exclude>
<exclude>**/generated/*.java</exclude>
</excludes>
<excludeRoots>
<excludeRoot>target/generated-sources</excludeRoot>
</excludeRoots>
<rulesets>
<ruleset>pmd-ruleset.xml</ruleset>
</rulesets>
<printFailingErrors>true</printFailingErrors>
</configuration>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<goals>
<goal>pmd</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement> <!--所有子模块都要执行的plugin-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
</plugin>
</plugins> </build> <reporting>
<!--所有子模块都要执行的报告-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
</plugin>
</plugins>
</reporting>

和上一节checkstyle不同的时候,这里的plugin下新增了dependency节点。这个节点负责加载一些资源过来,比如我们的配置文件ruleset。所以,这个dependency要先于项目存在,所以才要先单独install一下。当然,也可以把这个项目放到maven私服上,这样更简单了。

依旧把pmd的运行绑定到install命令上,这样,我们运行maven install的时候就可以进行pmd检查了。

检查报告在

j-context/target/site/pmd.html

也可以单独运行pmd

mvn pmd:pmd

idea插件

搜索安装idea pmd插件,导入我们的ruleset, 然后在项目上右键,run pmd即可。

Ruleset default内容

可以在maven官网看到: https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

PMD 包含 16 个规则集,涵盖了 Java 的各种常见问题,其中一些规则要比其他规则更有争议:

基本(rulesets/basic.xml)—— 规则的一个基本合集,可能大多数开发人员都不认同它: catch 块不该为空,无论何时重写 equals(),都要重写 hashCode(),等等。

命名(rulesets/naming.xml)—— 对标准 Java 命令规范的测试:变量名称不应太短;方法名称不应过长;类名称应当以小写字母开头;方法和字段名应当以小写字母开头,等等。

未使用的代码(rulesets/unusedcode.xml)—— 查找从未使用的私有字段和本地变量、执行不到的语句、从未调用的私有方法,等等。

设计(rulesets/design.xml)—— 检查各种设计良好的原则,例如: switch 语句应当有 default 块,应当避免深度嵌套的 if 块,不应当给参数重新赋值,不应该对 double 值进行相等比较。

导入语句(rulesets/imports.xml)—— 检查 import 语句的问题,比如同一个类被导入两次或者被导入 java.lang 的类中。

JUnit 测试(rulesets/junit.xml)—— 查找测试用例和测试方法的特定问题,例如方法名称的正确拼写,以及 suite() 方法是不是 static 和 public。

字符串(rulesets/string.xml)—— 找出处理字符串时遇到的常见问题,例如重复的字符串标量,调用 String 构造函数,对 String 变量调用 toString() 方法。

括号(rulesets/braces.xml)—— 检查 for、 if、 while 和 else 语句是否使用了括号。

代码尺寸(rulesets/codesize.xml)—— 测试过长的方法、有太多方法的类以及重构方面的类似问题。

Javabean(rulesets/javabeans.xml)—— 查看 JavaBean 组件是否违反 JavaBean 编码规范,比如没有序列化的 bean 类。

终结函数(finalizer)—— 因为在 Java 语言中, finalize() 方法不是那么普遍(我上次编写这个代码也经是好多年前的事了),所以它们的使用规则虽然很详细,但是人们对它们相对不是很熟悉。这类检查查找 finalize() 方法的各种问题,例如空的终结函数,调用其他方法的 finalize() 方法,对 finalize() 的显式调用,等等。

克隆(rulesets/clone.xml)—— 用于 clone() 方法的新规则。凡是重写 clone() 方法的类都必须实现 Cloneable, clone() 方法应该调用 super.clone(),而 clone() 方法应该声明抛出 CloneNotSupportedException 异常,即使实际上没有抛出异常,也要如此。

耦合(rulesets/coupling.xml)—— 查找类之间过度耦合的迹象,比如导入内容太多;在超类型或接口就已经够用的时候使用子类的类型;类中的字段、变量和返回类型过多等。

严格的异常(rulesets/strictexception.xml)—— 针对异常的测试:不应该声明该方法而抛出 java.lang.Exception 异常,不应当将异常用于流控制,不应该捕获 Throwable,等等。

有争议的(rulesets/controversial.xml)—— PMD 的有些规则是有能力的 Java 程序员可以接受的。但还是有一些争议。这个规则集包含一些更有问题的检验,其中包括把 null 赋值给变量、方法中有多个返回点,以及从 sun 包导入等。

日志(rulesets/logging-java.xml)—— 查找 java.util.logging.Logger 的不当使用,包括非终状态(nonfinal)、非静态的记录器,以及在一个类中有多个记录器。

参考

添加PMD插件扫描潜在的bug的更多相关文章

  1. IDEAL葵花宝典:java代码开发规范插件 checkstyle、visualVM、PMD 插件

    前言: visualVM: 运行java程序的时候启动visualvm,方便查看jvm的情况 比如堆内存大小的分配:某个对象占用了多大的内存,jvm调优必备工具. checkstyle: CheckS ...

  2. Gradle 1.12用户指南翻译——第三十三章. PMD 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  3. Ubuntu 14.04安装Chromium浏览器并添加Flash插件Pepper Flas

    转自Ubuntu 14.04安装Chromium浏览器并添加Flash插件Pepper Flash Player Chromium谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe ...

  4. Emacs添加主题插件(Win系统)

    Emacs添加主题插件(Win系统) */--> /* @licstart The following is the entire license notice for the JavaScri ...

  5. SSM整合中遇到的不能扫描注解的bug

    我的开发环境为: ubuntu14.04LTS 64bit; Spring Tool Suite  3.5.0.RELEASE Maven 3.2.3 SSM整合中遇到的不能扫描注解的bug 最终解决 ...

  6. IntelliJ IDEA 添加junit插件

    一.使用idea做junit测试需要添加junit插件 1.安装插件 File-->settings-->Plguins-->Browse repositories-->输入J ...

  7. eclipse手动安装alibaba代码规范插件+取消阿里编码规约插件扫描出来的警告及错误

    如果你的开发环境无法访问外网,那么手动安装阿里巴巴的代码规范插件是一个不错的选择.另外,很多教程说该插件需要jdk1.8以上,我试了一下jdk1.7也是可以运行的,更低的版本就不知道了,貌似jdk1. ...

  8. WordPress插件扫描工具plecost

    WordPress插件扫描工具plecost   WordPress是PHP语言开发的博客平台.该平台允许用户通过插件方式扩展博客功能.由于部分插件存在漏洞,给整个网站带来安全风险.Kali Linu ...

  9. atitit.MyEclipse10 中添加svn插件故障排除

    atitit.MyEclipse10 中添加svn插件故障排除 删除\configuration \org.eclipse.update 不行... 二. 在configuration下的config ...

随机推荐

  1. play framework系列之maven 构建

    一,文章内容 1,Play framwwork 的好处就是构建java 项目简单快速.经过下边几步即可完成. play new testSimpleMvn 选择2 java 项目即可. 然后进入到 t ...

  2. Codeforces Beta Round #14 (Div. 2) B. Young Photographer 水题

    B. Young Photographer 题目连接: http://codeforces.com/contest/14/problem/B Description Among other thing ...

  3. 微服务架构的分布式事务解决方案 - zhaorui2017的博客 - CSDN博客

    微服务架构的分布式事务解决方案 - zhaorui2017的博客 - CSDN博客   http://blog.csdn.net/zhaorui2017/article/details/7643679 ...

  4. Consul + fabio 实现自动服务发现、负载均衡 - DockOne.io

    Consul + fabio 实现自动服务发现.负载均衡 - DockOne.io   http://dockone.io/article/1567

  5. Linux/CentOS服务器 一个网卡绑定多IP地址(永久设置)

    有时我们在使用 Linux 服务器时需要配置多个IP地址.如果要配置多个IP地址是否需要多块网卡呢?答案是否定的.以 CentOS 系统为例,多个 IP 地址是可以共享一块物理网卡的. 如何永久为单网 ...

  6. delphi:临界区对象TCriticalSection(Delphi) 与 TRtlCriticalSection 的区别

    临界区对象TCriticalSection(Delphi) 与 TRtlCriticalSection 的区别 TRtlCriticalSection 是一个结构体,在windows单元中定义: 是I ...

  7. Delphi XE 5,Rad Studio XE 5 官方下载(附破解),更新 Update 1,Help Update 1

    Delphi XE 5 破解,有图有真相 Embarcadero RAD Studio XE5 Update 2 v19.0.14356.6604 (等待破解中...): http://altd.em ...

  8. JMeter学习(二十三)关联

    话说LoadRunner有的一些功能,比如:参数化.检查点.集合点.关联,Jmeter也都有这些功能,只是功能可能稍弱一些,今天就关联来讲解一下. JMeter的关联方法有两种:后置处理器-正则表达式 ...

  9. transitionFromView方法的使用

    transitionFromView方法的使用 效果 源码 // // ViewController.m // TransitionFromView // // Created by YouXianM ...

  10. MySQL查询字符串长度最长的记录

    select `字段`, length(`字段`) from 表名 where length(`字段`) = ( select max(length(`字段`)) from 表名  )http://s ...