构建检测,无规矩不成方圆

2023-11-02 22:10

本文主要是介绍构建检测,无规矩不成方圆,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这个专栏的第 5 篇文章《手把手教你依赖管理》中,我介绍了构建 Java 项目的一些最佳实践,同时也给你抛出了一个问题:如果用户偷懒不遵循这些规范该怎么办?

所谓没有规矩不成方圆,构建是持续交付过程中非常重要的一步,而好的构建检测则可以直接提 升交付产物的质量,使持续交付的流水线又快又稳。所以,也就有了 Maven 构建中的大杀器: Maven Enforcer 插件。

什么是 Maven Enforcer 插件?

Maven Enforcer 插件提供了非常多的通用检查规则,比如检查 JDK 版本、检查 Maven 版本、 检查依赖版本,等等。下图所示就是一个简单的使用示例。

 

上述的配置会在构建时(准确的说是在 validate 时)完成三项检查:

requireMavenVersion 检查 Maven 版本必须大于 3.3.9;

requireJavaVersion 检查 JDK 版本必须大于等于 1.9;

requireOS 检查 OS 必须是 Windows 系统。

如果你使用 Java 1.8, Maven 3.3.3, 在 Linux 上构建, 便会出现如下的错误:

Rule 0: org.apache.maven.plugins.enforcer.RequireMavenVersion failed with message: Detected Maven Version: 3.3.3 is not in the allowed range 3.3.9.
Rule 1: org.apache.maven.plugins.enforcer.RequireJavaVersion failed with message: Detected JDK Version: 1.8.0-77 is not in the allowed range 1.9.
Rule 2: org.apache.maven.plugins.enforcer.RequireOS failed with message: OS Arch: amd64 Family: unix Name: linux Version: 3.16.0-43-generic is not allowed by Family=windows

从而导致构建失败。那么,是否有办法在所有应用的构建前都执行 Enforcer 的检查呢。

我在专栏的第 5 篇文章《手把手教你依赖管理》中,也已经介绍了在携程内部,一般 Java 应用 的继承树关系,每个项目都必须继承来自技术委员会或公司层面提供的 super-pom。携程在 super-pom 之上又定义了一层 super-rule 的 pom,这个 pom 中定义了一系列的 Enforcer 规 则。 这样,只要是集成了 super-pom 的项目,就会在构建时自动运行我们所定义的检查。

也许你会问了, 如果用户不继承 super-pom 是不是就可以跳过这些规则检查了?是的, 继承 super-pom 是规则检查的前提。

但是,我们不会给用户这样的机会, 因为上线走的都是统一的构建系统。

构建系统在构建之前会先检查项目的继承树,继承树中必须包含 super-pom, 否则构建失败。并且,构建系统虽然允许用户自定义 Maven 的构建命令,但是会将 Enforcer 相关的参数过滤掉,用户填写的任何关于 Enforcer 的参数都被视为无效。Enforcer 会被强制按照统一标准执 行,这样就保证了所有应用编译时都要经过检查。

因为携程的构建系统只提供几个版本的 Java 和 Maven,并且操作系统是统一的 Linux CentOS 版本,所以就不需要使用之前例子中提到的三个检查,一定程度的缩小标准化范围,也是有效的 质量保证手段。

了解了 Maven Enforcer 插件,我再从 Maven Enforcer 内置的规则、自定义的 Enforcer 检查 规则,以及构建依赖检查服务这三个方面,带你一起看看构建监测的“豪华套餐”,增强你对交 付产物的信心。

丰富的内置的 Enforcer 规则

Maven Enforcer 提供了非常丰富的内置检查规则,在这里,我给你重点介绍一下 bannedDependencies 规则、dependencyConvergence 规则,和 banDuplicateClasses 规则。

第一,bannedDependencies 规则

该规则表示禁止使用某些依赖,或者某些依赖的版本,使用示例:

该代码检查的逻辑是,只允许使用版本大于等于 1.8.0 的 org.slf4j:slf4j-api 依赖,否则将会出 现如下错误: 

bannedDependencies 规则的常见应用场景包括:

1. 当我们知道某个 jar 包的某个版本有严重漏洞时,可以用这种方法禁止用户使用,从而避免 被攻击;

2. 某个公共组件的依赖必须要大于某个版本时,你也可以使用这个方法禁止用户直接引用不兼 容的依赖版本,避免公共组件运行错误。

第二,dependencyConvergence 规则

在《手把手教你依赖管理》一文中,我介绍了 Maven 的依赖仲裁的两个原则:最短路径优先原 则和第一声明优先原则。

但是,Maven 基于这两个原则处理依赖的方式过于简单粗暴。毕竟在一个成熟的系统中,依赖 的关系错综复杂,用户很难一个一个地排查所有依赖的关系和冲突,稍不留神便会掉进依赖的陷 阱里,这时 dependencyConvergence 就可以粉墨登场了。

dependencyConvergence 规则的作用是: 当项目中的 A 和 B 分别引用了不同版本的 C 时,Enforce 检查失败。 下面这个实例,可以帮你理解这个规则的作用。

