学习任务包括区块链中的公钥私钥以及钱包相关知识,以及java中ORM框架mybatis
第⼀部分:区块链中的公钥私钥以及钱包 使用java生成钱包地址公钥以及私钥 在gitee上拉取项目代码
1 git clone https://gitee.com/daitoulin/testmysql.git
首先需要在pom文件中引入开源包web3j(当然项目里已经引入了)
web3j包当中内置了生成钱包地址公钥私钥的算法,我们只需调用就可以很便捷的生成。
文件路径:testmysql\src\main\java\com\example\testmysql\utils\EthUtils.java
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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 package com.example.testmysql.utils;import com.example.testmysql.entity.EthWallet;import org.web3j.crypto.ECKeyPair;import org.web3j.crypto.Hash;import org.web3j.crypto.Keys;import org.web3j.crypto.Sign;import org.web3j.crypto.Sign.SignatureData;import java.math.BigInteger;import java.security.InvalidAlgorithmParameterException;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;public class EthUtils { public static void main (String[] args) { try { ECKeyPair keyPair = Keys.createEcKeyPair(); BigInteger privateKey = keyPair.getPrivateKey(); BigInteger publicKey = keyPair.getPublicKey(); System.out.println("Private Key: " + privateKey.toString(16 )); System.out.println("Public Key: " + publicKey.toString(16 )); String address = publicKeyToAddress(publicKey); System.out.println("Address: " + address); String message = "Hello blockchain" ; SignatureData signature = signMessage(message, privateKey); System.out.println("Signature: " + bytesToHex(signature.getR()) + bytesToHex(signature.getS()) + String.format("%02x" , signature.getV()[0 ]) ); String signatureStr = bytesToHex(signature.getR()) + bytesToHex(signature.getS()) + String.format("%02x" , signature.getV()[0 ]); System.out.println(signatureStr); boolean isValid = verifySignature(message, signature, address); System.out.println("Is signature valid: " + isValid); } catch (Exception e) { e.printStackTrace(); } } public static String getSignStr (SignatureData signature) { return bytesToHex(signature.getR()) + bytesToHex(signature.getS()) + String.format("%02x" , signature.getV()[0 ]); } public static EthWallet getWallet () throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException { EthWallet wallet = new EthWallet (); ECKeyPair keyPair = Keys.createEcKeyPair(); BigInteger privateKey = keyPair.getPrivateKey(); BigInteger publicKey = keyPair.getPublicKey(); String address = publicKeyToAddress(publicKey); wallet.setPrivateKey(privateKey.toString(16 )); wallet.setPublicKey(publicKey.toString(16 )); wallet.setAddress(address); return wallet; } public static String publicKeyToAddress (BigInteger publicKey) { return "0x" + Keys.getAddress(publicKey); } public static SignatureData signMessage (String message, BigInteger privateKey) throws Exception { byte [] messageHash = Hash.sha3(message.getBytes()); ECKeyPair keyPair = ECKeyPair.create(privateKey); return Sign.signMessage(messageHash, keyPair, false ); } public static boolean verifySignature (String message, SignatureData signature, String address) { try { byte [] messageHash = Hash.sha3(message.getBytes()); BigInteger recoveredPublicKey = Sign.signedMessageHashToKey(messageHash, signature); String keysAddress = publicKeyToAddress(recoveredPublicKey); System.out.println("keysAddress: " + keysAddress); return keysAddress.equals(address); } catch (Exception e) { e.printStackTrace(); return false ; } } public static String bytesToHex (byte [] bytes) { StringBuilder sb = new StringBuilder (); for (byte b : bytes) { sb.append(String.format("%02x" , b)); } return sb.toString(); } public static SignatureData stringToSignatureData (String signatureStr) { if (signatureStr.length() < 130 ) { throw new IllegalArgumentException ("Invalid signature string length." ); } String rHex = signatureStr.substring(0 , 64 ); String sHex = signatureStr.substring(64 , 128 ); String vHex = signatureStr.substring(128 , 130 ); byte [] r = hexToBytes(rHex); byte [] s = hexToBytes(sHex); byte [] v = new byte []{(byte ) Integer.parseInt(vHex, 16 )}; return new SignatureData (v, r, s); } public static byte [] hexToBytes(String hex) { int length = hex.length(); byte [] data = new byte [length / 2 ]; for (int i = 0 ; i < length; i += 2 ) { data[i / 2 ] = (byte ) ((Character.digit(hex.charAt(i), 16 ) << 4 ) + Character.digit(hex.charAt(i + 1 ), 16 )); } return data; } }
第二部分:数据库配置 MySQL安装 首先将压缩包解压到文件夹下(注意路径需要为全英文)
创建配置文件my.ini
,写入以下内容
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 [mysqld] port =3306 basedir =D:\mysql-8.0 .20 -winx64datadir =D:\mysql-8.0 .20 -winx64\datamax_connections =1000 max_connect_errors =10 character-set-server =utf8mb4default-storage-engine =INNODBdefault_authentication_plugin =mysql_native_passwordsql_mode =STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISI[mysql] default-character-set =utf8mb4[client] port =3306 default-character-set =utf8mb4
进入管理员模式的命令行后,移动到bin路径下
初始化mysql,得到默认密码 .rcnizekl4Jt
1 mysqld --initialize --console
进行mysql服务安装
1 mysqld --install "MySQL" --defaults-file="D:\work\mysql\my.ini"
不过启动不成功,先把刚刚安装的删了,修改下安装命令即可
1 2 mysqld --remove "MySQL" mysqld --install
我们进行登录
1 mysql -u root -p .rcnizekl4Jt
提示需要更改密码,我们重置一下
1 ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
最后配置一下环境变量即可
数据表创建 先新建个数据库,默认就可以
然后新建查询,创建我们要用到的表
1 2 3 4 5 6 7 8 9 CREATE TABLE `t_user` (`id` int (11 ) NOT NULL AUTO_INCREMENT, `nickname` varchar (50 ) NOT NULL COMMENT '昵称' , `username` varchar (50 ) NOT NULL COMMENT '账号' , `password` varchar (50 ) NOT NULL COMMENT '密码' , `create_time` varchar (40 ) NOT NULL COMMENT '创建时间' , `del_status` int (4 ) NOT NULL COMMENT '删除状态0删除,1存在' , PRIMARY KEY (`id`));
可以看到创建成功
插入两条数据试试
1 2 3 4 5 6 insert into t_user (`nickname`,`username`,`password`,`create_time`,`del_status`)values ("⽤户1","user1","e10adc3949ba59abbe56e057f20f883e","2024-10-01 13:00:41",1 ); insert into t_user (`nickname`,`username`,`password`,`create_time`,`del_status`)values ("⽤户2","user2","e10adc3949ba59abbe56e057f20f883e","2024-10-01 13:00:41",1 );
检查一下成功插入数据
第三部分:学习java中ORM框架 mybatis mybatis的作用
简化数据库操作
MyBatis允许开发者通过XML或注解的方式定义SQL语句,简化JDBC的繁琐操作,比如连接管理,语句创建和结果处理。
灵活的SQL映射
与ORM(对象关系映射)框架不同,MyBatis允许开发者直接编写SQL语句,提供了更大的灵活性和控制权,适合复杂的查询和性能调优。
对象映射
MyBatis能够将数据库查询结果映射到java对象,支持复杂的对象关系映射,使得数据处理更加便捷。
项目引入mybatis 打开pom.xml文件,引入mybatis依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.3.2</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.29</version > </dependency >
打开配置文件application.properties,添加一下代码
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 spring.application.name=testMysql server.port=8087 ### mybatis mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml mybatis.configuration.map-underscore-to-camel-case=true ### xxl-job, datasource spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useUnicode=true&useSSL=false&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ### datasource-pool spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.hikari.minimum-idle=10 spring.datasource.hikari.maximum-pool-size=30 spring.datasource.hikari.auto-commit=true spring.datasource.hikari.idle-timeout=30000 spring.datasource.hikari.pool-name=HikariCP spring.datasource.hikari.max-lifetime=900000 spring.datasource.hikari.connection-timeout=10000 spring.datasource.hikari.connection-test-query=SELECT 1 spring.datasource.hikari.validation-timeout=1000
实现完整的用户模块 编写接口 用户注册 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 @RequestMapping(value = "/register") public ResponseEntity<JSONObject> save (@RequestBody TUser user) { JSONObject jo = new JSONObject (); if (user.getUsername() == null || "" .equals(user.getUsername())){ jo.setCode("-1" ); jo.setMsg("username不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (user.getPassword() == null || "" .equals(user.getPassword())){ jo.setCode("-1" ); jo.setMsg("password不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (user.getNickname() == null || "" .equals(user.getNickname())){ jo.setCode("-1" ); jo.setMsg("nickname不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } TUser exist = userService.queryUserByUsername(user.getUsername()); if (exist != null ){ jo.setCode("-1" ); jo.setMsg("username已存在,请更改" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } user.setPassword(MD5Utils.string2MD5(user.getPassword())); user.setCreateTime(DateUtils.getTime()); user.setDelStatus(1 ); userService.save(user); jo.setCode("1" ); jo.setMsg("注册成功" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); }
mybatis代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <insert id ="save" parameterType ="com.example.testmysql.entity.TUser" useGeneratedKeys ="true" keyProperty ="id" > insert into t_user ( `username`, `password`, `nickname`, `create_time`, `del_status` ) VALUES ( #{username}, #{password}, #{nickname}, #{createTime}, #{delStatus} ); </insert >
用户登录 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 @RequestMapping(value = "/login") public ResponseEntity<JSONObject> login (@RequestBody TUser user) { JSONObject jo = new JSONObject (); if (user.getUsername() == null || "" .equals(user.getUsername())){ jo.setCode("-1" ); jo.setMsg("username不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (user.getPassword() == null || "" .equals(user.getPassword())){ jo.setCode("-1" ); jo.setMsg("password不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } TUser exist = userService.queryUserByUsername(user.getUsername()); if (exist == null ){ jo.setCode("-1" ); jo.setMsg("username不存在,请先注册" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (!MD5Utils.passwordIsTrue(user.getPassword(),exist.getPassword())){ jo.setCode("-1" ); jo.setMsg("密码错误,请重试" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } jo.setCode("1" ); jo.setMsg("登录成功" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); }
mybatis代码
1 2 3 <select id ="queryUserByUsername" parameterType ="string" resultType ="com.example.testmysql.entity.TUser" > select * from t_user where username = #{username} and del_status = 1 </select >
修改密码 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 @RequestMapping(value = "/updatePassword") public ResponseEntity<JSONObject> updatePassword (@RequestBody UpdateUser user) { JSONObject jo = new JSONObject (); if (user.getUsername() == null || "" .equals(user.getUsername())){ jo.setCode("-1" ); jo.setMsg("username不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (user.getOldPassword() == null || "" .equals(user.getOldPassword())){ jo.setCode("-1" ); jo.setMsg("旧密码不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (user.getNewPassword() == null || "" .equals(user.getNewPassword())){ jo.setCode("-1" ); jo.setMsg("新密码不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } TUser exist = userService.queryUserByUsername(user.getUsername()); if (exist == null ){ jo.setCode("-1" ); jo.setMsg("username不存在,请先注册" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (!MD5Utils.passwordIsTrue(user.getOldPassword(),exist.getPassword())){ jo.setCode("-1" ); jo.setMsg("旧密码错误,请重试" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } user.setNewPassword(MD5Utils.string2MD5(user.getNewPassword())); userService.updatePassword(user); jo.setCode("1" ); jo.setMsg("修改成功" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); }
mybatis代码
1 2 3 <update id ="updatePassword" parameterType ="com.example.testmysql.entity.UpdateUser" > update t_user set password = #{newPassword} where username = #{username} </update >
删除用户 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 @RequestMapping(value = "/deleteUser") public ResponseEntity<JSONObject> deleteUser (@RequestBody TUser user) { JSONObject jo = new JSONObject (); if (user.getUsername() == null || "" .equals(user.getUsername())){ jo.setCode("-1" ); jo.setMsg("username不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (user.getPassword() == null || "" .equals(user.getPassword())){ jo.setCode("-1" ); jo.setMsg("password不能为空" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } TUser exist = userService.queryUserByUsername(user.getUsername()); if (exist == null ){ jo.setCode("-1" ); jo.setMsg("username不存在,请先注册" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } if (!MD5Utils.passwordIsTrue(user.getPassword(),exist.getPassword())){ jo.setCode("-1" ); jo.setMsg("密码错误,请重试" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); } userService.deleteUser(user); jo.setCode("1" ); jo.setMsg("删除成功" ); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); }
mybatis代码
1 2 3 <update id ="deleteUser" parameterType ="com.example.testmysql.entity.UpdateUser" > update t_user set del_status = 0 where username = #{username} </update >
查询所有用户 1 2 3 4 5 6 7 8 9 10 11 @RequestMapping(value = "/queryAllUser") public ResponseEntity<JSONObject> queryAllUser () { JSONObject jo = new JSONObject (); List<TUser> users = userService.queryAllUser(); jo.setCode("1" ); jo.setMsg("查询成功" ); jo.setO(users); return new ResponseEntity <JSONObject>(jo, HttpStatus.OK); }
mybatis代码
1 2 3 <select id ="queryAllUser" resultType ="com.example.testmysql.entity.TUser" > select * from t_user </select >
测试接口 用户注册 /register 发送注册信息
1 2 3 4 5 { "nickname" : "rev1ve" , "username" : "test" , "password" : "test" }
用户登录 /login 发送登录json数据包
1 2 3 4 { "username" : "test" , "password" : "test" }
修改密码 /updatePassword 新旧密码的参数可以在/entity/UpdateUser.java
类找到
1 2 3 4 5 { "username" : "test" , "oldPassword" : "test" , "newPassword" : "123456" }
查询所有用户 /queryAllUser
参考文章 解决本地mysql和phpstudy的mysql冲突问题