视频AI分析定时任务思路解析
序言:
最近项目中用到视频ai分析,由于sdk涉及保密,不便透露,仅对定时任务分析的思路作出分享,仅供参考。
1、定时任务
由于ai服务器的性能上限,只能同时对64个rtsp流分析一种算法,或者对8个rtsp流分析8种算法。因此定时任务,做如下设计。
AiHandlerTask.java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ewaycloud.jw.ai.service.AiService;
import com.ewaycloud.jw.camera.entity.Camera;
import com.ewaycloud.jw.camera.mapper.CameraMapper;
import com.ewaycloud.jw.camera.service.CameraService;
import com.ewaycloud.jw.cases.dto.CaseDTO;
import com.ewaycloud.jw.cases.service.CaseService;
import com.ewaycloud.jw.channel.service.HikService;
import com.ewaycloud.jw.task.entity.Task;
import com.ewaycloud.jw.task.mapper.TaskMapper;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Date;
import java.util.List;/*** AI分析 定时任务 处理类** @author gwh* @date 2024-04-14 13:59:17*/
@Component
@EnableScheduling
public class AiHandlerTask {@ResourceAiService aiService;@ResourceTaskService taskService;@ResourceCameraService cameraService;@Resourceprivate TaskMapper taskMapper;@Resourceprivate CameraMapper cameraMapper;@Resourceprivate HikService hkService;@Resourceprivate CaseService caseService;/*** 注解中的Cron表达式: {秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}* 注意:日和周其中的一个必须为"?"* 10/5 20 10 * * ? 每天10点20分第10秒以后,每3秒执行一次,到10点21分就不会执行了** AI算法分析任务: 每5秒执行一次*/
// @Scheduled(cron = "0/5 * * * * ?")public void startTask(){// System.out.println("AI分析定时任务执行 每隔5秒执行一次:" + new Date());//查询要执行的任务List<Task> aiTasks = taskMapper.findAiTasks(null);if (null != aiTasks) {for(Task vo:aiTasks){if (null != vo.getDeptId()) {//查询某谈话室下边的摄像头列表(flag是1 谈话人特写 和2 被谈话人特写 的)List<Camera> cameraList = cameraMapper.findCamersByDeptId(vo.getDeptId());if (null != cameraList && cameraList.size()>0) {for(Camera camera:cameraList) {//根据摄像头编码cameraCode,调用海康接口拉流String cameraCode = camera.getCameraCode();try {//根据cameraCode、开始时间、结束时间 调用海康接口 拉回放流//查询时间(IOS8601格式yyyy-MM-dd'T'HH:mm:ss.SSSzzz,和结束时间相差不超过三天JSONObject data = hkService.playbackURLs( cameraCode, vo.getStartTime(), vo.getEndTime());//谈话人特写AI分析if (null != data && null != data.getString("url")) {String rtspUrl = data.getString("url");//疑似肢体冲突// startAiTask(rtspUrl, 1L, vo.getStartTime(), vo.getEndTime(), vo);//玩手机分析// startAiTask(rtspUrl, 2L, vo.getStartTime(), vo.getEndTime(), vo);//倒地分析// startAiTask(rtspUrl, 3L, vo.getStartTime(), vo.getEndTime(), vo);//人数异常startAiTask(rtspUrl, 5L, vo.getStartTime(), vo.getEndTime(), vo);}} catch (Exception e) {e.printStackTrace();}}}}}}// System.out.println("AI分析定时任务执行 每隔10秒执行一次:: " + new Date());}//执行拉流调用AI分析的方法public void startAiTask(String rtspUrl, Long aiId, String startTime, String endTime, Task vo) {//调用AI分析接口if (null != rtspUrl) {//调用海康AI算法分析String aiResponse = "";if (aiId == 1) {//疑似肢体冲突aiResponse = aiService.indoorPhysicalConfront(rtspUrl, startTime, endTime);vo.setBreakName("疑似肢体冲突");vo.setAiId(1L);} else if (aiId == 2) {//玩手机aiResponse = aiService.playCellphone(rtspUrl, startTime, endTime);vo.setBreakName("玩手机");vo.setAiId(2L);} else if (aiId == 3) {//倒地aiResponse = aiService.failDown(rtspUrl, startTime, endTime);vo.setBreakName("倒地");vo.setAiId(3L);} else if (aiId == 4) {//人员站立aiResponse = aiService.Standup(rtspUrl,startTime, endTime);vo.setBreakName("人员站立");vo.setAiId(4L);} else if (aiId == 5) {//人数异常aiResponse = aiService.PeopleNumChange(rtspUrl, startTime, endTime);vo.setBreakName("人数异常");vo.setAiId(5L);} else if (aiId == 6) {//声强突变aiResponse = aiService.audioAbnormal(rtspUrl, startTime, endTime);vo.setBreakName("声强突变");vo.setAiId(6L);} else if (aiId == 7) {//超时滞留aiResponse = aiService.overtimeTarry(rtspUrl, startTime, endTime);vo.setBreakName("超时滞留");vo.setAiId(7L);} else if (aiId == 8) {//攀高aiResponse = aiService.reachHeight(rtspUrl, startTime, endTime);vo.setBreakName("攀高");vo.setAiId(8L);}JSONObject aiResponseJSONObject = JSON.parseObject(aiResponse);
// System.out.println("AI分析定时任务返回aiResponseJSONObject:" + aiResponseJSONObject);String taskId = "";String taskStatus = "";if (null != aiResponseJSONObject && null != aiResponseJSONObject.getString("taskID") ){taskId = aiResponseJSONObject.getString("taskID");//调用海康查询任务状态接口获取AI分析任务状态String result = aiService.queryTaskVideoStatus(taskId);JSONObject resultJSONObject = JSON.parseObject(result);JSONArray statusJSONArray = resultJSONObject.getJSONArray("status");JSONObject statusJSONObject = (JSONObject) statusJSONArray.get(0);taskStatus = statusJSONObject.getString("taskStatus");//将AI分析结果taskStatus插入task表中,更新任务表,状态:1 未执行, 2等待, 3 正在执行 , 4 已完成vo.setTaskState(Integer.parseInt(taskStatus));vo.setTaskId(taskId); //保存 海康返回的 taskID//如果任务完成,关闭rtsp流if ("4".equals(taskStatus)) {//根据caseId更新案件表的 task_state =1 , ai任务状态(0:未执行 1:已执行)Long caseId = vo.getCaseId();CaseDTO caseDTO = new CaseDTO();caseDTO.setCaseId(caseId);caseDTO.setCaseState(1);caseService.updCaseInfo(caseDTO);//关闭rtsp流try {hkService.clearPlayUrls(rtspUrl);} catch (Exception e) {e.printStackTrace();}}}System.out.println("AI分析定时任务返回 taskId:" + taskId +" breakName: "+ vo.getBreakName() +" taskStatus: "+ taskStatus);//更新任务表, 根据caseId 和taskId查询任务,如果有更新,没有插入Task dto = new Task();dto.setCaseId(vo.getCaseId());dto.setTaskId(vo.getTaskId());List<Task> tasks = taskMapper.findTasks(dto);if(null != tasks && tasks.size()>0){for(Task po : tasks){vo.setId(po.getId());vo.setUpdateTime(new Date());taskService.updateById(po);}}else {vo.setCreateTime(new Date());vo.setUpdateTime(new Date());taskMapper.insert(vo);}}}}
2、算法实现,由于涉密,只贴出接口
AiService.java
import com.baomidou.mybatisplus.extension.service.IService;
import com.ewaycloud.jw.ai.entity.Ai;
import com.ewaycloud.jw.task.entity.Task;import java.util.List;/*** AI对接** @author gwh* @date 2024-03-13 13:49:09*/
public interface AiService extends IService<Ai> {String getAiDeviceInfo();/*** 创建--疑似肢体冲突事件--分析视频分析任务**/String indoorPhysicalConfront(String streamUrl, String startTime, String endTime);/*** 创建--玩手机--分析视频分析任务**/String playCellphone(String streamUrl, String startTime, String endTime);/*** 创建--倒地检测--分析视频分析任务**/String failDown(String streamUrl, String startTime, String endTime);/*** 创建--人员站立--分析视频分析任务**/String Standup(String streamUrl, String startTime, String endTime);/*** 创建--人数异常--分析视频分析任务**/String PeopleNumChange(String streamUrl, String startTime, String endTime);/*** 创建--声强突变--分析视频分析任务**/String audioAbnormal(String streamUrl, String startTime, String endTime);/*** 创建--超时滞留--分析视频分析任务**/String overtimeTarry(String streamUrl, String startTime, String endTime);/*** 创建--攀高--分析视频分析任务**/String reachHeight(String streamUrl, String startTime, String endTime);/*** 查询分析视频分析任务状态**/String queryTaskVideoStatus(String taskId);}
3、启动一个线程,Socket监听10006端口,接收ai服务器返回的结果
ListenThread.java
import com.ewaycloud.jw.ai.entity.AiResolveResult;
import com.ewaycloud.jw.ai.mapper.AiResolveResultMapper;
import com.ewaycloud.jw.task.entity.ContentTypeEnum;
import com.ewaycloud.jw.task.entity.Task;
import com.ewaycloud.jw.task.mapper.TaskMapper;
import com.mysql.cj.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.List;/*** @author gwhui* @date 2024/1/18 17:38* @desc 监听处理线程*/
@Slf4j
@Service
public class ListenThread implements Runnable {private final AlarmDataParser alarmDataParser = new AlarmDataParser();private static TaskMapper taskMapper;@Resourcepublic void setVerificDao(TaskMapper taskMapper) {ListenThread.taskMapper = taskMapper;}private static AiResolveResultMapper aiResolveResultMapper;@Resourcepublic void setVerificDao(AiResolveResultMapper aiResolveResultMapper) {ListenThread.aiResolveResultMapper = aiResolveResultMapper;}@Overridepublic void run() {
// int listenPort = propertiesUtil.getIntegerProperty("custom.isapi.listen.port", 9999);int listenPort =10006;try {ServerSocket serverSocket = new ServerSocket(listenPort);System.out.println("启动监听, 监听端口:" + listenPort);while (!Thread.currentThread().isInterrupted()) {Socket accept = serverSocket.accept();accept.setKeepAlive(true);System.out.println("设备(客户端)信息:" + accept.getInetAddress().getHostAddress());if (accept.isConnected()) {handleData(accept);}accept.close();}serverSocket.close();System.out.println("停止监听完成");} catch (InterruptedException e) {// 线程被中断的处理逻辑System.out.println("停止监听完成: " + e.getMessage());} catch (Exception e) {System.out.println("监听创建异常: " + e.getMessage());}}@Transactional(rollbackFor = Exception.class)public synchronized void handleData(Socket accept) throws Exception {InputStream inputData = accept.getInputStream();OutputStream outputData = accept.getOutputStream();// 输出数据ByteArrayOutputStream byOutputData = new ByteArrayOutputStream();byte[] buffer = new byte[2 * 1024 * 1024];int length = 0;// 持续接收处理数据直到接收完毕String recvAlarmData = "";while ((length = inputData.read(buffer)) > 0) {byOutputData.write(buffer, 0, length);String recvData = byOutputData.toString();recvAlarmData = recvAlarmData + recvData;// 获取boundaryString strBoundary = "boundary=";int beginIndex = recvData.indexOf(strBoundary);beginIndex += strBoundary.length();int lenIndex = recvData.indexOf("\r\n", beginIndex);String strBoundaryMark = recvData.substring(beginIndex, lenIndex);if (recvAlarmData.contains("--" + strBoundaryMark.trim() + "--")) {//表单结束符判断接收结束break;}}
// System.out.println("==============recvAlarmData========>> "+recvAlarmData);if(null != recvAlarmData){String taskId = null;int index = recvAlarmData.indexOf("<taskID>");if(index != -1){taskId = recvAlarmData.substring(index + 8, index + 40);}//获取服务器返回的图片String bkgUrl = null;int indexStartBkgUrl = recvAlarmData.indexOf("<bkgUrl>");int indexEndBkgUrl = recvAlarmData.indexOf("</bkgUrl>");if(indexStartBkgUrl != -1){bkgUrl = recvAlarmData.substring(indexStartBkgUrl+8, indexEndBkgUrl);bkgUrl =bkgUrl.replaceAll("&","&");}System.out.println("===AIrecieveData===>>taskId: "+taskId +" bkgUrl: "+ bkgUrl);//根据taskId查询 任务信息if(!StringUtils.isNullOrEmpty(taskId)){Task task = taskMapper.finTaskByTaskId(taskId);if(null != task){AiResolveResult vo = new AiResolveResult();vo.setCreateTime(new Date());vo.setUpdateTime(new Date());vo.setTaskId(taskId); //保存海康返回的 taskIdvo.setBreakName(task.getBreakName());vo.setAiId(task.getAiId());vo.setDeptId(task.getDeptId());vo.setCameraId(task.getCameraId());vo.setBreakTypeId(task.getAiId());vo.setRiskTime(task.getTalkTime());vo.setTalkAddress(task.getTalkAddress());vo.setTalkAddressName(task.getTalkAddressName());vo.setTalkUnit(task.getTalkUnit());vo.setTalkUnitName(task.getTalkUnitName());vo.setPhoto(bkgUrl); //保存海康返回的图片vo.setCaseId(task.getCaseId());vo.setCaseName(task.getCaseName());vo.setInterviewerName(task.getInterviewerName());//根据taskId查询任务结果表,如果有做更新操作,没有做插入操作List<AiResolveResult> aiResolveResults = aiResolveResultMapper.findAiResults(vo);if(null != aiResolveResults && aiResolveResults.size()>0){for(AiResolveResult aiResolveResult:aiResolveResults){if(null != aiResolveResult){aiResolveResult.setPhoto(vo.getPhoto());aiResolveResultMapper.updateById(aiResolveResult);}}}else {aiResolveResultMapper.insert(vo);}}}}String response = "HTTP/1.1 200 OK" +"\r\n" +"Connection: close" +"\r\n\r\n";outputData.write(response.getBytes());outputData.flush();outputData.close();inputData.close();//解析数据response = parseAlarmInfoByte(byOutputData);System.out.println("==============response========>> "+response);}private String parseAlarmInfoByte(ByteArrayOutputStream byOutputData) throws Exception {// 事件报文字节byte[] byAlarmDataInfo = byOutputData.toByteArray();int iDataLen = byAlarmDataInfo.length;String szBoundaryMark = "boundary=";String szContentTypeMark = "Content-Type: ";int iTypeMarkLen = szContentTypeMark.getBytes("UTF-8").length;String szContentLenMark = "Content-Length: ";int iLenMarkLen = szContentLenMark.getBytes("UTF-8").length;String szContentLenMark2 = "content-length: ";int iLenMarkLen2 = szContentLenMark2.getBytes("UTF-8").length;int iContentLen = 0;String szEndMark = "\r\n";int iMarkLen = szEndMark.getBytes("UTF-8").length;String szEndMark2 = "\r\n\r\n";int iMarkLen2 = szEndMark2.getBytes("UTF-8").length;String szJson = "text/json";String szJpg = "image/jpeg";int iStartBoundary = doDataSearch(byAlarmDataInfo, szBoundaryMark.getBytes("UTF-8"), 0, byAlarmDataInfo.length);iStartBoundary += szBoundaryMark.getBytes("UTF-8").length;int iEndBoundary = doDataSearch(byAlarmDataInfo, szEndMark.getBytes("UTF-8"), iStartBoundary, byAlarmDataInfo.length);byte[] byBoundary = new byte[iEndBoundary - iStartBoundary];System.arraycopy(byAlarmDataInfo, iStartBoundary, byBoundary, 0, iEndBoundary - iStartBoundary);String szBoundaryEndMark = "--" + new String(byBoundary).trim() + "--";int iDateEnd = doDataSearch(byAlarmDataInfo, szBoundaryEndMark.getBytes("UTF-8"), 0, byAlarmDataInfo.length);String szBoundaryMidMark = "--" + new String(byBoundary).trim();int iBoundaryMidLen = szBoundaryMidMark.getBytes("UTF-8").length;int startIndex = iEndBoundary;String szContentType = "";int[] iBoundaryPos = new int[11]; //boundary个数,这里最大解析10个int iBoundaryNum = 0;for (iBoundaryNum = 0; iBoundaryNum < 10; iBoundaryNum++) {startIndex = doDataSearch(byAlarmDataInfo, szBoundaryMidMark.getBytes("UTF-8"), startIndex, iDateEnd);if (startIndex < 0) {break;}startIndex += iBoundaryMidLen;iBoundaryPos[iBoundaryNum] = startIndex;}iBoundaryPos[iBoundaryNum] = iDateEnd;//最后一个是结束符for (int i = 0; i < iBoundaryNum; i++) {// Content-Typeint iStartType = doDataSearch(byAlarmDataInfo, szContentTypeMark.getBytes("UTF-8"), iBoundaryPos[i], iBoundaryPos[i + 1]);if (iStartType > 0) {iStartType += iTypeMarkLen;int iEndType = doDataSearch(byAlarmDataInfo, szEndMark.getBytes("UTF-8"), iStartType, iBoundaryPos[i + 1]);if (iEndType > 0) {byte[] byType = new byte[iEndType - iStartType];System.arraycopy(byAlarmDataInfo, iStartType, byType, 0, iEndType - iStartType);szContentType = new String(byType).trim();}}// Content-Lengthint iStartLength = doDataSearch(byAlarmDataInfo, szContentLenMark.getBytes("UTF-8"), iBoundaryPos[i], iBoundaryPos[i + 1]);if (iStartLength > 0) {iStartLength += iLenMarkLen;int iEndLength = doDataSearch(byAlarmDataInfo, szEndMark.getBytes("UTF-8"), iStartLength, iBoundaryPos[i + 1]);if (iEndLength > 0) {byte[] byLength = new byte[iEndLength - iStartLength];System.arraycopy(byAlarmDataInfo, iStartLength, byLength, 0, iEndLength - iStartLength);iContentLen = Integer.parseInt(new String(byLength).trim());}}// Content-Length(兼容错误大小写)int iStartLength2 = doDataSearch(byAlarmDataInfo, szContentLenMark2.getBytes("UTF-8"), iBoundaryPos[i], iBoundaryPos[i + 1]);if (iStartLength2 > 0) {iStartLength2 += iLenMarkLen2;int iEndLength2 = doDataSearch(byAlarmDataInfo, szEndMark.getBytes("UTF-8"), iStartLength2, iBoundaryPos[i + 1]);if (iEndLength2 > 0) {byte[] byLength2 = new byte[iEndLength2 - iStartLength2];System.arraycopy(byAlarmDataInfo, iStartLength2, byLength2, 0, iEndLength2 - iStartLength2);iContentLen = Integer.parseInt(new String(byLength2).trim());}}// 通过\r\n\r\n判断报文数据起始位置int iStartData = doDataSearch(byAlarmDataInfo, szEndMark2.getBytes("UTF-8"), iBoundaryPos[i], iBoundaryPos[i + 1]);if (iStartData > 0) {iStartData += iMarkLen2;// 有的报文可能没有Content-Lengthif (iContentLen <= 0) {iContentLen = iBoundaryPos[i + 1] - iStartData;}// 截取数据内容byte[] byData = new byte[iContentLen];System.arraycopy(byAlarmDataInfo, iStartData, byData, 0, iContentLen);// 根据类型处理数据int contentType = ContentTypeEnum.getEventType(szContentType);String storeFolder = System.getProperty("user.dir") + "\\output\\listen\\event\\";switch (contentType) {case ContentTypeEnum.APPLICATION_JSON:case ContentTypeEnum.APPLICATION_XML: {String rawContent = new String(byData).trim();alarmDataParser.parseAlarmInfo(contentType, storeFolder, rawContent, null);break;}case ContentTypeEnum.IMAGE_JPEG:case ContentTypeEnum.IMAGE_PNG:case ContentTypeEnum.VIDEO_MPG:case ContentTypeEnum.VIDEO_MPEG4:case ContentTypeEnum.APPLICATION_ZIP: {alarmDataParser.parseAlarmInfo(contentType, storeFolder, null, byData);break;}default: {System.out.println("未匹配到可以解析的content-type, 请自行补全处理!");}}}}// 响应报文String response = "";// 消费交易事件 (实际如果没有消费机设备可以不需要消费机的处理代码)String eventType = "";String eventConfirm = "";if (eventType.equals("ConsumptionEvent") || eventType.equals("TransactionRecordEvent") || eventType.equals("HealthInfoSyncQuery")) {response = "HTTP/1.1 200 OK" +"\r\n" +"Content-Type: application/json; charset=\"UTF-8\"" +"\r\n" +"Content-Length: " + eventConfirm.length() +"\r\n\r\n" + eventConfirm +"\r\n";} else {response = "HTTP/1.1 200 OK" +"\r\n" +"Connection: close" +"\r\n\r\n";}return response;}private int doDataSearch(byte[] bySrcData, byte[] keyData, int startIndex, int endIndex) {if (bySrcData == null || keyData == null || bySrcData.length <= startIndex || bySrcData.length < keyData.length) {return -1;}if (endIndex > bySrcData.length) {endIndex = bySrcData.length;}int iPos, jIndex;for (iPos = startIndex; iPos < endIndex; iPos++) {if (bySrcData.length < keyData.length + iPos) {break;}for (jIndex = 0; jIndex < keyData.length; jIndex++) {if (bySrcData[iPos + jIndex] != keyData[jIndex]) {break;}}if (jIndex == keyData.length) {return iPos;}}return -1;}}
4、数据库设计
瀚高国产数据库
5、前端页面设计
相关文章:

视频AI分析定时任务思路解析
序言: 最近项目中用到视频ai分析,由于sdk涉及保密,不便透露,仅对定时任务分析的思路作出分享,仅供参考。 1、定时任务 由于ai服务器的性能上限,只能同时对64个rtsp流分析一种算法,或者对8个rts…...
tcp 粘包和拆包 及 解决粘包方案
什么是粘包和拆包 .TCP 是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使…...

【2024泰迪杯】B 题:基于多模态特征融合的图像文本检索20页论文及Python代码
【2024泰迪杯】B 题:基于多模态特征融合的图像文本检索20页论文及Python代码 相关链接 【2024泰迪杯】A 题:生产线的故障自动识别与人员配置 Python代码实现 【2024泰迪杯】B 题:基于多模态特征融合的图像文本检索Python代码实现 【2024泰迪…...

华为设备telnet 远程访问配置实验简述
一、实验需求: 1、AR1模拟电脑telnet 访问AR2路由器。 二、实验步骤: 1、AR1和AR2接口配置IP,实现链路通信。 2、AR2配置AAA模式 配置用户及密码 配置用户访问级别 配置用户telnet 访问服务 AR2配置远程服务数量 配置用户远程访问模式为AAA 配置允许登录…...
在HTML中,如何正确使用语义化标签?
在HTML中,使用语义化标签可以使得网页结构更加清晰和易于理解。以下是一些正确使用语义化标签的方法: 使用合适的标题标签(h1-h6)来标识网页的标题,以及页面中的各个区块的标题。 <h1>网页标题</h1> <…...
WHAT - 高性能和内存安全的 Rust(一)
目录 一、介绍1.1 示例代码1.2 关键特性内存安全零成本抽象:高效性能示例代码:使用迭代器的零成本抽象示例代码:泛型和单态化总结 并发编程:防止数据竞争Rust 并发编程示例Rust 的所有权系统防止数据竞争总结 丰富的类型系统包管理…...
八、C#运算符
C#运算符 晕杜甫是一种告诉编辑器执行特定的数学或逻辑操作的符号。C#有丰富的内置运算符,分类如下: 算术运算符关系运算符逻辑运算符位运算符赋值运算符其他运算符 算术运算符 下表显示了 C# 支持的所有算术运算符。假设变量 A 的值为 10,…...
【HiveSQL】join关联on和where的区别及效率对比
测试环境:hive on spark spark版本:3.3.1 一、执行时机二、对结果集的影响三、效率对比1.内连接1)on2)where 2.外连接1)on2)where 四、总结PS 一、执行时机 sql连接中,where属于过滤条件&#…...

