Hyperledger Fabric 2.x Java区块链应用

一、说明
在上一篇文章中 《Hyperledger Fabric 2.x 自定义智能合约》 分享了智能合约的安装并使用 cli 客户端进行合约的调用;本文将使用 Java 代码基于 fabric-gateway-java 进行区块链网络的访问与交易,并集成 SpringBoot 框架。
Fabric Gateway SDK 实现Fabric的编程模型,提供了一系列简单的API给应用程序与Fabric区块链网络进行交互;
网络拓扑图:

应用程序将各自的网络交互委托给其网关,每个网关都了解网络信道拓扑,包括组织的多个Peer节点和排序节点,使应用程序专注于业务逻辑;Peer节点可以使用gossip协议在组织内部和组织之间相互通信。
二、Mavn依赖
添加网关sdk的依赖:
<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway-java</artifactId>
<version>2.2.3</version>
</dependency>
三、准备配置文件
工程的目录结构如下图所示:

3.1. 准备网络证书
创建目录 crypto-config 把 orderer 和 peer 节点的证书文件复制进来。
证书文件从 fabric-samples 的 test-network 目录中复制 ordererOrganizations 与 peerOrganizations 文件夹:

3.2. 创建网络配置
创建文件 connection.json 内容如下:
{
"name": "basic-network",
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
},
"orderer": "300"
}
}
},
"channels": {
"mychannel": {
"orderers": [
"orderer.example.com"
],
"peers": {
"peer0.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true
},
"peer0.org2.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
],
"certificateAuthorities": [
"ca-org1"
],
"adminPrivateKeyPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk"
},
"signedCertPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem"
}
},
"Org2": {
"mspid": "Org2MSP",
"peers": [
"peer0.org2.example.com"
],
"certificateAuthorities": [
"ca-org2"
],
"adminPrivateKeyPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/priv_sk"
},
"signedCertPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem"
}
}
},
"orderers": {
"orderer.example.com": {
"url": "grpcs://192.168.28.134:7050",
"mspid": "OrdererMSP",
"grpcOptions": {
"ssl-target-name-override": "orderer.example.com",
"hostnameOverride": "orderer.example.com"
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
},
"adminPrivateKeyPEM": {
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/keystore/priv_sk"
},
"signedCertPEM": {
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/Admin@example.com-cert.pem"
}
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://192.168.28.134:7051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com",
"hostnameOverride": "peer0.org1.example.com",
"request-timeout": 120001
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
}
},
"peer0.org2.example.com": {
"url": "grpcs://192.168.28.134:9051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org2.example.com",
"hostnameOverride": "peer0.org2.example.com",
"request-timeout": 120001
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
}
}
},
"certificateAuthorities": {
"ca-org1": {
"url": "https://192.168.28.134:7054",
"grpcOptions": {
"verify": true
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
]
},
"ca-org2": {
"url": "https://192.168.28.134:8054",
"grpcOptions": {
"verify": true
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
]
}
}
}
需按实际情况修改url中的地址,内容中分别包含了
channels、organizations、orderers、peers、ca的配置
3.3. SpringBoot配置
在 application.yml 中添加以下内容,用于访问网关的相关配置:
fabric:
# wallet文件夹路径(自动创建)
walletDirectory: wallet
# 网络配置文件路径
networkConfigPath: connection.json
# 用户证书路径
certificatePath: crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem
# 用户私钥路径
privateKeyPath: crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk
# 访问的组织名
mspid: Org1MSP
# 用户名
username: user1
# 通道名字
channelName: mychannel
# 链码名字
contractName: mycc
四、连接合约
分别构建网关、通道和合约的Bean对象,代码如下:
/**
* 连接网关
*/
@Bean
public Gateway connectGateway() throws IOException, InvalidKeyException, CertificateException {
//使用org1中的user1初始化一个网关wallet账户用于连接网络
Wallet wallet = Wallets.newFileSystemWallet(Paths.get(this.walletDirectory));
X509Certificate certificate = readX509Certificate(Paths.get(this.certificatePath));
PrivateKey privateKey = getPrivateKey(Paths.get(this.privateKeyPath));
wallet.put(username, Identities.newX509Identity(this.mspid, certificate, privateKey));
//根据connection.json 获取Fabric网络连接对象
Gateway.Builder builder = Gateway.createBuilder()
.identity(wallet, username)
.networkConfig(Paths.get(this.networkConfigPath));
//连接网关
return builder.connect();
}
/**
* 获取通道
*/
@Bean
public Network network(Gateway gateway) {
return gateway.getNetwork(this.channelName);
}
/**
* 获取合约
*/
@Bean
public Contract contract(Network network) {
return network.getContract(this.contractName);
}
五、合约调用
创建controller类,注入Contract对象调用合约方法:
@Resource
private Contract contract;
@Resource
private Network network;
@GetMapping("/getUser")
public String getUser(String userId) throws ContractException {
byte[] queryAResultBefore = contract.evaluateTransaction("getUser",userId);
return new String(queryAResultBefore, StandardCharsets.UTF_8);
}
@GetMapping("/addUser")
public String addUser(String userId, String userName, String money) throws ContractException, InterruptedException, TimeoutException {
byte[] invokeResult = contract.createTransaction("addUser")
.setEndorsingPeers(network.getChannel().getPeers(EnumSet.of(Peer.PeerRole.ENDORSING_PEER)))
.submit(userId, userName, money);
String txId = new String(invokeResult, StandardCharsets.UTF_8);
return txId;
}
六、测试接口
调用接口 getUser:
http://127.0.0.1:9001/getUser?userId=1
返回:
{
"money": 300,
"name": "zlt",
"userId": "1"
}
调用接口 addUser:
http://127.0.0.1:9001/addUser?userId=6&userName=test6&money=600
返回:
2ae291bb6a366b5ba01ad49e4237da8def9e9828cc2c982e8c49d4b763af0157
七、代码下载
gitee:https://gitee.com/zlt2000/my-fabric-application-java
github:https://github.com/zlt2000/my-fabric-application-java
扫码关注有惊喜!

