Spring Boot项目中集成Geth与以太坊区块链进行交互操作实例

前置条件已经安装Geth并启动。
现在我们讲一下Spring Boot项目中集成Geth,然后怎么以太坊区块链进行交互操作。

1、添加依赖到工程pom.xml

<dependency>  <groupId>org.web3j</groupId>  <artifactId>core</artifactId>  <version>4.8.7</version>  
</dependency>
<dependency><groupId>org.web3j</groupId><artifactId>geth</artifactId><version>4.8.7</version>
</dependency>

2、添加配置到yml文件

web3j:
#  client-address: http://192.168.99.100:8545client-address: http://127.0.0.1:8545admin-client: truehttpTimeoutSeconds: 60000

3、ETH配置类EthConfig.java


/*** @author deray.wang* @date 2024/04/20 17:18*/
@Configuration
public class EthConfig {@Value("${web3j.client-address}")private String rpc;@Beanpublic Web3j web3j() {OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.connectTimeout(30*1000, TimeUnit.MILLISECONDS);builder.writeTimeout(30*1000, TimeUnit.MILLISECONDS);builder.readTimeout(30*1000, TimeUnit.MILLISECONDS);OkHttpClient httpClient = builder.build();Web3j web3j = Web3j.build(new HttpService(rpc,httpClient,false));return web3j;}/*** 初始化admin级别操作的对象* @return Admin*/@Beanpublic Admin admin() {OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.connectTimeout(30*1000, TimeUnit.MILLISECONDS);builder.writeTimeout(30*1000, TimeUnit.MILLISECONDS);builder.readTimeout(30*1000, TimeUnit.MILLISECONDS);OkHttpClient httpClient = builder.build();Admin admin = Admin.build(new HttpService(rpc,httpClient,false));return admin;}/*** 初始化personal级别操作的对象* @return Geth*/@Beanpublic Geth geth() {OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.connectTimeout(30*1000, TimeUnit.MILLISECONDS);builder.writeTimeout(30*1000, TimeUnit.MILLISECONDS);builder.readTimeout(30*1000, TimeUnit.MILLISECONDS);OkHttpClient httpClient = builder.build();Geth geth = Geth.build(new HttpService(rpc,httpClient,false));return geth;}}

4、封装两个bean:转账ETH参数类 TransferEchBean.java 和BlockchainTransaction.java

/*** 转账ETH参数类* @author*/
@Data
@ApiModel
@ToString
public class TransferEchBean {@ApiModelProperty("fromAddr")private String fromAddr;@ApiModelProperty("密码")private String privateKey;@ApiModelProperty("toAddr")private String toAddr;@ApiModelProperty("amount")private BigDecimal amount;@ApiModelProperty("data")private String data;}
/*** @author deray.wang* @date 2024/04/20 13:44*/
@Data
public class BlockchainTransaction {private String id;//发送发件人IDprivate Integer fromId;//交易金额private long value;//收件人IDprivate Integer toId;private Boolean accepted;
}

5、封装操作区块链的方法 BlockchainService.java

BlockchainService.java类


