Java

升级 Maven 插件

升级 Maven 插件

D瓜哥
D瓜哥在 关于升级 Spring 等依赖的一些经验 中,介绍了一些升级 Spring 等依赖的一些经验。在 升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 的影响 中,分析了升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 异常的影响。在升级中,还遇到一些 Maven 插件相关的问题。这里也分享出来,希望对大家有所帮助。 Properties 文件编码错误 在升级过程中,遇到过 Properties 文件编码错误的问题。可以通过配置对应的编码来解决这个问题。配置如下: <!-- D瓜哥 · https://www.diguage.com --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.0</version> <configuration> <propertiesEncoding>ISO-8859-1</propertiesEncoding> </configuration> </plugin> 参考资料 Apache Maven Resources Plugin – Filtering Properties Files。 使用 Maven Enforcer 插件检查依赖 私以为“机器可以干的事情,就应该交给机器干”。对于依赖管理,Maven Enforcer 插件就可以对依赖做必要的检查。所以,推荐使用 Maven Enforcer 插件来检查低版本及有安全漏洞的依赖。 详细介绍请参考: 使用 Maven Enforcer 插件检查依赖 字节码文件包含原始参数名称 一些对外发布的依赖,建议将原始参数名称编译到构建结果里。可以通过指定构建参数来完成。 <!-- D瓜哥 · https://www.diguage.com --> <plugin> <groupId>org.
升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 的影响

升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 的影响

D瓜哥
在 关于升级 Spring 等依赖的一些经验 中,分享了一些开源依赖的升级经验。部分小伙伴质疑升级 iBATIS/MyBATIS 会影响对 DuplicateKeyException 异常的处理。这篇文章就从源码分析/代码更新的就角度来分析一下升级相关依赖是否会对 DuplicateKeyException 异常的处理带来实质性的影响。 由于主要的技术栈涉及 MySQL 驱动、iBATIS、MyBATIS、Spring 周边等。所以,本文仅分析涉及的这些依赖。 D瓜哥使用 MySQL: Employees Sample Database 搭建了一个 Spring + MyBATIS + MySQL Connector/J 的测试环境。连续插入两条一样的数据,单步调试,在 com.mysql.jdbc.MysqlIO#sendCommand 方法中,就可以观察到如下异常: 图 1. MySQL Error 1062 从这里可以明显看出,MySQL 驱动返回的异常中, venderCode 编码是 1062。 顺着这个线,往上走,到 org.apache.ibatis.session.defaults.DefaultSqlSession#update(java.lang.String, java.lang.Object) 方法中,可以看到, 图 2. MyBATIS wrap Exception 在这里,会将 SQLException 包装成 PersistenceException,这也是 MyBATIS 对外暴露的统一的异常类。 继续往上走,就到了 org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke 方法: 图 3. MyBATIS translateException 在 SqlSessionInterceptor#invoke 方法的异常处理中,将 PersistenceException 异常通过 org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible 方法,将异常转换成 DataAccessException 对象。 DataAccessException 类是 Spring 数据访问的异常类基类。
深入理解 Java 代码块

深入理解 Java 代码块

