在 Hyperledger Fabric 1.0 從零開始(十二)——fabric-sdk-java應用 中我已經把官方sdk具體改良辦法,即便用辦法發出來了,全部的類及文件都是完整的,在文章的結尾也說明了用法主要都依賴於ChaincodeManager這個智能合約管理器,建議以單例的形式生成該對象。html
鑑於新入門的朋友在實際運用上可能須要更加簡單明瞭的方案,這裏就把最直接的方案給出,具體是寫了一個FabricManager管理器,這個管理器將會接管整個java sdk與peer節點服務器及orderer排序服務器的通信過程,包括event等時間的攔截等等,可是這裏仍是給一個demo級的,具體實際運用須要你們根據本身的實際場景進行簡單的修改和完善。java
在此以前,請現將 Hyperledger Fabric 1.0 從零開始(十二)——fabric-sdk-java應用 這篇文章中的類及結構按照本身的須要結合到本身的項目中,確保不會報錯。git
而後咱們開始編寫FabricManager管理器,這個管理器包含兩個簡單部分,第一部分是項目配置,第二部分是調用方法。github
1 /** 2 * 根據節點做用類型獲取節點服務器配置 3 * 4 * @param type 5 * 服務器做用類型(一、執行;二、查詢) 6 * @return 節點服務器配置 7 */ 8 private FabricConfig getConfig() { 9 FabricConfig config = new FabricConfig();//建立配置 10 config.setOrderers(getOrderers());//設置排序服務器 11 config.setPeers(getPeers());//[]設置節點服務器對象 12 config.setChaincode(getChaincode("xxx","xxxcc", "github.com/hyperledger/fabric/chaincode/go/release/xxx", "1.0"));//設置智能合約對象 13 config.setCryptoConfigPath(getCryptoConfigPath());//設置crypto-config所在路徑 14 return config; 15 }
FabricConfig.java類建立配置,在構造器裏設置crypto-config所在路徑,默認路徑爲src/main/resources/fabric/crypto-config/服務器
1 public FabricConfig() { 2 // 默認channel-artifacts所在路徑 /xxx/WEB-INF/classes/fabric/channel-artifacts/ 3 channelArtifactsPath = getChannlePath() + "/channel-artifacts/"; 4 // 默認crypto-config所在路徑 /xxx/WEB-INF/classes/fabric/crypto-config/ 5 cryptoConfigPath = getChannlePath() + "/crypto-config/"; 6 }
以下圖未知:ide
經過getOrderers()方法新建排序服務器,在由config.setOrderers()方法添加排序服務器到設置。區塊鏈
1 private Orderers getOrderers() { 2 Orderers orderer = new Orderers(); 3 orderer.setOrdererDomainName("example.com");//設置排序服務器所在的根域名 4 orderer.addOrderer("orderer0.example.com", "grpc://x.x.x.x");//新增排序服務器 5 orderer.addOrderer("orderer1.example.com", "grpc://x.x.x.xx"); 6 orderer.addOrderer("orderer2.example.com", "grpc://x.x.x.xxx"); 7 return orderer; 8 }
排序服務器能夠添加一個或多個,排序服務器的域名和排序服務器的訪問地址按提供的文件填寫。spa
經過getPeers ()方法新建節點服務器,在由config. setPeers ()方法添加節點服務器到設置。debug
1 private Peers Peers() { 2 Peers peers = new Peers(); 3 peers.setOrgName("XXX");//設置組織名稱 4 peers.setOrgMSPID("XXXMSP");//組織名稱+MSP 5 peers.setOrgDomainName("xxx.example.com");//設置組織根域名 6 peers.addPeer("peer1.xxx.example.com", "peer1.xxx.example.com", "grpc://x.x.x.x:7051", "grpc://x.x.x.x:7053", "http://x.x.x.x:7054");//添加排序服務器 7 return peers; 8 }
組織名稱、MSPID、組織根域名根據實際狀況填寫。code
經過getChaincode ()方法獲取智能合約對象,在由config. setChaincode ()方法添加智能合約對象到設置。
1 private Chaincode getChaincode(String channelName, String chaincodeName, String chaincodePath, String chaincodeVersion) { 2 Chaincode chaincode = new Chaincode(); 3 chaincode.setChannelName(channelName);//設置當前將要訪問的智能合約所屬頻道名稱 4 chaincode.setChaincodeName(chaincodeName);//設置智能合約名稱 5 chaincode.setChaincodePath(chaincodePath);//設置智能合約安裝路徑 6 chaincode.setChaincodeVersion(chaincodeVersion);//設置智能合約版本號 7 chaincode.setInvokeWatiTime(100000); 8 chaincode.setDeployWatiTime(120000); 9 return chaincode; 10 }
項目配置到這裏基本就完成了,接下來是調用過程。
在述說調用過程以前,我把完整的代碼粘貼出來,固然仍是demo級的,但已經可使用於生產了,以下:
1 package cn.xx.xxx.util; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.security.NoSuchAlgorithmException; 6 import java.security.NoSuchProviderException; 7 import java.security.spec.InvalidKeySpecException; 8 9 import org.hyperledger.fabric.sdk.exception.CryptoException; 10 import org.hyperledger.fabric.sdk.exception.InvalidArgumentException; 11 import org.hyperledger.fabric.sdk.exception.TransactionException; 12 13 import cn.aberic.fabric.ChaincodeManager; 14 import cn.aberic.fabric.FabricConfig; 15 import cn.aberic.fabric.bean.Chaincode; 16 import cn.aberic.fabric.bean.Orderers; 17 import cn.aberic.fabric.bean.Peers; 18 import lombok.extern.slf4j.Slf4j; 19 20 @Slf4j 21 public class FabricManager { 22 23 private ChaincodeManager manager; 24 25 private static FabricManager instance = null; 26 27 public static FabricManager obtain() 28 throws CryptoException, InvalidArgumentException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, TransactionException, IOException { 29 if (null == instance) { 30 synchronized (FabricManager2.class) { 31 if (null == instance) { 32 instance = new FabricManager(); 33 } 34 } 35 } 36 return instance; 37 } 38 39 private FabricManager() 40 throws CryptoException, InvalidArgumentException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, TransactionException, IOException { 41 manager = new ChaincodeManager(getConfig()); 42 } 43 44 /** 45 * 獲取節點服務器管理器 46 * 47 * @return 節點服務器管理器 48 */ 49 public ChaincodeManager getManager() { 50 return manager; 51 } 52 53 /** 54 * 根據節點做用類型獲取節點服務器配置 55 * 56 * @param type 57 * 服務器做用類型(一、執行;二、查詢) 58 * @return 節點服務器配置 59 */ 60 private FabricConfig getConfig() { 61 FabricConfig config = new FabricConfig(); 62 config.setOrderers(getOrderers()); 63 config.setPeers(getPeers()); 64 config.setChaincode(getChaincode("xxx", "xxxcc", "github.com/hyperledger/fabric/chaincode/go/release/xxx", "1.0")); 65 config.setChannelArtifactsPath(getChannleArtifactsPath()); 66 config.setCryptoConfigPath(getCryptoConfigPath()); 67 return config; 68 } 69 70 private Orderers getOrderers() { 71 Orderers orderer = new Orderers(); 72 orderer.setOrdererDomainName("example.com"); 73 orderer.addOrderer("orderer1.example.com", "grpc://x.x.x.x:7050"); 74 orderer.addOrderer("orderer0.example.com", "grpc://x.x.x.xx:7050"); 75 orderer.addOrderer("orderer2.example.com", "grpc://x.x.x.xxx:7050"); 76 return orderer; 77 } 78 79 /** 80 * 獲取節點服務器集 81 * 82 * @return 節點服務器集 83 */ 84 private Peers getPeers() { 85 Peers peers = new Peers(); 86 peers.setOrgName("XXX"); 87 peers.setOrgMSPID("XXXMSP"); 88 peers.setOrgDomainName("xxx.example.com"); 89 peers.addPeer("peer1.xxx.example.com", "peer1.xxx.example.com", "grpc://x.x.x.x:7051", "grpc://x.x.x.x:7053", "http://x.x.x.x:7054"); 90 return peers; 91 } 92 93 /** 94 * 獲取智能合約 95 * 96 * @param channelName 97 * 頻道名稱 98 * @param chaincodeName 99 * 智能合約名稱 100 * @param chaincodePath 101 * 智能合約路徑 102 * @param chaincodeVersion 103 * 智能合約版本 104 * @return 智能合約 105 */ 106 private Chaincode getChaincode(String channelName, String chaincodeName, String chaincodePath, String chaincodeVersion) { 107 Chaincode chaincode = new Chaincode(); 108 chaincode.setChannelName(channelName); 109 chaincode.setChaincodeName(chaincodeName); 110 chaincode.setChaincodePath(chaincodePath); 111 chaincode.setChaincodeVersion(chaincodeVersion); 112 chaincode.setInvokeWatiTime(100000); 113 chaincode.setDeployWatiTime(120000); 114 return chaincode; 115 } 116 117 /** 118 * 獲取channel-artifacts配置路徑 119 * 120 * @return /WEB-INF/classes/fabric/channel-artifacts/ 121 */ 122 private String getChannleArtifactsPath() { 123 String directorys = FabricManager.class.getClassLoader().getResource("fabric").getFile(); 124 log.debug("directorys = " + directorys); 125 File directory = new File(directorys); 126 log.debug("directory = " + directory.getPath()); 127 128 return directory.getPath() + "/channel-artifacts/"; 129 } 130 131 /** 132 * 獲取crypto-config配置路徑 133 * 134 * @return /WEB-INF/classes/fabric/crypto-config/ 135 */ 136 private String getCryptoConfigPath() { 137 String directorys = FabricManager.class.getClassLoader().getResource("fabric").getFile(); 138 log.debug("directorys = " + directorys); 139 File directory = new File(directorys); 140 log.debug("directory = " + directory.getPath()); 141 142 return directory.getPath() + "/crypto-config/"; 143 } 144 145 }
調用過程其實就是對FabricManager管理器的具體應用,通常都在impl中進行,具體可執行代碼以下:
1 ChaincodeManager manager = FabricManager.obtain().getManager(); 2 3 manager.invoke(fcn, arguments); 4 5 manager.query(fcn, arguments);
具體返回結果的運用須要各位智能合約編寫返回結果的解析來支持,這裏須要結合業務來實操,沒法說的詳盡。
須要注意區塊鏈的事務處理,另外還有invoke和query的區別。
至此整個java sdk的改良使用和調用方法應該就完成了,若是還有什麼問題,能夠留言討論。