springboot+Bcos智能合约的部署与调用

springboot+Bcos智能合约的部署与调用

一、引入java sdk

​ 引入java sdk官方文档说的比较清晰,根据https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk/quick_start.html的步骤引入即可

image-20220118234529172

二、配置BCOS网络并在JAVA上连接

1.首先进入bcos目录下的console/conf,比如我的目录是 ~/fisco/console/conf

cd ~/fisco/console/conf

image-20220118234755137

修改其中的config.toml文件

vi config.toml

找到[network],将其中的127.0.0.1:20200和另一个 修改为本机ip地址,由于我是在虚拟机上,ip地址是192.168.33.11,所以修改如下

image-20220118234930547

2.进入~/fisco/nodes/127.0.0.1/sdk

cd ~/fisco/nodes/127.0.0.1/sdk

image-20220118235304162

将四个文件复制到项目的main下的resources/conf文件夹下(自己创建一个conf)

image-20220118235331242

之后配置bcos的配置文件,官网上提供了基于spring和springboot的配置方案,但是我测试之后发现在后续的配置中都很麻烦,并且都没有跑通,所以还是选用最简单的xml配置方案,也很方便。

在项目的main/resources下创建applicationContext.xml文件

image-20220118235839564

其完整内容如下

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <bean id="defaultConfigProperty" class="org.fisco.bcos.sdk.config.model.ConfigProperty">
        <property name="cryptoMaterial">
            <map>
                <entry key="certPath" value="conf" />
            </map>
        </property>
        <property name="network">
            <map>
                <entry key="peers">
                    <list>
                        <value>192.168.33.11:20200</value>
                        <value>192.168.33.11:20201</value>
                    </list>
                </entry>
            </map>
        </property>
        <property name="account">
            <map>
                <entry key="keyStoreDir" value="account" />
                <entry key="accountAddress" value="" />
                <entry key="accountFileFormat" value="pem" />
                <entry key="password" value="" />
                <entry key="accountFilePath" value="" />
            </map>
        </property>
        <property name="threadPool">
            <map>
                <entry key="channelProcessorThreadSize" value="16" />
                <entry key="receiptProcessorThreadSize" value="16" />
                <entry key="maxBlockingQueueSize" value="102400" />
            </map>
        </property>
    </bean>

    <bean id="defaultConfigOption" class="org.fisco.bcos.sdk.config.ConfigOption">
        <constructor-arg name="configProperty">
            <ref bean="defaultConfigProperty"/>
        </constructor-arg>
    </bean>

    <bean id="bcosSDK" class="org.fisco.bcos.sdk.BcosSDK">
        <constructor-arg name="configOption">
            <ref bean="defaultConfigOption"/>
        </constructor-arg>
    </bean>
</beans>

其中peers配置中的节点ip地址和端口要和上面配置的相同

<entry key="peers">
	<list>
		<value>192.168.33.11:20200</value>
		<value>192.168.33.11:20201</value>
	</list>
</entry>

三、编写智能合约并在项目中部署

1.bcos支持solidity,所以用remix开发即可

https://ethereum.github.io/browser-solidity/#optimize=false&version=soljson-v0.7.1+commit.f4a555be.js

这里使用自带的HelloWorld.sol演示,这个文件在~/fisco/console/contracts/solidity

image-20220119154309514

pragma solidity ^0.4.2;

contract HelloWorld{
    string name;
	
    
    function set(string n){
		emit test(n);
    	name = n;
    }
    
	event test(string a);

    function HelloWorld(){
       name = "Hello, World!";
    }

    function get()constant returns(string){
        return name;
    }

}

​ 这个不涉及到表,实际上bcos的智能合约支持表结构存储,具体可以看官方文档https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/manual/smart_contract.html#kvtable

​ 需要注意的是,BCOS和mysql等不同的是表设置的主键是可以重复的,而且无论是增删改查,都需要传入主键值作为参数,而且不提供全表查询功能,所以如果需要全表查询,建议主键值可以设置一个全部都相同的,方便查询。

​ 比如设计一个表是

namenumber
张三1
李四2
王五3
赵六4

​ 如果把name当做主键,搜索时只能使用 table.select(name, table.newCondition());这里的name不是主键列名,而是张三、李四、王五这些名字,此时就无法做到全表查询。

​ 如果按下面这个设计表

typenamenumber
school张三1
school李四2
school王五3
school赵六4

查询时可以直接 table.select(“school”, table.newCondition()); 这样查询的就是全部数据了

2.通过bcos自带的脚本将sol文件转化为java文件

进入console目录

cd ~/fisco/console

调用下面的start.sh脚本

./sol2java.sh org.example.demo.contract

这个org.example.demo.contract是你在项目中存放智能合约的包,按实际需求写

image-20220119190718900

之后我们进入contracts/sdk/java/org/example/demo/contract

cd contracts/sdk/java/org/example/demo/contract

image-20220119190950075

可以看到HelloWorld.java文件,将其下载到本机上(sz可以百度一下安装和使用方法,这里不赘述)

