health4j—Java项目的全面体检工具

简介: 最近利用业余时间写了一个Java代码静态分析工具的聚合器。集成了三种主流的静态分析工具:pmd,checkstyle,findbugs。可以用这三种工具提供的几千种规则集,来给你的项目进行全面体检,同时附带了归纳整理并提供邮件通知。

最近利用业余时间写了一个Java代码静态分析工具的聚合器。集成了三种主流的静态分析工具:pmdcheckstylefindbugs。可以用这三种工具提供的几千种规则集,来给你的项目进行全面体检,同时附带了归纳整理并提供邮件通知。代码开源在github上,取名为health4j

开发这个工具的初衷是希望它能约束自己代码的规范性。同时,引导自己采用一些已被业界认可的“最佳实践”,保证至少自己的代码更加“health”。写它的另一个目的,是继续我的个人爱好——“自动化”工具。

代码的整洁、规范,对于一个软件项目的重要性不言而喻。特别是那些曾经维护过别人遗留代码的人,相信你们都深有感触。但不要说别人,即便是我们自己写的代码,隔个三五个月自己再回头看,有时也是不知所云。当然对于代码缺陷而言,更可能会成为影响项目健壮性的一个定时炸弹。因此我认为,此举至少对我个人而言是有利的。

分析工具简介

这三个Java界的主流静态代码分析工具的对比:


需要说明的是,checkstyle主要用于检查代码书写规范。pmd,findbugs则是非常出名的缺陷分析工具。它们收集了非常多的检查规则和缺陷模式。其中pmd用于分析java源码,而findbugs分析的是java编译后的字节码,jtest是商业工具,目前并未集成。

设计

逻辑结构图:


该项目目前提供了三个分析工具的实现。每个工具都被拆分为三个部件:EnvVerifier(环境验证器),CommandInvoker(命令执行器),ReportExtractor(报告提取器)。每个工具的执行,在内部都会触发这三个部件的依次执行。并且每个工具都被内聚为一个任务,以供在线程池中并发执行。

每个工具的运行,都会伴随着输出自己的xml格式的报表文件。根据配置文件中是否启用了合并器,来决定是否需要对每个工具输出的报表文件作解析并提取(ReportExtractor),以供下面的聚合器聚合之用。

如果开启了聚合器,从每个工具输出的报表文件中,提取出公共的数据信息(来自于每个工具数据信息的抽象),然后根据给定的聚合模板,生成一份聚合后的html报表。

如果开启了通知器,那将会根据通知器的实现(默认给出的是邮件通知),将聚合后的html发送给目标。

类图结构:


从代码的设计图中可看出,每个动作都有与之对应的接口抽象。因此虽然只提供了三个工具的实现,但它仍然有良好的扩展性。只需提供相应的接口实现,并定义好需要的配置文件信息,可以添加更多的分析工具。在每个工具的实现上,添加图中的Tool注解,并标明其名称(name属性)。health4j在运行时,会自动扫描到该实现,并将其加入到线程池中执行。

Java SE的服务加载器

在开发web项目的时候,我们通常会引入spring来作为Ioc容器,这样我们可以将抽象与具体的实现隔离。但对于一个小的standalone项目,这么做似乎有些杀鸡用牛刀的感觉。不过幸好JDK自1.6版本后就提供了SPI(ServiceProvider Interface)的默认实现。有了它,你在写一些小工具的时候,不用spring这么“重”的bean容器,也可以实现Ioc。具体的做法很简单。它提供了一个ServiceLoader的泛型类。会从一个指定的位置加载对某个Service(该Service通常被定义为一个接口或抽象类)实现的配置。

比如这里的两个服务接口:ReportMerger,ReportNotifier。我们首先在一个项目的资源文件夹内创建一个名为“META-INF.services”文件夹。然后里面创建两个配置文件。每个配置文件都以接口的完全限定名作为文件名称:


而每个文件的内容也异常简单,你只需要指定该服务接口的提供者(实现类)的完全限定名即可:

