基于Web3j构建以太坊去中心化投票系统,从智能合约到Java实战
传统电子投票系统往往依赖于中心化服务器,存在数据可被篡改、投票者身份验证困难、结果透明度不足等问题,区块链技术以其去中心化、不可篡改、公开透明的特性,为构建可信投票系统提供了理想的解决方案。
本文将介绍如何使用 Solidity 编写投票智能合约,并通过 Web3j(Java生态最流行的以太坊交互库)构建一个完整的去中心化投票系统。
技术架构概览
整个系统的技术栈如下:
| 层级 | 技术选型 | 说明 |
|---|---|---|
| 区块链层 | 以太坊(Ganache本地测试链) | 运行智能合约 |
| 合约层 | Solidity 0.8.x | 实现投票核心逻辑 |
| 交互层 | Web3j 4.x | Java与以太坊通信的桥梁 |
| 应用层 | Spring Boot | 提供REST API |
| 存储层 | MySQL(可选) | 缓存链上数据,提升查询性能 |
编写投票智能合约
首先使用Solidity编写投票合约,核心逻辑包括:初始化候选人、投票、防止重复投票、查询票数。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract Voting {
struct Candidate {
uint id; // 候选人编号
string name; // 候选人姓名
uint voteCount; // 得票数
}
// 候选人列表
mapping(uint => Candidate) public candidates;
// 投票记录:地址 -> 是否已投票
mapping(address => bool) public voters;
// 候选人总数
uint public candidatesCount;
// 投票事件,便于前端监听
event VotedEvent(uint indexed candidateId, address indexed voter);
constructor() {
addCandidate("张三");
addCandidate("李四");
addCandidate("王五");
}
// 添加候选人(仅初始化时调用)
function addCandidate(string memory _name) private {
candidatesCount++;
candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
}
// 投票函数
function vote(uint _candidateId) public {
// 每个地址只能投一票
require(!voters[msg.sender], "You have already voted.");
// 候选人必须有效
require(_candidateId > 0 && _candidateId <= candidatesCount, "Invalid candidate.");
voters[msg.sender] = true;
candidates[_candidateId].voteCount++;
emit VotedEvent(_candidateId, msg.sender);
}
// 查询候选人得票数
function getVoteCount(uint _candidateId) public view returns (uint) {
return candidates[_candidateId].voteCount;
}
}
合约设计要点:
voters映射确保一个地址只能投票一次,防止刷票;- 所有票数直接记录在链上,任何人都可以验证,无法后台篡改;
VotedEvent事件方便应用层实时监听投票动态。
搭建Web3j开发环境
引入依赖
在Spring Boot项目的 pom.xml 中添加:
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.10.3</version>
</dependency>
准备开发环境
- 安装 Ganache,用于本地模拟以太坊测试链;
- 安装 Remix(在线IDE)或配置 Truffle/Hardhat 用于编译部署合约;
- 记录Ganache提供的RPC地址(默认
http://localhost:8545)和测试账户私钥。
生成合约的Java包装类
Web3j提供了命令行工具,可以将编译后的ABI和BIN文件直接生成Java类:
web3j generate generate \ -a Voting.abi \ -b Voting.bin \ -o src/main/java \ -p com.example.voting.contract
生成的 Voting.java 封装了合约部署、交易发送、事件监听等全部方法,无需手写RPC调用。
Java后端核心实现
配置Web3j连接
@Configuration
public class Web3jConfig {
@Bean
public Web3j web3j() {
return Web3j.build(new HttpService("http://localhost:8545"));
}
@Bean
public Credentials credentials() {
// Ganache测试账户私钥
return Credentials.create(
"0x你的私钥..."
);
}
}
部署合约服务
@Service
public class VotingService {
private final Web3j web3j;
private final Credentials The End
发布于:2026-10-06,除非注明,否则均为原创文章,转载请注明出处。
