以太坊作为全球第二大区块链平台,凭借其智能合约功能和庞大的生态系统,已成为区块链应用开发的核心选择之一,尽管以太坊的原生语言是Solidity,但Java作为一门成熟、企业级的应用开发语言,凭借其丰富的库生态、稳定的性能和庞大的开发者群体,在以太坊应用开发中仍占据重要地位,本文将从环境搭建、核心工具使用、智能合约交互、实战案例等方面,详细介绍如何用Java开发以太坊应用。
开发环境准备
在开始Java以太坊开发前,需要先搭建完整的开发环境,包括Java开发环境、以太坊节点或第三方服务集成,以及核心依赖库的引入。
基础环境配置
- JDK安装:推荐使用JDK 11或更高版本(Java 17 LTS为当前稳定选择),确保
JAVA_HOME环境变量配置正确,可通过java -version验证安装。 - 构建工具:Maven或Gradle,本文以Maven为例(在
pom.xml中管理依赖)。
<

核心依赖库引入
Java以太坊开发的核心依赖是Web3j,一个轻量级的Java库,用于与以太坊节点交互(发送交易、调用合约、查询余额等),在pom.xml中添加以下依赖:
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.9.8</version> <!-- 使用最新稳定版本 -->
</dependency>
<!-- 可选:用于生成Java合约封装类 -->
<dependency>
<groupId>org.web3j</groupId>
<artifactId>codegen</artifactId>
<version>4.9.8</version>
</dependency>
<!-- 可选:用于单元测试 -->
<dependency>
<groupId>org.web3j</groupId>
<artifactId>testing</artifactId>
<version>4.9.8</version>
<scope>test</scope>
</dependency>
连接以太坊节点
Web3j通过RPC(Remote Procedure Call)与以太坊节点通信,无论是本地节点还是第三方服务,都需要节点的HTTP或WebSocket RPC地址。
本地节点搭建(以Geth为例)
- 安装Geth:从以太坊官网下载对应系统的安装包。
- 启动节点:在终端执行以下命令(创建主网节点,需同步大量数据,开发时可使用测试网如Ropsten):
geth --http --http.addr "0.0.0.0" --http.port "8545" --http.api "eth,web3,personal"
--http开启HTTP RPC服务,--http.addr允许所有IP访问,--http.api暴露的API接口。
第三方节点服务(以Infura为例)
- 注册Infura账号:访问Infura官网创建项目,获取RPC URL(格式为
https://<网络>.infura.io/v3/<PROJECT_ID>)。 - 测试网(如Goerli)RPC URL示例:
https://goerli.infura.io/v3/YOUR_PROJECT_ID。
Java代码连接节点
通过Web3j的Web3j.build()方法创建连接对象:
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
public class EthereumConnection {
public static void main(String[] args) {
// 本地节点RPC地址
String rpcUrl = "http://localhost:8545";
// 第三方服务(如Infura)
// String rpcUrl = "https://goerli.infura.io/v3/YOUR_PROJECT_ID";
// 创建Web3j实例
Web3j web3j = Web3j.build(new HttpService(rpcUrl));
// 测试连接:获取最新区块号
try {
String latestBlockNumber = web3j.ethBlockNumber().send().getBlockNumber().toString();
System.out.println("Latest Block Number: " + latestBlockNumber);
} catch (Exception e) {
System.err.println("Failed to connect to Ethereum node: " + e.getMessage());
}
}
}
运行后,若输出最新区块号,则表示连接成功。
智能合约交互
智能合约是以太坊应用的核心,Java通过Web3j与智能合约交互(部署、调用、查询),需先通过合约ABI(Application Binary Interface)和字节码生成Java封装类。
智能合约编写(以Solidity为例)
编写一个简单的智能合约SimpleStorage.sol,实现存储和读取整数的功能:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 private storedData;
event ValueChanged(uint256 oldValue, uint256 newValue);
function set(uint256 x) public {
uint256 oldValue = storedData;
storedData = x;
emit ValueChanged(oldValue, x);
}
function get() public view returns (uint256) {
return storedData;
}
}
将合约编译(使用Remix IDE或Solidity编译器),获取ABI(JSON格式)和字节码(Bytecode)。
生成Java合约封装类
使用Web3j的codegen工具根据ABI和字节码生成Java类,假设ABI文件为SimpleStorage.abi,字节码文件为SimpleStorage.bin,执行以下Maven命令:
mvn org.web3j:codegen -Dweb3j.generatorType=SOCK \ -Dweb3j.abiFile=src/main/resources/SimpleStorage.abi \ -Dweb3j.binFile=src/main/resources/SimpleStorage.bin \ -Dweb3j.packageName=com.example.eth.contract
执行后,会在target/generated-sources/web3j目录下生成SimpleStorage.java类,包含合约的所有方法(set()、get()等)和事件(ValueChanged)。
部署智能合约
部署合约需要账户的私钥和足够的ETH(支付Gas费),以下代码演示如何部署SimpleStorage合约:
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;
import java.math.BigInteger;
public class DeployContract {
public static void main(String[] args) throws Exception {
// 1. 创建Web3j连接
Web3j web3j = Web3j.build(new HttpService("http://localhost:8545"));
// 2. 加载账户私钥(开发环境可通过geth账户管理创建)
String privateKey = "YOUR_PRIVATE_KEY"; // 注意:私钥需妥善保管,勿硬编码到生产代码
Credentials credentials = Credentials.create(privateKey);
// 3. 设置Gas参数(Gas Price和Gas Limit)
BigInteger gasPrice = BigInteger.valueOf(20000000000L); // 20 Gwei
BigInteger gasLimit = BigInteger.valueOf(6721975); // 根据合约复杂度调整
ContractGasProvider gasProvider = new StaticGasProvider(gasPrice, gasLimit);
// 4. 部署合约(使用生成的SimpleStorage类)
SimpleStorage contract = SimpleStorage.deploy(
web3j,
credentials,
gasProvider,
BigInteger.ZERO // 无构造函数参数
).send(); // 同步发送,阻塞直到部署完成
// 5. 输出合约地址
System.out.println("Contract deployed at: " + contract.getContractAddress());
}
}
部署成功后,contract.getContractAddress()会返回合约的以太坊地址,后续交互需通过此地址。
调用智能合约方法
(1)调用写方法(修改状态,如set())
public class CallSetMethod {
public static void main(String[] args) throws Exception {
Web3j web3j = Web3j.build(new HttpService("http://localhost:8545"));
Credentials credentials = Credentials.create("YOUR_PRIVATE_KEY");
// 加载已部署的合约(需传入合约地址)
String contractAddress = "0x..."; // 替换为实际合约地址
SimpleStorage contract = SimpleStorage.load(
contractAddress,
web3j,
credentials,
new StaticGasProvider(
BigInteger.valueOf(20000000000L),
BigInteger.valueOf(6721975)
)