千家信息网

如何使用p3c实现自定义代码规范检查

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章将为大家详细讲解有关如何使用p3c实现自定义代码规范检查,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。p3c,一款代码规范的检查工具,有对应的
千家信息网最后更新 2026年11月01日如何使用p3c实现自定义代码规范检查

这篇文章将为大家详细讲解有关如何使用p3c实现自定义代码规范检查,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

p3c,一款代码规范的检查工具,有对应的ide插件,能在编码过程中对设置的规则进行提示,便打算对它进行拓展,增加对fastjson检查是否打开setAutoType特性的检查。

 p3c主要包括3部分:

  • PMD实现(p3c-pmd):使用PMDhttps://pmd.github.io/来实现代码规范检查

  • Intellij IDEA插件

  • Eclipse插件

1. PMD

 p3c使用了PMD。PMD是一款静态代码扫描工具,该工具可以做到检查Java代码中是否含有未使用的变量、是否含有空的抓取块、是否含有不必要的对象等。PMD使用JavaCC生成解析器来解析源代码并生成AST(抽象语法树),通过对AST的检查可以直接从源代码文本层面来对代码进行检查,在PMD内部称为规则。即是否符合规则指的是,穷举源码各种可能的写法,然后在AST上检查是否出现。而规则的实现,重点便在对AST的处理上。

1.1. AST

 关于AST的介绍网上有很多,可以直接搜索,这里重要提两点:

  • AST是源代码的抽象语法结构的树状表示

  • 抽象语法树并不依赖于原语言的语法,也就是说同语法分析阶段所采用的上下文无关

 PMD使用JavaCC来生成AST。关于JavaCC也可以在网上查看相关资料,这里不多介绍,只要知道JavaCC是一个词法分析生成器和语法分析生成器便行。

1.2. 自定义规则

 PMD官方文档介绍了自定义规则的实现步骤,过程比较清晰,这里不赘述,只介绍下本文需要设计的步骤。