sz HelloWorld.java

image-20220119191058722

将其放到项目中的contract目录下

image-20220119191205021

3.接着我们在demo包下创建一个conf目录,在其下创建SdkBeanConfig类,用来配置连接区块链

package org.example.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.client.Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.math.BigInteger;

@Configuration
@Slf4j
public class SdkBeanConfig {

    private BcosSDK bcosSDK;
    private Client client;

    @Autowired
    private ContractConfig contractConfig;
    @Bean
    public Client client() throws  Exception{
        //指定配置xml文件的位置
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        bcosSDK = context.getBean(BcosSDK.class);
        //选择群组1
        client = bcosSDK.getClient(Integer.valueOf(1));
        //连接后返回当前区块高度
        BigInteger blockNumber = client.getBlockNumber().getBlockNumber();
        System.out.println("==========================");
        System.out.println(blockNumber);
        System.out.println("==========================");

        return client;
    }

4.之后同级目录创建ContractConfig类,来记录智能合约地址

package org.example.demo.config;

import lombok.Data;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
public class ContractConfig {
    private String HelloWorldAddress;
}

(文件位置别创建错了)

image-20220119192657296

5.创建一个controller类,方便后续的测试

image-20220119192805193

内容如下

package org.example.demo.controller;

import org.example.demo.service.HelloWorldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("hello")
public class HelloController {

    @Autowired private HelloWorldService service;

    @GetMapping("set")
    public String set(@RequestParam("n") String n) throws Exception {
        System.out.println("n = " + n);
        return service.set(n);
    }

    @GetMapping("get")
    public String get() throws Exception {
        return service.get();
    }
}

6.之后再创建一个HelloWorldService类,来实现对智能合约方法的调用

image-20220119193942023

package org.example.demo.service;

import javax.annotation.PostConstruct;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.demo.config.ContractConfig;
import org.example.demo.contract.HelloWorld;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@NoArgsConstructor
@Data
public class HelloWorldService {


    @Autowired private Client client;

    @Autowired private ContractConfig contractConfig;

    AssembleTransactionProcessor txProcessor;

    private HelloWorld helloWorld;

    @PostConstruct
    //项目部署时运行一次
    public void init() throws Exception {
        this.txProcessor =
                TransactionProcessorFactory.createAssembleTransactionProcessor(
                        this.client, this.client.getCryptoSuite().getCryptoKeyPair());
        //判断在智能合约配置类里,该智能合约是否已经有地址
        if(contractConfig.getHelloWorldAddress() == null ||
                contractConfig.getHelloWorldAddress().isEmpty()){
            //如果没有的话,将其部署到链上
            helloWorld = HelloWorld.deploy(client,client.getCryptoSuite().getCryptoKeyPair());
            System.out.println("address = " + helloWorld.getContractAddress());
            //将该合约的地址填写到智能合约配置类中
            contractConfig.setHelloWorldAddress(helloWorld.getContractAddress());
        }else{
            //如果已有地址,则加载
            helloWorld = HelloWorld.load(
                    contractConfig.getHelloWorldAddress(),
                    client,
                    client.getCryptoSuite().getCryptoKeyPair()
            );
        }
;
    }

    public String set(String n) throws Exception {
        TransactionReceipt set = helloWorld.set(n);
        return set.getBlockNumber();
    }

    public String get() throws Exception {
        String mess = helloWorld.get();
        return mess;
    }

}

7.全部写好后,我们开始测试结果

启动项目后,我们可以看到当前部署后的智能合约地址0x192e21b94ba64a2254380d387dfa40e25b464ed0

image-20220119200045966

打开浏览器,输入localhost:8080/hello/get,可以正确得到返回值

image-20220119200213722

再输入localhost:8080/hello/set?n=testContract,返回了十六进制的高度

image-20220119200531145

再次输入localhost:8080/hello/get,发现修改成功

image-20220119200657383

现在重新运行一下项目

可以看到控制台的智能合约地址已经变成了 0xd8c64830531cafe67125d41dda90efc03fa17ea7

image-20220119200739742

我们打开浏览器,输入localhost:8080/hello/get,发现返回值复原了,证明确实是又重新部署了智能合约

image-20220119200856474

现在我们进入ContractConfig类中,把第一次的智能合约地址赋给HelloWorldAddress

image-20220119201006847

package org.example.demo.config;

import lombok.Data;
import org.springframework.context.annotation.Configuration;

/**
 * @Auther sundaohan
 * @Package com.neu.config.bcos
 * @Title ContractConfig
 * @Description TODO
 * @Date 2022/1/18 下午9:33
 */
@Data
@Configuration
public class ContractConfig {
    private String HelloWorldAddress = "0x192e21b94ba64a2254380d387dfa40e25b464ed0";
}

再次启动项目后,打开浏览器,输入localhost:8080/hello/get,发现返回值是我们当时修改的testContract,证明这次加载的是我们当时部署的那个合约

image-20220119201121089

至此,BCOS智能合约在springboot框架下的java项目中的部署与调用演示完毕。

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值