FISCO BCOS 區塊鏈應用(五)結合WeBase開發區塊鏈目錄管理系統

目錄

前提條件及說明

1.1 搭建Fisco Bcos區塊鏈底層平臺

1.2 搭建java項目並引入 web3sdk

1.3 搭建WeBase區塊鏈管理平臺

應用開發

 1合約設計

2代碼實現

3合約編譯

4 java SDK集成

應用端對接

業務代碼接入

應用界面效果


前提條件及說明

1.1 搭建Fisco Bcos區塊鏈底層平臺

官方地址:

https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/introduction.html

打不開可以看看其他的2.2版本地址:

 https://www.bookstack.cn/read/fisco-bcos-2.2/808d0089225626d5.md

本案例環境以fisco bcos2.4 , 雙機, 單羣組, 4機構 8節點爲例.

1.2 搭建java項目並引入 web3sdk

        <dependency>
            <groupId>org.fisco-bcos</groupId>
            <artifactId>web3sdk</artifactId>
            <version>2.4.0</version>
            <scope>${dependency.scope}</scope>
        </dependency>

1.3 搭建WeBase區塊鏈管理平臺

官方地址:

https://webasedoc.readthedocs.io/zh_CN/latest/

搭建到節點管理平臺即可.即部署 節點前置服務+節點管理服務.

Fisco Bcos內置的案例居爲0.4.x版本. 建議也使用該版本進行合約開發.

WeBase提供solidity開發IDE, 可以直接編寫,編譯合約代碼,我們使用172.16.0.119是內網IP, 同學們使用需替換成自己部署的地址

http://172.16.0.119:5002/WeBASE-Front/#/contract

也推薦使用常用的在線IDE, remix

https://remix.ethereum.org/

 

基於Fisco Bcos能較爲便捷的把指定的業務數據上鍊.

內置封裝了Table.sol接口合約. 我們開發業務應用時可基於該合約接口, 以類似操作數據庫DAO層的形式, 實現CRUD操作. 

常規使用了Table.sol中的table合約

 

contract TableFactory {
    function openTable(string memory) public view returns (Table); //open table
    function createTable(string, string, string) public returns (int256); //create table
}

其中createtable中的3個參數分別爲 表名, 主鍵字段, 值字段,多個用逗號分割.

//Table main contract
contract Table {
    function select(string, Condition) public view returns (Entries);
    function insert(string, Entry) public returns (int256);
    function update(string, Entry, Condition) public returns (int256);
    function remove(string, Condition) public returns (int256);

    function newEntry() public view returns (Entry);
    function newCondition() public view returns (Condition);
}

 

  • Table合約的insert、remove、update和select函數中key的類型爲string,其長度最大支持255字符。
  • Entry的get/set接口的key的類型爲string,其長度最大支持255字符,value支持的類型有int256(int)、address和string,其中string的不能超過16MB

應用開發

 1合約設計

        系統功能開發都需要基於業務和一定的應用場景. 我們以已有的目錄管理系統作爲應用案例.  目錄是數據採集、共享、交換的嚮導,通過收集維護各部門的數據目錄, 最終形成某個全量的信用主體應用目錄, 並可對外公開發布。  通過數據項、信息類的標準化、制訂、編目,最終把目錄信息上鍊。

 

 已基於業務表設計的table合約有數據項合約、信息類合約以及目錄節點合約。

合約一旦部署發佈,則不可刪除, 則合約修改已新增的形式.

如信息類合約 UBcosInfoclassContract_V3.  需自行把 V1,V2版本的數據重新通過v3版本合約上鍊.  信息類合約是把傳統數據庫表中的數據用table合約用相同的結構把數據上鍊.

2代碼實現

 

確定業務表上鍊的字段包括:

string rid, string clsname, string clscode,string clsenname,string reftype,string sourcedept,string remark

其中rid作爲table key.  table表名暫定爲: u_bcos_infoclass_v3

在構造函數裏進行表的創建, 合約包含了 select,insert,update,remove 4個接口。 

UBcosInfoclassContract_V3 合約代碼:

pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "./Table.sol";

