1、先进入fabcar文件夹
2、启动网络 ./startFabric.sh down
启动成功
3、查看启动情况 docker 镜像
4、新建SpringBoot工程项目。导入如下Fabric依赖包
<dependency><groupId>org.hyperledger.fabric-sdk-javagroupId><artifactId>fabric-sdk-javaartifactId><version>1.4.7version>
dependency><dependency><groupId>org.hyperledger.fabricgroupId><artifactId>fabric-gateway-javaartifactId><version>2.2.0version>
dependency>
5、工程目录结构如下
在test-network目录下面找到 ordererOraganizations和peerOrganizations
把ordererOraganizations和peerOrganizations复制到你IDEA的resource目录下
修改 connection.json 网络连接文件
注意&#xff1a;所有的私钥、证书和ip等都要换成自己虚拟机里的或者服务器上的&#xff0c;具体位置如下图所示
{"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&#64;org1.example.com/msp/keystore/5874889f2c0f604d3139e99c215a06c27293759407544fc152f5d91fa7e93303_sk"},"signedCertPEM": {"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin&#64;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&#64;org2.example.com/msp/keystore/1382e74e25dfe94a4bc9d98cb6b4083d2fc7de3b7532e24a7f1429e449efacc4_sk"},"signedCertPEM": {"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin&#64;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&#64;example.com/msp/keystore/648bc99748eaa1e193e037c857bada1fbf75742a3c678a1d8475ba3e102359bb_sk"},"signedCertPEM": {"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin&#64;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"}]}}
}&#96;&#96;&#96;xml
打开hosts文件&#xff0c;添加IP映射
cd c:\\Windows\System32\drivers\etcnotepad .\hosts10.65.93.36 peer0.org1.example.com
10.65.93.36 peer0.org2.example.com
10.65.93.36 orderer.example.com
fabcar.properties文件内容如下&#xff0c;相关目录私钥换成你自己的
# 网络配置文件路径
networkConfigPath &#61; src/main/resources/connection.json
# 用户1&#xff0c;机构2证书路径
certificatePath &#61; src/main/resources/crypto-config/peerOrganizations/org2.example.com/msp/signcerts/cert.pem
# 用户1&#xff0c;机构2证书私钥路径
privateKeyPath &#61; src/main/resources/crypto-config/peerOrganizations/org2.example.com/msp/keystore/003a5bc024c5fa2a284c947a2a13bad77a6485f80e0b79b9bb105a79d275d8d5_sk
# 通道名字
channelName &#61; mychannel
# 链码名字
contractName &#61; fabcar
# 运行端口
server.port&#61;8081
6、核心业务层代码如下&#xff1a;
启动类
package com.hp.fabcar;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;&#64;SpringBootApplication
public 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;&#64;RestController
&#64;RequestMapping("/car")
&#64;Slf4j
&#64;AllArgsConstructor
public class FabcarController {final Gateway gateway;final Contract contract;/*根据key查询对应的car*/&#64;GetMapping("/{key}")public Map<String, Object> queryCarByKey(&#64;PathVariable String key) throws GatewayException {Map<String, Object> result &#61; Maps.newConcurrentMap();byte[] queryAssets &#61; contract.evaluateTransaction("QueryCar",key);result.put("payload", StringUtils.newStringUtf8(queryAssets));result.put("status", "ok");return result;}/*查询所有的car*/&#64;GetMapping("/all")public Map<String, Object> queryAllCar() throws GatewayException{Map<String, Object> result &#61; Maps.newConcurrentMap();byte[] queryAllAssets &#61; contract.evaluateTransaction("QueryAllCars");result.put("payload", StringUtils.newStringUtf8(queryAllAssets));result.put("status", "ok");return result;}/*新增一个car的资产*/&#64;PostMapping("/add")&#64;ResponseBodypublic Map<String,Object> createCar(&#64;RequestParam("carnumber")String carnumber,&#64;RequestParam("make")String make,&#64;RequestParam("model")String model,&#64;RequestParam("colour")String colour,&#64;RequestParam("owner")String owner) throws GatewayException, TimeoutException, InterruptedException {Network network &#61; gateway.getNetwork("mychannel");Map<String, Object> result &#61; Maps.newConcurrentMap();byte[] transaction &#61; 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;&#64;Configuration
&#64;AllArgsConstructor
&#64;Slf4j
public class HyperLedgerFabricGateway {&#64;Beanpublic Gateway gateway() throws Exception {// 主要读取java的配置文件Properties properties &#61; new Properties();InputStream inputStream &#61; Gateway.class.getResourceAsStream("/fabcar.properties");properties.load(inputStream);String networkConfigPath &#61; properties.getProperty("networkConfigPath");String certificatePath &#61; properties.getProperty("certificatePath");X509Certificate certificate &#61; readX509Certificate(Paths.get(certificatePath));String privateKeyPath &#61; properties.getProperty("privateKeyPath");PrivateKey privateKey &#61; getPrivateKey(Paths.get(privateKeyPath));Wallet wallet &#61; Wallets.newInMemoryWallet();wallet.put("user1", Identities.newX509Identity("Org2MSP", certificate, privateKey));Gateway.Builder builder &#61; Gateway.createBuilder().identity(wallet, "user1").networkConfig(Paths.get(networkConfigPath));Gateway gateway &#61; builder.connect();log.info("&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61; connected fabric gateway {} ", gateway);return gateway;}/*获取合约的办法*/&#64;Beanpublic Contract fabcar(Gateway gateway) {// 获取mychannel的网络 也就是通道Network network &#61; gateway.getNetwork("mychannel");// 获取contract的链码 名字为fabcarContract contract &#61; network.getContract("fabcar");return contract;}/*获取证书的办法*/private static X509Certificate readX509Certificate(final Path certificatePath) throws IOException, CertificateException {// 通过路径获取到文件 如果成功获取 返回身份识别证书的结果try (Reader certificateReader &#61; Files.newBufferedReader(certificatePath, StandardCharsets.UTF_8)) {return Identities.readX509Certificate(certificateReader);}}/*获取私钥的办法 */private static PrivateKey getPrivateKey(final Path privateKeyPath) throws IOException, InvalidKeyException {// 通过路径获取到文件 如果成功获取 返回身份识别私钥的结果try (Reader privateKeyReader &#61; Files.newBufferedReader(privateKeyPath, StandardCharsets.UTF_8)) {return Identities.readPrivateKey(privateKeyReader);}}
}
启动springboot项目
7、测试接口
创建一个car如下&#xff0c;成功添加