Hyperledger Fabric 2.x Java区块链应用的更多相关文章
- 用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码
部署并运行 Java 链代码示例 您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger ...
- 用Java为Hyperledger Fabric(超级账本)编写区块链智能合约链代码
编写第一个 Java 链代码程序 在上一节中,您已经熟悉了如何构建.运行.部署和调用链代码,但尚未编写任何 Java 代码. 在本节中,将会使用 Eclipse IDE.一个用于 Eclipse 的 ...
- Hyperledger Fabric 手动搭建【区块链学习三】
Hyperledger Fabric 手动搭建 前面我们学习了区块链是什么.还有自动搭建学习东西我们就要从简单到深入(入门到放弃),现在自动部署已经跑通了接下来就是手动搭建Fabric 网络可以更好的 ...
- hyperledger fabric超级账本java sdk样例e2e代码流程分析
一 checkConfig Before 1.1 private static final TestConfig testConfig = TestConfig.getConfig() ...
- HyperLedger Fabric Introduction——区块链超级账本介绍
介绍 HyperLedger Fabric是一个基于模块化架构的分布式账本解决方案平台,它拥有深度加密.便捷扩展.部署灵活及可插拔等特性.它设计之初的目的是支持不同组件的可插拔实现,并适应整个经济生态 ...
- 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
摘要: 全球开源区块链领域影响最为广泛的Hyperledger Fabric日前宣布了1.1版本的正式发布,带来了一系列丰富的新功能以及在安全性.性能与扩展性等方面的显著提升.阿里云容器服务区块链解决 ...
- HyperLedger Fabric 1.4 区块链开发平台(4.1)
目前区块链开发平台分“公有链平台”和“联盟链系统”两类,“公有链平台”主要以以太坊为主的平台,可以在该类平台上进行代币的发行和根据各种模块搭建应用:“联盟链系统”主要以超级账本为主的开源系统,该类开源 ...
- Hyperledger Fabric【区块链学习一】
Hyperledger Fabric 学习 什么是区块链 什么是区块链在我们没有接触的时候,只知道它是一个去中心化的存储方式.当我们发生交易,或者动作的时候我们会将记录通知给所有参与者共同维护,达到去 ...
- HyperLedger Fabric 学习思路分享
HyperLedger Fabric 学习思路分享 HyperLedger Fabric最初是由Digital Asset和IBM公司贡献的.由Linux基金会主办的一个超级账本项目,它是一个目前非常 ...
随机推荐
- 10个JS技巧
1.过滤唯一值 Set 对象是es6新引入的,配合扩展运算符[...]一起使用,我们可以用它来过滤数组的唯一值. const array = [1, 1, 2, 3, 5, 5, 1] const u ...
- Solon Web 开发,七、视图模板与Mvc注解
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- 【C++】STL算法
STL算法 标签:c++ 目录 STL算法 一.不变序列算法 1.熟悉的min(), max() 2.找最值还自己动手么?不了不了 3.熟悉的find()和新学会的count() 二.变值算法 1.f ...
- java类的反射机制
1.获得一个类的类对象有哪些方式? - 方法1:类型.class,例如:String.class- 方法2:对象.getClass(),例如:"hello".getClass()- ...
- 搭服务器之kvm--vnc连接虚拟机连接闪退直接消失 以及virsh shutdown命令无效解决办法。
之前暑期见识到了虚拟化在企业中的应用,感慨不小,以前只是自己在玩儿桌面vmware workstation,安装的虚拟机也没啥大感觉.在公司机房里大家用的dell poweredge 420,8gme ...
- postgresql安装(windows)
官网: https://www.postgresql.org/ 下载页面:https://www.enterprisedb.com/downloads/postgres-postgresql-down ...
- linux编译安装(全面教程解析)
目录 一:编译安装 1.编译安装特点 2.编译安装 简介 编译安装 1.使用源代码,编译打包软件 2,编译安装,只能按照源代码 一:编译安装 1.编译安装特点 1.可以自定制软件 2.按需求构建软件 ...
- [JavaWeb]Log4j的前因后果
Log4j的前因后果 简介 Log4j的进化史 Log4J的三大组件: Logger:日志记录器,负责收集处理日志记录 (如何处理日志) Appender:日志输出目的地,负责日志的输出 (输出到什么 ...
- python 小兵 三元运算符
1 if 条件成立: 2 val = 1 3 else: 4 val = 2 改成三元运算: val = 1 if 条件成立 else 2 举例 条件成立走左边,条件成立走右边 a = 2 b = 5 ...
- AT2582 [ARC075D] Mirrored
首先因为这个问题的解的范围我们是不清楚的,可以先考虑一下解的范围以便后面的解题. 那么我们可以大胆猜测这个数的位数应该不会很长,否则除非使用一条与 \(D\) 有关的式子外,不论我们用什么方法都计算不 ...