长安链使用Golang编写智能合约教程(三)
本篇主要介绍长安链Go SDK写智能合约的一些常见方法的使用方法或介绍
资料来源:
- 官方文档
- 官方示例合约库
官方SDK接口文档
教程一:智能合约编写1
教程二:智能合约编写2
一、获取参数、获取状态、获取历史记录的方法解析
注意!
这些查询链上数据的方法:只能是查询本合约之前上链的数据,别的合约上链的数据就算key相同你也是不能查的,其他查询方法也一样
// GetArgs get arg from transaction parameters// @return: 参数map GetArgs() map[string][]byte (常用,获取参数的方法,之前的示例基本上都用到)
// GetState get [key, field] from chain// @param key: 获取的参数名// @param field: 获取的参数名// @return1: 获取结果,格式为string// @return2: 获取错误信息 // Deprecated: 无法通过返回值来判断state是否存在,建议使用GetStateWithExists GetState(key, field string) (string, error)(通过空间域名+key 查询值)官方说废弃了建议用GetStateWithExists
// GetStateWithExists get [key, field] from chain// @param key: 获取的参数名// @param field: 获取的参数名// @return1: 获取结果,格式为string// @return2: 是否存在,bool, 字符串长度为0不代表不存在// @return3: 获取错误信息GetStateWithExists(key, field string) (string, bool, error)
(通过空间域名+key 查询值) 返回值,是否存在,错误参数
其中如果不存在返回空和false
// GetBatchState get [BatchKeys] from chain// @param batchKey: 获取的参数名// @return1: 获取结果// @return2: 获取错误信息GetBatchState(batchKeys []*vmPb.BatchKey) ([]*vmPb.BatchKey, error)
没看懂怎么用,像是批量查询,但是BatchKey很多参数
// GetStateByte get [key, field] from chain// @param key: 获取的参数名// @param field: 获取的参数名// @return1: 获取结果,格式为[]byte, nil表示不存在// @return2: 获取错误信息GetStateByte(key, field string) ([]byte, error)
(通过空间域名+key 查询值) 返回值[]byte,错误参数
// GetStateFromKey get [key] from chain// @param key: 获取的参数名// @return1: 获取结果,格式为string// @return2: 获取错误信息 // Deprecated: 无法通过返回值来判断state是否存在,建议使用GetStateFromKeyWithExistsGetStateFromKey(key string) (string, error)
注意!
通过key去查值,如果前面你存值是用 field 、key 两个参数存的,那么你用一个key值是取不到任何值的
// GetStateFromKeyWithExists get [key] from chain// @param key: 获取的参数名// @return1: 获取结果,格式为string// @return2: 是否存在,bool, 字符串长度为0不代表不存在// @return3: 获取错误信息GetStateFromKeyWithExists(key string) (string, bool, error)
同上
// GetStateFromKeyByte get [key] from chain// @param key: 获取的参数名// @return1: 获取结果,格式为[]byte, nil表示不存在// @return2: 获取错误信息GetStateFromKeyByte(key string) ([]byte, error)
同上
二、存数据、删除数据的一些方法
// PutState put [key, field, value] to chain// @param1 key: 参数名// @param1 field: 参数名// @param2 value: 参数值,类型为string// @return1: 上传参数错误信息PutState(key, field string, value string) error
存数据方法: 参数依次是 key值、空间域名、要存的数据 (string)
官方的一些示例是:空间域名、 key值、要存的数据 (string)
// PutStateByte put [key, field, value] to chain// @param1 key: 参数名// @param1 field: 参数名// @param2 value: 参数值,类型为[]byte// @return1: 上传参数错误信息PutStateByte(key, field string, value []byte) error存数据方法: 参数依次是 key值、空间域名、要存的数据 []byte
官方的一些示例是:空间域名、 key值、要存的数据 []byte
// PutStateFromKey put [key, value] to chain// @param1 key: 参数名// @param2 value: 参数值,类型为string// @return1: 上传参数错误信息 PutStateFromKey(key string, value string) error
存数据方法: 参数依次是 key值、要存的数据 string
注意 ,不带空间域名去存,取值的时候也要不带空间域名
// PutStateFromKeyByte put [key, value] to chain// @param1 key: 参数名// @param2 value: 参数值,类型为[]byte// @return1: 上传参数错误信息 PutStateFromKeyByte(key string, value []byte) error
存数据方法: 参数依次是 key值、要存的数据 []byte
// DelState delete [key, field] to chain// @param1 key: 删除的参数名// @param1 field: 删除的参数名// @return1:删除参数的错误信息 DelState(key, field string) error
删除数据方法: 参数依次是 key值、空间域名
注意:删除不是真的删除数据,会新增一条交易,交易内容是 key 、field 的字段isdelete变成 true , 并且如果区块链上没有 key、field的数据同样也能删除、也会新增一条数据
// DelStateFromKey delete [key] to chain// @param1 key: 删除的参数名// @return1:删除参数的错误信息 DelStateFromKey(key string) error
删除数据的方法通过key
三、获取其他值的一些方法
// GetCreatorOrgId get tx creator org id// @return1: 合约创建者的组织ID// @return2: 获取错误信息GetCreatorOrgId() (string, error)
获取合约创建者的组织ID
// GetCreatorRole get tx creator role// @return1: 合约创建者的角色// @return2: 获取错误信息GetCreatorRole() (string, error)
获取合约创建者的角色
// GetCreatorPk get tx creator pk// @return1: 合约创建者的公钥// @return2: 获取错误信息GetCreatorPk() (string, error)
获取合约创建者的公钥
在IDE可以获取,在使用证书+私钥的链,还没测过
// GetSenderOrgId get tx sender org id// @return1: 交易发起者的组织ID// @return2: 获取错误信息 GetSenderOrgId() (string, error) 获取交易发起者的组织ID
// GetSenderRole get tx sender role// @return1: 交易发起者的角色// @return2: 获取错误信息GetSenderRole() (string, error)
获取交易发起者的角色
// GetSenderPk get tx sender pk// @return1: 交易发起者的公钥// @return2: 获取错误信息GetSenderPk() (string, error)
获取 交易发起者的公钥
// GetBlockHeight get tx block height// @return1: 当前块高度// @return2: 获取错误信息GetBlockHeight() (int, error)
获取当前块高度
// GetTxId get current tx id// @return1: 交易ID// @return2: 获取错误信息GetTxId() (string, error)
获取 交易ID
// GetTxInfo get tx info// @param txId :合约交易IDGetTxInfo(txId string) protogo.Response
获取合约交易ID
// GetTxTimeStamp get tx timestamp// @return1: 交易timestamp// @return2: 获取错误信息GetTxTimeStamp() (string, error)
获取交易timestamp
// EmitEvent emit event, you can subscribe to the event using the SDK// @param1 topic: 合约事件的主题// @param2 data: 合约事件的数据,参数数量不可大于16EmitEvent(topic string, data []string)
发布合约事件,发布了的化,主题和参数,会被订阅者收到
// Log record log to chain server// @param message: 事情日志的信息//DeprecatedLog(message string)
日记记录,会写进节点日志
// Debugf record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Debugf(format string, a ...interface{})
同上
// Infof record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Infof(format string, a ...interface{})
同上
// Warnf record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Warnf(format string, a ...interface{})
同上
// Errorf record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Errorf(format string, a ...interface{})
同上
// CallContract invoke another contract and get response// @param1: 合约名称// @param2: 合约方法// @param3: 合约合约参数// @return1: 合约结果 CallContract(contractName, method string, args map[string][]byte) protogo.Response
合约里面调用别的合约?不知道是干嘛的
官方解释:跨合约调用,用于调用已经安装的其他合约的
四、获取历史数据的一些方法
// NewIterator range of [startKey, limitKey), front closed back open// @param1: 范围查询起始key// @param2: 范围查询结束key// @return1: 根据起始key生成的迭代器// @return2: 获取错误信息NewIterator(startKey string, limitKey string) (ResultSetKV, error)不清出这个起始key、结束key是什么意思,如果key是一些字母也有起始和结束吗?
难以理解,懂得朋友辛苦留言指导一下
// NewIteratorWithField range of [key+"#"+startField, key+"#"+limitField), front closed back open// @param1: 分别与param2, param3 构成查询起始和结束的key// @param2: [param1 + "#" + param2] 来获取查询起始的key// @param3: [param1 + "#" + param3] 来获取查询结束的key// @return1: 根据起始位置生成的迭代器// @return2: 获取错误信息 NewIteratorWithField(key string, startField string, limitField string) (ResultSetKV, error)同上
// NewIteratorPrefixWithKeyField range of [key+"#"+field, key+"#"+field], front closed back closed// @param1: [ param1 + "#" +param2 ] 构成前缀范围查询的key// @param2: [ param1 + "#" +param2 ] 构成前缀范围查询的key// @return1: 根据起始位置生成的迭代器// @return2: 获取错误信息NewIteratorPrefixWithKeyField(key string, field string) (ResultSetKV, error)同上
// NewIteratorPrefixWithKey range of [key, key], front closed back closed// @param1: 前缀范围查询起始key// @return1: 根据起始位置生成的迭代器// @return2: 获取错误信息NewIteratorPrefixWithKey(key string) (ResultSetKV, error)
查询key相同的所有数据,使用方法可以参考教程二
只能是查询本合约之前上链的数据,别的合约上链的数据就算key相同你也是不能查的,其他查询方法也一样
// NewHistoryKvIterForKey query all historical data of key, field// @param1: 查询历史的key// @param2: 查询历史的field// @return1: 根据key, field 生成的历史迭代器// @return2: 获取错误信息 NewHistoryKvIterForKey(key, field string) (KeyHistoryKvIter, error)
查询 field 、key相同的所有数据,使用方法可以参考教程二
只能是查询本合约之前上链的数据,别的合约上链的数据就算key相同你也是不能查的,其他查询方法也一样
// GetSenderAddr Get the address of the origin caller address, same with Origin()// @return1: origin caller address// @return2: 获取错误信息// DeprecatedGetSenderAddr() (string, error)被弃用了,别学
// Sender Get the address of the sender address, if the contract is called by another contract, the result will be// the caller contract's address.// Sender will return system contract address when executing the init or upgrade method (If you need to return the// user address, we recommend using Origin method here), because the init and upgrade methods are cross-contract// txs (system contract -> common contract).// @return1: sender address// @return2: 获取错误信息Sender() (string, error)获取发送者的地址。如果合约是由另一个合约调用的,结果将是调用者合约的地址。
// Origin Get the address of the tx origin caller address// @return1: origin caller address// @return2: 获取错误信息Origin() (string, error)获取交易原始调用者的地址
五、示例合约
以下合约是我在写这个教程测试用的,只写了部分接口测试
/*
Copyright (C) BABEC. All rights reserved.
Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.SPDX-License-Identifier: Apache-2.0
*/package mainimport ("chainmaker/pb/protogo""chainmaker/sandbox""chainmaker/sdk""encoding/json""fmt""log""strconv"
)type FactContract struct {
}// 存证对象
type Fact struct {FileHash stringFileName stringTime int
}// 新建存证对象
func NewFact(fileHash string, fileName string, time int) *Fact {fact := &Fact{FileHash: fileHash,FileName: fileName,Time: time,}return fact
}func (f *FactContract) InitContract() protogo.Response {return sdk.Success([]byte("Init contract success"))
}func (f *FactContract) UpgradeContract() protogo.Response {return sdk.Success([]byte("Upgrade contract success"))
}func (f *FactContract) InvokeContract(method string) protogo.Response {switch method {case "save":return f.Save()case "findByFileHash":return f.FindByFileHash()case "deltedByFileHash":return f.DeleteByFileHash()case "getHistoryByFileHash":return f.GetHistoryByFileHash()case "getStateFromKey":return f.GetStateFromKey()case "getStateByte":return f.GetStateByte()case "getStateWithExists":return f.GetStateWithExists()case "getCreatorOrgId":return f.GetCreatorOrgId()case "getCreatorPk":return f.GetCreatorPk()case "GetSenderOrgId":return f.GetSenderOrgId()case "GetSenderRole":return f.GetSenderRole()case "GetSenderPk":return f.GetSenderPk()case "GetBlockHeight":return f.GetBlockHeight()case "GetTxId":return f.GetTxId()case "GetTxTimeStamp":return f.GetTxTimeStamp()default:return sdk.Error("invalid method")}
}func (f *FactContract) Save() protogo.Response {params := sdk.Instance.GetArgs()// 获取参数fileHash := string(params["file_hash"])fileName := string(params["file_name"])timeStr := string(params["time"])time, err := strconv.Atoi(timeStr)if err != nil {msg := "time is [" + timeStr + "] not int"sdk.Instance.Errorf(msg)return sdk.Error(msg)}// 构建结构体fact := NewFact(fileHash, fileName, time)// 序列化factBytes, err := json.Marshal(fact)if err != nil {return sdk.Error(fmt.Sprintf("传过来的参数序列化失败, err: %s", err))}// 发送事件sdk.Instance.EmitEvent("topic_vx", []string{fact.FileHash, fact.FileName})// 存储数据err = sdk.Instance.PutStateByte("fact_bytes", fact.FileHash, factBytes)if err != nil {return sdk.Error("fail to save fact bytes")}// 记录日志// sdk.Instance.Infof("[save] fileHash=" + fact.FileHash)// sdk.Instance.Infof("[save] fileName=" + fact.FileName)createUser, _ := sdk.Instance.GetSenderRole()sdk.Instance.Infof("[saveUser] create=" + createUser)// 返回结果return sdk.Success([]byte(fact.FileName + fact.FileHash))}func (f *FactContract) FindByFileHash() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to call get_state")}// 反序列化var fact Factif err = json.Unmarshal(result, &fact); err != nil {return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))}// 记录日志sdk.Instance.Infof("[find_by_file_hash] fileHash=" + fact.FileHash)sdk.Instance.Infof("[find_by_file_hash] fileName=" + fact.FileName)// 返回结果return sdk.Success(result)
}func (f *FactContract) DeleteByFileHash() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果err := sdk.Instance.DelState("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to delere get_state")}// 返回结果return sdk.Success(nil)
}func (f *FactContract) GetHistoryByFileHash() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果iter, err := sdk.Instance.NewHistoryKvIterForKey("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to delere get_state")}defer iter.Close()var keyModifications []*sdk.KeyModification// 遍历结果for {if !iter.HasNext() {break}keyModification, err := iter.Next()if err != nil {sdk.Instance.Infof("Error iterating: %v", err)}if keyModification == nil {break}keyModifications = append(keyModifications, keyModification)sdk.Instance.Infof("Key: %s, Field: %s, Value: %s, TxId: %s, BlockHeight: %d, IsDelete: %t, Timestamp: %s, \n",keyModification.Key, keyModification.Field, keyModification.Value, keyModification.TxId, keyModification.BlockHeight, keyModification.IsDelete, keyModification.Timestamp)}jsonBytes, err := json.Marshal(keyModifications)if err != nil {return sdk.Error(fmt.Sprintf("Error marshaling keyModifications: %v", err))}// 返回结果return sdk.Success(jsonBytes)
}func (f *FactContract) GetStateFromKey() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, err := sdk.Instance.GetStateFromKey(fileHash)if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetStateFromKey] result=" + result)byteSlice := []byte(result)// 返回结果return sdk.Success(byteSlice)
}func (f *FactContract) GetStateByte() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetStateByte] result=" + string(result))// 返回结果return sdk.Success(result)
}func (f *FactContract) GetStateWithExists() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, exit, err := sdk.Instance.GetStateWithExists("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to call get_state")}exitStr := fmt.Sprintf("%v", exit)sdk.Instance.Infof("[GetStateByte] result=" + result + "bool:" + string(exitStr))// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetCreatorOrgId() protogo.Response {// 查询结果result, err := sdk.Instance.GetCreatorOrgId()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetCreatorOrgId] GetCreatorOrgId=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetCreatorPk() protogo.Response {// 查询结果result, err := sdk.Instance.GetCreatorPk()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetCreatorPk] GetCreatorPk=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetSenderOrgId() protogo.Response {// 查询结果result, err := sdk.Instance.GetSenderOrgId()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetSenderOrgId] GetSenderOrgId=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetSenderRole() protogo.Response {// 查询结果result, err := sdk.Instance.GetSenderRole()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetSenderRole] GetSenderRole=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetSenderPk() protogo.Response {// 查询结果result, err := sdk.Instance.GetSenderPk()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetSenderPk] GetSenderPk=" + result)// 返回结果return sdk.Success([]byte(result))
}
func (f *FactContract) GetBlockHeight() protogo.Response {// 查询结果result, err := sdk.Instance.GetBlockHeight()if err != nil {return sdk.Error("failed to call get_state")}str := strconv.Itoa(result) // 将int转换为字符串bytes := []byte(str) // 将字符串转换为[]byte// 返回结果return sdk.Success(bytes)
}func (f *FactContract) GetTxId() protogo.Response {// 查询结果result, err := sdk.Instance.GetTxId()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetTxId] GetTxId=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetTxTimeStamp() protogo.Response {// 查询结果result, err := sdk.Instance.GetTxTimeStamp()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetTxTimeStamp] GetTxTimeStamp=" + result)// 返回结果return sdk.Success([]byte(result))
}func main() {err := sandbox.Start(new(FactContract))if err != nil {log.Fatal(err)}
}
相关文章:
长安链使用Golang编写智能合约教程(三)
本篇主要介绍长安链Go SDK写智能合约的一些常见方法的使用方法或介绍 资料来源: 官方文档官方示例合约库 官方SDK接口文档 教程一:智能合约编写1 教程二:智能合约编写2 一、获取参数、获取状态、获取历史记录的方法解析 注意! …...

