FiscoBcos は Java を使用してコントラクトを呼び出します [2 番目の方法]

環境 : ubuntu20
フィスコ : 2.8.0
java:1.8
堅牢性 : 0.6.10

序文

この記事では、http 関連パッケージを使用してネットワーク リクエストを送信し、コントラクトを直接呼び出す方法について説明します。
事前に fisco ノードと webbase-front を起動してください

契約書の作成と展開

簡単な契約書をご用意させていただきますHelloWorld.sol

pragma solidity>=0.4.24 <0.6.11;

contract HelloWorld {
    
    
    string name;

    constructor() public {
    
    
        name = "Hello, World!";
    }

    function get() public view returns (string memory) {
    
    
        return name;
    }

    function set(string memory n) public {
    
    
        name = n;
    }
}

書いたらデプロイしてコントラクトアドレスを取得します。
ここに画像の説明を挿入します

Springboot プロジェクトを初期化する

空のプロジェクトを開始し、Web パッケージ、fastjson パッケージ、および hutool パッケージの依存関係のみをインポートします。

     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <!-- fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <!-- hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

次に、http リクエストを送信するための依存関係パッケージとして 2 つのパッケージをインポートする必要があります。ここでは okhttps を使用しますが、もちろん、http リクエスト用のオープンソースの依存関係パッケージは他にもあります。

        <!-- okhttps -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

http リクエスト ツール クラスを作成する

単純な http リクエスト送信コードは次のとおりです。

       RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data.toJSONString());  // 进行json传值,post 请求【第一个是提交方式和编写形式,第二个参数是数据】
            Request request = new Request.Builder()
                    .url(transUrl)  //发送请求到哪个地址
                    .post(requestBody) //post请求
                    .build();
            final Call call = client.newCall(request);
            Response response = call.execute();  //发送请求,获得返回体数据

しかし、コントラクト トランザクションを呼び出すたびに http リクエスト コードを再実行する必要があり、これは繰り返しが多すぎるため、ツール クラス HttpUtils を作成する必要があります。

import java.io.IOException;
import java.util.List;


@Component
public class HttpUtils {
    
    
    private static String contractAddress;
    private static String contractName;
    private static String contractAbi;
    private static String transUrl;


    @Value("${contract.address}")
    private void setContractAddress(String _address){
    
    
        contractAddress = _address;
    }

    @Value("${contract.name}")
    private void setContractName(String _name){
    
    
        contractName = _name;
    }

    @Value("${contract.abi}")
    private void setContractAbi(String _abi){
    
    
        contractAbi = _abi;
    }

    @Value("${transurl}")
    private void setTransUrl(String _url){
    
    
        transUrl = _url;
    }



    private static OkHttpClient client = new OkHttpClient();


    static private String commonReq(String userAddress, String funcName, List funcParam) {
    
    
        JSONArray abiJSON = JSON.parseArray(contractAbi);
        JSONObject data = new JSONObject();
        data.put("groupId", "1");  //群组
        data.put("user", userAddress); // 发送交易的用户地址
        data.put("contractName", contractName); //合约名
        data.put("version", "");
        data.put("funcName", funcName);  //  方法名
        data.put("funcParam", funcParam);//方法数据
        data.put("contractAddress", contractAddress);//合约地址
        data.put("contractAbi", abiJSON); //合约的abi
        data.put("useAes", false);
        data.put("useCns", false);  
        data.put("cnsName", "");//cns版本管理,没有用cns部署就不需要

        try {
    
    
            RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data.toJSONString());
            Request request = new Request.Builder()
                    .url(transUrl)  //webasefront url
                    .post(requestBody) //post请求
                    .build();
            final Call call = client.newCall(request);
            Response response = call.execute();
            return response.body().string();
        }catch (IOException exception){
    
    
            System.out.println(exception.getMessage());
        }
        return null;
    }