如何解决windows自动更新,释放C盘更新内存
第一步:首先关闭windows自动更新组件 没有更新windows需求,为了防止windows自动更新,挤占C盘空间,所以我们要采取停止Windows Update服务。按下WinR打开运行对话框,输入services.msc, 然后按Enter。在服务…...

初学51单片机之PWM实例呼吸灯以及遇到的问题(已解答)
PWM全名Pulse Width Modulation中文称呼脉冲宽度调制 如图 这是一个周期10ms、频率是100HZ的波形,但是每个周期内,高低电平宽度各不相同,这就是PWM的本质。 占空比是指高电平占整个周期的比列,上图第一个波形的占空比是40%,第二个…...

手机天线都去哪里了?
在手机的演变历程中,天线的设计和位置一直是工程师们不断探索和创新的领域。你是否好奇,现在的手机为什么看不到那些曾经显眼的天线了呢? 让我们一起揭开这个谜题。 首先,让我们从基础开始:手机是如何发出电磁波的&…...

计算机网络 —— 应用层(电子邮件)
计算机网络 —— 应用层(电子邮件) 电子邮件发送电子邮件的过程SMTP特性工作流程 电子邮件格式MIME关键组件工作方式 POP/IMAPPOP(邮局协议)IMAP(因特网邮件访问协议) 基于万维网的电子邮箱特点优势常见的基…...
Java18新特性(极简)
一、引言 自1995年Java语言首次亮相以来,它已经成为企业级应用、移动应用和游戏开发等领域不可或缺的一部分。随着技术的不断进步,Java也在持续演化,每个新版本都带来了诸多新特性和性能优化,旨在提升开发者的编程效率和应用程序的…...
vscode连接ssh远程服务器
当使用Visual Studio Code (VSCode) 连接SSH远程服务器时,可以遵循以下步骤。这些步骤将帮助你设置并连接到远程服务器,包括免密登录的设置(如果需要)。 一、安装并配置Remote-SSH插件 下载并安装VSCode:确保你已经下…...
【趣味测试】
编程过程中遇到的趣味知识 1 Cpp 1.1 浮点数计算 if (0.1 0.2 0.3) {std::cout << "0.1 0.2 0.3 true" << std::endl;} else {std::cout << "0.1 0.2 0.3 false" << std::endl;}if (0.1 0.3 0.4) {std::cout << &…...

数据结构经典面试之数组——C#和C++篇
文章目录 1. 数组的基本概念与功能2. C#数组创建数组访问数组元素修改数组元素数组排序 3. C数组创建数组访问数组元素修改数组元素数组排序 4. 数组的实际应用与性能优化5. C#数组示例6. C数组示例总结 数组是编程中常用的数据结构之一,它用于存储一系列相同类型的…...
docker的基本知识
文章目录 前言docker的基本知识1. docker 的底层逻辑2. docker 的核心要素2.1. 镜像的基本概念:2.2. 容器的基本概念:2.3. 仓库的基本概念: 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。 …...

React Native性能优化红宝书
一、React Native介绍 React Native 是Facebook在React.js Conf2015 推出的开源框架,使用React和应用平台的原生功能来构建 Android 和 iOS 应用。通过 React Native,可以使用 JavaScript 来访问移动平台的 API,使用 React 组件来描述 UI 的…...

后端不提供文件流接口,前台js使用a标签实现当前表格数据(数组非blob数据)下载成Excel
前言:开发过程中遇到的一些业务场景,如果第三方不让使用,后端不提供接口,就只能拿到table数据(Array),实现excel文件下载。 废话不多说,直接上代码,方法后续自行封装即可: functio…...

如何使用ChatGPT辅助设计工作
文章目录 设计师如何使用ChatGPT提升工作效率?25个案例告诉你!什么是 prompt?咨询信息型 prompt vs 执行任务 prompt编写出色 prompt 的基本思路撰写 prompt 的案例和技巧1、将 ChatGPT 视作专业人士2、使用 ChatGPT 创建表单3、使用 ChatGPT…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...