org.slf4j:slf4j-jdk14:1.6.1 依赖了 org.slf4j:slf4j-api:1.6.1, 而 org.slf4j:slf4j-nop:1.6.0 依赖 了 org.slf4j:slf4j-api:1.6.0,当我们在构建项目时, 便会有如下错误: 

这时就需要开发人员介入了,使用 dependecy 的 exclusions 元素排除掉一个不合适的版本。 虽然这会给编程带来一些麻烦, 但是非常必要。因为,我始终认为你应该清楚地知道系统依赖 了哪些组件, 尤其是在某些组价发生冲突时,这就更加重要了。

第三,banDuplicateClasses 规则

该规则是 Extra Enforcer Rules 提供的,主要目的是检查多个 jar 包中是否存在同样命名的 class,如果存在编译便会报错。 同名 class 若内容不一致,可能会导致 java.lang.NoSuchFieldError,java.lang.NoSuchMethodException 等异常,而且排查起来非 常困难,因为人的直觉思维很难定位到重复类这个非显性错误上,例如下面这种情况:

org.jboss.netty 包与 io.netty 包中都包含一个名为 NettyBundleActivator 的类,另外还有 2 个重复类:spring/NettyLoggerConfigurator 和 microcontainer/NettyLoggerConfigurator。

 当激活了 banDuplicateClasses 规则之后,Enforcer 检查,便会有如下的报错:

通常情况下,用户需要排除一个多余的 jar 包来解决这个问题,但有些情况下两个 jar 包都不能 被排除,如果只是个别类名冲突了,那么可以通过 ignoreClasses 去忽略冲突的类,类名可以 使用通配符(*),如: org.jboss.netty.container.*。

但是,用户不能随意更改这个配置,因为它必须得到一定的授权,否则随意忽略会产生其他不确 定的问题。因此我们将这个插件做了一些改动,通过 API 来获取 ignoreClasses 的内容。当用 户有类似的需求时,可以提交 ignoreClasses ,但必须申请,经过 Java 专家审批之后才可忽略 掉。

自定义的 Enforcer 检查规则 除了上述的官方规则,实际上携程还做了若干个扩展的规则,如:

CheckVersion,用于检查模块的版本号必须是数字三段式,或者带有 SNAPSHOT 的数字三 段式;

CheckGroupId,用于检查 GroupId 是否符合规范,我们为每个部门都分别指定了 GroupId;

CheckDistributionManagementRepository,用于检查项目的 distributionManagement 中的 repository 节点,并为每个部门都指定了他们在 Nexus 上面的 repositroy;

CheckSubModuleSaveVersion,用于检查子模块版本号是否与父模块版本号一致。 以上,便是携程基于 Maven Enforcer 在构建检查上的一些实践,你可以借鉴使用。

但是,有时候 Maven Enforcer 也无法满足我们所有的需求,比如,它无法完成非 Java 项目的检查。因此,我们还有一个通用的依赖检查服务。

构建依赖检查服务

其他语言, 比如 C#,NodeJS 等,没有 Maven Enforcer 这样成熟的工具来做构建时的依赖检 查。对于这类语言我们的做法是:构建后,收集该项目所有的依赖及其版本号,将这些数据发送

给依赖检查服务 Talos,Talos 根据内置的规则进行依赖检查。Talos 是一套携程自研的,独立的,组件依赖检查系统,其中包含的检查逻辑,完全可以自由定义。

而且,Talos 依赖检查的逻辑更新非常灵活,可以直接在平台内使用 Java 代码在线编写检查逻 辑,提交后便可实时生效。

以下是一段 .NET 项目检查逻辑的示例代码:

该逻辑的含义是: 当项目的依赖存在 foo.dll 和 bar.dll 时,bar.dll 的版本号必须大于 1.0.0.0。看, 是不是非常方便快捷通用!

这样一套组合拳下来,构建检测以及项目依赖的问题已不再那么让人望而生畏了。因此,工欲善 其事必先利其器, 好的工具可以解放大量的生产力,最重要的是构建检测后的交付让你我更有 信心了。有条不紊的流程与规范,就像一列高速列车下的枕木,时刻保证着整个系统稳定而可靠 地推进。

总结与实践

我围绕着构建检测,和你一起学习并介绍了:

  1. Maven Enforcer 插件可以帮我们更好地完成编译检测;

  2. 可以使用内置的 Maven Enforcer 规则,覆盖常规检测;

  3. 可以使用自定义 Maven Enforcer 检查规则的方式,增加版本号规则等的检查;

  4. Maven Enforcer 之外,你还可以自己丰富一些例如依赖版本检测这样的服务,以提高检测 效果。

Maven Enforcer 提供了非常丰富的内置检查规则,感兴趣的话,你可以通过 https://maven.apache.org/enforcer/enforcer-rules/index.html 以及 http://www.mojohaus.org/extra-enforcer-rules/ 逐个尝试这些规则,并说说哪些规则是你工 作总最最需要的。

 

 

 

 

这篇关于构建检测,无规矩不成方圆的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/333635

相关文章

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Golang使用etcd构建分布式锁的示例分享

《Golang使用etcd构建分布式锁的示例分享》在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统,分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要,它有助于维护一致性,防止竞... 目录引言环境准备新建Go项目实现加锁和解锁功能测试分布式锁重构实现失败重试总结引言我们将使用Go作

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.