Vercel deploy- Nextjs project error-URL link-env variable
Vercel deploy- Nextjs project error-URL link-env variable Error Check Database URL Check next-auth URL NEXTAUTH_URLhttps://yourappname.vercel.app/ 依次排查可能性 Application error: a server-side exception has occurred (see the server logs for more in…...

Java | Leetcode Java题解之第123题买卖股票的最佳时机III
题目: 题解: class Solution {public int maxProfit(int[] prices) {int n prices.length;int buy1 -prices[0], sell1 0;int buy2 -prices[0], sell2 0;for (int i 1; i < n; i) {buy1 Math.max(buy1, -prices[i]);sell1 Math.max(sell1, b…...

Ubuntu22.04之扩展并挂载4T硬盘(二百三十三)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...
Redis实现延迟队列
最近用到一个延迟消息的功能,第一时间想到使用MQ或者MQ的插件,因为数据量不大,所以尝试使用Redis来实现了,毕竟Redis也天生支持类似MQ的队列消费,所以,在这里总结了一下Redis实现延迟消息队列的方式。 一、…...

如何准确查找论文数据库?
在学术研究过程中,查找相关论文是获取最新研究成果、支持自己研究的重要途径。准确查找论文数据库不仅可以节省时间,还能确保找到高质量的学术资源。本文将介绍一些有效的方法和策略,帮助您准确查找论文数据库。 1. 选择合适的数据库 不同的…...

翻译《The Old New Thing》- What a drag: Dragging a virtual file (IStream edition)
What a drag: Dragging a virtual file (IStream edition) - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080319-00/?p23073 Raymond Chen 2008年03月19日 拖拽虚拟文件(IStream 版本) 上一次,我们看…...

【FPGA】Verilog语言从零到精通
接触fpga一段时间,也能写点跑点吧……试试系统地康康呢~这个需要耐心但是回报巨大的工作。正原子&&小梅哥 15_语法篇:Verilog高级知识点_哔哩哔哩_bilibili 1Verilog基础 Verilog程序框架:模块的结构 类比:c语言的基础…...

unity打包的WebGL部署到IIS问题
部署之后会出错,我遇到的有以下几种; 进度条卡住不动 明明已经部署到了IIS上,为什么浏览网页的时候还是过不去或者直接报错。 进度条卡住不动的问题其实就是wasm和data的错误。 此时在浏览器上按F12进入开发者模式查看错误(下图…...
GPT-4o:人工智能的新里程碑
GPT-4o,作为OpenAI最新推出的人工智能技术,无疑在人工智能领域掀起了新一轮的浪潮。这款新型的语言模型不仅继承了GPT系列的核心优势,更在多个方面实现了突破性的进展。以下,我们将从版本间的对比分析、GPT-4o的技术能力以及个人整…...

发现一个ai工具网站
网址 https://17yongai.com/ 大概看了下,这个网站收集的数据还挺有用的,有很多实用的ai教程。 懂ai工具的可以在这上面找找灵感。...

第二十五章新增H5基础(以及视频~兼容)
1.HTML5中新增布局标签 HTML5新增了页眉,页脚,内容块等文档结构相关标签,可以使文档结构更加清晰明了。 1.新增的结构标签 1、<header>标签 定义文档或者文档中内容块的页眉。通常可以包含整个页面或一个内容区域的标题,…...
[英语单词] production quality
Our goal is to implement a production quality switch platform that supports standard management interfaces and opens the forwarding functions to programmatic extension and control. 说在openswitch的文档里有说这两词,含义是产品质量。是production修…...
windows安装nodeJs,以及常用操作
1. 官网(Node.js — Run JavaScript Everywhere (nodejs.org))下载想要安装的node版本 的安装包完成安装 2.环境变量设置: 系统变量: Path新增:D:\Program Files\nodejs (node安装目录) 3.设置淘宝源: npm config set registr…...

MySql part1 安装和介绍
MySql part1 安装和介绍 数据 介绍 什么是数据库,数据很好理解,一般来说数据通常是我们所认识的 描述事物的符号记录, 可以是数字、 文字、图形、图像、声音、语言等,数据有多种形式,它们都以经过数字化后存入计算机…...

SpringBoot打war包并配置外部Tomcat运行
简介 由于其他原因,我们需要使用SpringBoot打成war包放在外部的Tomcat中运行,本文就以一个案例来说明从SpringBoot打war包到Tomcat配置并运行的全流程经过 环境 SpringBoot 2.6.15 Tomcat 8.5.100 JDK 1.8.0_281 Windows 正文 一、SpringBoot配置打war包 第一步&a…...
2024.5.31每日一题
LeetCode 找出缺失的重复数字 题目链接:2965. 找出缺失和重复的数字 - 力扣(LeetCode) 题目描述 给你一个下标从 0 开始的二维整数矩阵 grid,大小为 n * n ,其中的值在 [1, n2] 范围内。除了 a 出现 两次ÿ…...
Oracle 数据库 varchar2 从 4000 扩展到 32k
Oracle 数据库 varchar2 从 4000 扩展到 32k 0. 引言1. 扩展 varchar2 支持长度2. 测试 0. 引言 今天来个项目需求,有1个字段的存储内容大概1万字。 当然其中1个方法是将这个字段的内容切分成几个字段,还有1个方法就是将 varchar2 默认支持 4000 的能力…...

postgressql——事务提交会通过delayChkpt阻塞checkpoint(9)
事务提交会通过delayChkpt阻塞checkpoint Postgresql事务在事务提交时(执行commit的最后阶段)会通过加锁阻塞checkpoint的执行,尽管时间非常短,分析为什么需要这样做: 首先看提交堆栈 #1 0x0000000000539175 in Co…...

开发者工具-sources(源代码选项)
一、概要说明 源代码面板从视觉效果上分为三个区域:菜单区、内容区、监听区。 菜单区里面有5个子分类: 网页(Page):指页面源,包含了该页面中所有的文件,即使多个域名下的文件也都会展示出来,包括iframe…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
【Ftrace 专栏】Ftrace 参考博文
ftrace、perf、bcc、bpftrace、ply、simple_perf的使用Ftrace 基本用法Linux 利用 ftrace 分析内核调用如何利用ftrace精确跟踪特定进程调度信息使用 ftrace 进行追踪延迟Linux-培训笔记-ftracehttps://www.kernel.org/doc/html/v4.18/trace/events.htmlhttps://blog.csdn.net/…...
Android屏幕刷新率与FPS(Frames Per Second) 120hz
Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数,单位是赫兹(Hz)。 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms 90Hz 屏幕:每秒刷新 90 次,…...