1.2.1. 定义规则集

 PMD的规则需要配置在XML文件中

  • 新建如下的空文件表示规则集

                                                        My custom rules                                                        ```        * 在上面的``` ruleset ``` 标签中引用自定义规则        ```                ```* 配置规则集            ###### 1.2.2. 配置规则 可以在 ``` rule ``` 标签中对某一规则进行配置* 配置提示消息和告警级别        ```              5                ```        告警优先级分为1-5个level,1最高,5最低        * 配置运行参数        可以通过 ``` properties ``` 和 ``` propertie ```对类属性赋值        ###### 1.2.3. 编写规则 规则的编写比较简单,PMD已经给我们做好了配套的开发框架和工具,只要确定后规则出现的情况,按照固定的模式去编写即可。* 确定实现方式        可以使用纯Java方式实现,也可以使用XPath方式实现。                对于纯Java方式,PMD框架本身实现了对AST数的遍历,用户只要在遍历各个节点的时候,对自定义规则的各种情况进行分析判断即可,过程类似与DOM文件的SAX解析,以流和事件的方式来解析AST内容。                对于XPath方式,则是将AST作为一个XML数,以XPath的方式来遍历解析内容。        * 根据测试代码确定可能出现的情况        PMD自带了一个designer,可以用来生成对应代码的AST内容。对于本文需要达到的效果,涉及到如下代码:                ```                import com.alibaba.fastjson.parser.ParserConfig;        public class NegativeExample {                        public static void main(String[] args) {                ParserConfig.getGlobalInstance().setAutoTypeSupport(true);            }        }                ```                在designer中可以得到如下的AST内容          ![file](https://oscimg.oschina.net/oscnet/491a18dd2086a3919b55fe84e4de1007549.jpg)                具体内容这里就不贴出来了,可以下载desigin然后贴上上面的代码就会有。                对于本文的需求,需要确定在有import ``` ParserConfig ``` 类的时候,调用了 ``` setAutoTypeSupport ``` 方法且参数为 ``` true ```。当然这个条件是不够严谨的,还需要判断是否调用了 ``` ParserConfig ```,也要考虑有通过import导入直接写全限定名的。但考虑到一般的写法,以及ide的格式化处理,这样处理已经可以满足大部分场景了。        * 编写规则实现类        确定了规则的判断条件,就可以着手写代码了。                对于Java方式,可以直接继承 ```net.sourceforge.pmd.lang.java.rule.AbstractJavaRule ``` 类,然后重写各种节点的visit方法即可。                例如如下,用于判断是否有import ``` ParserConfig ``` 类                ```        private final String PARSER_CONFIG_IMPORT_NAME = "com.alibaba.fastjson.parser.ParserConfig";                private boolean hasImport = false;                @Override    public Object visit(ASTImportDeclaration node, Object data) {        if (PARSER_CONFIG_IMPORT_NAME.equals(node.getImportedName())) {            hasImport = true;        }        return super.visit(node, data);    }        ```        对于XPath方式,可以通过继承 ``` net.sourceforge.pmd.lang.rule.XPathRule ``` 类,重写 ``` setXPath ``` 方法设定对应的XPath即可。上面提到过,可以通过 ``` property ``` 配置对类的属性进行赋值,因而,对于XPat方式,可以在xml配置中进行如下设置来启用XPath。                ```                Rule Description                  3                                                                                                                       ```###### 1.2.4. 测试规则 PMD推荐对于每个规则,至少要有一个正向和逆向的测试用例,来验证规则出现和不出现的情况。对于规则的测试,PMD也提供了一套框架,只要按照约定好的方式添加xml测试文件即可。 PMD约定了几个规则,用来加载测试案例* 测试类要继承 ``` net.sourceforge.pmd.testframework.PmdRuleTst ```类,该整合了Junt,可以在里面增加需要的测试方法。* 对于在 ``` src/test/resource ``` 和测试类对应的路径下增加一个xml目录,在增加同第一步同名的xml文件,该文件用于书写测试集。        例如官网给出的例子        规则实现类路径如下:        ```net.sourceforge.pmd.lang.java.rule.bestpractices.AbstractClassWithoutAbstractMethodTest                        ```                测试案例集如下:                ```        src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AbstractClassWithoutAbstractMethod.xml                ```                xml的规则则可以参考官网介绍,这里不再赘述。#### 2. p3c-pmd 代码规范实现的主要模块,使用pmd来实现。p3c-pmd模块在代码组织上很工整,可以按照相同的模式增加自定义的规则/规则集。 对于本文需求,打算在该模块的基础上增加一个extend模块,用于实现自定义规则集。如下,为对应的源码路径好规则集路径![file](https://oscimg.oschina.net/oscnet/3e3f8a123f38290ab7992a2ac7db6e7d9d0.jpg)![file](https://oscimg.oschina.net/oscnet/2e451daf3afca20540f4802d6ae072b8c66.jpg) 本文采用纯Java方式实现规则,按照1.2.3.节的描述,可以得到如下的实现类

public class AvoidFastJsonAutoTypeSupportRule extends AbstractAliRule {

private final String PARSER_CONFIG_IMPORT_NAME = "com.alibaba.fastjson.parser.ParserConfig";private final String SET_AUTO_TYPE_SUPPORT_NAME = "setAutoTypeSupport";private boolean hasImport = false;@Overridepublic Object visit(ASTImportDeclaration node, Object data) {    if (PARSER_CONFIG_IMPORT_NAME.equals(node.getImportedName())) {        hasImport = true;    }    return super.visit(node, data);}@Overridepublic Object visit(ASTPrimaryExpression node, Object data) {    if (hasImport) {        int size = node.jjtGetNumChildren();        for (int i = 0; i < size; i++) {            Node child = node.jjtGetChild(i);            String imageName = null;            if (child instanceof ASTPrimaryPrefix) {                ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) child;                imageName = prefix.jjtGetChild(0).getImage();            }else if (child instanceof ASTPrimarySuffix){                ASTPrimarySuffix suffix = (ASTPrimarySuffix) child;                imageName = suffix.getImage();            }            if (imageName == null) {                continue;            }else if (imageName.endsWith(SET_AUTO_TYPE_SUPPORT_NAME)){                ASTPrimarySuffix argumentSuffix = (ASTPrimarySuffix) node.jjtGetChild(i + 1);                try {                    List booleanArgs = argumentSuffix.findChildNodesWithXPath("//PrimaryPrefix/Literal/BooleanLiteral");                    if (booleanArgs.size() == 1) {                        ASTBooleanLiteral booleanLiteral = (ASTBooleanLiteral) booleanArgs.get(0);                        if (booleanLiteral.isTrue()) {                            ViolationUtils.addViolationWithPrecisePosition(this, argumentSuffix, data,                                I18nResources.getMessage("java.extend.AvoidFastJsonAutoTypeSupportRule.rule.msg" ));                        }                    }                } catch (JaxenException e) {                    e.printStackTrace();                } finally {                    break;                }            }        }    }    return super.visit(node, data);}

}

 对应规则集中的配置为

java.extend.AvoidFastJsonAutoTypeSupportRule.rule.desc 1

  public class NegativeExample {      public static void main(String[] args) {          ParserConfig.getGlobalInstance().setAutoTypeSupport(true);      }  }

]]>

 这里有几点需要注意的,类 ``` AvoidFastJsonAutoTypeSupportRule ``` 继承自 ``` com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule ```,AbstractAliRule继承自AbstractJavaRule,重写了setDescription,setMessage和addViolationWithMessage等方法,这里提到的3个方法,增加了多语言支持。p3c-pmd使用Resource Bundle来提供多语言支持。每个消息都有一个唯一id来对应,p3c-pmd通过重写方法,将方法参数映射为消息的id,以统一消息的配置。如下为本地对应的消息提示内容
        

说明:fastjson的setAutoTypeSupport特性存在安全漏洞 ]]>

 对于测试,按照1.2.4.的介绍,则有如下的文件路径![file](https://oscimg.oschina.net/oscnet/67322e2edc5dcc7d1e8148149930404a64d.jpg)文件内容比较简单,这里就不贴出来了。 至此,已经完成了自定义规则的实现,现在就是要把该内容应用到ide上了。首先,需要将该模块进行编译,这里直接保存到本地maven参考,好在本地调试。 直接将p3c-pmd的版本升级为2.0.1,然后执行mvn install,可以在本地仓库看到对应的版本![file](https://oscimg.oschina.net/oscnet/fe9ed36fd7ef30cb794e550782ee4d5d4c3.jpg)有了该版本,则可以在其他模块引用该版本进行新功能调试,下面将以idea-plugin模块为例。#### 3. idea-plugin idea-plugin主要实现了idea的插件,能够对代码进行实时检查。这里涉及到idea自定义插件的开发,这里就不深入了,网上有很多教程。这里只介绍如何将上面自定义的规则接入该模块。1.修改idea-plugin模块的build.gradle文件,开启本地仓库配置,以便从本地直接加载最新的p3c-pmd依赖。

buildscript { repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' } mavenLocal() mavenCentral()

}dependencies {    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"}

}

allprojects { group 'com.alibaba.p3c.idea' apply plugin: 'java' apply plugin: 'kotlin' apply plugin: 'maven-publish'

sourceCompatibility = 1.8compileJava.options.encoding = 'UTF-8'configurations.all {    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'}repositories {    mavenLocal()    jcenter()    mavenCentral()}dependencies {    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"    testCompile group: 'junit', name: 'junit', version: '4.11'}

}

如上,增加了```mavenLocal()```2.修改p3c-common的build.gradle,更改p3c-pmd的版本为2.0.13.修改p3c-common模块resources/rulesets/java/ali=pmd.xml,增加

```

