
Java/JEE
Yanbin_Q
真没什么要交待的,保持沉默
展开
-
多线程环境中使用 Mockito 来 Mock 静态方法
首先回顾一下 Mockito 的静态方法 Mock 的使用方法,随着 Mockito 版本的升级,引入依赖的方式也发生了些许的变化,以 Maven 项目为例,如果在 JUnit 5 下用 Mockito 的 pom.xml 依赖中为。,最后对 Mockito 产生的缺憾是它无法用来 Mock 非测试线程(主线程)中的静态方法调用。其实这也是可以变通的,下面慢慢道来。回看三年前的一篇日志。由它引入的全部相关依赖。原创 2024-11-26 14:03:42 · 441 阅读 · 0 评论 -
ThreadLocal, InheritableThreadLocal 以及 TransmittableThreadLocal
ThreadLocal 用于保存与线程绑定的数据,它在框架内部使用的很频繁,但凡见到 XxxContextHolder.currentContext() 之类的十之八九用到了 ThreadLocal, 如 Spring 框架中的。ThreadLocal 是 Java 编程人员要掌握的一个基本类,似乎没什么太多要说。但因为本文要牵出 TransmittableThreadlLocal, 再顺带说下几乎隐形的 InheritableThreadLocal。原创 2024-11-26 14:02:10 · 154 阅读 · 0 评论 -
Java 线程池有限大小工作队列 - 不丢弃任务的实现
我们在创建 Java 线程池,无论是用 Executors, ThreadPoolExecutor, 还是 Spring 的 ThreadPoolTaskExecutor, 如果不指定工作队列的大小的话,默认为 Integer.MAX_VALUE(2147483647), 基本不会把它爆满,但是在许多的任务要执行时大量 Runnable 对象的创建却足以把内存撑爆掉。原创 2024-11-26 08:43:37 · 239 阅读 · 0 评论 -
Java 直接插入 CLOB/BLOB 数据到 Oracle 数据库
向数据库中插入 CLOB 或 BLOB 类型的数据,Oracle 总是比其他类型的数据库操作上要麻烦多了。当然,对于不大于 4K 长度的 CLOB 字符串在 JDBC 中可简单的用PreparedStatement.setString(idx, "short string")。如果要插入大于 4K 长度的内容,网上找来的例子许多都是分两步走先插入 EMPTY_CLOB() 或 EMPTY_BLOB() 然后 SELECT 原来的记录FOR UPDATE, 再更新先前插入的记录这就存在两个问题,...原创 2021-12-23 07:36:26 · 1601 阅读 · 0 评论 -
SpringBoot2 应用 Axis 1.4 开发 WebService
有了前一篇应用 Axis 1.4 开发 WebService的对 Axis 1 较为深刻的理解后,现在正式给古老的 Axis 1.4 拉个伴,那就是 SpringBoot2。SpringBoot2 + Axis 1 的主要工作就是把 Axis 的web.xml用 SpringBoot2 的方式进行转述。在 SpringBoot 中用 Axis 1 后,有两个特性不再支持不再支持 jws 即时发布 Web Service,不能直接搬用 url-pattern *.jws,没继续深究,实际中希...原创 2021-12-22 06:24:58 · 732 阅读 · 0 评论 -
应用 Axis 1.4 开发 WebService
Axis 1 的最后一个版本还是 2006-04-22 发布的 1.4 Final 版,当前的版本是 Axis 2, 即于 2021-08-01 发布的 Axis v1.8.0 版本。想想在 2006 年 4 月份,软件开发是一种什么样的景象,JDK 5 于 2004-09-30 发布,同年 12 月 12 日 JDK 6 才出来, Spring 还是 1.x 的版本。那时候仍是 EJB 兴旺的年代,微服务概念的出现还有等好多年。那为什么还要学习 Axis 1.4 呢?目的就是为了放弃,先前的 ...原创 2021-12-22 06:24:00 · 196 阅读 · 0 评论 -
mvn 命令上传文件到 Maven 仓库
针对一个 Maven 的 Java 项目,我们执行 mvn deploy 命令时想要把生成的 jar 包上传到 Maven 仓库(本文将使用私有的 Nexus 仓库)中去。所要用到的插件Maven Deploy Plugin,本文实际就是讲述如何用该插件上传 jar 包到 Maven 仓库,更多用法请参考该插件的官方文档。本文关键性的两个配置文件是 pom.xml 和 settings.xml。前者配置仓库的地址,后者中配置用户名和密码。要确定 Maven 使用了哪个 settings.xml文件...原创 2021-11-15 01:35:58 · 776 阅读 · 0 评论 -
为 Java 注册 classpath: 协议用 URL 读取文件
本文为 Java 注册 classpath协议读取文件的目的就是要让下面的代码能工作起来 1 2 String text = IOUtils.toString(new URL("classpath:/db.properties"), "UTF-8"); System.out.println(text); 假设在 classpath 下有个文件 db.properties, 比如在 Maven 项目的 src/main/resources 目录中,.原创 2021-06-19 03:28:52 · 720 阅读 · 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 版本有以下三Java SE 16.0.1 Java SE 11.0.11(LTS) Java SE..原创 2021-06-19 03:28:16 · 90 阅读 · 0 评论 -
使用 Java 转换 Apache Avro 为 Parquet 数据格式(依赖更新)
在上篇使用 Java 转换 Apache Avro 为 Parquet 数据格式实现把 Avro 数据转换为 Parquet 文件或内存字节数组,并支持 LogicalType。其中使用到了 hadoop-core 依赖,注意到它传递的依赖都非常老旧,到官方 Maven仓库一看才发现还不是一般的老长时间无人问津的项目,那一定有它的替代品。对啦,据说 hadoop-core 在 2009 年 7 月份更名为 hadoop-common 了,没找到官方说明,只看到 StackOverflow 的...原创 2021-06-19 03:23:34 · 394 阅读 · 0 评论 -
使用 Java 转换 Apache Avro 为 Parquet 数据格式
Avro 和 Parquet 是处理数据时常用的两种编码格式,它们同为 Hadoop 大家庭中的成员。这两种格式都是自我描述的,即在数据文件中带有 Schema。Avro 广泛的应用于数据的序列化,如 Kafka,它是基于行的格式,可被流式处理,而 Parquet 是列式存储格式的,适合于基于列的查询,不能用于流式处理。既然是一个系统中可能同时用到了这两种数据存储格式,那么就可能有它们之间相互转换的需求。本文探索如何从 Avro 转换为 Parquet 格式数据,以 Java 语言为例,所涉及到的话题.原创 2021-02-25 05:13:38 · 759 阅读 · 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.pl...原创 2021-02-25 05:11:01 · 3171 阅读 · 0 评论 -
解决 jvisualvm 启动后长时间 Computing description... 的问题
Java 虚拟机分析工具用 JDK 自带的jconsole,jvisualvm, 和jmc(Java Mission Control) 就已经非常好了,还真极少情况下(甚至没有)非得用商业的 Profiler 工具如 YourKit Java Profiler 或 JProfiler 的情况。用于实时观察 JVM 的内存, CPU, 线程等运行状况,对比 Heap 快照,发现线程死锁的应用情景,我比较喜欢用jvisualvm(VisualVM)。有很长一段时间,因为在家办公司,只要连接到公司的...原创 2021-02-25 05:08:41 · 532 阅读 · 1 评论 -
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).printInvoc...原创 2020-06-30 10:17:42 · 7358 阅读 · 1 评论 -
Java 普通线程池与 ForkJoinPool 的效果对比
Java 多线程编程常用的一个接口是ExecutorService, 其实就一个线程池的接口,一般由两种方式创建线程池,一为 Executors 的工厂方法,二则创建 ForkJoinPool 实例,当然也有直接使用 ThreadPoolExecutor 的。关于什么时候用ForkJoinPool或普通的线程池(如 Executors.newFixedThreadPool(2) 或 ne...原创 2020-04-13 01:36:36 · 4531 阅读 · 0 评论 -
等待所有的 CompletableFuture 完成
现实中有这样的用法,创建一批在线程池中运行的 CompletableFuture 实例,然后等待它们全部执行完再继续后面的操作。比如说 AWS 的 Lambda, 单单提交任务到线程池,不等待所有任务全部完成便退出主线程的话,AWS 便认为 Lambda 执行完毕,无视线程池中正在执行的任务而强行结束该 Lambda 实例。以往我们通常的作法如下ExecutorService thre...原创 2019-10-29 10:59:43 · 8823 阅读 · 1 评论 -
转换 Iterator 为 Java 8 的 Stream
Java 中有关抽象的可遍历的对象有 Iterator, Iterable 和 Java 8 的 Stream, Iterable 可简单的用如下代码转换为StreamStreamSupport.stream(iterable.spliterator(), false)再回过头来,为什么要把 Iterator 或 Iterable 转换为 Stream, 因为 Iterator 和 ...原创 2019-10-24 05:12:19 · 757 阅读 · 0 评论 -
试手 RxJava 2.x 及对线程的初步理解
在进行数据流处理过程中,需要一个高效苗条的流处理组件,比如对输入流能进行分组(窗口),能进行流量控制(Back Pressure - 背压),这也就涉及到响应式编程,流处理框架。这方面如果直接基于 Akka actor 来构建 Akka ActorSystem 也是比较复杂,依赖的组件也不少。还有构筑在 Akka actor 之上的 Akka Streams,再往上的 Flink Streamin...原创 2019-10-24 05:11:48 · 155 阅读 · 0 评论 -
Java 与'嵌入式' PostgreSQL 数据库的单元测试
在我们对数据库 DAO 类进行单元测试时,通常不应该依赖于一个外部数据库,所以会选用特定比较接近于真实数据库类型的内存或嵌入式数据库,如 HSQLDB(HyperSQL), H2, Derby 等。但总难免会用到特定数据库的特性,这时候就无法用前述各种数据库进行测试了。非要单元测试中覆盖到所用的数据库特性的话可以选择用 docker,如Testcontainers, 经过模块扩展,它可以由 do...原创 2019-10-24 05:04:46 · 1271 阅读 · 0 评论 -
Kafka 生产消费 Avro 序列化数据
本文实践了如何连接 Kafka 生产和消费 Avro 序列化格式的数据, 不能像 NgAgo-gDNA 那样, 为保证实验内容及结果的可重复性, 文中所用的各中间件和组件版本如下:Apache Kafka: kafka_2.11-0.10.0.1, 这个版本在初始始化生产者消费者的属性与之前版本有所不同.kafka-clients: Java API 客户端, 版本为 0.1原创 2017-01-17 23:33:09 · 5023 阅读 · 0 评论 -
该如何从 Java 8 升级到 Java 10
Java 9 出来了很久,买的书《Java 9 Revealed - For Earyly Adoption and Migration》,说怎么迁移到 Java 9,可是突然间 Java 9 就无法通过正常渠道从 Oracle 官网下载了,这书还让不让人看。当然要看,因为尽管 Java 10 出来了,但实际的变化全压在 Java 9 这个版本上的,就当是通过 Java 10 来学习 Java 9...原创 2018-05-31 08:46:44 · 8165 阅读 · 2 评论 -
Java 9 - 快速创建不可变集合
平台之所以谓之平台,以其能建立一个生态,并与之外围达成共赢。霸道点的平台也会反噬外围生态,像微软集成浏览器,媒体播放器。还有即将的 iOS 12 要把应用商店多是收费的 AR 皮尺放到它自己系统中来,走别人的路,让别人无路可走。从此众泰皮尺部的唯一的生产工具就会是人手一部能安装 iOS 12 iPhone 了。JDK 也不例外,Java 8 之前日期库的话 Joda-Time 是首要之选,Java...原创 2018-06-11 11:38:01 · 2642 阅读 · 0 评论 -
Mockito 也能 Mock final 类和 final 方法了
以实际 Java 项目中的单元测试 Mock 框架基本是 Mockito 了,因为它有一个十分流畅的 API。Mockito 也为 JUnit 5 配上了 MockitoExtension, 所以 JUnit 5 下使用 Mockito 的关节也打通了。但在我们享受 Mockito 便利的同时,与 JMockit 相比局限性就很明显,因为 Mockito 是通过创建匿名子类来进行 Mock 的,所...原创 2018-05-15 12:12:45 · 14322 阅读 · 4 评论 -
JUnit 5 使用 Mockito 2 进行测试
JUnit 5 刚出来那时,也就是第一个版本 5.0.0 时,还不能很好的支持 Mockito 的测试,因为 Mockito 没能跟得那么紧密。那时候 JUnit 5 只能试验性的提供了一个极不正式的 com.example.mockito.MockitoExtension, 看那包名就知道不是来真的,所以决定再等。JUnit 5 不再原生支持 JUnit 4 的 Rule,一切都将是 Exten...原创 2018-05-14 06:32:54 · 2720 阅读 · 0 评论 -
Java 8 根据属性值对列表去重
对列表的去重处理,Java 8 在 Stream 接口上提供了类似于 SQL 语句那样的 distinct() 方法,不过它也只能基于对象整体比较来去重,即通过 equals/hashCode 方法。distinct 方法的功效与以往的 new ArrayList(new HashSet(books)) 差不多。用起来是List<Book> unique = book.stream()...原创 2018-02-08 02:51:06 · 5487 阅读 · 0 评论 -
并发(Concurrent) 与并行(Parallel) 的区别
刚开始阅读 《Akka IN ACTION》这本书,刚开始是对 Revolution 这个词翻译成中文是革命 感到诧异,因为革命 通俗来讲就是 杀人 的意思。至于 Revolution 英文解释不深究了,只是感叹何以颠覆性的变化就一定要杀人呢?也由此引出了编程中经常面对的 Concurrent(名词为:Concurrency) 和 Parallel(名词为:Parallelism) 这两个词,基本...原创 2018-02-09 15:24:35 · 25342 阅读 · 3 评论 -
使用 Mockito 的 @InjectMocks 创建被测试类实例
初识 Mockito 这个测试框架后,我们要使用 Mock 的属性创建一个被测试类实例时,大概会下面这么纯手工来打造。假定类 UserService 有一个属性 UserDao userDao, 需要构造 UserService 实例时 Mock 内部状态UserDao userDao = Mockito.mock(UserDao.class);UserServic原创 2018-02-02 13:30:40 · 6189 阅读 · 0 评论 -
用 PreparedStatement 向 SqlServer 中一次性插入多条记录
标准 SQL 都提供了下面这种方式一条 INSERT INTO 语句插入多条记录INSERT INTO Customers(Id, Name, Age) VALUES (1, 'Name1', 21.5), (2, 'Name2', 32.3)VALUES 之后用括号列出每一条记录。但是在 Java 中想把上面的语句转换成 PreparedStatement 来插原创 2017-12-12 16:23:01 · 2591 阅读 · 0 评论 -
JMockit 中被 Mocked 的对象属性及方法的默认值
前脚研究完 Mockito 中被 Mocked 的对象属性及方法的默认值, 虽然目今更多的是拥抱着 Mockito, 但总有时对 JMockit 也会挤眉弄眼,谁叫 JMockit 无所不能呢!被 Mockito 的 Mock 对象方法的默认返回值洗脑之后,进而觉察出 JMockit 应该有同样的实现方式。经过类似的测试,这里不详细列出测试过程,只是在基于前篇的测试中加入 JMocki原创 2017-11-13 10:40:09 · 1119 阅读 · 0 评论 -
Java 9 - 平台日志 API
关于 Java 9 的新特性从某本书的最后一个说起:平台日志 API。个人没感觉这个有什么实质的用途,所谓的平台日志是指 JDK 自身代码,或者是 JVM 组件中的日志输出,而在自己应用程序代码中却不会去用这个平台日志 API。这个所谓的 Platform Logging API 名称的意义也就是在这里,平台用的,在诊断时用来观察 JDK 类或 JVM 中的日志输出,比如应该可以截获到 JVM ...原创 2018-05-31 08:48:26 · 834 阅读 · 0 评论 -
对 Java 9 把单个下划线作为关键字的猜想
我们知道 Java 的合法命名是以字母或下划线开头的字符串,当然,以前单个下划线 _ 也是一个合法的变量命名。但是自 Java 8 的第一个版本开始,单个下划线的变量名编译时会有警告int _ = 99;用 Java 8 编译时提示警告:Test.java:2: warning: '_' used as an identifier int _ = 99; ^ (use...原创 2018-05-31 08:48:58 · 1274 阅读 · 2 评论 -
Java 9 线程栈遍历 API
什么是线程栈继续纠缠 Java 9 的新特性,仍然是一个边角料,即 Java 9 增加了对线程栈遍历的 API。那么什么是线程栈,JVM 在创建每一个线程的同时都会创建一个私有的虚拟机栈,每一桢代表着一个方法调用,每次方法的调用与退出意味着压栈与出栈。每一桢上有局部变量,操作数常量引用等信息,这也是为什么局部变量是能最快被销毁的对象。过深的栈(比如过多的递归调用) 会出现我们程序员赖以生存的 St...原创 2018-05-31 08:50:42 · 630 阅读 · 0 评论 -
使用 Google Guava Striped 实现基于 Key 的并发锁
写 Java 代码至今,在应对可能冲突的共享资源操作时会尽量用 JDK 1.5 开始引入的并发锁(如 Lock 的各类实现类, ReentrantLock 等) 进行锁定,而不是原来的synchronized关键字强硬低性能锁。这里是应用 JDK 1.5 的Lock的基本操作步骤private Lock lock = new ReentrantLock();private ...原创 2019-07-22 08:59:58 · 1447 阅读 · 2 评论 -
Jackson 反序列化 "Y"/"N" 为相应的布尔值
JSON 表示布尔值标准的形式是 true 和 false,如果 Java 对应的类型是对象 Boolean,那么在 JSON 中也可以是 null。如果收到 JSON 数据是用 'Y'/'N', 或 'Yes'/'No' 来表示布尔值的,那么使用 Java 的 Jackson 库如何把它们反序列化为相应的布尔属性值呢?如果按照 JSON 规范必须把内容中的布尔值全部转换为 true ...原创 2018-12-17 06:10:30 · 1734 阅读 · 0 评论 -
Java 8 Map 中新增的方法使用记录
得益于 Java 8 的 default 方法特性,Java 8 对 Map 增加了不少实用的默认方法,像 getOrDefault, forEach, replace, replaceAll, putIfAbsent, remove(key, value), computeIfPresent, computeIfAbsent, compute 和merge 方法。另外与 Map 相关的 Map....原创 2018-10-31 13:16:38 · 434 阅读 · 0 评论 -
跳过构造函数创建 Java 对象(测试)
如果一个 Java 类在初始化时会有外部依赖,这就给单元测试创建它的实例时造成困难。当然被测试类可以改造为依赖全部构造时注入或创建实例后延迟注入,这里不考虑这种改造。单说下面的例子public class OrderService { private PriceInquiry priceInquiry = new PriceInquiry(); ......... ...原创 2018-08-22 12:49:25 · 817 阅读 · 0 评论 -
Jackson 序列化忽略指定类型的属性
本文准确来讲是探讨如何用 Jackson 来序列化 Apache avro 对象,因为简单用 Jackson 来序列化 Apache avro 对象会报错。原因是序列化 Schema getSchema() 时会报错,后面会讲到,需要序列化时忽略该属性。那么能不能在 getSchema() 上加上 @JsonIgnore 来忽略该属性呢?原理上是通的。不过手工修改的 avsc 生成的 Java 文...原创 2018-08-08 22:27:53 · 4650 阅读 · 0 评论 -
如何快乐的使用 Java 8 的 Lambda
Java 8 的 Lambda 特性较之于先前的泛型加入更能鼓舞人心的,我对 Lambda 的理解是它得以让 Java 以函数式思维的方式来写代码。而写出的代码是否是函数式,并不单纯在包含了多少 Lambda 表达式,而在思维,要神似。实际中看过一些代码,为了 Lambda 表达式而 Lambda(函数式),有一种少年不识愁滋味,为赋新词强说愁的味道。从而致使原本一个简单的方调用硬生生的要显式...原创 2018-08-09 12:46:24 · 273 阅读 · 0 评论 -
Java8 Optional 几个常见错误用法
Java 8 引入的 Optional 类型,基本是把它当作 null 值优雅的处理方式。其实也不完全如此,Optional 在语义上更能体现有还是没有值。所以它不是设计来作为 null 的替代品,如果方法返回 null 值表达了二义性,没有结果或是执行中出现异常。在 Oracle 做 Java 语言工作的 Brian Goetz 在 Stack Overflow 回复 Should ...原创 2018-07-23 12:46:52 · 1539 阅读 · 1 评论 -
Java 9 - 说说响应式流
最初看到 Java 9 的这个新特性没太在意,及至重新关注到 Spring 5/Springboot 2 的响应式编程的时候才真正重视起 Reactive Streams(响应式流或反应式流)。应用响应式流的编程也就叫做响应式编程(Reactive Programming),无论是翻译成反应式编程都有些令人摸不准头脑。与此对应的在 Web 设计方面有一个叫做响应式 Web 设计(Responsiv...原创 2018-07-23 12:46:12 · 2567 阅读 · 0 评论