D瓜哥
在 Java 虚拟机操作码探秘:常量指令 中对 Java 虚拟机操作码中关于常量操作的指令(操作码)做了初步介绍。估计会有人疑问:文中的“栈”、“栈顶”等是什么?接下来就准备解答这些疑问。 在答疑解惑之前,先来了解一下 Java 编译器对 Java 代码中的代码块是如何处理的?常见的代码块有普通代码块和静态代码块,下面对其做分别介绍。由于涉及到构造函数,所以,先对构造函数做一个介绍。 构造函数 无构造函数 先来看看当没有声明构造函数时,编译结果是什么样的: /** * 无构造函数示例 * * @author D瓜哥 · https://www.diguage.com */ public class Example { } 编译后,使用 javap -c 查看一下编译结果: $ javap -c Example Compiled from "Example.java" public class Example { public Example(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return } 从结果上来看:编译器自动给没有声明构造函数的类,生成了一个无参构造函数,并且在其中调用了父类(这里是 Object)的无参构造函数。这是大家都熟知的基础知识。 有参构造函数 再来看看当有声明参数的构造函数时,编译结果是什么样的: /** * 有参构造函数示例 * * @author D瓜哥 · https://www.
Java 虚拟机操作码探秘:常量指令

Java 虚拟机操作码探秘:常量指令

D瓜哥
在 Java 虚拟机指令(操作码)集 中给出了一个操作码的列表。针对所有的指令,仅仅给出了一个大概介绍,对理解来说可以说毫无助力。为了弥补这个短板,这里也学习 “Hessian 协议解释与实战”系列 那样,来一个详细解释和实战,配合实例来做个深入分析和讲解。这是这个系列的第一篇文章,就以列表中第一部分“常量”指令开始。 从 Java 虚拟机指令(操作码)集 列表上来看,一共 21 个指令;按照处理数据的类型,合并同类项后,剩下有 nop、 aconst_null、 iconst_<i>、 lconst_<l>、 fconst_<f>、 dconst_<d>、 bipush、 sipush、 ldc 和 ldc2_w 等几个指令。下面,按照顺序,对其进行一一讲解。 操作码助记符的首字母一般是有特殊含义的,表示操作码所作用的数据类型: i 代表对 int 类型的数据操作; l 代表 long; s 代表 short; b 代表 byte;c 代表 char;f 代表 float, d 代表 double; a 代表 reference。 尖括号之间的字母指定了指令隐含操作数的数据类型,<n> 代表非负的整数; <i> 代表是 int 类型数据; <l> 代表 long 类型; <f> 代表 float 类型; <d> 代表 double 类型。 另外还需要指出一点:这种指令表示法在整个 Java 虚拟机规范之中都是通用的。
制定组织内 Maven BOM 的一些规范

制定组织内 Maven BOM 的一些规范

D瓜哥
在 关于升级 Spring 等依赖的一些经验 中介绍了 D瓜哥在升级项目依赖时,遇到的一些问题以及一些需要注意的地方。但是,这里还存在一个问题:各个依赖的版本依然散落在各个项目中;升级依赖,需要在所有项目中,把所有相关项目的依赖都巴拉一下,费时费力。解决这个问题的一个比较好的办法是制定一个组织内部的 Maven BOM,集中管理相关依赖的版本。这样升级的时候,还需要修改 BOM 的版本号即可。 Maven BOM 介绍 BOM(Bill of Materials)是由 Maven 提供的功能,它通过定义一整套相互兼容的 jar 包版本集合,使用时只需要依赖该BOM文件,即可放心的使用需要的依赖 jar 包,且无需再指定版本号。 一些基本原则 Spring & Spring Boot 是 Java 生态中,全世界广泛使用的开发框架,在各种场景中都经受过考验。所以,Spring & Spring Boot 选择的 Jar 在稳定性和兼容性方面都有保证。另外,Spring Boot 本身就集成了非常非常多的依赖,并为此创建了一个网页 Spring Boot Dependency versions 来说明它集成的依赖及版本。故而,可以选择以 Spring Boot 为底本,来制作自己的 BOM。 如果不需要 Spring 相关依赖,可以将 Spring 相关依赖删除掉,然后在其之上增加组织内部依赖而创建自己的 BOM。 如果需要 Spring 相关依赖,那么直接继承 在稳定性方面,经过更多人检验的版本,则稳定性更有保障。所以,选择最近两年下载次数比较多的版本。 更新的版本,更容易获得技术升级带来的红利。所以,在可能的情况下,优先选择高版本。 优先考虑目标 JDK 的支持情况。例如,一些依赖的高版本或低版本不支持 Java 8,但是 Java 8 是生产环境部署的主要版本,那么太高的版本和低版本都不适合。 外部 Jar 包选择标准 尽量将外部中间件统一到同一种依赖的同一个版本上。例如:数据库连接池全部使用 HikariCP;JSON 处理统一使用 Jackson。
Java 虚拟机指令(操作码)集

Java 虚拟机指令(操作码)集

D瓜哥
最近在研究 Java 虚拟机字节码。在 《Java虚拟机规范》 看到一个整理完整的 Java 虚拟机指令集(也叫操作码)列表。转载过来,方便查阅。 关于 Java 虚拟机指令(操作码),准备写一个“探秘”系列: Java 虚拟机操作码探秘:常量指令 — 重点介绍一下关于“常量”指令。 分类 操作码 助记符 指令含义 常量 0 0x00 nop 什么都不做 1 0x01 aconst_null 将 null 推送至栈顶 2 0x02 iconst_m1 将 int 类型 -1 推送至栈顶 3 0x03 iconst_0 将 int 类型 0 推送至栈顶 4 0x04 iconst_1 将 int 类型 1 推送至栈顶 5 0x05 iconst_2 将 int 类型 2 推送至栈顶 6 0x06 iconst_3 将 int 类型 3 推送至栈顶
关于升级 Spring 等依赖的一些经验

关于升级 Spring 等依赖的一些经验

D瓜哥
到公司后,熟悉了一些项目后,发现大部分项目的依赖都比较陈旧,比如某些项目还在使用 Spring 3.x 的版本。所以,在进行需求开发时,也顺手把一些项目的依赖给升级了一下。周五,一个小伙伴问我关于升级 Spring 的经验。正好趁此机会,把一些经验总结一下。 下面的描述以 Java 8 为准,没有在其他版本 Java 上试验过。参考时,请慎重。描述的原则如下: 尽量选择还在维护中的版本,而不是已经 End of Life 的过时版。这样有问题可以及时反馈并得到修复。 Java 8 是目标版本,所以,一定要兼容 Java 8。 Spring Framework 升级 Spring Framework 从 3.2.6.RELEASE 开始提供 BOM。可以利用 BOM 简化 Spring 依赖声明: <!-- D瓜哥 · https://www.diguage.com --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>5.3.25</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 这样,就不需要重复声明 Spring 依赖的版本,直接使用即可。 Spring Framework Bom 保证了 Spring 自身依赖的版本统一。 这里,关于 Spring 的升级,还有几点需要说明: 从 Spring 3.X 升级到 Spring 4.X+ 后,原来的 MappingJacksonHttpMessageConverter 已经被删除了;直接使用 MappingJackson2HttpMessageConverter 即可。
Hessian、Msgpack 和 JSON 实例对比

Hessian、Msgpack 和 JSON 实例对比

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。 目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 本文用实际来对比一下 JSON、Hessian 和 MessagePack 的区别。
Hessian 协议解释与实战(五):对象与映射

Hessian 协议解释与实战(五):对象与映射

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 在上一篇文章 Hessian 协议解释与实战(四):数组与集合 中研究了数组和集合的处理方式。接下来介绍对象和映射的处理。 基础工具方法 基础工具方法就不再赘述,请直接参考 Hessian 协议解释与实战(一):基础工具方法 中提到的几个方法。
Hessian 协议解释与实战(四):数组与集合

Hessian 协议解释与实战(四):数组与集合

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 在上一篇文章 Hessian 源码分析(Java) 对 Hessian 的 Java 实现做了一个概要的分析,对处理流程以及整体架构做了一个简单的分析。接下来,回到主题,继续来解释 Hessian 序列化协议。这篇文章,我们来重点分析一下数组与集合相关的操作。