环境 : ubuntu20
fisco : 2.8.0
java:1.8
solidity: 0.6.10
Preface
This article will explain how to use http related packages to send network requests to directly call the contract
Please start the fisco node and webase-front in advance
Contract writing and deployment
We prepare a simple contractHelloWorld.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;
}
}
After writing, we will deploy it and get the contract address.
Initialize a springboot project
We start an empty project and only import the web package, fastjson package, and hutool package dependencies
<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>
Then we also need to import two packages as dependency packages for us to send http requests. We use okhttps, and of course there are other open source dependency packages for http requests.
<!-- 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>
Write http request tool class
A simple http request sending code is as follows
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(); //发送请求,获得返回体数据
But every time we call a contract transaction, we have to re-execute the http request code, which is too repetitive, so we need to write a tool class 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
Explain that this kind of sending not only carries the contract address, method parameters and parameters of the contract, but also requires various node-related information.
For details, you can check the official website of webase-front for sending transactions. document.
Write controller method
Then we write a TestController to call the set and get methods of the helloworld contract
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;
}
}
Then we start the project and test it
Test effect
Call set method
Successfully called
{
"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"
}
call get method
Finished test
Conclusion
This method of calling is relatively lightweight, because you only need to send an http interface request. However, if there are more interfaces, the writing workload will be larger, and the returned string will need to be processed into the required form. Object. But if you use the first calling method in the previous article, multi-interface projects will be more convenient, because various request body and return body objects have been generated for us.