应用开发指南

应用开发步骤

主要开发步骤

使用web3sdk开发区块链java应用主要包括如下过程:
  1. 数据结构和接口设计,编写合约,并将合约代码转换成java代码
  2. 编写应用程序:调用合约接口完成合约部署和调用逻辑
  3. 配置java应用
  4. 运行并测试java应用

编写合约

合约功能设计:实现简单计数器

实现一个简单的计数器,主要功能包括:
  • 设置和读取计数器名字、增加计数、读取当前计数功能。
  • 通过receipt log的方式,把修改记录log到区块中,供客户端查询。

(注: receipt log用处很大,是区块链和业务端同步交易处理过程和结果信息的有效渠道)

智能合约代码Counter.sol

根据合约功能要求可实现智能合约 Counter.sol ,合约代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
pragma solidity ^0.4.2;
contract Counter{
    string name;
    uint256 counter;
    //event handle
    event counted(uint256 c,uint256 oldvalue,uint256 currvalue,string memo); 
    event changename(string oldname); 

    function Counter(){
       name="I'm counter";
       counter = 0;
    }

    function setname(string n){
    	name=n;
	    changename(n);
    }
	
    function getname()constant returns(string){
        return name;
    }

    function addcount(uint256 c,string memo)
    {
   	uint256 oldvalue = counter;
        counter = counter+c;
        counted(c,oldvalue,counter,memo); //event
    }
	
    function getcount()constant returns(uint256){
        return counter;
    }
}

将合约代码Counter.sol转换为java代码Counter.java

web3sdk提供了 counter_compile.sh 脚本将Counter.sol转换成Counter.java:
# 进入合约编译脚本所在目录 (设web3sdk位于~/mydata目录)
$ cd ~/mydata/web3sdk/dist/bin
# 执行合约编译脚本
# (com是java代码所属的包,转换后可手动修改)
$ bash counter_compile.sh org.bcosliteclient
查看生成的java代码
$ cd ~/mydata/web3sdk/dist/output
$ tree
# ...此处省略若干输出...
├── Counter.abi  # Counter.sol编译生成的abi文件
├── Counter.bin  # Counter.sol编译生成的bin文件
└── org
   └── bcosliteclient
       ├── Counter.java # Counter.sol转换成的java代码
       ├── Evidence.java
       ├── EvidenceSignersData.java
       └── Ok.java

output目录生成了合约的.abi, .bin等文件,以及org/bcosliteclient/Counter.java文件。

这个java文件可以复制到客户端开发环境里,后续建立的java工程的对应的包路径下。

若转换成java代码时报错,请参考 faq【合约转换成java代码出错】 .

Counter.sol对应的Counter.java代码如下:

搭建并配置java应用

下载java应用bcosliteclient

编译bcosliteclient应用

# 解压应用程序(设下载的压缩包bcosliteclient.zip位于~/mydata目录下)
$ cd ~/mydata && unzip bcosliteclient.zip

# 编译bcosliteclient应用
$ cd bcosliteclient && gradle build
此时bcosliteclient应用目录如下:
$ tree -L 2
├── bcosliteclient # 编译生成目录
│   ├── bin        # 包含部署和调用Counter.sol合约的可执行脚本
│   ├── conf       # 配置文件,包含客户端配置文件applicationContext.xml,客户端证书
│   └── lib        # jar包目录
├── build          # 编译生成的临时目录
│   ├── ...省略若干行...
├── build.gradle   
├── lib
│   ├── fastjson-1.2.29.jar
│   └── web3sdk.jar    # 应用引用的web3sdk jar包
└── src
   ├── bin             # 包含可执行程序bcosclient
   ├── contract        
   |── org             # 源码目录
   └── resources       # 配置文件目录

配置java应用

参考 web3sdk配置 配置java应用,主要配置选项包括:

../../_images/javaconfig.png

部署和调用合约

部署Counter.sol合约

按照上节操作配置好java应用工程后,可调用相关接口部署和调用Counter.sol合约。
# 设bcosliteclient应用位于~/mydata目录
$ cd ~/mydata/bcosliteclient/bcosliteclient/bin
# 部署合约
$ chmod a+x bcosclient && ./bcosclient deploy
-----> start test !
init AOMP ChannelEthereumService
-->Got ethBlockNumber: 42
Deploy contract :null,address :0x8bc176465048ec377a824b7cf36f3cd7452cd093
<--start blockNumber = 42,finish blocknmber=43

由输出结果看出,合约部署成功,合约地址为 0x8bc176465048ec377a824b7cf36f3cd7452cd093 ,且部署成功后,区块链系统区块高度由42增加为43.

调用Counter.sol合约

使用 bcosliteclient/bcosliteclient/bin 目录下的 bcosclient 脚本调用Counter.sol合约:
# 设bcosliteclient应用位于~/mydata目录
$ cd ~/mydata/bcosliteclient/bcosliteclient/bin
# 调用合约(合约地址是0x8bc176465048ec377a824b7cf36f3cd7452cd093)
$ chmod a+x bcosclient && ./bcosclient call_contract 0x8bc176465048ec377a824b7cf36f3cd7452cd093
-----> start test !
init AOMP ChannelEthereumService
-->Got ethBlockNumber: 43
counter value before transaction:0
setname-->oldname:[MyCounter from:0,inc:100],newname=[MyCounter from:0,inc:100]
Current Counter:100
addcount-->inc:100,before:0,after:100,memo=when tx done,counter inc 100
<--start blockNumber = 43,finish blocknmber=44

