由于是第一篇写关于 Lombok 的日志,所以有些不情愿去开门见山直接触及 @With, 而要先提一提本人对 Lombok 的接触过程。
两三年之前写 Java 代码一直都是全手工打造。一个数据类,所有必须的 setter/getter, toString, hashcode() 等全体现在源代码中,当然是在 IDE 中自动生成的。听说过 Lombok,但觉得它用了会影响到对源代码的阅读,因为造成代码的行为与源代码所展示的不一致,还可能依赖于特定的 IDE 或构建工具插件,所以一直未真正应用。
然而现代语言一直在避免不断书写象 JavaBean 里那一大片样本代码,同时解决试图提高覆盖率写出毫无意义单元测试的烦恼。比如 Scala 发展出了 case class, Kotlin 的 data class, Python 的 @dataclass,还有 JDK 14 引入的及至 JDK 16 转正的 record, 都是为了自动生成 Java 类的 setter/getter/toSring/hashcode/equals 等方法。 所以源代码中看不到实际可调用方法不该再是问题,况且在 JDK 5 加入的 enum 类型本质上也是在源代码的背后生成了一系列的方法和类型声明的。 Read More
刚刚回顾了一下 JDBC 操作 SQL Server 时如何传入列表参数,即如何给 in (?) 条件直接传入一个列表参数,然而本质上是不支持,最终不得不展开为 in (?, ?,...?) 针对每个元素单独设置参数,不定长的参数对于重用已编译 PreparedStatement 语句的帮助不大。
那么 JDBC 操作 PostgreSQL 是何种状态呢?展开为多个参数当然是有效的。继续尝试 Spring 提供的 NamedParameterJdbcTemplate 的操作方式
String query = "select * from users where id in (:ids)";
Map<String, Object> parameters = new HashMap<>();
parameters.put("ids", IntStream.rangeClosed(1, 5).boxed().collect(toList()));
List<Map<String, Object>> maps = namedParameterJdbcTemplate.queryForList(query, parameters);执行后查看到实际执行的语句是
select * from users where id in (?, ?, ?, ?, ?)
Read More
使用 JDK 5 的线程池实现有近 20 年的时间了,快速创建一个线程池经常是调用 Executors 中的工厂方法。但是涉及过更精细的线程池管理控制时不得不用 ThreadPoolExecutor 的构造方法,这也就是为什么有些公司不建议用 Executors 的工厂方法创建线程池,而应该直接创建 ThreadPoolExecutor 或 ForkJoinPool 实例。
例如代码ExecutorService threadPool = Executors.newFixedThreadPool(10);
实际上调用的是new ThreadPoolExecutor(nThreads, nThreads,
前两个参数 corePoolSize 和 maximumPoolSize 是一样的; OL, TimeUnit.MILLISECONDS 表示线程创建后只要线程池还在就是永生的; workQueue 是一个大小为 Integer.MAX_VALUE 的队列, 几乎可以无限提交任务,耗尽内存
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
不建议用 Executors 的工厂方法的原因大致有二: Read More
本文进行实际测试 FastAPI 的并发能力,即同时能处理多少个请求,另外还能接收多少请求放在等待队列当中; 并找到如何改变默认并发数; 以及它是如何运用线程或进程来处理请求。我们可以此与 Flask 进行对比,参考 Python Flask 框架的并发能力及线,进程模型,是否真如传说中所说的 FastAPI 性能比 Flask 强, FastAPI 是否对得起它那道闪电的 Logo。
本文使用 JMeter 进行测试,测试机器为 MacBook Pro, CPU 6 核超线程,内存 16 Gb。
对于每一种类型 Web 服务基本的测试是每秒发送 2 个请求,连续发送 1000 个,500 秒发送完所有请求,程序中 API 方法接受到请求后 sleep 800 秒,保证在全部 1000 个请求送出之前一直占着连接,并有充足的时间对连接进行分析。在测试极端并发数时,由于在 Mac OS X 尽管设置了 ulimit 最多也只能创建 4000 多一点线程,所以在模拟更多用户数时,JMeter 在远程 Linux(Docker 或虚拟机) 上运行测试用例。
请求的 URL 是 http://localhost:8080/?id=${count}, 带一个自增序列用以识别不同的请求, JMeter 的 Thread Group 配置为 Number of Threads (users): 1000, Ramp-up period (seconds): 500 Read More
JMeter 是一个极好的测试 Web API 及压力测试的工具,另一个的话就是 Python 版的 LOCUST(它也能远程运行测试)。JMeter 的测试可以在本地模拟并发用户,那么为什么要远程执行 JMeter 测试呢?因为一台机器能模拟的并发用户数受限,一个用户就是对应着一个 Java 线程。比如我在 MacBook Pro(内存 16Gb) 上无论如何调整ulimit -n,ulimit -u, 或用 JAVA_TOOL_OPTIONS, HEAP, JVM_ARGS 设置-Xmx, 调大到 10 G, 或用 -Xss 调小栈大小,都无法让 JMeter 模拟的用户数达到 5000。
文后有本人亲自测试 Java/Python 在 Mac OS X 和 Linux 下可创建多少个线程
如果能够远程运行 JMeter 的测试就能突破单机上的线程限制了,比如 Mac OS X 不行,找个 Linux 远程机器(可以是虚拟机)来执行,一台机器不够,找多个。想要模拟 15000 个并发用户,测试可分配到 5 台机器上执行,每个节点跑 3000 个用户并发就行,有点操控肉机的感觉。 Read More
还是很 久很久以前,当初有 Java 调用本地动态库需求的时候,尝试过用 javah/native 原生的方式在 Java 中使用动态库,再就是小试了 JNative,它调用动态库只需 Java 端的动作, 它最后的更新日期是 9 年前 2013-04-26,基本是应该选择放弃了。
关于 JNative 的使用写过两篇
如今想继续发掘下是否有别的更好的调用本地库的 JNI 组件,找到有- JNIWrapper:居然是一个收费的,而且价格不菲,不作绍
- BridJ:也是 7 年前才有过代码的更新
- JNA(Java Native Access): 也就它稍为活跃一点点
- JNR-FFI:最近几个月也有更新,不知道使用体验如何
Read More
多数的 Java 入门教程都是要求同时设置 JAVA_HOME 和 PATH(包含 $JAVA_HOME/bin) 两个环境变量,反正两个都有了就保险。其实一般情况下系统能在 PATH 中找到 java 程序时就知道 JAVA_HOME, 基本上只要配置 PATH 就行,而 JAVA_HOME 环境变量是可选的。但也有例外,比如 TOMCAT 就可能要求有 JAVA_HOME 环境变量。
在 macOS 下,JAVA_HOME 与 PATH 的关系又显得有点微妙了。一个新的 macOS 系统,它自带有 java 命令$ which java
你要直接执行它的话
/usr/bin/java$ java
所以它实际上只是执行 java 的辅助入口,没有实际的 JDK 或 JRE 是没用的。 Read More
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
向数据库中插入 CLOB 或 BLOB 类型的数据,Oracle 总是比其他类型的数据库操作上要麻烦多了。当然,对于不大于 4K 长度的 CLOB 字符串在 JDBC 中可简单的用PreparedStatement.setString(idx, "short string")。如果要插入大于 4K 长度的内容,网上找来的例子许多都是分两步走- 先插入 EMPTY_CLOB() 或 EMPTY_BLOB()
- 然后 SELECT 原来的记录
FOR UPDATE, 再更新先前插入的记录
这就存在两个问题,含 CLOB/BLOB 的表必需要有主键,还有因为FOR UPDATE的使用我们需要开启事物,不能采用自动提交。
其实还有更简单的方法可直接插入大的 CLOB/BLOB 数据,要用到 Oracle JDBC 驱动的 setStringForClob(), CLOB.createTemporary(), 或 BLOB.createTemporary() 方法。来看下面的例子,例子中只演示 CLOB, 类似的方法可应用于 BLOB, NCLOB。
本文中所使用的 Oracle JDBC 驱动比较老,是 ojdbc:ojdbc:5。Docker 启动一个本地的 Oracle 11G 作为测试数据库$ docker run -d -p 1521:1521 -p 8080:8080 wnameless/oracle-xe-11g-r2
默认的 SID 是 xe, 数据库用户名和密码分别是 system/oracle Read More- 有了前一篇 应用 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,没继续深究,实际中希望这么部署的方式用得较少
- 不再支持 SOAPMonitorService,它是一个 Java Applet, Java Applet 在新版的 JDK 中已被移除,早就不推荐使用了
在 SpringBoot 中配置 Servlet 或 ServletListener 有两种方式- ServletRegistrationBean/ServletListenerRegistrationBean
- @WebServlet/@WebListener
spring-boot-starter 引入了 log4j-to-slf4j, jul-to-slf4j, 所以不需要配置 log4j.properties, 需要的话可用 logback.xml 配置日志输出。 Read More - 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 呢?目的就是为了放弃,先前的 Axis 1.4 的项目不稍加理解,怎么能顺利的过度到 Axis 2 呢?要说眼下更好的用来开发 SOAP WebService 的库应该首选 Apache CXF。本来拟定的文章标题的 Springboot2 应用 Axis 1.4 开发 WebService, 但一发挥就用力过猛,只得下回另立新篇来再加上 Springboot2 了,因此本篇就是为 SpringBoot2 与 Axis 1 的结合铺路的。
什么是 SOAP,Simple Object Access Protocol, 简单对象访问协议,一种 XML-RPC 的实现。谁都敢号称简单,与当今的 REST API 一对照,任何人都会觉得 SOAP 是把一个远程调用搞得无比的复杂。SOAP 有 1.1 和 1.2 两个版本,现在提 SOAP 基本就是 SOAP 1.2 的代名词。另外,SOAP 1.2 开始也承认不简单,不再明确为 Simple Object Access Protocol 的缩写,而叫做 Messaging Framework (Second Edition)。 Read More