在 Hyperledger Fabric 1.0 从零开始(十二)——fabric-sdk-java应用 中我已经把官方sdk具体改良办法,即使用办法发出来了,所有的类及文件都是完整的,在文章的结尾也说明了用法主要都依赖于ChaincodeManager这个智能合约管理器,建议以单例的形式生成该对象。
鉴于新入门的朋友在实际运用上可能需要更加简单明了的方案,这里就把最直接的方案给出,具体是写了一个FabricManager管理器,这个管理器将会接管整个java sdk与peer节点服务器及orderer排序服务器的通讯过程,包括event等时间的拦截等等,但是这里还是给一个demo级的,具体实际运用需要大家根据自己的实际场景进行简单的修改和完善。
然后我们开始编写FabricManager管理器,这个管理器包含两个简单部分,第一部分是项目配置,第二部分是调用方法。
项目配置
节点服务器设置
1 /**
2 * 根据节点作用类型获取节点服务器配置3 *4 *@paramtype5 * 服务器作用类型(1、执行;2、查询)6 *@return节点服务器配置7 */
8 privateFabricConfig 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 returnconfig;15 }
创建配置
FabricConfig.java类创建配置,在构造器里设置crypto-config所在路径,默认路径为src/main/resources/fabric/crypto-config/
1 publicFabricConfig() {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 }
如下图未知:
设置排序服务器
通过getOrderers()方法新建排序服务器,在由config.setOrderers()方法添加排序服务器到设置。
1 privateOrderers getOrderers() {2 Orderers orderer = newOrderers();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 returnorderer;8 }
排序服务器可以添加一个或多个,排序服务器的域名和排序服务器的访问地址按提供的文件填写。
设置节点服务器对象
通过getPeers ()方法新建节点服务器,在由config. setPeers ()方法添加节点服务器到设置。
1 privatePeers Peers() {2 Peers peers = newPeers();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 returnpeers;8 }
组织名称、MSPID、组织根域名根据实际情况填写。
设置智能合约对象
通过getChaincode ()方法获取智能合约对象,在由config. setChaincode ()方法添加智能合约对象到设置。
1 privateChaincode getChaincode(String channelName, String chaincodeName, String chaincodePath, String chaincodeVersion) {2 Chaincode chaincode = newChaincode();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 returnchaincode;10 }
项目配置到这里基本就完成了,接下来是调用过程。
在述说调用过程之前,我把完整的代码粘贴出来,当然还是demo级的,但已经可以使用于生产了,如下:
1 packagecn.xx.xxx.util;2
3 importjava.io.File;4 importjava.io.IOException;5 importjava.security.NoSuchAlgorithmException;6 importjava.security.NoSuchProviderException;7 importjava.security.spec.InvalidKeySpecException;8
9 importorg.hyperledger.fabric.sdk.exception.CryptoException;10 importorg.hyperledger.fabric.sdk.exception.InvalidArgumentException;11 importorg.hyperledger.fabric.sdk.exception.TransactionException;12
13 importcn.aberic.fabric.ChaincodeManager;14 importcn.aberic.fabric.FabricConfig;15 importcn.aberic.fabric.bean.Chaincode;16 importcn.aberic.fabric.bean.Orderers;17 importcn.aberic.fabric.bean.Peers;18 importlombok.extern.slf4j.Slf4j;19
20 @Slf4j21 public classFabricManager {22
23 privateChaincodeManager manager;24
25 private static FabricManager instance = null;26
27 public staticFabricManager obtain()28 throwsCryptoException, InvalidArgumentException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, TransactionException, IOException {29 if (null ==instance) {30 synchronized (FabricManager2.class) {31 if (null ==instance) {32 instance = newFabricManager();33 }34 }35 }36 returninstance;37 }38
39 privateFabricManager()40 throwsCryptoException, InvalidArgumentException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, TransactionException, IOException {41 manager = newChaincodeManager(getConfig());42 }43
44 /**
45 * 获取节点服务器管理器46 *47 *@return节点服务器管理器48 */
49 publicChaincodeManager getManager() {50 returnmanager;51 }52
53 /**
54 * 根据节点作用类型获取节点服务器配置55 *56 *@paramtype57 * 服务器作用类型(1、执行;2、查询)58 *@return节点服务器配置59 */
60 privateFabricConfig getConfig() {61 FabricConfig config = newFabricConfig();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 returnconfig;68 }69
70 privateOrderers getOrderers() {71 Orderers orderer = newOrderers();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 returnorderer;77 }78
79 /**
80 * 获取节点服务器集81 *82 *@return节点服务器集83 */
84 privatePeers getPeers() {85 Peers peers = newPeers();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 returnpeers;91 }92
93 /**
94 * 获取智能合约95 *96 *@paramchannelName97 * 频道名称98 *@paramchaincodeName99 * 智能合约名称100 *@paramchaincodePath101 * 智能合约路径102 *@paramchaincodeVersion103 * 智能合约版本104 *@return智能合约105 */
106 privateChaincode getChaincode(String channelName, String chaincodeName, String chaincodePath, String chaincodeVersion) {107 Chaincode chaincode = newChaincode();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 returnchaincode;115 }116
117 /**
118 * 获取channel-artifacts配置路径119 *120 *@return/WEB-INF/classes/fabric/channel-artifacts/121 */
122 privateString getChannleArtifactsPath() {123 String directorys = FabricManager.class.getClassLoader().getResource("fabric").getFile();124 log.debug("directorys = " +directorys);125 File directory = newFile(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 privateString getCryptoConfigPath() {137 String directorys = FabricManager.class.getClassLoader().getResource("fabric").getFile();138 log.debug("directorys = " +directorys);139 File directory = newFile(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的改良使用和调用方法应该就完成了,如果还有什么问题,可以留言讨论。