为 Java 注册 classpath: 协议用 URL 读取文件

 本文为 Java 注册 classpath 协议读取文件的目的就是要让下面的代码能工作起来

假设在 classpath 下有个文件 db.properties, 比如在 Maven 项目的 src/main/resources 目录中,或是在某个 jar 包的根位置。如果我们直接执行上面的代码将会得到异常

Exception in thread "main" java.net.MalformedURLException: unknown protocol: classpath
    at java.net.URL.<init>(URL.java:617)
    at java.net.URL.<init>(URL.java:507)

说是不认识的 classpath 协议。

前面代码是有实际用途的,比如说我们使用 XML 时就能支持远程协议

阅读全文 >>

类别: Java/JEE. 标签: , . 阅读(39). 评论(0) »

Java 10 ~ 16 一路向前冲(新特性一箩筐)

Java 一路突突突, 版本 16 在 2021-03-16 都发布了, 而我们一直碍于 Java 9 的大改还在 Java 8 上原地踏步, 以往每当有新版本 JDK 发布后都是很快就验证,立马升级。Java SE versions history) 列出了所有 Java 的历史版本的发布日期。在今天(2021-05-04) 网站 Java SE Downloads 上直接提供下载的 Java SE 版本有以下三

  1. Java SE 16.0.1
  2. Java SE 11.0.11(LTS)
  3. Java SE 8u291

两个 LTS(长期支持) 版 8 和  11,外加一个目前最新的非  LTS 版本 16, 其他的版本都被归档到了 Java Archive. 查看一下 Java 支持的 roadmap, 几个 LTS 版本的服务支持年限

版本本      发布日       原定支持至      延期支持至
Java 8      2014/3       2022/3             2030/12
Java 11     2018/9      2023/9              2026/9
Java 17     2021/9      2026/9              2029/9

注意到 Java 8 将比 Java 11 和将来的 Java 17 生命力还顽强,一下就觉得这么久坚守在 Java 8 的阵地上不应觉得有什么好害羞的。眼看着下一个 LTS 版本的 Java 17 就要在今年 9 月份发布了,Java 11 看来是要错过了,等准备好和 Java 8 告别时要直接跳到 Java 17 了。 阅读全文 >>

类别: Java/JEE. 标签: , . 阅读(82). 评论(2) »

探索 Apache, Tomcat, SpringBoot 对请求数据的解压缩

通常我们都会配置 Web 服务端对响应数据进行压缩,如用 Apache 的 mod_deflate 模块,或配置 Tomcat connector 启用压缩,又或者是在 Java Web 项目中加 Web Filter 来压缩特定的响应数据。这样客户端发送 HTTP 请求时在头中声明如 Accept-Encoding: gzip,服务端就可能会对响应数据进行压缩,同时带上 Content-Encoding: gzip 响应头。

有时候 HTTP Post 的数据太大同样会要求客户端在传输数据之前对请求数据进行压缩,本文主要关注服务端如何自动解压客户端发出的压缩数据。

先以 Apache2 为例,以 Ubuntu 20.04 为例,用命令 apt-get install apache2 安装 Apache 2.4.41, 它自动启用了 mod_deflate 模块。mod_deflate 模块的配置文件 /etc/apache2/modes-enabled/deflate.conf 内容如下

它表示只对以上特定的响应数据类型进行压缩,下面来测试下对 html 内容的压缩 阅读全文 >>

类别: Java/JEE. 标签: , , . 阅读(44). 评论(0) »

使用 Java 转换 Apache Avro 为 Parquet 数据格式(依赖更新)

在上篇 使用 Java 转换 Apache Avro 为 Parquet 数据格式 实现把 Avro 数据转换为 Parquet 文件或内存字节数组,并支持 LogicalType。其中使用到了 hadoop-core 依赖,注意到它传递的依赖都非常老旧,到官方 Maven 仓库一看才发现还不是一般的老

长时间无人问津的项目,那一定有它的替代品。对啦,据说 hadoop-core 在 2009 年 7 月份更名为 hadoop-common 了,没找到官方说明,只看到 StackOverflow 的 Differences between Hadoop-coomon, Hadoop-core and Hadoop-client? 是这么说的。 应该是这么个说法,不然为何 hadoop-core 一直停留在  1.2.1 的版本,而且原来 hadoop-core 中的类在 hadoop-common 中可以找到,如类 org.apache.hadoop.fs.Path。不过在 hadoop-core-1.2.1 中的 fs/s3 包不见,这么重要的 s3 文件系统没了。 阅读全文 >>

类别: Java/JEE. 标签: , , . 阅读(66). 评论(0) »

Mockito 3.4.0 开始可 Mock 静态方法

Java 单元测试最趁手的 Mock 组件当属 Mockito,虽然它最初是基于继承来实现  Mock 的,所以对私有方法,私有属性,静态方法,final 类,final 方法,构造函数无能为力。于是有时不得不引入 JMockit 或 PowerMockit 来辅助。不过现在的 Mockito 功力有所增强。

首先是 Mockito 2.1.0 开始可以 Mock final 类和 final 方法,要在 classpath 下创建个文件 mockito-extensions/org.mockito.plugins.MockMaker, 内容为 mock-maker-inline。之前写过一篇介绍:Mockto 也能 Mock final 类和 final 方法了,其中也探索了它的实现细节,使用到了 ByteBuddy 修改字节码。

Mockito 3.4.0 通过类似的 mockto-extensions 扩展的方式,实现了对静态方法的 Mock。所有使用到的接口是 org.mockito.MockedStatic,它当前在 Mockito 3.7.7 中还是一个试验性方法 @Incubating,能拿来用就行。 阅读全文 >>