以增加自定义规则检查。

4.在p3c-common模块下,执行gradle clean buildPlugin,生成对应的插件。

4. 验证

 本地安装该插件,可以得到如下效果

这里只验证效果,没有真正引入fastjson依赖,也验证了pmd检查的是源码文本。

关于如何使用p3c实现自定义代码规范检查就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

规则 代码 检查 方式 测试 模块 配置 内容 文件 方法 插件 生成 语法 消息 版本 路径 工具 情况 分析 验证 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 天津市摩尔互联网科技 厦门中拓互联网络科技有限公司 互联网巨头反垄断金融科技 互联网科技ppt模板 科技大学互联网专业好不好 互联网之后的科技是什么 中国互联网有什么科技含量 互联网和黑科技的看法 互联网科技扶贫时间 中国互联网公司排名锤子科技 朱啸虎曾投资哪些互联网科技企业 互联网科技圈年度人物 上海创道互联网络科技有限公司 易企秀互联网科技是做什么的 九思连强互联网电子科技有限公司 珠海东科互联网科技有限公司 容联科技互联网电商 互联网公司属于科技吗 承德科技产业互联网平台 小牛互联网科技有限公司地址 精品咖啡豆 中资互联网科技 北京互联网科技 世界互联网领先科技成果 亿账通互联网科技 长亮科技互联网金融 以后互联网后是啥科技 全球顶尖互联网科技公司 江阴互联网智能科技产品进口 银川新华互联网科技学校招聘
0