在以太坊区块链的世界里,新区块的诞生是网络活动的脉搏,无论是跟踪交易确认、智能合约交互,还是进行数据分析,及时获取新区块信息都至关重要,对于Java开发者而言,web3j库提供了一个强大且便捷的途径来与以太坊节点交互,其中监听新区块事件是一项核心且常用的功能,本文将详细介绍如何使用web3j来监听以太坊的新区块事件。

在深入技术细节之前,我们先理解一下监听新区块事件的意义:
web3j是一个轻量级、响应式的Java库,用于与以太坊节点进行交互,它支持以太坊的所有核心功能,包括账户管理、交易发送、智能合约部署与调用、以及各种事件监听,web3j的设计目标是让Java开发者能够方便地集成以太坊功能到他们的应用中,无论是命令行工具、后台服务还是Spring Boot应用。
web3j提供了EthBlock相关的API来获取区块信息,而监听新区块事件,最直接和高效的方式是使用web3j.ethNewBlockFlowable()或web3j.ethNewBlockHeadersFlowable()方法,这些方法返回一个Flowable(来自RxJava库),允许我们以响应式的方式处理新到来的区块。

确保你的项目中添加了web3j的依赖,如果你使用Maven:
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.9.8</version> <!-- 请使用最新版本 -->
</dependency>
Gradle用户则添加:
implementation 'org.web3j:core:4.9.8' // 请使用最新版本
你需要先创建一个Web3j实例,连接到你的以太坊节点(可以是本地节点如Geth,或远程节点如Infura)。

Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_PROJECT_ID")); // 替换为你的节点URL
使用ethNewBlockFlowable()来订阅新区块事件,每当新区块被挖出并同步到你的节点时,这个Flowable就会发出一个EthBlock对象。
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.http.HttpService;
import io.reactivex.Flowable;
public class EthereumBlockListener {
public static void main(String[] args) {
// 连接到以太坊节点 (这里以Infura为例)
Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_PROJECT_ID"));
// 订阅新区块事件
Flowable<EthBlock> blockFlowable = web3j.ethNewBlockFlowable();
System.out.println("开始监听新区块事件...");
// 订阅并处理新块
blockFlowable.subscribe(block -> {
EthBlock.Block blockObject = block.getBlock();
System.out.println("新区块已生成!");
System.out.println("区块号: " blockObject.getNumber());
System.out.println("区块哈希: " blockObject.getHash());
System.out.println("父区块哈希: " blockObject.getParentHash());
System.out.println("矿工地址: " blockObject.getMiner());
System.out.println("交易数量: " blockObject.getTransactions().size());
System.out.println("----------------------------------------");
}, throwable -> {
System.err.println("监听新区块时发生错误: " throwable.getMessage());
});
// 为了保持程序运行,防止订阅被取消
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代码解析:
Web3j.build(...): 创建与以太坊节点的连接。web3j.ethNewBlockFlowable(): 返回一个Flowable<EthBlock>,每当新区块可用时,它会发出EthBlock对象。subscribe(...): 订阅Flowable,你可以提供三个参数(onNext, one rror, onComplete),这里我们主要处理onNext(新块到达)和onError(发生错误)。block.getBlock(): 获取EthBlock对象中的Block实例,其中包含了区块的所有详细信息,如区块号、哈希、父哈希、矿工地址、交易列表等。如果你只关心区块头信息(不包含具体交易详情,以减少数据传输和处理开销),可以使用ethNewBlockHeadersFlowable():
Flowable<EthBlock.Block> blockHeaderFlowable = web3j.ethNewBlockHeadersFlowable();
blockHeaderFlowable.subscribe(blockHeader -> {
System.out.println("新区块头已生成!");
System.out.println("区块号: " blockHeader.getNumber());
System.out.println("区块哈希: " blockHeader.getHash());
// ... 其他区块头信息
});
EthFilter(尽管ethNewBlockFlowable本身是针对所有新区块)。Disposable disposable = blockFlowable.subscribe(...); // 当需要停止时 // disposable.dispose();