基于区块链的合同存证应用开发
任务一:环境准备
1.启动区块链网络
目录: /root/xuperchain/output/
启动区块链网络
bash start
- 1
2.创建钱包账户
目录: /root/xuperchain/output/
创建tenant, landlord钱包账户,命令如下:
bin/xchain-cli account newkeys --output data/tenant
bin/xchain-cli account newkeys --output data/landlord
- 1
- 2
- 3
3.向钱包账户转账
目录: /root/xuperchain/output/
通过data/tenant/address,data/landlord/address文件拿到钱包地址
cat data/tenant/address
cat daata/landlord/address
- 1
- 2
- 3
分别给两个地址分别转账,命令如下:
bin/xchain-cli transfer -to (address) --amount 10000000 --keys data/keys/ -H 127.0.0.1:37101
- 1
查看账余额,命令如下:
bin/xchain-cli account balance -- keys () -H 127.0.0.1:37101
- 1
任务二:前端工程编码
1.下载前端工程
目录: /root/Desktop
下载路径:http://:8999/blockchain-6/blockchain-device-Part.3/09/
wget :8999/blockchain-6/blockchain-devicePart.3/09/
- 1
2.解压前端工程
将下载好的 拖到桌面, 解压
unzip
- 1
3.启动前端项目
在项目根目录下运行命令:
安装依赖:
npm install --unsafe-perm
- 1
启动:
npm run serve
- 1
运行成功弹出项目访问地址
任务三:配置数据库
1.连接数据库
终端输入如下命令,连接 mysql 数据库,密码为 123456
mysql -uroot -p
- 1
2.创建数据库
创建test数据库
create database test;
- 1
查看所有数据库
show databases;
- 1
3.创建数据表
使用test数据库
use test;
- 1
创建表
CREATE TABLE `house_leasing_contract` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
`landlord` varchar(255) NOT NULL COMMENT '房东的账户公钥',
`tenant` varchar(255) NOT NULL COMMENT '租客的账户公钥',
`rent_amount` bigint NOT NULL COMMENT '每月租金金额',
`deposit_amount` bigint NOT NULL COMMENT '押金金额',
`rent_due_date` int NOT NULL COMMENT '租金到期日',
`lease_start_date` datetime NOT NULL COMMENT '租赁开始日期',
`lease_end_date` datetime NOT NULL COMMENT '租赁开始日期',
`lease_duration` int NOT NULL COMMENT '租赁期限',
`contract_hash` varchar(255) NULL COMMENT '租赁协议的哈希值',
`property_hash` varchar(255) NULL COMMENT '租赁物业信息的哈希值',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=COMPACT;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
任务四:编写后端程序
1.构建 Java 项目
打开Intellij IDEA, 点击新建项目,设置项目名为:house-leasing,项目位置:~/Desktop,语言: Java, 构建系统:Maven,JDK: 11, 点击创建。
修改包路径,将[]改为[src],右键选中包名,依次选中【重构】–>【重命名】,重命 名软件包,如下图所示:
修改Maven依赖 文件地址:/root/Desktop/house-leasing/ 修改内容为:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zhonghui</groupId>
<artifactId>house-leasing</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>house-leasing</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baidu.xuper</groupId>
<artifactId>xuper-java-sdk</artifactId>
<version>0.3.0</version>
</dependency
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 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
编辑项目配置文件 /root/Desktop/house-leasing/src/main/resources 目录下创建文件
编辑配置文件内容:
=8090
: jdbc:mysql://localhost:3306/test
: root
: 123456
-class-name:
-aliases-package: src/entity
-locations: classpath:/mapper/*.xml
- 1
- 2
- 3
- 4
- 5
- 6
- 7
最后将桌面上的合约和编译文件拖入/root/Desktop/house-leasing/src/main/resources目录下, 如下图所示:
使用solc编译合约,进入 /root/Desktop/houseLeasing/src/main/resources目录下执行如下命令
./solc --abi --bin -o --output-dir
- 1
在/root/Desktop/HouseLeasing/src/main/resources/–output-dir目录下生成的abi和bin文件:
2. 编写代码
以下代码文件路径均为/root/Desktop/houseLeasing/src/main/的相对路径,完整的项目文件如下图所 示。
代码一
代码文件路径:java/src/
新建文件,实现构建xuperchain客户端, 获取账户,解决跨域请求, 时 间格式化等功能。代码如下
package src;
import com.baidu.xuper.api.Account;
import com.baidu.xuper.api.XuperClient;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustom
izer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
@SpringBootApplication
public class HouseLeasingApplication {
@Bean
public XuperClient createXuperClient(){
return new XuperClient("127.0.0.1:37101");
}
@Bean
public Account createAccount(){
return
Account.getAccountFromPlainFile("/root/xuperchain/output/data/landlord");
}
@Bean
public LocalDateTimeSerializer localDateTimeDeserializer() {
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MMdd HH:mm:ss"));
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer
jackson2ObjectMapperBuilderCustomizer() {
return builder -> builder.serializerByType(LocalDateTime.class,
localDateTimeDeserializer());
}
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1,允许任何来源
corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
//2,允许任何请求头
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
//3,允许任何方法
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
//4,允许凭证
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
public static void main(String[] args) {
SpringApplication.run(HouseLeasingApplication.class, args);
}
}
- 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
代码二
代码文件路径:java/src/
创建文件,配置合约名称和账户名称。代码如下:
package src;
public class Config {
//每次启动需要更换
public static String CONTRACT_NAME = "contract14";
public static String ACCOUNT_NAME = "1234567890113490";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
代码三
代码文件路径:java/src/
创建文件,部署合约并完成调用。 并修改‘_landlord’ 参数地址为 root/xuperchain/output/data/landlord/address内容 并修改‘_tenant’ 参数地址为 root/xuperchain/output/data/tenant/address内容 代码如下:
package src;
import com.alibaba.fastjson.JSON;
import com.baidu.xuper.api.Account;
import com.baidu.xuper.api.AddressTrans;
import com.baidu.xuper.api.Transaction;
import com.baidu.xuper.api.XuperClient;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
@Component
public class StartTask {
@Resource
private XuperClient client;
@Resource
private Account account;
@PostConstruct
public void createContract() {
//前面命令行已经给该账户转了钱
BigInteger balance = client.getBalance(account.getAddress());
System.out.println("balance:" + balance);
//创建合约账户, 长度必须是16
client.createContractAccount(account, Config.ACCOUNT_NAME);
//转账给合约账户
Transaction transfer = client.transfer(account, "XC" +
Config.ACCOUNT_NAME + "@xuper", BigInteger.valueOf(100), "1");
// 查询余额
BigInteger result = client.getBalance("XC" + Config.ACCOUNT_NAME +
"@xuper");
System.out.println("contract balance:" + result);
//设置合约帐号
account.setContractAccount("XC" + Config.ACCOUNT_NAME + "@xuper");
try {
// 合约编译文件
byte[] abi = Files.readAllBytes(Paths.get("/root/Desktop/houseleasing/src/main/resources/--output-dir/"));
byte[] bin = Files.readAllBytes(Paths.get("/root/Desktop/houseleasing/src/main/resources/--output-dir/"));
Map<String, String> params = new HashMap<>();
params.put("creator", "XC" + Config.ACCOUNT_NAME + "@xuper");
Transaction tx1 = client.deployEVMContract(account, bin, abi,
Config.CONTRACT_NAME, params);
System.out.println("tx: " + tx1.getContractResponse().getStatus());
//调用合约
Map<String, String> signContractParams = new HashMap<>();
signContractParams.put("_landlord",
AddressTrans.xChainToEvmAddress("W757cBMtRvdN6FD27yNC1Sn4jUGH5gzUP").getAddr());
signContractParams.put("_tenant",
AddressTrans.xChainToEvmAddress("TqQz1tgJK6x5KmgrebrFbwHmUQCw5j4RV").getAddr());
signContractParams.put("_leaseStartDate",
String.valueOf((System.currentTimeMillis()) / 1000 - 1000));
signContractParams.put("_leaseEndDate",
String.valueOf((System.currentTimeMillis()) / 1000 + 1000));
signContractParams.put("_rentAmount", "100000");
signContractParams.put("_depositAmount", "100000");
signContractParams.put("_rentDueDate", "20000");
Transaction addFlight = client.invokeEVMContract(account,
Config.CONTRACT_NAME, "signContract", signContractParams, BigInteger.ZERO);
System.out.println("addFlightParams:" +
JSON.toJSONString(addFlight.getContractResponse()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 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
代码四
代码文件路径:java/src/mapper/
创建文件,编写入库接口。代码如下:
package ;
import ;
import ;
import ;
@Mapper
@Repository
public interface HouseLeasingMapper {
void saveHouseLeasing(HouseLeasingContract houseLeasingContract);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
代码五
代码文件路径:java/src/entity/
创建文件,编写租赁实体类。代码如下
package src.entity;
import java.math.BigInteger;
import java.time.LocalDateTime;
/**
* 房东的账户公钥(landlord)、租客的账户公钥(tenant)、每月租金金额(rentAmount)、
* 押金金额(depositAmount)、租金到期日(rentDueDate)、租赁开始日期(leaseStartDate)、
* 租赁结束日期(leaseEndDate)、租赁期限(leaseDuration)、租赁协议的哈希值
(contractHash)、
* 租赁物业信息的哈希值(propertyHash)。
*/
public class HouseLeasingContract {
private static final long serialVersionUID = 1L;
private Integer id;
private String landlord;
private String tenant;
private BigInteger rentAmount;
private BigInteger depositAmount;
private Integer rentDueDate;
private LocalDateTime leaseStartDate;
private LocalDateTime leaseEndDate;
private Integer leaseDuration;
private String contractHash;
private String propertyHash;
private LocalDateTime createTime;
private LocalDateTime updateTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLandlord() {
return landlord;
}
public void setLandlord(String landlord) {
this.landlord = landlord;
}
public String getTenant() {
return tenant;
}
public void setTenant(String tenant) {
this.tenant = tenant;
}
public BigInteger getRentAmount() {
return rentAmount;
}
public void setRentAmount(BigInteger rentAmount) {
this.rentAmount = rentAmount;
}
public BigInteger getDepositAmount() {
return depositAmount;
}
public void setDepositAmount(BigInteger depositAmount) {
this.depositAmount = depositAmount;
}
public Integer getRentDueDate() {
return rentDueDate;
}
public void setRentDueDate(Integer rentDueDate) {
this.rentDueDate = rentDueDate;
}
public LocalDateTime getLeaseStartDate() {
return leaseStartDate;
}
public void setLeaseStartDate(LocalDateTime leaseStartDate) {
this.leaseStartDate = leaseStartDate;
}
public LocalDateTime getLeaseEndDate() {
return leaseEndDate;
}
public void setLeaseEndDate(LocalDateTime leaseEndDate) {
this.leaseEndDate = leaseEndDate;
}
public Integer getLeaseDuration() {
return leaseDuration;
}
public void setLeaseDuration(Integer leaseDuration) {
this.leaseDuration = leaseDuration;
}
public String getContractHash() {
return contractHash;
}
public void setContractHash(String contractHash) {
this.contractHash = contractHash;
}
public String getPropertyHash() {
return propertyHash;
}
public void setPropertyHash(String propertyHash) {
this.propertyHash = propertyHash;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
}
- 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
代码六
代码文件路径:java/src/controller/
创建文件,完成接口编写。代码如下:
package src.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baidu.xuper.api.*;
import com.baidu.xuper.pb.XchainOuterClass;
import com.google.protobuf.ByteString;
import org.springframework.util.Base64Utils;
import src.Config;
import src.entity.HouseLeasingContract;
import src.mapper.HouseLeasingMapper;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class BlockController {
@Resource
private XuperClient xuperClient;
@Resource
private Account account;
@Resource
private HouseLeasingMapper mapper;
/**
*
* @return
*/
@RequestMapping(value = "/getBlockInformation")
public Map<String, Object> getBlockInformation() {
Map<String, Object> resMap = new HashMap<>();
try {
Map<String, Object> data = new HashMap<>();
XchainOuterClass.BCStatus node1 =
xuperClient.getBlockchainStatus("xuper");
XchainOuterClass.InternalBlock block1 = node1.getBlock();
long height = block1.getHeight();
System.out.println("最新区块高度:" + height);
data.put("height", height);
// 获取最新区块交易Hash
List<XchainOuterClass.Transaction> transactionsList =
block1.getTransactionsList();
if (transactionsList.size() > 0) {
ByteString txid = transactionsList.get(transactionsList.size() -
1).getTxid();
System.out.println("最新区块交易Hash:" +
Base64Utils.encodeToString(txid.toByteArray()));
data.put("Hash",
Base64Utils.encodeToString(txid.toByteArray()));
}
resMap.put("code", 200);
resMap.put("message", "请求成功");
resMap.put("data", data);
} catch (Exception e) {
resMap.put("code", 500);
resMap.put("message", "请求失败");
}
return resMap;
}
@RequestMapping(value ="/getBlockCashPledgeInformation")
public Map<String, Object> getBlockCashPledgeInformation() {
Map<String, Object> resMap = new HashMap<>();
try{
Transaction rentInfo = xuperClient.invokeEVMContract(account,
Config.CONTRACT_NAME, "rentInfo", null, BigInteger.ZERO);
ContractResponse contractResponse = rentInfo.getContractResponse();
String bodyStr = contractResponse.getBodyStr();
HouseLeasingContract houseLeasingContract = buildEntity(bodyStr);
mapper.saveHouseLeasing(houseLeasingContract);
resMap.put("code", 200);
resMap.put("message", "请求成功");
resMap.put("data", houseLeasingContract);
} catch (Exception e){
System.err.println(e.getMessage());
resMap.put("code", 500);
resMap.put("message", "请求失败");
}
return resMap;
}
private HouseLeasingContract buildEntity(String bodyStr){
HouseLeasingContract result = new HouseLeasingContract();
JSONArray objects = JSONObject.parseArray(bodyStr);
result.setLandlord(AddressTrans.evmToXChainAddress(((JSONObject)objects.get(0))
.get("_landlord").toString()).getAddr());
result.setTenant(AddressTrans.evmToXChainAddress(((JSONObject)objects.get(1)).g
et("_tenant").toString()).getAddr());
result.setRentAmount(new BigInteger(((JSONObject)
objects.get(5)).get("_rentAmount").toString()));
result.setDepositAmount(new BigInteger(((JSONObject)
objects.get(6)).get("_depositAmount").toString()));
result.setRentDueDate(Integer.valueOf(((JSONObject)
objects.get(7)).get("_rentDueDate").toString()));
LocalDateTime leaseStartDate =
LocalDateTime.ofEpochSecond(Long.parseLong(((JSONObject)
objects.get(2)).get("_leaseStartDate").toString()), 0,
ZoneOffset.ofHours(8));
result.setLeaseStartDate(leaseStartDate);
LocalDateTime leaseEndDate = LocalDateTime.ofEpochSecond(Long.parseLong(
((JSONObject) objects.get(3)).get("_leaseEndDate").toString()),
0, ZoneOffset.ofHours(8));
result.setLeaseEndDate(leaseEndDate);
result.setLeaseDuration(Integer.valueOf(((JSONObject)
objects.get(4)).get("_leaseDuration").toString()));
result.setCreateTime(LocalDateTime.now());
result.setUpdateTime(LocalDateTime.now());
return result;
}
}
- 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
- 111
代码七
代码文件路径:resources/mapper/
创建文件,编写入库sql。代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-////DTD Mapper 3.0//EN"
"/dtd/">
<mapper namespace="">
<insert id="saveHouseLeasing"
parameterType="">
INSERT INTO
house_leasing_contract(landlord,
tenant,rent_amount,deposit_amount,rent_due_date,lease_start_date,
lease_end_date,lease_duration,contract_hash,property_hash ,create_time,
update_time)
VALUES
(#{landlord},#{tenant},#{rentAmount},#{depositAmount},#{rentDueDate},#
{leaseStartDate},#{leaseEndDate},
#{leaseDuration}, #{contractHash}, #{propertyHash}, #{createTime}, #
{updateTime})
</insert>
</mapper>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
3.引入依赖
右侧导航栏-Maven-重新加载所有Maven项目
4.启动项目
目录: java/src/
任务五、运行项目
1.测试 getBlockInformation
接口 浏览器访问:http://127.0.0.1:8090/getBlockInformation
http://127.0.0.1:8090/getBlockInformation
- 1
2. 测试前端页面
浏览器访问:http://localhost:8020/