//执行写操作
    public static JSONObject writeContract(String userAddress,String funcName,List funcParam) {
    
    
        String result = HttpUtils.commonReq(userAddress,funcName, funcParam);
        JSONObject _obj = JSON.parseObject(result);
        if (_obj.getIntValue("code") > 0 || !_obj.get("status").equals("0x0")) {
    
    
            System.out.println(_obj);
            return null;
        }
        return _obj;
    }


 //执行读操作
    public static JSONArray readContract(String contractAddress,String funcName,List funcParam){
    
    
        String result = HttpUtils.commonReq(contractAddress,funcName, funcParam);
        JSONArray _obj = JSON.parseArray(result);
        return _obj;
    }
    

}

アプリケーションのプロパティ


contract.address=0xbdfb70e866a5531205ac2505c18e6a54acd7849e # 合约部署地址
contract.name=HelloWorld  # 合约名
contract.abi=[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"get","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"n","type":"string"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"}]   # helloworld代码的abi
transurl=http://192.168.19.133:5002/WeBASE-Front/trans/handle   # webase-front的ip地址和发送交易的路径

server.port=8086

この種の送信には、コントラクト アドレス、メソッド パラメータ、コントラクトのパラメータが含まれるだけでなく、さまざまなノード関連の情報も必要であることを説明します。
詳細については、以下を確認してください。トランザクションを送信するための webbase-front の公式 Web サイト。

書き込みコントローラーメソッド

次に、Helloworld コントラクトの set メソッドと get メソッドを呼び出す TestController を作成します。

package com.yijiuyiyi.helloworld2.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yijiuyiyi.helloworld2.entity.HelloWorldSet;
import com.yijiuyiyi.helloworld2.util.HttpUtils;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class TestController {
    
    


    private String   userAddress =  "0x49176c03339b314451e543a764db3f4b6fe8e0e2";  //交易需要有个发起人调用,我就随机用一个用户地址来调用

    @PostMapping("/set")
    public  JSONObject  set(@RequestBody HelloWorldSet dto) throws Exception {
    
    

        List list = new ArrayList<>();
        list.add(dto.getN());
        JSONObject jsonObject = HttpUtils.writeContract(userAddress, "set", list);

        return jsonObject;
    }

    @GetMapping("/get")
    public  JSONArray  get() throws Exception {
    
    

        JSONArray array = HttpUtils.readContract("get", new ArrayList());
        return array;
    }
}

次に、プロジェクトを開始してテストします

テスト効果

set メソッドの呼び出し
ここに画像の説明を挿入します
呼び出しに成功しました

{
    
    
    "blockHash": "0x9bcf1618ab5e24b6206b1e6cb372de6d1d5cf9900e0a162b31b95756f8a2ab1d",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "contractAddress": "0x0000000000000000000000000000000000000000",
    "transactionIndex": "0x0",
    "message": "Success",
    "receiptProof": null,
    "transactionHash": "0x868fc0f2b86874ba65562785790db2baf17a487414a3a50340dd59ff5d4c3c8b",
    "output": "0x",
    "input": "0x4ed3885e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c68656c6c6f313233333434340000000000000000000000000000000000000000",
    "gasUsed": "29493",
    "statusMsg": "None",
    "txProof": null,
    "root": "0x6f022173c185f30dbf45c32fc9bf66d7b19d427975e676ba012cd1dc0a263e9d",
    "blockNumber": "1897",
    "statusOK": true,
    "from": "0x49176c03339b314451e543a764db3f4b6fe8e0e2",
    "to": "0xbdfb70e866a5531205ac2505c18e6a54acd7849e",
    "logs": [],
    "status": "0x0"
}

getメソッドを呼び出す
ここに画像の説明を挿入します

テストが終了しました

結論

この呼び出し方法は http インターフェイス リクエストを送信するだけなので比較的軽量ですが、インターフェイスの数が増えると書き込みの負荷が大きくなり、返された文字列を必要な形式に処理する必要があります。ただし、前の記事の最初の呼び出しメソッドを使用すると、さまざまなリクエスト本文と戻り本文オブジェクトが生成されるため、マルチインターフェイス プロジェクトがより便利になります。

おすすめ

転載: blog.csdn.net/weixin_52865146/article/details/133295625