由输出结果可看出,计数器合约Counter.sol调用成功后,计数器值增加100,区块链系统块高由43增加为44.

gradle文件配置说明

gradle配置文件说明

应用SDK的【build.gradle】要通过【compile】和【runtime】添加web3sdk.jar依赖和应用外部依赖库:
../../_images/build-gradle.png

一个完整的build.gradle示例如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
apply plugin: 'maven'
apply plugin: 'java'
apply plugin: 'eclipse'

//指定JDK版本,改成系统中版本
sourceCompatibility = 1.8
targetCompatibility = 1.8

[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'

// In this section you declare where to find the dependencies of your project
repositories {
    maven {
        url "http://maven.aliyun.com/nexus/content/groups/public/"		
    }

    mavenLocal()
    mavenCentral()
}


List logger = [
	"org.slf4j:jul-to-slf4j:1.7.10",
	"org.apache.logging.log4j:log4j-api:2.1",
	"org.apache.logging.log4j:log4j-core:2.1",
	"org.apache.logging.log4j:log4j-slf4j-impl:2.1",
	"org.apache.logging.log4j:log4j-web:2.1"
]

def spring_version="4.3.16.RELEASE"
List spring =[ 
	"org.springframework:spring-core:$spring_version", 
	"org.springframework:spring-beans:$spring_version", 
	"org.springframework:spring-context:$spring_version", 
	"org.springframework:spring-tx:$spring_version", 
	"org.springframework:spring-jdbc:$spring_version", 
	"org.springframework:spring-test:$spring_version"
]

List alibaba = [
        'com.alibaba:druid:1.0.29',
        'com.alibaba:fastjson:1.2.29'
]

// In this section you declare the dependencies for your production and test code
dependencies {
    compile logger,spring,alibaba
    runtime logger,spring,alibaba
    //【添加用户自定义jar包依赖】
    compile 'org.apache.commons:commons-lang3:3.1'
    compile "com.fasterxml.jackson.core:jackson-databind:2.9.6"
    runtime "com.fasterxml.jackson.core:jackson-databind:2.9.6"
    compile 'io.netty:netty-all:4.1.15.Final'
    runtime 'io.netty:netty-all:4.1.15.Final'
    compile 'io.netty:netty-tcnative:2.0.0.Final'
    runtime 'io.netty:netty-tcnative:2.0.0.Final'
    compile 'com.google.guava:guava:19.0'
    runtime 'com.google.guava:guava:19.0'
    //【添加web3sdk.jar包依赖】
    compile 'lib/web3sdk.jar'
    runtime 'lib/web3sdk.jar'
   	
   	// web3j依赖
   	compile 'org.apache.httpcomponents:httpclient:4.5.5',
            'org.bouncycastle:bcprov-jdk15on:1.54',
            'com.lambdaworks:scrypt:1.4.0',
            'com.squareup:javapoet:1.7.0',
            'io.reactivex:rxjava:1.2.4',
			'com.github.jnr:jnr-unixsocket:0.15'
			
	//testCompile 'junit:junit:4.12'
}

sourceSets {
	main {
		java {
	        srcDir 'src/main/java'
	        srcDir 'src/test/java'
		}
        resources  {
            srcDir 'src/main/resources'
        }
	}
}

jar {
	destinationDir file('dist/apps')
	archiveName project.name + '.jar'
	exclude '**/*.xml'
	exclude '**/*.properties'

    doLast {
        copy {
            from file('tools/')
            into 'dist/'
        }
		copy {
			from configurations.runtime
			into 'dist/lib'
		}
		copy {
            from file('src/test/resources/')
            into 'dist/conf'
        }
		copy {
			from file('.').listFiles().findAll{File f -> (f.name.endsWith('.crt') || f.name.endsWith('.keystore'))}
			into 'dist/conf'
		}
	}
}

总结

SDK应用开发步骤总结

根据以上描述,使用web3sdk开发区块链应用主要包括如下过程:
  1. 根据应用功能设计合约数据结构和接口;
  2. 编写智能合约,可先用Nodejs简单验证合约代码逻辑是否正确,验证通过后,将合约代码转换成java代码
  3. 编写java应用,调用合约java接口完成合约部署和调用功能
  4. 配置并编译java应用
  5. 应用功能测试

SDK应用部署/调用合约主要流程

参考 CounterClient.java
  1. 初始化AMOP的ChannelEthereumService
  2. 使用AMOP初始化Web3j
  3. 初始化交易签名密钥对
  4. 初始化交易参数
  5. 调用合约接口部署或调用合约

其他说明

  • 从零开发SDK应用时,可使用eclipse新建java工程,编译配置文件build.gradle可参考bcosliteclient.zip中的编译配置;
  • java应用跟目录的lib目录下要存放FISCO BCOS的web3sdk.jar,web3sdk升级时,直接替换java应用的web3sdk.jar到最新即可。