基于Web3j构建以太坊去中心化投票系统,从智能合约到Java实战

博主:neragonerago 2026-10-06 11:42:23 1

传统电子投票系统往往依赖于中心化服务器,存在数据可被篡改、投票者身份验证困难、结果透明度不足等问题,区块链技术以其去中心化、不可篡改、公开透明的特性,为构建可信投票系统提供了理想的解决方案。

本文将介绍如何使用 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,除非注明,否则均为区块链社区- 欧亿APP下载原创文章,转载请注明出处。