contract UBcosInfoclassContract_V3 {
    event CreateResult(int256 count);
    event InsertResult(int256 count);
    event UpdateResult(int256 count);
    event RemoveResult(int256 count);

    TableFactory tableFactory;
    string constant TABLE_NAME = "u_bcos_infoclass_v3";
    constructor() public {
        tableFactory = TableFactory(0x1001); //The fixed address is 0x1001 for TableFactory
           //創建信息類合約表, 參數分別爲: 
		 //TABLE_NAME:表名, 
		 //表關鍵字段:rid, 
		//表值字段:"clsname,clscode,clsenname,reftype,sourcedept,remark"
        tableFactory.createTable(TABLE_NAME, "rid", "clsname,clscode,clsenname,reftype,sourcedept,remark");
    }

    //select records
    function select(string rid)
        public
        view
        returns (string, string, string,string)
    {
        Table table = tableFactory.openTable(TABLE_NAME);

        Condition condition = table.newCondition();

        Entries entries = table.select(rid, condition);
        string memory rid_bytes;
        string memory clsname_bytes;
        string memory clscode_bytes;
        string memory sourcedept_bytes;

        if(entries.size()>0){
            Entry entry = entries.get(0);
            rid_bytes = entry.getString("rid");
            clsname_bytes = entry.getString("clsname");
            clscode_bytes = entry.getString("clscode");
            sourcedept_bytes = entry.getString("sourcedept");
        }
        return (rid_bytes, clsname_bytes, clscode_bytes,sourcedept_bytes);
    }
    //insert records
    function insert(string rid, string clsname, string clscode,string clsenname,string reftype,string sourcedept,string remark)
        public
        returns (int256)
    {
        Table table = tableFactory.openTable(TABLE_NAME);

        Entry entry = table.newEntry();
        entry.set("rid", rid);
        entry.set("clsname", clsname);
        entry.set("clscode", clscode);
        entry.set("clsenname", clsenname);
        entry.set("reftype", reftype);
        entry.set("sourcedept", sourcedept);
        entry.set("remark", remark);

        int256 count = table.insert(rid, entry);
        emit InsertResult(count);

        return count;
    }
    //update records
    function update(string rid, string clsname, string clscode,string clsenname,string reftype,string sourcedept,string remark)
        public
        returns (int256)
    {
        Table table = tableFactory.openTable(TABLE_NAME);

        Entry entry = table.newEntry();
        entry.set("clsname", clsname);
        entry.set("clscode", clscode);
        entry.set("clsenname", clsenname);
        entry.set("reftype", reftype);
        entry.set("sourcedept", sourcedept);
        entry.set("remark", remark);

        Condition condition = table.newCondition();
        condition.EQ("rid", rid);
        

        int256 count = table.update(rid, entry, condition);
        emit UpdateResult(count);

        return count;
    }
    //remove records
    function remove(string rid ) public returns (int256) {
        Table table = tableFactory.openTable(TABLE_NAME);

        Condition condition = table.newCondition();
        condition.EQ("rid", rid);
        //condition.EQ("item_id", item_id);

        int256 count = table.remove(rid, condition);
        emit RemoveResult(count);

        return count;
    }
}

3合約編譯

在WeBase結點管理服務中 新建合約, 並粘貼代碼. 點擊編譯即可.

可以在IDE面板直接進行合約方法的調用

編譯後可導出得到合約的java文件.  地層還是console控制檯代碼轉換, Webase命令行操作的方式進行了可視化界面集成.

 

4 java SDK集成

 通過得到的UBcosInfoclassContract_V3.java文件

   對合約類進行接口封裝

package com.dxx.blockchain.contract.transaction;

/**
 * 信息類合約交易接口
 * @author wuhaixin
 * 2020年6月14日
 */

public interface UBcosInfoclassContractV3Transaction {
    
    /**
     * 插入信息類,返回[blockNumber,trans_hash]
     * 2020年6月14日下午10:25:56
     * @param rid
     * @param clsname
     * @param clscode
     * @param clsenname
     * @param reftype
     * @param sourcedept
     * @param remark
     * @return
     * @throws Exception
     * @author wuhaixin
     */
    public String[] insertInfoClass(String rid,String clsname,String clscode,String clsenname,String reftype,String sourcedept,String remark) throws Exception;
    
    /**
     * 更新信息類.返回[blockNumber,trans_hash]
     * 2020年6月14日下午10:25:45
     * @param rid
     * @param clsname
     * @param clscode
     * @param clsenname
     * @param reftype
     * @param sourcedept
     * @param remark
     * @return
     * @throws Exception
     * @author wuhaixin
     */
    public String[] updateInfoClass(String rid,String clsname,String clscode,String clsenname,String reftype,String sourcedept,String remark) throws Exception;
    
    /**
     * 根據rid刪除鏈上的記錄返回[blockNumber,trans_hash]
     * 2020年6月14日下午10:25:27
     * @param rid
     * @return
     * @throws Exception
     * @author wuhaixin
     */
    public String[] removeInfoClass(String rid) throws Exception;
    
    /**
     * 返回 rid,clsname,clscode,sourcedept
     * 2020年6月14日下午10:25:13
     * @param rid
     * @return
     * @throws Exception
     * @author wuhaixin
     */
    public String[] selectInfoClass(String rid) throws Exception;

}

部分實現類代碼