/*** @author deray.wang* @date 2024/04/20 13:36*/
public interface BlockchainService {/*** 获取账户的Nonce* @param web3j* @param addr* @return*/BigInteger getAcountNonce(Web3j web3j, String addr);/*** 获取账户余额* @param web3j* @param addr* @return*/BigDecimal getAccountBalance(Web3j web3j, String addr);/*** 查询区块内容* @param web3j* @param blockNumber* @return*/EthBlock getBlockEthBlock(Web3j web3j, BigInteger blockNumber);/*** 创建钱包* @param password* @return*/ServiceResponse newAccount(String password);/*** 地址列表* @return*/List<String> getAllAccounts();/*** 转账ETH* @param web3j* @param fromAddr* @param privateKey* @param toAddr* @param amount* @param data* @return*/ServiceResponse transferETHD(Web3j web3j, TransferEchBean filterBean);/*** 普通转账ETH* @param web3j* @param filterBean* @return*/ServiceResponse tranETH(Web3j web3j, TransferEchBean filterBean);

实现类:BlockchainServiceImpl.java

/*** @author deray.wang* @date 2024/11/20 13:52*/
@Service
public class BlockchainServiceImpl implements BlockchainService {private static final Logger LOGGER = LoggerFactory.getLogger(BlockchainService.class);private static BigInteger gNoce = null;@Value("${wallet.file}")private String FILE;@Autowiredprivate Admin admin;@Autowiredprivate static Web3j web3j;@Autowiredprivate Geth geth;/*** 获取账户的Nonce* @param web3j* @param addr* @return*/@Overridepublic  BigInteger getAcountNonce(Web3j web3j, String addr) {return getNonce(web3j,addr);}@Overridepublic BigDecimal getAccountBalance(Web3j web3j, String addr) {return getBalance(web3j,addr);}/****/@Overridepublic ServiceResponse transferETHD(Web3j web3j, TransferEchBean filterBean){//封装业务参数Map<String,String> map = new HashMap<String,String>();map.put("time", String.valueOf(new Date()));map.put("type","info");map.put("msg","Web3 Test!!!000000000000000000000000000");JSONObject jsonObj=new JSONObject(map);//将data转化为hexString datahex = null;try {datahex = HexUtils.toHexString(jsonObj.toString().getBytes("UTF-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}return transferETH(web3j,filterBean.getFromAddr(),filterBean.getPrivateKey(),filterBean.getToAddr(),filterBean.getAmount(),datahex);}/****/@Overridepublic ServiceResponse tranETH(Web3j web3j, TransferEchBean filterBean){。。return ServiceResponse.createFailResponse("",0,"");}/*** 指定地址发送交易所需nonce获取* @param web3j* @param addr* @return*/public static  BigInteger getNonce(Web3j web3j, String addr){EthGetTransactionCount transactionCount = null;try {transactionCount = web3j.ethGetTransactionCount(addr, DefaultBlockParameterName.LATEST).sendAsync().get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}BigInteger nonce = transactionCount.getTransactionCount();
//        LOGGER.info("Tx hash: {}",  "transfer nonce : " + nonce);return nonce;}/*** 获取代币余额* @param web3j* @param fromAddress* @param contractAddress* @return*/public static BigInteger getTokenBalance(Web3j web3j, String fromAddress, String contractAddress) {String methodName = "balanceOf";List<Type> inputParameters = new ArrayList<>();List<TypeReference<?>> outputParameters = new ArrayList<>();Address address = new Address(fromAddress);inputParameters.add(address);TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {};outputParameters.add(typeReference);Function function = new Function(methodName, inputParameters, outputParameters);String data = FunctionEncoder.encode(function);Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);EthCall ethCall;BigInteger balanceValue = BigInteger.ZERO;try {ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());balanceValue = (BigInteger) results.get(0).getValue();} catch (IOException e) {e.printStackTrace();}return balanceValue;}/*** 转账ETH* @param web3j* @param fromAddr 发起人钱包地址* @param privateKey 钱包私钥* @param toAddr 转入的钱包地址* @param amount 转账金额,单位是wei* @param data  备注的信息* @param* @return*/ServiceResponse transferETH(Web3j web3j, String fromAddr, String privateKey, String toAddr, BigDecimal amount, String data){// 获得nonceBigInteger nonce = getNonce(web3j, fromAddr);// value转换BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();// gasPrice转账费用BigInteger gasPrice;gasPrice = Convert.toWei("0", Convert.Unit.GWEI).toBigInteger();//注意手续费的设置,这块很容易遇到问题BigInteger gasLimit = Convert.toWei("45000", Convert.Unit.WEI).toBigInteger();// 查询调用者余额,检测余额是否充足BigDecimal ethBalance = getBalance(web3j, fromAddr);BigDecimal balance = Convert.toWei(ethBalance, Convert.Unit.ETHER);BigDecimal tt = Convert.toWei(String.valueOf(1), Convert.Unit.ETHER);checkMoney(String.valueOf(amount),String.valueOf(balance));BigInteger val = gasPrice.multiply(gasLimit);if (balance.compareTo(tt.add(new BigDecimal(val))) < 0) {//throw new RuntimeException("余额不足,请核实");return ServiceResponse.createFailResponse("",0,"交易失败:余额不足,请核实");}//对交易签名,并发送交易if(gNoce == null){gNoce = nonce;}LOGGER.info("Tx hash: {}",  "transfer nonce : " + gNoce+" gasPrice:"+gasPrice+" gasLimit:"+gasLimit+" toAddr:"+toAddr+" value:"+value+" data:"+data);RawTransaction rawTransaction = RawTransaction.createTransaction(gNoce, gasPrice, gasLimit, toAddr, value, data);gNoce = gNoce.add(new BigInteger("1"));//RawTransaction.createEtherTransaction(nonce,gasPrice,gasLimit,to,value);if (privateKey.startsWith("0x")){privateKey = privateKey.substring(2);}ECKeyPair ecKeyPair = ECKeyPair.create(new BigInteger(privateKey, 16));Credentials credentials = Credentials.create(ecKeyPair);System.out.println(credentials.getAddress());System.out.println("PrivateKey:" + credentials.getEcKeyPair().getPrivateKey());//进行签名操作 签名Transaction,这里要对交易做签名byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);String hexValue = Numeric.toHexString(signedMessage);//发送交易EthSendTransaction ethSendTransaction = null;if (!"".equals(hexValue)) {try {ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();if(ethSendTransaction.hasError()) {String message = ethSendTransaction.getError().getMessage();System.out.println("transaction failed,info:" + message);//Utils.writeFile("F:/testErr.txt", "transaction failed,info:" + message);return ServiceResponse.createFailResponse("",0,"交易失败:"+message);}} catch (InterruptedException e) {System.out.println("transaction failed,info:" + ethSendTransaction.getError().getMessage());e.printStackTrace();return ServiceResponse.createFailResponse("",0,"交易失败:"+ethSendTransaction.getError().getMessage());} catch (ExecutionException e) {System.out.println("transaction failed,info:" + ethSendTransaction.getError().getMessage());e.printStackTrace();return ServiceResponse.createFailResponse("",0,"交易失败:"+ethSendTransaction.getError().getMessage());}}String transactionHash = ethSendTransaction.getTransactionHash();if(ethSendTransaction.hasError()){String message=ethSendTransaction.getError().getMessage();return ServiceResponse.createFailResponse("",0,"交易失败:"+message);}else {EthGetTransactionReceipt send = null;try {send = web3j.ethGetTransactionReceipt(transactionHash).send();} catch (IOException e) {e.printStackTrace();}if (send != null) {System.out.println("交易成功");//System.out.println(send.getTransactionReceipt());}Map<String,String> mapRes = new HashMap<String,String>();mapRes.put("txHash", transactionHash);return ServiceResponse.createSuccessResponse("",mapRes,"交易成功,等待记账!");}}/*** 获取ETH余额* @param web3j* @param address* @return*/public static BigDecimal getBalance(Web3j web3j, String address) {try {EthGetBalance ethGetBalance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST).send();//单位转换BigDecimal banlance = Convert.fromWei(new BigDecimal(ethGetBalance.getBalance()),Convert.Unit.ETHER);return banlance;} catch (IOException e) {e.printStackTrace();//throw new Exception("查询钱包余额失败");return null;}}public static BigInteger getTransactionGasLimit(Web3j web3j, Transaction transaction) {try {EthEstimateGas ethEstimateGas = web3j.ethEstimateGas(transaction).send();if (ethEstimateGas.hasError()){throw new RuntimeException(ethEstimateGas.getError().getMessage());}return ethEstimateGas.getAmountUsed();} catch (IOException e) {throw new RuntimeException("net error");}}/*** generate a random group of mnemonics* 生成一组随机的助记词*/private String generateMnemonics() {byte[] initialEntropy = new byte[16];new SecureRandom().nextBytes(initialEntropy);String mnemonic = MnemonicUtils.generateMnemonic(initialEntropy);return mnemonic;}private Map<String,String> createAccount() {//创建Map对象Map<String, String> map = new HashMap<String,String>();       //数据采用的哈希表结构Bip39Wallet wallet = null;// 创建一个存放keystore的文件夹String path = FILE;try {// 创建钱包wallet = WalletUtils.generateBip39Wallet("", new File(path));} catch (Exception e) {LOGGER.info("创建钱包失败");}// 获取keystore的名字String keyStoreKey = wallet.getFilename();LOGGER.info("keyStoreKey ================ " + keyStoreKey);// 获取助记词String mnemonic = wallet.getMnemonic();LOGGER.info("mnemonic ======================== " + mnemonic);// 使用密码和助记词让账户解锁Credentials credentials = WalletUtils.loadBip39Credentials("", wallet.getMnemonic());// 获取账户地址String address = credentials.getAddress();LOGGER.info("address ================= " + address);// 获取公钥String publicKey = credentials.getEcKeyPair().getPublicKey().toString(16);LOGGER.info("publicKey ==================== " + publicKey);// 获取私钥String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);LOGGER.info("privateKey ================== " + privateKey);map.put("address",address);map.put("privateKey",privateKey);map.put("publicKey",publicKey);map.put("createTime", TimeUtil.getNowString());return map;}/*** 查询区块内容* @param web3j* @param blockNumber* @return*/@Overridepublic EthBlock getBlockEthBlock(Web3j web3j,BigInteger blockNumber){DefaultBlockParameter defaultBlockParameter = new DefaultBlockParameterNumber(blockNumber);Request<?, EthBlock> request = web3j.ethGetBlockByNumber(defaultBlockParameter, true);EthBlock ethBlock = null;try {ethBlock = request.send();//返回值 - 区块对象System.out.println(ethBlock.getBlock());} catch (IOException e) {e.printStackTrace();}return ethBlock;}/*** 输入密码创建地址* @param password 密码(建议同一个平台的地址使用一个相同的,且复杂度较高的密码)* @return 地址hash*/@Overridepublic ServiceResponse newAccount(String password) {return ServiceResponse.createSuccessResponse("",createAccount());}/*** 根据hash值获取交易* @param hash* @return* @throws IOException*/public static EthTransaction getTransactionByHash(String hash) throws IOException {Request<?, EthTransaction> request = web3j.ethGetTransactionByHash(hash);return request.send();}/*** 账户解锁,使用完成之后需要锁定* @param address* @return* @throws IOException*/public  Boolean lockAccount(String address) throws IOException {Request<?, BooleanResponse> request = geth.personalLockAccount(address);BooleanResponse response = request.send();return response.success();}/*** 解锁账户,发送交易前需要对账户进行解锁* @param address 地址* @param password 密码* @param duration 解锁有效时间,单位秒* @return* @throws IOException*/public Boolean unlockAccount(String address, String password, BigInteger duration) throws IOException{Request<?, PersonalUnlockAccount> request = admin.personalUnlockAccount(address, password, duration);PersonalUnlockAccount account = request.send();return account.accountUnlocked();}/*** 发送交易并获得交易hash值* @param transaction* @param password* @return* @throws IOException*/public  String sendTransaction(Transaction transaction, String password) throws IOException {Request<?, EthSendTransaction> request = admin.personalSendTransaction(transaction, password);EthSendTransaction ethSendTransaction = request.send();return ethSendTransaction.getTransactionHash();}/***  获取钱包里的所有用户* @return*/@Autowiredpublic List<String> getAllAccounts() {List<String> list = new ArrayList<String>();try {Request<?, EthAccounts> request = geth.ethAccounts();list = request.send().getAccounts();System.out.println(list.toString());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return  list;}/*** 钱包地址余额是否足够转账校验* @param bigDecimalValue* @param addressBalance* @return*/public static String checkMoney(String bigDecimalValue,String addressBalance){if(new BigDecimal(addressBalance).subtract(new BigDecimal(bigDecimalValue)).compareTo(new BigDecimal("0")) <= 0){System.out.println("转账金额大于钱包地址余额");return  "转账金额大于钱包地址余额";}else{System.out.println("=======================");return "";}}}

6、Controller类AccountController

/*** @author deray.wang* @date 2019/11/27 17:16*/
@Slf4j
@Api(value = "用户账号接口", tags = "用户账号接口")
@RestController
@RequestMapping(CommonConst.API_PATH_VERSION_1 + "/account")
public class AccountController {@Autowiredprivate BlockchainService blockchainService;@RequestMapping(value = "/newAccount", method = RequestMethod.POST)@ApiOperation(httpMethod = "POST", value = "创建地址", produces = MediaType.APPLICATION_JSON_VALUE)public ServiceResponse newAccount(@ApiParam(name = "password") @RequestParam(name = "password") String password) {return blockchainService.newAccount(password);}@RequestMapping(value = "/getAccount", method = RequestMethod.GET)@ApiOperation(httpMethod = "GET", value = "获取钱包里的所有用户", produces = MediaType.APPLICATION_JSON_VALUE)public ServiceResponse getAllAccounts() {List<String> accounts = blockchainService.getAllAccounts();return ServiceResponse.createSuccessResponse("",accounts);}
}

大部分操作已经实现。有需要的可以联系我沟通。剩下的操作,给区块链处理,比如转账确认。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/24972.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P8697 [蓝桥杯 2019 国 C] 最长子序列

P8697 [蓝桥杯 2019 国 C] 最长子序列 题目 分析代码 题目 分析 先分析一波xdm 题意呢就是在s中找有多少个能和t匹配的字符&#xff0c;注意&#xff1a;连续匹配&#xff0c;输出连续的次数 欧克&#xff0c;开始分析&#xff0c;首先&#xff0c;哎~字母&#xff01;还强调…

一篇docker从入门到精通

Docker Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙盒机制&#xff0c;相互之间不会有任何接口&#xff08;类似 iP…

TCP/IP 5层协议簇:物理层

目录 1. 物理层&#xff08;physical layer&#xff09; 2. 网线/双绞线 1. 物理层&#xff08;physical layer&#xff09; 工作设备&#xff1a;网线、光纤、空气 传输的东西是比特bit 基本单位如下&#xff1a;数字信号 信号&#xff1a;【模拟信号&#xff08;放大器&a…

生成对抗网络(GAN)

生成对抗网络&#xff08;GAN&#xff09;:生成对抗网络是一种深度学习模型&#xff0c;由 Ian Goodfellow 等人在 2014 年提出。GAN由生成器和判别器组成&#xff0c;生成器生成假数据&#xff0c;判别器区分真假数据。两者通过对抗训练不断提升&#xff0c;最终生成器能够生成…

FastJSON 默认行为:JSON.toJSONString 忽略 null 字段

完整的 FakeRegistrationController 代码&#xff0c;这让我可以全面分析后端逻辑&#xff0c;特别是为什么空的字段&#xff08;如 compareDate&#xff09;不返回给前端。我将详细分析代码的每个接口&#xff0c;尤其是与 list 请求和字段返回相关的部分&#xff0c;并解释原…

网络通信/IP网络划分/子网掩码的概念和使用

文章目录 概述子网的考题子网掩码的历史有/无类地址子网划分!子网掩码超网技术/CIDR子网掩码和路由IP子网掩码定义 网络规划网络规划-拆子网网络规划-组超网子网划分案例 区分于其他特殊IP地址IP地址和网络地址子网掩码和网络地址子网掩码和广播地址 子网间的通信其他 概述 本…

中国的Cursor! 字节跳动推出Trae,开放Windows版(附资源),开发自己的网站,内置 GPT-4o 强大Al模型!

Trae是什么 Trae 是字节跳动推出的免费 AI IDE&#xff0c;通过 AI 技术提升开发效率。支持中文&#xff0c;集成了 Claude 3.5 和 GPT-4 等主流 AI 模型&#xff0c;完全免费使用。Trae 的主要功能包括 Builder 模式和 Chat 模式&#xff0c;其中 Builder 模式可帮助开发者从…

SpringBatch简单处理多表批量动态更新

项目需要处理一堆表&#xff0c;这些表数据量不是很大都有经纬度信息&#xff0c;但是这些表的数据没有流域信息&#xff0c;需要按经纬度信息计算所属流域信息。比较简单的项目&#xff0c;按DeepSeek提示思索完成开发&#xff0c;AI真好用。 阿里AI个人版本IDEA安装 IDEA中使…

C++ | 高级教程 | 文件和流

&#x1f47b; 概念 文件流输出使用标准库 fstream&#xff0c;定义三个新的数据类型&#xff1a; 数据类型描述ofstream输出文件流&#xff0c;用于创建文件并向文件写入信息。ifstream输入文件流&#xff0c;用于从文件读取信息。fstream文件流&#xff0c;且同时具有 ofst…

0.MySQL安装|卸载内置环境|配置官方yum源|安装mysql|登录mysql|设置配置文件(centos8.2)

卸载内置环境 检查是否有mariadb和mysql服务 ps ajx |grep mariadb ps ajx |grep mysql停止mysql服务 systemctl stop mysqld找到mysql安装包 rpm -qa | grep mysql删除安装包 rpm -qa | grep mysql | xargs yum -y remove检查 ls /etc/my.cnfls /var/lib/mysql/配置官方…

第2章_保护您的第一个应用程序

第2章_保护您的第一个应用程序 在本章中&#xff0c;您将学习如何使用 Keycloak 保护您的第一个应用程序。为了让事情更有趣&#xff0c;您将运行的示例应用程序由两部分组成&#xff0c;前端 Web 应用程序和后端 REST API。这将向您展示用户如何向前端进行身份验证&#xff0…

将DeepSeek接入vscode的N种方法

接入deepseek方法一:cline 步骤1:安装 Visual Studio Code 后,左侧导航栏上点击扩展。 步骤2:搜索 cline,找到插件后点击安装。 步骤3:在大模型下拉菜单中找到deep seek,然后下面的输入框输入你在deepseek申请的api key,就可以用了 让deepseek给我写了一首关于天气的…

QListView实现文件选择功能

一.效果 这个功能很常用,但是最高效的做法是先让左侧的源列表默认排序,然后再进行文件选择,这样在选择操作后,无论是源列表还是目标列表,都能很容易保证原来的顺序。 二.实现 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #in…

组件传递props校验

注意&#xff1a;prop是只读的&#xff01;不可以修改父组件的数据。 可以检验传过来的内容是否类型没问题。 App.vue <template><div><!-- <parentDemo/> --><componentA/></div></template> <script> import ComponentA …

好用的Docker项目:本地部署IOPaint打造专属在线图片处理工作站

文章目录 前言1.什么是IOPaint&#xff1f;2.本地部署IOPaint3.IOPaint简单实用4.公网远程访问本地IOPaint5.内网穿透工具安装6.配置公网地址7.使用固定公网地址远程访问总结 前言 在这个快节奏的时代&#xff0c;一张完美的照片往往能带来意想不到的效果。但有时候&#xff0…

P8716 [蓝桥杯 2020 省 AB2] 回文日期

1 题目说明 2 题目分析 暴力不会超时&#xff0c;O(n)的时间复杂度&#xff0c; < 1 0 8 <10^8 <108。分析见代码&#xff1a; #include<iostream> #include<string> using namespace std;int m[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};// 判断日期…

Redisson使用场景及原理

目录 一、前言 二、安装Redis 1、Windows安装Redis ​2、启动方式 3、设置密码 三、项目集成Redission客户端 1、引入依赖 四、实用场景 1、操作缓存 2、分布式锁 3、限流 3.1 创建限流器 3.2 设置限流参数 3.3 获取令牌 3.4 带超时时间获取令牌 3.5 总结 一、…

观成科技:海莲花“PerfSpyRAT”木马加密通信分析

1.概述 在2024年9月中旬至10月&#xff0c;东南亚APT组织“海莲花”通过GitHub发布开源安全工具项目&#xff0c;针对网络安全人员发起了定向攻击。通过对相关攻击活动进行分析&#xff0c;可以将其与一些海莲花的样本关联起来。这些样本的通信数据结构与海莲花此前使用的攻击…

如何在docker上部署java服务

目录结构 首先 Dockerfile FROM bladex/alpine-java:openjdk17_cn_slimMAINTAINER admin@rsz.comENV TZ=Asia/ShanghaiRUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneRUN mkdir -p /xhWORKDIR /xhEXPOSE 8106ADD ./blade-system.…

Hive从入门到运用

hive简介 hive的设计思想&#xff08;本质是一个翻译器&#xff09; 上传安装包 解压&#xff0c;查看 运行hive&#xff08;一定要启动hadoop&#xff0c;是有依赖关系的。&#xff09; 测试启动方法&#xff0c;和建表 文件创建很上传到hdfs&#xff0c;直接上传到hive表的目…