Fabric 2.3网络调用Fabric-Java-SDK进行简单开发 FabCar

1、先进入fabcar文件夹

2、启动网络 ./startFabric.sh down

启动成功

3、查看启动情况 docker 镜像

4、新建SpringBoot工程项目。导入如下Fabric依赖包

<dependency><groupId>org.hyperledger.fabric-sdk-java</groupId><artifactId>fabric-sdk-java</artifactId><version>1.4.7</version></dependency> <dependency><groupId>org.hyperledger.fabric</groupId><artifactId>fabric-gateway-java</artifactId><version>2.2.0</version></dependency>

5、工程目录结构如下

在test-network目录下面找到 ordererOraganizations和peerOrganizations
把ordererOraganizations和peerOrganizations复制到你IDEA的resource目录下

修改 connection.json 网络连接文件
注意:所有的私钥、证书和ip等都要换成自己虚拟机里的或者服务器上的,具体位置如下图所示

{"name": "basic-network","version": "1.0.0","dependencies": {},"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/5874889f2c0f604d3139e99c215a06c27293759407544fc152f5d91fa7e93303_sk"},"signedCertPEM": {"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/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/1382e74e25dfe94a4bc9d98cb6b4083d2fc7de3b7532e24a7f1429e449efacc4_sk"},"signedCertPEM": {"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/cert.pem"}}},"orderers": {"orderer.example.com": {"url": "grpcs://10.65.93.38: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/648bc99748eaa1e193e037c857bada1fbf75742a3c678a1d8475ba3e102359bb_sk"},"signedCertPEM": {"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/cert.pem"}}},"peers": {"peer0.org1.example.com": {"url": "grpcs://10.65.93.38: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://10.65.93.38: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://10.65.93.38: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://10.65.93.38: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"}]}}}```xml

打开hosts文件,添加IP映射

cd c:\\Windows\System32\drivers\etcnotepad .\hosts10.65.93.36 peer0.org1.example.com10.65.93.36 peer0.org2.example.com10.65.93.36 orderer.example.com

fabcar.properties文件内容如下,相关目录私钥换成你自己的

# 网络配置文件路径networkConfigPath = src/main/resources/connection.json# 用户1,机构2证书路径certificatePath = src/main/resources/crypto-config/peerOrganizations/org2.example.com/msp/signcerts/cert.pem# 用户1,机构2证书私钥路径privateKeyPath = src/main/resources/crypto-config/peerOrganizations/org2.example.com/msp/keystore/003a5bc024c5fa2a284c947a2a13bad77a6485f80e0b79b9bb105a79d275d8d5_sk# 通道名字channelName = mychannel# 链码名字contractName = fabcar# 运行端口server.port=8081

6、核心业务层代码如下:
启动类

package com.hp.fabcar;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class FabcarApplication {public static void main(String[] args) {SpringApplication.run(FabcarApplication.class, args);}}

操作链码的控制层 FabcarController 文件

package com.hp.fabcar.controller;import com.google.common.collect.Maps;import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.apache.commons.codec.binary.StringUtils;import org.hyperledger.fabric.gateway.*;import org.hyperledger.fabric.sdk.Peer;import org.springframework.web.bind.annotation.*;import java.util.EnumSet;import java.util.Map;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.TimeoutException;@RestController@RequestMapping("/car")@Slf4j@AllArgsConstructorpublic class FabcarController {final Gateway gateway;final Contract contract;/*根据key查询对应的car*/@GetMapping("/{key}")public Map<String, Object> queryCarByKey(@PathVariable String key) throws GatewayException {Map<String, Object> result = Maps.newConcurrentMap();byte[] queryAssets = contract.evaluateTransaction("QueryCar",key);result.put("payload", StringUtils.newStringUtf8(queryAssets));result.put("status", "ok");return result;}/*查询所有的car*/@GetMapping("/all")public Map<String, Object> queryAllCar() throws GatewayException{Map<String, Object> result = Maps.newConcurrentMap();byte[] queryAllAssets = contract.evaluateTransaction("QueryAllCars");result.put("payload", StringUtils.newStringUtf8(queryAllAssets));result.put("status", "ok");return result;}/*新增一个car的资产*/@PostMapping("/add")@ResponseBodypublic Map<String,Object> createCar(@RequestParam("carnumber")String carnumber,@RequestParam("make")String make,@RequestParam("model")String model,@RequestParam("colour")String colour,@RequestParam("owner")String owner) throws GatewayException, TimeoutException, InterruptedException {Network network = gateway.getNetwork("mychannel");Map<String, Object> result = Maps.newConcurrentMap();byte[] transaction = contract.createTransaction("CreateCar").setEndorsingPeers(network.getChannel().getPeers(EnumSet.of(Peer.PeerRole.ENDORSING_PEER))).submit(carnumber, make, model, colour, owner);result.put("payload", StringUtils.newStringUtf8(contract.evaluateTransaction("QueryCar", carnumber)));result.put("status", "ok");return result;}}

HyperLedgerFabricGatewayJavaConfig 文件

package com.hp.fabcar.controller;import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.hyperledger.fabric.gateway.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.io.IOException;import java.io.InputStream;import java.io.Reader;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.security.InvalidKeyException;import java.security.PrivateKey;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.Properties;@Configuration@AllArgsConstructor@Slf4jpublic class HyperLedgerFabricGateway {@Beanpublic Gateway gateway() throws Exception {// 主要读取java的配置文件Properties properties = new Properties();InputStream inputStream = Gateway.class.getResourceAsStream("/fabcar.properties");properties.load(inputStream);String networkConfigPath = properties.getProperty("networkConfigPath");String certificatePath = properties.getProperty("certificatePath");X509Certificate certificate = readX509Certificate(Paths.get(certificatePath));String privateKeyPath = properties.getProperty("privateKeyPath");PrivateKey privateKey = getPrivateKey(Paths.get(privateKeyPath));Wallet wallet = Wallets.newInMemoryWallet();wallet.put("user1", Identities.newX509Identity("Org2MSP", certificate, privateKey));Gateway.Builder builder = Gateway.createBuilder().identity(wallet, "user1").networkConfig(Paths.get(networkConfigPath));Gateway gateway = builder.connect();log.info("=========================================== connected fabric gateway {} ", gateway);return gateway;}/*获取合约的办法*/@Beanpublic Contract fabcar(Gateway gateway) {// 获取mychannel的网络 也就是通道Network network = gateway.getNetwork("mychannel");// 获取contract的链码 名字为fabcarContract contract = network.getContract("fabcar");return contract;}/*获取证书的办法*/private static X509Certificate readX509Certificate(final Path certificatePath) throws IOException, CertificateException {// 通过路径获取到文件 如果成功获取 返回身份识别证书的结果try (Reader certificateReader = Files.newBufferedReader(certificatePath, StandardCharsets.UTF_8)) {return Identities.readX509Certificate(certificateReader);}}/*获取私钥的办法 */private static PrivateKey getPrivateKey(final Path privateKeyPath) throws IOException, InvalidKeyException {// 通过路径获取到文件 如果成功获取 返回身份识别私钥的结果try (Reader privateKeyReader = Files.newBufferedReader(privateKeyPath, StandardCharsets.UTF_8)) {return Identities.readPrivateKey(privateKeyReader);}}}

启动springboot项目

7、测试接口

创建一个car如下,成功添加