钉钉企业微应用开发C#-HTTP回调接口
官方的STREAM回调推送的方式,试了几次都认证不过,就放弃了还是用HTTP的模式吧。
/// <summary>/// 应用回调/// </summary>/// <param name="model"></param>/// <returns></returns>public static Dictionary<string, string> CallBack(DingCallBackModel model){WriteLogHelper.WriteLogsAsync(JsonHelper.SerializeObject(model), "实例回调日志");var timeStamp = GetTimestamp(DateTime.Now).ToString();// 2. 使用加解密类型DingTalkEncryptor callbackCrypto = new DingTalkEncryptor(AppsettingsConfig.DingDingConfig.Token, AppsettingsConfig.DingDingConfig.AesKey, AppsettingsConfig.DingDingConfig.AppKey);string decryptMsg = callbackCrypto.getDecryptMsg(model.Msg_signature, model.TimeStamp, model.Nonce, model.Encrypt);string msg = "success";// 3. 反序列化回调事件json数据var approveModel = JsonHelper.DeserializeObject<ApprovalInstanceModel>(decryptMsg);WriteLogHelper.WriteLogsAsync(JsonHelper.SerializeObject(approveModel), "实例回调日志-解密");var type = approveModel.EventType;switch (type){case "check_url":WriteLogHelper.WriteLogsAsync("审批回调:" + JsonHelper.SerializeObject(model), "实例回调日志");// 测试回调break;case "bpms_instance_change":// 实例改变break;}var rspMsg = callbackCrypto.getEncryptedMap(msg);return rspMsg;}
check_url就是钉应用后台设置回调URL时传入数据的类型。拿到数据
public string Msg_signature { set; get; } = "";
public string TimeStamp { set; get; }
public string Nonce { set; get; } = "123456";
/// <summary>
/// 加密后的结果
/// </summary>
public string Encrypt { set; get; }
分为几部分,前面几项用来解密Encrypt密文的参数。
通过提供的DingTalkEncryptor 的 getDecryptMsg方法来进行解密
得到解密后的内容序列化成对象。
/*** 钉钉开放平台加解密方法*/public class DingTalkEncryptor{//private static readonly Charset CHARSET = Charset.forName("utf-8");//private static readonly Base64 base64 = new Base64();private byte[] aesKey;private String token;private String corpId;/**ask getPaddingBytes key固定长度**/private static readonly int AES_ENCODE_KEY_LENGTH = 43;/**加密随机字符串字节长度**/private static readonly int RANDOM_LENGTH = 16;/*** 构造函数* @param token 钉钉开放平台上,开发者设置的token* @param encodingAesKey 钉钉开放台上,开发者设置的EncodingAESKey* @param corpId 企业自建应用-事件订阅, 使用appKey* 企业自建应用-注册回调地址, 使用corpId* 第三方企业应用, 使用suiteKey** @throws DingTalkEncryptException 执行失败,请查看该异常的错误码和具体的错误信息*/public DingTalkEncryptor(String token, String encodingAesKey, String corpId){if (null == encodingAesKey || encodingAesKey.Length != AES_ENCODE_KEY_LENGTH){throw new DingTalkEncryptException(DingTalkEncryptException.AES_KEY_ILLEGAL);}this.token = token;this.corpId = corpId;aesKey = Convert.FromBase64String(encodingAesKey + "=");}/*** 将和钉钉开放平台同步的消息体加密,返回加密Map*/public Dictionary<String, String> getEncryptedMap(String plaintext){var time = DateTime.Now.Millisecond;return getEncryptedMap(plaintext, time);}/*** 将和钉钉开放平台同步的消息体加密,返回加密Map* @param plaintext 传递的消息体明文* @param timeStamp 时间戳* @param nonce 随机字符串* @return* @throws DingTalkEncryptException*/public Dictionary<String, String> getEncryptedMap(String plaintext, long timeStamp){if (null == plaintext){throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL);}var nonce = Utils.getRandomStr(RANDOM_LENGTH);if (null == nonce){throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_NONCE_ILLEGAL);}String encrypt = this.encrypt(nonce, plaintext);String signature = getSignature(token, timeStamp.ToString(), nonce, encrypt);Dictionary<String, String> resultMap = new Dictionary<String, String>();resultMap["msg_signature"] = signature;resultMap["encrypt"] = encrypt;resultMap["timeStamp"] = timeStamp.ToString();resultMap["nonce"] = nonce;return resultMap;}/*** 密文解密* @param msgSignature 签名串* @param timeStamp 时间戳* @param nonce 随机串* @param encryptMsg 密文* @return 解密后的原文* @throws DingTalkEncryptException*/public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg){//校验签名String signature = getSignature(token, timeStamp, nonce, encryptMsg);if (!signature.Equals(msgSignature)){throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);}// 解密String result = decrypt(encryptMsg);return result;}/** 对明文加密.* @param text 需要加密的明文* @return 加密后base64编码的字符串*/private String encrypt(String random, String plaintext){try{byte[] randomBytes = System.Text.Encoding.UTF8.GetBytes(random);// random.getBytes(CHARSET);byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plaintext);// plaintext.getBytes(CHARSET);byte[] lengthByte = Utils.int2Bytes(plainTextBytes.Length);byte[] corpidBytes = System.Text.Encoding.UTF8.GetBytes(corpId);// corpId.getBytes(CHARSET);//MemoryStream byteStream = new MemoryStream();var bytestmp = new List<byte>();bytestmp.AddRange(randomBytes);bytestmp.AddRange(lengthByte);bytestmp.AddRange(plainTextBytes);bytestmp.AddRange(corpidBytes);byte[] padBytes = PKCS7Padding.getPaddingBytes(bytestmp.Count);bytestmp.AddRange(padBytes);byte[] unencrypted = bytestmp.ToArray();RijndaelManaged rDel = new RijndaelManaged();rDel.Mode = CipherMode.CBC;rDel.Padding = PaddingMode.Zeros;rDel.Key = aesKey;rDel.IV = aesKey.ToList().Take(16).ToArray();ICryptoTransform cTransform = rDel.CreateEncryptor();byte[] resultArray = cTransform.TransformFinalBlock(unencrypted, 0, unencrypted.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);//Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");//IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);//cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);//byte[] encrypted = cipher.doFinal(unencrypted);//String result = base64.encodeToString(encrypted);//return result;}catch (Exception e){throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR);}}/** 对密文进行解密.* @param text 需要解密的密文* @return 解密得到的明文*/private String decrypt(String text){byte[] originalArr;try{byte[] toEncryptArray = Convert.FromBase64String(text);RijndaelManaged rDel = new RijndaelManaged();rDel.Mode = CipherMode.CBC;rDel.Padding = PaddingMode.Zeros;rDel.Key = aesKey;rDel.IV = aesKey.ToList().Take(16).ToArray();ICryptoTransform cTransform = rDel.CreateDecryptor();originalArr = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);//return System.Text.UTF8Encoding.UTF8.GetString(resultArray);设置解密模式为AES的CBC模式//Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");//IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));//cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);使用BASE64对密文进行解码//byte[] encrypted = Base64.decodeBase64(text);解密//originalArr = cipher.doFinal(encrypted);}catch (Exception e){throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);}String plainText;String fromCorpid;try{// 去除补位字符byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);Console.Out.WriteLine("bytes size:" + bytes.Length);// 分离16位随机字符串,网络字节序和corpIdbyte[] networkOrder = bytes.Skip(16).Take(4).ToArray();// Arrays.copyOfRange(bytes, 16, 20);for (int i = 0; i < 4; i++){Console.Out.WriteLine("networkOrder size:" + (int)networkOrder[i]);}Console.Out.WriteLine("bytes plainText:" + networkOrder.Length + " " + JsonSerializer.Serialize(networkOrder));int plainTextLegth = Utils.bytes2int(networkOrder);Console.Out.WriteLine("bytes size:" + plainTextLegth);plainText = System.Text.UTF8Encoding.UTF8.GetString(bytes.Skip(20).Take(plainTextLegth).ToArray()); // new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);fromCorpid = System.Text.UTF8Encoding.UTF8.GetString(bytes.Skip(20 + plainTextLegth).ToArray()); //new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);Console.Out.WriteLine("bytes plainText:" + plainText);}catch (Exception e){throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);}Console.Out.WriteLine(fromCorpid + "=====" + corpId);// corpid不相同的情况if (!fromCorpid.Equals(corpId)){throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);}return plainText;}/*** 数字签名* @param token isv token* @param timestamp 时间戳* @param nonce 随机串* @param encrypt 加密文本* @return* @throws DingTalkEncryptException*/public String getSignature(String token, String timestamp, String nonce, String encrypt){try{Console.Out.WriteLine(encrypt);String[] array = new String[] { token, timestamp, nonce, encrypt };Array.Sort(array, StringComparer.Ordinal);//var tmparray = array.ToList();//tmparray.Sort(new JavaStringComper());//array = tmparray.ToArray();Console.Out.WriteLine("array:" + JsonSerializer.Serialize(array));StringBuilder sb = new StringBuilder();for (int i = 0; i < 4; i++){sb.Append(array[i]);}String str = sb.ToString();Console.Out.WriteLine(str);//MessageDigest md = MessageDigest.getInstance("SHA-1");//md.update(str.getBytes());//byte[] digest = md.digest();System.Security.Cryptography.SHA1 hash = System.Security.Cryptography.SHA1.Create();System.Text.Encoding encoder = System.Text.Encoding.ASCII;byte[] combined = encoder.GetBytes(str);byte 转换//sbyte[] myByte = new sbyte[]//byte[] mySByte = new byte[myByte.Length];//for (int i = 0; i < myByte.Length; i++)//{// if (myByte[i] > 127)// mySByte[i] = (sbyte)(myByte[i] - 256);// else// mySByte[i] = (sbyte)myByte[i];//}byte[] digest = hash.ComputeHash(combined);StringBuilder hexstr = new StringBuilder();String shaHex = "";for (int i = 0; i < digest.Length; i++){shaHex = ((int)digest[i]).ToString("x");// Integer.toHexString(digest[i] & 0xFF);if (shaHex.Length < 2){hexstr.Append(0);}hexstr.Append(shaHex);}return hexstr.ToString();}catch (Exception e){throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);}}}/*** 钉钉开放平台加解密异常类*/public class DingTalkEncryptException : Exception{/**成功**/public static readonly int SUCCESS = 0;/**加密明文文本非法**/public readonly static int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;/**加密时间戳参数非法**/public readonly static int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;/**加密随机字符串参数非法**/public readonly static int ENCRYPTION_NONCE_ILLEGAL = 900003;/**不合法的aeskey**/public readonly static int AES_KEY_ILLEGAL = 900004;/**签名不匹配**/public readonly static int SIGNATURE_NOT_MATCH = 900005;/**计算签名错误**/public readonly static int COMPUTE_SIGNATURE_ERROR = 900006;/**计算加密文字错误**/public readonly static int COMPUTE_ENCRYPT_TEXT_ERROR = 900007;/**计算解密文字错误**/public readonly static int COMPUTE_DECRYPT_TEXT_ERROR = 900008;/**计算解密文字长度不匹配**/public readonly static int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009;/**计算解密文字corpid不匹配**/public readonly static int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010;private static Dictionary<int, String> msgMap = new Dictionary<int, String>();static DingTalkEncryptException(){msgMap[SUCCESS] = "成功";msgMap[ENCRYPTION_PLAINTEXT_ILLEGAL] = "加密明文文本非法";msgMap[ENCRYPTION_TIMESTAMP_ILLEGAL] = "加密时间戳参数非法";msgMap[ENCRYPTION_NONCE_ILLEGAL] = "加密随机字符串参数非法";msgMap[SIGNATURE_NOT_MATCH] = "签名不匹配";msgMap[COMPUTE_SIGNATURE_ERROR] = "签名计算失败";msgMap[AES_KEY_ILLEGAL] = "不合法的aes key";msgMap[COMPUTE_ENCRYPT_TEXT_ERROR] = "计算加密文字错误";msgMap[COMPUTE_DECRYPT_TEXT_ERROR] = "计算解密文字错误";msgMap[COMPUTE_DECRYPT_TEXT_LENGTH_ERROR] = "计算解密文字长度不匹配";msgMap[COMPUTE_DECRYPT_TEXT_CORPID_ERROR] = "计算解密文字corpid不匹配";}private int code;public DingTalkEncryptException(int exceptionCode) : base(msgMap[exceptionCode]){this.code = exceptionCode;}}/** PKCS7算法的加密填充*/public class PKCS7Padding{//private readonly static Charset CHARSET = Charset.forName("utf-8");private readonly static int BLOCK_SIZE = 32;/*** 填充mode字节* @param count* @return*/public static byte[] getPaddingBytes(int count){int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);if (amountToPad == 0){amountToPad = BLOCK_SIZE;}char padChr = chr(amountToPad);String tmp = string.Empty; ;for (int index = 0; index < amountToPad; index++){tmp += padChr;}return System.Text.Encoding.UTF8.GetBytes(tmp);}/*** 移除mode填充字节* @param decrypted* @return*/public static byte[] removePaddingBytes(byte[] decrypted){int pad = (int)decrypted[decrypted.Length - 1];if (pad < 1 || pad > BLOCK_SIZE){pad = 0;}//Array.Copy()var output = new byte[decrypted.Length - pad];Array.Copy(decrypted, output, decrypted.Length - pad);return output;}private static char chr(int a){byte target = (byte)(a & 0xFF);return (char)target;}}/*** 加解密工具类*/public class Utils{/**** @return*/public static String getRandomStr(int count){String baset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";Random random = new Random();StringBuilder sb = new StringBuilder();for (int i = 0; i < count; i++){int number = random.Next(baset.Length);sb.Append(baset[number]);}return sb.ToString();}/** int转byte数组,高位在前*/public static byte[] int2Bytes(int count){byte[] byteArr = new byte[4];byteArr[3] = (byte)(count & 0xFF);byteArr[2] = (byte)(count >> 8 & 0xFF);byteArr[1] = (byte)(count >> 16 & 0xFF);byteArr[0] = (byte)(count >> 24 & 0xFF);return byteArr;}/*** 高位在前bytes数组转int* @param byteArr* @return*/public static int bytes2int(byte[] byteArr){int count = 0;for (int i = 0; i < 4; ++i){count <<= 8;count |= byteArr[i] & 255;}return count;}}public class JavaStringComper : IComparer<string>{public int Compare(string x, string y){return String.Compare(x, y);}}// 测试加解密的正确性public class Program{public static void Main(string[] args){String[] a = new String[] { "1", "W", "t" };var ding = new DingTalkEncryptor("tokenxxxx", "o1w0aum42yaptlz8alnhwikjd3jenzt9cb9wmzptgus", "dingxxxxxx");var msg = ding.getEncryptedMap("success");Console.Out.WriteLine(msg);//msg_signature, $data->timeStamp, $data->nonce, $data->encryptvar text = ding.getDecryptMsg(msg["msg_signature"], msg["timeStamp"], msg["nonce"], msg["encrypt"]);Console.Out.WriteLine(text);// "msg_signature":"c01beb7b06384cf416e04930aed794684aae98c1","encrypt":"","timeStamp":,"nonce":""//{"timeStamp":"1605695694141","msg_signature":"702c953056613f5c7568b79ed134a27bd2dcd8d0",//"encrypt":"","nonce":"WelUQl6bCqcBa2fMc6eI"}text = ding.getDecryptMsg("f36f4ba5337d426c7d4bca0dbcb06b3ddc1388fc", "1605695694141", "WelUQl6bCqcBa2fM", "X1VSe9cTJUMZu60d3kyLYTrBq5578ZRJtteU94wG0Q4Uk6E/wQYeJRIC0/UFW5Wkya1Ihz9oXAdLlyC9TRaqsQ==");Console.Out.WriteLine(text);}}
public class ApprovalInstanceModel
{
//public long Id { set; get; } = 0;
public string EventType { set; get; }
public string ProcessInstanceId { set; get; }
/// <summary>
/// 企业ID
/// </summary>
public string CorpId { set; get; }
public string Title { set; get; }
/// <summary>
/// 审批状态类型
/// </summary>
public string Type { set; get; }
/// <summary>
/// 审批详情URL
/// </summary>
public string Url { set; get; }
/// <summary>
/// 审批结果 agree refuse 或为空
/// </summary>
public string Result { set; get; }
/// <summary>
/// 员工ID
/// </summary>
public string StaffId { set; get; }
/// <summary>
/// 审批模板code
/// </summary>
public string ProcessCode { set; get; }
public long FinishTime { set; get; } = 0;
public long CreateTime { set; get; } = 0;
public DateTime CreateTimeNormal { set; get; }
public DateTime FinishTimeNormal { set; get; }
}
bpms_instance_change 类型是审批发起与结束时会触发的用来更新我们的微应用单据数据的状态,以及更新时有审批进度的URL,可以关联起来。
好了以上就是审批回调URL的接口内容了。
相关文章:
钉钉企业微应用开发C#-HTTP回调接口
官方的STREAM回调推送的方式,试了几次都认证不过,就放弃了还是用HTTP的模式吧。 /// <summary>/// 应用回调/// </summary>/// <param name"model"></param>/// <returns></returns>public static Dictio…...

Rust编程基础之条件表达式和循环
1.if表达式 if 表达式允许根据条件执行不同的代码分支, 以下代码是一个典型的使用if表达式的例子: fn main() {let number 3; if number < 5 {println!("condition was true");} else {println!("condition was false");} } 所有的 if 表达式都以…...
MATLAB算法实战应用案例精讲-【人工智能】ROS机器人(补充篇)
目录 前言 ROS 机器人导航调参 1 速度和加速度 2 全局路径规划 3 局部路径规划...

基于8086汽车智能小车控制系统
**单片机设计介绍,基于8086汽车智能小车控制系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于 8086 的汽车智能小车控制系统是一种将微处理器技术应用于汽车控制的系统。下面是其主要的设计介绍: 硬…...

全光谱大面积氙光灯太阳光模拟器老化测试
氙灯光源太阳光模拟器广泛应用于光解水产氢、光化学催化、二氧化碳制甲醇、光化学合成、光降解污染物、 水污染处理、生物光照,光学检测、太阳能电池研究、荧光材料测试(透射、反射、吸收) 太阳能电池特性测试,光热转化,光电材料特性测试,生物…...
linux添加一条到中间路由器的路由
有时候需要配置一些明细路由,不能直接通过网关进行路由转发 配置示例 ip route add 10.0.12.0/24 via 10.0.41.1 dev bond0 这个命令是用于在Linux操作系统上配置IP路由的命令。具体来说,这个命令的含义是: ip route add: 这部分表示要添加…...
不同MySQL服务的表以及库的数据迁移(/备份)
目标: 将本地主机上usernameroot,passwordroot,port3307的MySQL服务中migration_one数据库的table_11数据表导出到本地的D:\start_java\XinQiUtilsOrDemo\testMigrationMySQL\table_11.bak注意:目前D:\start_java\XinQiUtilsOrDemo\testMigrationMySQL该…...

聊聊芯片超净间的颗粒(particle)
在芯片制造领域,颗粒的存在可能对生产过程产生巨大影响。其中,每个微小的颗粒,无论是来自人员、设备,还是自然环境,都有可能在制程中引发故障,从而对产品性能产生负面影响。这就是为什么在芯片厂中…...

服务器(windows Server 2019为例)中的日志中文乱码的解决办法
1. 首先,打开控制面板,找到区域(Region),把Format设置为国语简体中文,点击高级(Administrative)后设置Current system locale为国语简体中文,按照图中步骤:...

Linux 学习(CentOS 7)
CentOS 7 学习 Linux系统内核作者: Linux内核版本 内核(kernel)是系统的心脏,是运行程序和管理像磁盘和打印机等硬件设备的核心程序,它提供了一个在裸设备与应用程序间的抽象层。 Linux内核版本又分为稳定版和开发版,两种版本是相互关联&am…...
架构决策记录 ADR
在项目和产品开发过程中,软件工程团队需要做出架构决策以实现其目标。这些决策可以是技术性的,也可以与流程相关。 技术决策:例如决定使用JBOSS Data Grid作为缓存解决方案还是选择Amazon Elasticache,或者决定使用AWS Network L…...

SSM之spring注解式缓存redis->redis整合,redis的注解式开发及应用场景,redis的击穿穿透雪崩
redis整合redis的注解式开发及应用场景redis的击穿穿透雪崩 1.redis整合 mysql整合 pom配置; String-fmybatis.xml --> mybatis.cfg.xml: 包扫描; 注册了一个jdbc.properties(url/password/username/...); 配置数据源(数据库连…...
数据库性能优化(查询优化、索引优化、负载均衡、硬件升级等方面)
数据库性能优化是提升数据库系统整体性能和响应速度的一系列技术和策略。它可以通过多种方式来实现,包括优化查询语句、索引设计、硬件升级、负载均衡等手段。 合适的数据模型设计 正确的数据模型设计是性能优化的基石。合理的表结构和关系设计可以减少冗余数据&…...

谁说 Linux 不能玩游戏?
在上个世纪最早推出视频游戏的例子是托马斯戈德史密斯(Thomas T. Goldsmith Jr.)于1947年开发的“「Cathode Ray Tube Amusement Device」”,它已经显着发展,并且已成为人类生活中必不可少的一部分。 通过美国游戏行业的统计数据&…...

发电机负载测试方案
发电机负载测试是为了评估发电机在不同负载条件下的性能和稳定性。下面是一个可能的发电机负载测试方案: 测试前准备: - 确定测试的负载范围和条件,包括负载大小、负载类型(如电阻性、感性或容性负载)、负载持续时间等…...
Flask三种文件下载方法
Flask 是一个流行的 Python Web 框架,它提供了多种方法来实现文件下载。在本文中,我们将介绍三种不同的方法,以便你能够选择最适合你应用程序的方法。 方法一:使用 send_file 函数 send_file 函数是 Flask 中最常用的文件下载方法…...
OpenCV C++ 图像处理实战 ——《基于NCC多角度多目标匹配》
OpenCV C++ 图像处理实战 ——《基于NCC多角度多目标匹配》 一、结果演示二、NCC模板匹配2.1、OpenCV matchTemplate2.2、多角度2.3、多目标2.4、NMS非极大值抑制三、代码实现3.1 制作模板3.1 单目标匹配3.1.1 模板图像旋转3.1.2 旋转目标坐标3.2 多目标匹配3.2.1 制作模板3.2.…...
【书籍篇】Spring实战第4版 第2部分 Web中的Spring
Spring实战第4版 第2部分 Web中的Spring 五. 构建Spring Web应用程序5.1 SpirngMVC请求流程5.2 搭建Spring MVC5.2.1 配置DispatcherServlet5.2.2 配置WebConfig5.2.3 配置RootConfig 5.3 编写基本的控制器5.4 Spittr首页5.6 复杂的控制器5.6.1 定义类级别的请求处理5.6.2 传递…...
IC - 基础知识 - SOC与MCU
说明 工作中有涉及到SOC和MCU,非嵌入式专业,对两个概念理解不是很清晰。 共同点 MCU和SOC是两种常见的集成电路 (IC) 设计形式,它们的区别在于它们的设计目的和应用场景。工作中将MCU和SOC都称为IC也是没问题的,但是专业人员会…...

【elasticsearch+kibana基于windows docker安装】
创建网络:es和kibana容器互联 docker network create es-net加载镜像 docker pull elasticsearch:7.12.1运行 docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -e ES_JAVA_OPTS"-Xms512m -Xmx512m" -v $…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...