钉钉企业微应用开发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 $…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
