FiscoBcos使用Java调用合约【第二种方法】

环境 : ubuntu20
fisco : 2.8.0
java:1.8
solidity: 0.6.10

前言

这篇将讲解如何使用http的相关包,发送网络请求直接调用合约
请提前启动fisco节点和webase-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请求的依赖包,我们使用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;
    }
    

}

applicaiton.properties


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

解释一下这种发送除了携带合约地址,合约的方法参数和参数外,还需要各种节点相关信息,
具体可以查看webase-front发送交易的官方文档。

编写controller方法

然后我们写一个TestController来调用helloworld合约的set和get方法

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