com.freedom.health4j.api.impl.common.DefaultMerger

这样在获取该接口提供者的时候,我们便无需显示将该提供者的实例化过程与该服务绑定。示例:

private static void merge(ReportInfo reportInfo) {
        if (Boolean.valueOf(commonConfig.getProperty(Constants.COMMON_ENABLE_MERGE_KEY))) {
            ServiceLoader<ReportMerger> serviceLoader = ServiceLoader.load(ReportMerger.class);
            Iterator<ReportMerger> mergerIterator = serviceLoader.iterator();

            if (!mergerIterator.hasNext()) {
                throw new RuntimeException("can not load service provider for service : ReportMerger");
            }

            ReportMerger merger = mergerIterator.next();
            merger.setCommonConfig(commonConfig);
            merger.merge(reportInfo);
        }
    }

虽然这种方式不及Spring等专业Ioc容器那样强大。不过对于开发一些工具类的小应用而言,却是非常简单并且实用。

使用与集成

该工具可作为独立的jar执行,也可以构建为unix-like-service(见)。当然作为自动化的一部分,我们仍然希望有非人为因素之外的其他触发条件。这里,可以列举几个常用的触发条件:

  • 时间触发:利用linux定时任务在指定的时间触发
  • 事件触发:在VCS等代码版本控制软件的hook中触发
  • 持续集成:通过maven/ant等构建工具的task触发
无论哪种触发方式,该工具首先需要发布到项目的源代码所宿主的服务器上去。并且每个工具拥有者自己的规则集合,这些规则都可配置,它们都位于release/conf文件夹内。
其运行结果示例如下图:

综述

很多事情的发展都有着相似的历程:从最初的固执己见到最后的遵循标准。标准代表了各自利益的共同部分,如果你的团队到现在还没有形成统一的代码风格,到现在还没有意识到采用最佳实践是避免缺陷的最终选择,那么你需要这份工具。当然有了这份工具才只是第一步,它只是一个你是否执行标准的检查器。下一步才是关键:你们需要坐下来商讨哪些是值得你们为之改变规则,也就是你们希望形成的标准。

项目地址:https://github.com/yanghua/health4j


原文发布时间为:2015-01-26

本文作者:vinoYang

本文来自云栖社区合作伙伴 CSDN博客,了解相关信息可以关注CSDN博客。

目录
相关文章
|
20天前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
31 1
|
1天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
10 3
|
4天前
|
前端开发 Java 数据库
如何实现一个项目,小白做项目-java
本教程涵盖了从数据库到AJAX的多个知识点,并详细介绍了项目实现过程,包括静态页面分析、数据库创建、项目结构搭建、JSP转换及各层代码编写。最后,通过通用分页和优化Servlet来提升代码质量。
12 1
|
27天前
|
JavaScript 前端开发 Java
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
这篇文章详细介绍了如何在前端Vue项目和后端Spring Boot项目中通过多种方式解决跨域问题。
295 1
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
|
12天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
12天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
15天前
|
Web App开发 Java
使用java操作浏览器的工具selenium-java和webdriver下载地址
【10月更文挑战第12天】Selenium-java依赖包用于自动化Web测试,版本为3.141.59。ChromeDriver和EdgeDriver分别用于控制Chrome和Edge浏览器,需确保版本与浏览器匹配。示例代码展示了如何使用Selenium-java模拟登录CSDN,包括设置驱动路径、添加Cookies和获取页面源码。
|
11天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
24天前
|
Java Apache Maven
Java/Spring项目的包开头为什么是com?
本文介绍了 Maven 项目的初始结构,并详细解释了 Java 包命名惯例中的域名反转规则。通过域名反转(如 `com.example`),可以确保包名的唯一性,避免命名冲突,提高代码的可读性和逻辑分层。文章还讨论了域名反转的好处,包括避免命名冲突、全球唯一性、提高代码可读性和逻辑分层。最后,作者提出了一个关于包名的问题,引发读者思考。
Java/Spring项目的包开头为什么是com?
|
26天前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
35 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用