类别: Java/JEE. 标签: , . 阅读(1,205). 评论(2) »

解决 jvisualvm 启动后长时间 Computing description... 的问题

Java 虚拟机分析工具用 JDK 自带的 jconsole, jvisualvm, 和  jmc(Java Mission Control) 就已经非常好了,还真极少情况下(甚至没有)非得用商业的 Profiler 工具如 YourKit Java Profiler 或 JProfiler 的情况。用于实时观察 JVM 的内存, CPU, 线程等运行状况,对比 Heap 快照,发现线程死锁的应用情景,我比较喜欢用 jvisualvm(VisualVM)。

有很长一段时间,因为在家办公司,只要连接到公司的 VPN 后再执行 jvisualvm 来打开 VisualVM 时,会有很长的时间(可能长达 10 几分钟)卡在窗口右下角状态栏的 Computing description...,要等到它消失后才能开始连接 JVM,这时候我的 Java 应用可能早就退出了。要是本地不连 VPN 的话就正常,启动 VisualVM 是正常的,但调试有些工作项目又必须连接公司的 VPN。

这种使用 VisualVM 的体验有如恶梦一般,还是有经常要用到 VisualVM 的需求,所以再也不能忍受这种无谓的等待。依然是 Google + StackOverflow 的模式,找到原来罪魁祸首是 /etc/hosts 中的 127.0.0.1 这个条目。 阅读全文 >>

类别: JVM. 标签: , , , , . 阅读(169). 评论(0) »

Mockito 的 anyString(), any(Foo.class) 等不能匹配 null 值

使用 Mockito Mock 方法式,一直以为可以用 anyString(), any(Foo.class) 等匹配 null 值,其实不行,null 值必须显式的用 null, 或 eq(null) 来匹配。anyString(), anyInt() 等只能匹配非 null 值,查看它们的返回值实际是 "" 和 0 等, 而更为特别的是 any(Foo.class) 看到的是 null, 仍然不能匹配 null 值。进一步用 Mockito.mockingDetails(mock).printInvocations() 打印出的内容,anyString(), any(Foo.class) 都会显示为 null 值。

说的有点罗嗦,看下面的例子, 被测试类 UserDao,sql 和 sqlArguments 由各自的 setter 方法来控制,默认它们都为 null 阅读全文 >>

类别: Java/JEE. 标签: . 阅读(824). 评论(0) »

Java 普通线程池与 ForkJoinPool 的效果对比

Java 多线程编程常用的一个接口是 ExecutorService, 其实就一个线程池的接口,一般由两种方式创建线程池,一为 Executors 的工厂方法,二则创建 ForkJoinPool 实例,当然也有直接使用 ThreadPoolExecutor 的。

关于什么时候用 ForkJoinPool 或普通的线程池(如 Executors.newFixedThreadPool(2) 或 new ThreadPoolExecutor(...)) 不过多的述说。如果要运用到 ForkJoinTask 的话就要用 ForkJoinPool, 它是 Java7 新引入的线程池类型。

关于 Java7 的 fork-join 框架可参考很多年前的一篇 Java 的 fork-join 框架实例备忘。ForkJoinPool 的一个典型特征是能够进行 Work stealing。它也是 Akka actor 效率高效的一个有力保证。

本文只能某一种情形下在选择普通线程池与 ForkJoinPool 的区别,直接说吧,普通线程更容易造成死锁,而 ForkJoinPool 却能应对相同的状况。 阅读全文 >>

类别: Java/JEE. 标签: . 阅读(2,158). 评论(0) »

运行时动态创建 Spring Bean

通常我们注册 Spring Bean 是通过像 @Named, @Bean, @Component, @Service 这样的注解来注册的,或者用更为古老的 XML 配置文件的方式。难免有时候要根据实际业务需求在 Spring  运行期间动态注册 Spring Bean, 比如基本某种形式的配置文件或系统属性来注册相应的 Bean, 这好像又回到了 XML 文件注册方式,也不尽然。

那为什么在运行期还要去注册 Spring Bean 呢,直接 new 对象不行吗?当然行得通,不过这样的话就不能更好的使用到  Spring IOC 的好处了。像待注册的 Bean 构造函数可以直接用到其他的 Spring  对象,或 @Value 引入环境变量,还有 @PostContruct 这样的行为。

最初思考如何注册 Spring Bean 时还是费了不少周折,如今清晰了许多。了当的说,不管是 Spring  初始时还是运行时,注册 Bean 的关键(应是唯一) 入口就是 BeanDefinitionRegistry 接口的方法 阅读全文 >>

类别: Spring. 标签: , . 阅读(701). 评论(1) »

用 Java 把内存中的表格数据合并到 SQL Server 表中

承接近两年前的 用 PreparedStatement 向 SqlServer 中一次性插入多条记录,其文后用 User-Defined Type 可用下面简单的代码把 Java 本地内存中表格数据一股脑的刷入到 SQL Server 数据库表格中

String sql = "INSERT INTO Customers SELECT * FROM ?";
SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) conn.prepareStatement(sql);
SQLServerDataTable dataTable = ..... // 生成好的本地表格数据
pstmt.setStructured(1, "CustomersTableType", dataTable);
pstmt.execute();

上面的 dataTable 本地表格类型变量容易生成,关键是必须在正式数据库数须预先用 CREATE TYPE 创建好 CustomersTableType 这个用户自定义类型,这会受权限的约束。如果由 DBA 预先完全依照目标表来创建好这个用户自定义类型,又无法确定是否总是要操作该目标表的所有字段。

数据库是允许我们创建临时的用户自定义类型 阅读全文 >>

类别: Database, Java/JEE. 标签: . 阅读(81). 评论(0) »