/**
 * 信息類合約交易實現
 * @author wuhaixin
 * 2020年6月14日
 */
@Component
public class UBcosInfoclassContractV3TransactionImpl implements UBcosInfoclassContractV3Transaction{


/**
     * 插入信息類,返回[blockNumber,trans_hash]
     * 2020年6月14日下午10:25:56
     * @param rid
     * @param clsname
     * @param clscode
     * @param clsenname
     * @param reftype
     * @param sourcedept
     * @param remark
     * @return
     * @throws Exception
     * @author wuhaixin
     */
    public String[] insertInfoClass(String rid,String clsname,String clscode,String clsenname,String reftype,String sourcedept,String remark) throws Exception{
        
        clsname = clsname==null?"":clsname;
        clscode = clscode==null?"":clscode;
        clsenname = clsenname==null?"":clsenname;
        reftype = reftype==null?"":reftype;
        sourcedept = sourcedept==null?"":sourcedept;
        remark = remark==null?"":remark;
        
        Web3j web3j = Web3jFactory.getWeb3j();
        Credentials credentials = CredentialsFactory.getCredentials();
        
        BigInteger gasPrice = new BigInteger("0");
        BigInteger gasLimit = new BigInteger("300000000");

        //可以使用deploy或者load函數初始化合約對象,兩者使用場景不同,前者適用於初次部署合約,後者在合約已經部署並且已知合約地址時使用。
        //deploy每次會產生一個新的合約地址.
        //UBcosInfoclassContract_V3 contract = UBcosInfoclassContract_V3.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send();
        //load使用固定的合約地址.
        UBcosInfoclassContract_V3 contract = UBcosInfoclassContract_V3.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
        TransactionReceipt transactionReceipt = contract.insert(rid, clsname, clscode, clsenname, reftype, sourcedept, remark).send();
        String blockNumber = transactionReceipt.getBlockNumber().intValue()+"";
        String trans_hash = transactionReceipt.getTransactionHash();
        return new String[]{blockNumber,trans_hash};
    }

至此, 信息類合約接口已開發完畢, 可提供給應用系統使用.

應用端對接

業務代碼接入

信息類業務應用代碼如下:

主要是上鍊與保存區塊信息

 String[] transResult = uBcosInfoclassContractV3Transaction.insertInfoClass(result.getId(), result.getClsname(), result.getClscode(), 
                    result.getClsenname(), result.getReftype(), result.getSourcedept(), result.getRemark());
/**
* 控制層頂部添加@RequestMapping("/infoclass")
* 編碼人員根據實際選擇資源授權的類型.admin
* 方法名採用動賓結構,uri請求則去除賓語,比如方法:addUser,則requestmapping("/add")
* 若是頁面跳轉,則與方法名一致,如addUser對應得jsp頁面爲addUser.jsp
* controller的入口界面文件除外.如userIndex.jsp
* 最終訪問路徑爲: {應用名稱}/infoclass/admin/*,{應用名稱}/infoclass/usr/*,{應用名稱}/infoclass/web/*,
* InfoClassController 控制器
* 2018年07月05日
* @author whx
*/
@Controller
@RequestMapping("/infoclass")
public class InfoClassController {

   /**注入信息類合約交易接口*/
    @Autowired
    UBcosInfoclassContractV3Transaction uBcosInfoclassContractV3Transaction;

  
/**
* 新增對象
* 2018年07月05日
* @param entity
* @author whx
*/
@Operator(operator="添加信息類")
@ResponseBody
@RequestMapping("/admin/addInfoClass")
public AjaxResponse addInfoClass(InfoClassDO entity){
	AjaxResponse resp = AjaxResponse.instance();
	resp.setSuccess(false);
	InfoClassDO result = infoClassService.saveAndCreateTable(entity);
	
	try {
	    result.setSourcedept(AuthedUserUtil.getUserAccount());
	
              String[] transResult = uBcosInfoclassContractV3Transaction.insertInfoClass(result.getId(), result.getClsname(), result.getClscode(), 
                    result.getClsenname(), result.getReftype(), result.getSourcedept(), result.getRemark());
            
            result.setBlockNumber(Integer.parseInt(transResult[0]));
            result.setTrans_hash(transResult[1]);
            infoClassService.update(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
	
	if(result!=null){
		resp.setSuccess(true);
		resp.setMessage("保存成功!");
	}else{
		resp.setMessage("信息類英文名稱對應的數據庫表已存在,無法新建信息類,請修改編碼或使用生成功能!");
	}
	return resp;
}
}
}

應用界面效果

信息類管理模塊增改時會插入區塊鏈的塊高和交易Hash

 

 

該區塊交易信息也可以從區塊鏈管理平臺上查看.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章