当前位置: 首页 > news >正文

jbase实现业务脚本化

经过晚上和早上的努力,终于补上框架最后一块了,业务脚本侦听变化后自动编译jar包和调用,实现维护成本低,开发效率高的框架的基本体系。

实现自动编译jar包的类

package appcode;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import java.util.*;
import java.io.*;
import org.apache.commons.io.FileUtils;
import java.nio.charset.StandardCharsets;
import java.nio.charset.*;public class AutoBuild {/// <summary>/// 缓存路径和类型,允许多线程读一个线程写/// </summary>private static ConcurrentHashMap<String, Boolean> Building = new ConcurrentHashMap<>();/// <summary>/// 编译指定路径的java代码/// </summary>/// <param name="basePath">根路径</param>/// <param name="codepath">类代码路径</param>/// <param name="proname">工程名称,不带后缀的</param>/// <param name="standprofilepath">标准工程文件全路径</param>/// <returns>返回空成功,非空就是失败原因</returns>public static String Build(String basePath,String codepath, String proname, String standprofilepath){Process proc = null;try{//有编译的退出if (Building.containsKey(codepath)){System.out.println(codepath+"已经有进程在编译了,退出本次编译!");return "";}try{if (!Building.containsKey(codepath)){AutoBuild.HashTryAdd(Building, codepath, true);}}catch (Exception ex){System.out.println("编译并发"+ex.getMessage());}//编译临时总目录String buildPath = Paths.get(basePath, "AutoBuildTmp").toString();File directory = new File(buildPath);//没有编译的临时目录就创建if (!directory.exists()) {directory.mkdirs();}//构建项目编译文件夹String proBuildPath = Paths.get(buildPath, proname).toString();File directoryPro = new File(proBuildPath);//没有编译的临时目录就创建if (!directoryPro.exists()) {directoryPro.mkdirs();}File fi = new File(codepath);//编译目录类全名String clsFullName = Paths.get(proBuildPath, fi.getName()).toString();System.out.println("拷贝:" + codepath + "到:"+ clsFullName);List<String> lines = FileUtils.readLines(fi, "UTF-8");StringBuilder sbNewCode=new StringBuilder();String jarRootPath=proBuildPath;System.out.println("包名称:" + proname);String [] arr=proname.split("\\.");String pakName="";if(arr.length>1){for(int p=0;p<arr.length-1;p++){jarRootPath=Paths.get(jarRootPath,arr[p]).toString();//创建jar包目录结构File directoryProJarChild = new File(jarRootPath);//没有编译的临时目录就创建if (!directoryProJarChild.exists()) {directoryProJarChild.mkdirs();}if(pakName==""){pakName=arr[p];}else{pakName+="."+arr[p];}}}sbNewCode.append("package "+pakName+";"+System.lineSeparator());for (String line : lines) {sbNewCode.append(line+System.lineSeparator());}WriteText2File(clsFullName,sbNewCode.toString());//复制类代码//copyFile(new File(codepath), new File(clsFullName));String cmmand = "javac";StringBuilder retsb = new StringBuilder();//得到javac编译命令串String cmdStr=GetJavacStr(basePath,standprofilepath,fi.getName());System.out.println("编译命令:" + cmdStr);System.out.println("运行路径:" + directoryPro);// 创建进程并执行命令Process process = Runtime.getRuntime().exec(cmdStr,null,directoryPro);// 获取命令行程序的输出结果BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {retsb.append(line);}// 等待命令行程序执行完毕int exitCode=process.waitFor();// 关闭资源reader.close();System.out.println("编译返回:" + exitCode);//编译完成if (exitCode == 0){// 获取目录中的所有文件和子目录File[] files = directoryPro.listFiles();// 遍历文件和子目录for (File file : files) {if (!file.isDirectory()) {if (file.getName().endsWith(".class")) {copyFile(new File(file.toString()),new File(Paths.get(jarRootPath,file.getName()).toString()));}}}String pakStr="jar cf "+proname+".jar"+" "+arr[0];System.out.println("打包命令:" + pakStr);System.out.println("打包运行路径:" + directoryPro);//打包jar包Process processPak = Runtime.getRuntime().exec(pakStr,null,directoryPro);// 等待命令行程序执行完毕int exitCodePak=processPak.waitFor();System.out.println("打包返回:" + exitCodePak);if (exitCodePak == 0){String jarOutPath=Paths.get(proBuildPath,proname+".jar").toString();String jarBinPath=Paths.get(basePath,"BinAshx",proname+".jar").toString();System.out.println("从:" + jarOutPath+"拷贝到:"+jarBinPath);//拷贝生成的jar包到BinAshxcopyFile(new File(jarOutPath), new File(jarBinPath));}//删除源文件//DeleteFile(new File(proBuildPath));return "";}String retstr = retsb.toString();return retstr;}catch (Exception ex){return ex.getMessage();}finally{if (Building.containsKey(codepath)){Building.remove(codepath);}}}/// <summary>/// 解决多线程写并发/// </summary>/// <param name="hs"></param>/// <param name="key"></param>/// <param name="value"></param>public static void HashTryAdd(ConcurrentHashMap<String, Boolean> hs, String key, Boolean value){try{//更新类型if (!hs.containsKey(key)){hs.put(key, value);}}catch (Exception ex){System.out.println("并发编译捕获的正常日志,忽略"+ex.getMessage());//更新类型if (!hs.containsKey(key)){hs.put(key, value);}}}///拷贝文件public static void copyFile(File srcFile, File destFile) {//判断原文件是否存在if (!srcFile.exists()) {throw new IllegalArgumentException("源文件:" + srcFile + "不存在!");}//判断原文件是否为一个文件if (!srcFile.isFile()) {throw new IllegalArgumentException(srcFile + "不是一个文件!");}try {FileInputStream in = new FileInputStream(srcFile);FileOutputStream out = new FileOutputStream(destFile);/*** 读取原文件,以字节流的形式读到byte数组,1024个字节=1KB* 循环读取* in.read()读到bytes数组中,位置从0-bytes.length*/byte[] bytes = new byte[10 * 1024];int b;  //b为读取到的字节长度while ((b = in.read(bytes, 0, bytes.length)) != -1) {//写入out.write(bytes, 0, b);out.flush();}//关闭in.close();out.close();}catch (IOException e) {e.printStackTrace();}}///删除文件和目录public static void DeleteFile(File file){//判断文件不为null或文件目录存在if (file == null || !file.exists()){return;}//取得这个目录下的所有子文件对象File[] files = file.listFiles();//遍历该目录下的文件对象for (File f: files){//判断子目录是否存在子目录,如果是文件则删除if (f.isDirectory()){DeleteFile(f);}else {f.delete();}}}///得到javac编译命令///basePath:根地址///standprofilepath:依赖jar包工程地址///javaName:java类文件名称private static String GetJavacStr(String basePath,String standprofilepath,String javaName){String retStr="javac -encoding UTF-8 -classpath ";try {//判断配置是否存在File file = new File(standprofilepath);if (!file.exists()) {System.out.println(standprofilepath + "文件不存在,请确认!");return "";}//解析xmlDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(file);// 获得根节点Element rootElement = document.getDocumentElement();// 获得根节点下的所有子节点NodeList students = rootElement.getChildNodes();String classPath="";for (int i = 0; i < students.getLength(); i++) {// 由于节点多种类型,而一般我们需要处理的是元素节点Node childNode = students.item(i);// 元素节点就是非空的子节点,也就是还有孩子的子节点if (childNode.getNodeType() == Node.ELEMENT_NODE) {Element childElement = (Element) childNode;//不是对象配置元素就忽略if (childElement.getNodeName() != "orderEntry") {continue;}//解析得到包名String name = childElement.getAttribute("name");String oneJarPath=Paths.get(basePath,name+".jar").toString();if(classPath==""){classPath=oneJarPath;}else{classPath+=";"+oneJarPath;}}}retStr+=classPath+" "+javaName;return retStr;}catch (Exception ex) {System.out.println(standprofilepath + ex.getMessage());ex.printStackTrace();}return "";}/*** 将文本写入文件** @param filePath 文件全路径* @param text     文本**/public static void WriteText2File(String filePath, String text) {// 创建文件File file = new File(filePath);if (!file.exists()) {try {// 创建文件父级目录File parentFile = file.getParentFile();if (!parentFile.exists()) {parentFile.mkdirs();}// 创建文件file.createNewFile();}catch (IOException e) {e.printStackTrace();}}// 将文本写入文件WriteText2File(file, text);}/*** 将文本写入文件** @param file 文件对象* @param text 文本**/public static void WriteText2File(File file, String text) {BufferedWriter writer = null;try {FileOutputStream writerStream = new FileOutputStream(file);writer = new BufferedWriter(new OutputStreamWriter(writerStream, "UTF-8"));writer.write(text);writer.flush();}catch (IOException e) {e.printStackTrace();}finally {if (writer != null) {try {writer.close();} catch (IOException e) {e.printStackTrace();}}}}}

然后实现目录Java监控调用编译

import java.io.*;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;//监控文件
public class FileListener extends FileAlterationListenerAdaptor {//启动@Overridepublic void onStart(FileAlterationObserver observer) {super.onStart(observer);}//新建目录@Overridepublic void onDirectoryCreate(File directory){}//目录修改@Overridepublic void onDirectoryChange(File directory){}//目录删除@Overridepublic void onDirectoryDelete(File directory){}//创建文件@Overridepublic void onFileCreate(File file) {String compressedPath = file.getAbsolutePath();if(compressedPath.contains("AutoBuildTmp")){return;}if (file.canRead()) {String confStr = compressedPath.replace(MainInit.BllJavaBasePath, "").replace("\\", "/").split("\\.")[0];MainMiddleware.GetObjectByConfString(confStr,null,"",compressedPath);}}//修改文件@Overridepublic void onFileChange(File file) {String compressedPath = file.getAbsolutePath();if(compressedPath.contains("AutoBuildTmp")){return;}String confStr = compressedPath.replace(MainInit.BllJavaBasePath, "").replace("\\", "/").split("\\.")[0];MainMiddleware.GetObjectByConfString(confStr,null,"",compressedPath);}//删除文件@Overridepublic void onFileDelete(File file) {}//停止@Overridepublic void onStop(FileAlterationObserver observer) {super.onStop(observer);}
}

文件侦听器

import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.HiddenFileFilter;import java.io.File;//监控文件
public class FileMonitor {//监视器private FileAlterationMonitor monitor;//构造函数public FileMonitor(long interval){monitor = new FileAlterationMonitor(interval);}/*** 给文件添加监听** @param path     文件路径* @param listener 文件监听器*/public void monitor(String path, FileAlterationListener listener) {IOFileFilter directories = FileFilterUtils.and(FileFilterUtils.directoryFileFilter(),HiddenFileFilter.VISIBLE);IOFileFilter files       = FileFilterUtils.and(FileFilterUtils.fileFileFilter(),FileFilterUtils.suffixFileFilter(".java"));IOFileFilter filter = FileFilterUtils.or(directories, files);FileAlterationObserver observer = new FileAlterationObserver(new File(path),filter);monitor.addObserver(observer);observer.addListener(listener);}//停止public void stop() throws Exception {monitor.stop();}//启动public void start() throws Exception {monitor.start();}
}

主初始化实现java脚本监控

import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.nio.file.*;
import java.io.*;public class MainInit {//是否已经执行了初始化private static boolean HasInit=false;//网站根地址private static String webBasePath="";//业务脚本根地址public static String BllJavaBasePath="";//执行初始化public static void TryInit(String basePath) {//只初始化一次if (HasInit == true) {return;}HasInit = true;webBasePath = basePath;File fiBase=new File(basePath);String parentPath=fiBase.getParent();File fiParent=new File(parentPath);String codeBasePath=basePath;//开发环境if(fiParent.getName().equals("artifacts")){//到out一级File fiParent1=new File(fiParent.getParent());//到WebUI一级File fiParent2=new File(fiParent1.getParent());codeBasePath=Paths.get(fiParent2.toString(),"web").toString()+File.separator;}//用容器的配置xml初始化容器LIS.Core.Context.ObjectContainer.InitIoc(basePath);try{BllJavaBasePath=codeBasePath;System.out.println("监控目录:"+codeBasePath);FileMonitor fileMonitor = new FileMonitor(5000);fileMonitor.monitor(codeBasePath, new FileListener());fileMonitor.start();}catch (Exception ex) {ex.printStackTrace();}}
}

主中间件调整

import appcode.IBaseHttpHandler;import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.concurrent.ConcurrentHashMap;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;import java.util.*;@javax.servlet.annotation.WebServlet(name = "MianMiddleware")
public class MainMiddleware extends javax.servlet.http.HttpServlet {/// <summary>/// 缓存路径和类型,允许多线程读一个线程写/// </summary>private static ConcurrentHashMap<String, Class> hsType = new ConcurrentHashMap<>();///网站根地址public static String WebBasePath="";///执行post请求@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//得到网站根路径if(WebBasePath==""){WebBasePath= getServletContext().getRealPath("/");}//尝试执行初始化主逻辑MainInit.TryInit(WebBasePath);response.setContentType("text/html");request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");String url=request.getRequestURI();//解析得到类名String className = url.split("\\.")[0];PrintWriter writer = response.getWriter();//取第一部分if (className.charAt(0) == '/') {className = className.substring(1);}int index=className.indexOf("/");className=className.substring(index+1);//反射得到类型Object objDeal = GetObjectByConfString(className,writer,WebBasePath,"");//转换处理接口if(objDeal!=null){//转换成接口appcode.IBaseHttpHandler baseDeal=(appcode.IBaseHttpHandler)objDeal;baseDeal.ProcessRequest(request,response);}else{Write(writer,"未找到名称为:"+className+"的处理类");}}/// <summary>/// 通过配置得当对象/// </summary>/// <param name="confStr">配置UI/login/ashx/AshDemo</param>/// <param name="writer">输出</param>/// <param name="basePath">Web根</param>/// <param name="isBuild">是否是编译</param>/// <returns></returns>public static Object GetObjectByConfString(String confStr,PrintWriter writer,String basePath,String javaBllClsPath) {try {//根if(basePath==""){basePath=WebBasePath;}System.out.println("confStr:"+confStr);//不包含类型或者要强行编译就进行编译if (!hsType.containsKey(confStr)||javaBllClsPath!="") {String [] nameArr=confStr.split("/");String classFullName = "";//类代码全路径String classCodePath = basePath;for (int i = 0; i < nameArr.length; i++){//类代码文件全名classCodePath = Paths.get(classCodePath, nameArr[i]).toString();//类带命名空间的全名if(classFullName!=""){classFullName += "." + nameArr[i];}else{classFullName = nameArr[i];}}//类代码地址,后面实现用脚本编译用classCodePath = classCodePath + ".java";if(javaBllClsPath!=""){classCodePath=javaBllClsPath;}String standardPath=Paths.get(basePath,"Conf","StandAshxProj.iml").toString();//编译返回String buildRet=appcode.AutoBuild.Build(basePath,classCodePath,classFullName,standardPath);System.out.println("buildRet:"+buildRet);//编译的jar名字String clsJarPath = Paths.get(basePath, "BinAshx", classFullName + ".jar").toString();System.out.println("加载jar包:"+clsJarPath);//自己生成jar包路径URL url = new File(clsJarPath).toURI().toURL();URL[] urls = new URL[]{url};//加载程序集,这里很重要,一定要指定父加载器,否则加载的类和父加载器的类不认为是一个类URLClassLoader loader = new URLClassLoader(urls, MainMiddleware.class.getClassLoader());//加载类Class c = loader.loadClass(classFullName);//先写死,后面执行编译和从jar包反射hsType.put(confStr, c);}Class c = hsType.get(confStr);//创建对象Object o = c.newInstance();return o;}catch (Exception ex) {ex.printStackTrace();}return null;}//get直接走post的逻辑@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request,response);}///输出数据到前台private static void Write(PrintWriter writer,String str){writer.println(str);writer.flush();writer.close();}}

在这里插入图片描述

自动编译的临时目录结构
在这里插入图片描述

自动生成的jar包
在这里插入图片描述

在这里插入图片描述

在idea里面改业务脚本代码后用浏览器访问就能立即生效,简单高效,适用于服务型系统。整个涉及到目录文件监控、驱动javac和jar打包、反射重复加载类、文件读写等。

相关文章:

jbase实现业务脚本化

经过晚上和早上的努力&#xff0c;终于补上框架最后一块了&#xff0c;业务脚本侦听变化后自动编译jar包和调用&#xff0c;实现维护成本低&#xff0c;开发效率高的框架的基本体系。 实现自动编译jar包的类 package appcode;import org.w3c.dom.Document; import org.w3c.do…...

【安全】Java幂等性校验解决重复点击(6种实现方式)

目录 一、简介1.1 什么是幂等&#xff1f;1.2 为什么需要幂等性&#xff1f;1.3 接口超时&#xff0c;应该如何处理&#xff1f;1.4 幂等性对系统的影响 二、Restful API 接口的幂等性三、实现方式3.1 数据库层面&#xff0c;主键/唯一索引冲突3.2 数据库层面&#xff0c;乐观锁…...

基于设深度学习的人脸性别年龄识别系统 计算机竞赛

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习机器视觉的…...

0001Java安卓程序设计-基于Android多餐厅点餐桌号后厨前台服务设计与开发

文章目录 **摘** **要****目** **录**系统设计开发环境 编程技术交流、源码分享、模板分享、网课教程 &#x1f427;裙&#xff1a;776871563 摘 要 移动互联网时代的到来&#xff0c;给人们的生活带来了许多便捷和乐趣。随着用户的不断增多&#xff0c;其规模越来越大&#…...

Node.js 中解析 HTML 的方法介绍

在 Web 开发中&#xff0c;解析 HTML 是一个常见的任务&#xff0c;特别是当我们需要从网页中提取数据或操作 DOM 时。掌握 Node.js 中解析 HTML 的各种方式&#xff0c;可以大大提高我们提取和处理网页数据的效率。本文将介绍如何在 Node.js 中解析 HTML。 基本概念 HTML 解析…...

软件开发项目文档系列之十如何撰写测试用例

目录 1 概述1.1 编写目的1.2 定义1.3 使用范围1.4 参考资料1.5 术语定义 2 测试用例2.1 功能测试2.1.1 用户登录功能2.1.2 商品搜索功能 2.2 性能测试2.2.1 网站响应时间2.2.2 并发用户测试 附件&#xff1a; 测试用例撰写的要素和注意事项附件1 测试用例要素附件2 测试用例的注…...

AI:53-基于机器学习的字母识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…...

实习记录--(海量数据如何判重?)--每天都要保持学习状态和专注的状态啊!!!---你的未来值得你去奋斗

海量数据如何判重&#xff1f; 判断一个值是否存在&#xff1f;解决方法&#xff1a; 1.使用哈希表&#xff1a; 可以将数据进行哈希操作&#xff0c;将数据存储在相应的桶中。 查询时&#xff0c;根据哈希值定位到对应的桶&#xff0c;然后在桶内进行查找。这种方法的时间复…...

【MATLAB源码-第67期】基于麻雀搜索算法(SSA)的无人机三维地图路径规划,输出最短路径和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 ​麻雀搜索算法&#xff08;Sparrow Search Algorithm, SSA&#xff09;是一种新颖的元启发式优化算法&#xff0c;它受到麻雀社会行为的启发。这种算法通过模拟麻雀的食物搜索行为和逃避天敌的策略来解决优化问题。SSA通过模…...

Promise的并发控制 - 从普通并发池到动态并发池

一、场景 给你一个有200个URL的数组&#xff0c;通过这些URL来发送请求&#xff0c;要求并发请求数不能超过五个。 这是一道很常考的面试题&#xff0c;接下来让我们来学习一下Promise并发控制 二、普通并发池的实现 主要思路就是&#xff0c;判断当前队列是否满&#xff0c;…...

Java类加载机制(类加载器,双亲委派模型,热部署示例)

Java类加载机制 类加载器类加载器的执行流程类加载器的种类加载器之间的关系ClassLoader 的主要方法Class.forName()与ClassLoader.loadClass()区别 双亲委派模型双亲委派 类加载流程优缺点 热部署简单示例 类加载器 类加载器的执行流程 类加载器的种类 AppClassLoader 应用类…...

【C语言初学者周冲刺计划】3.2将一个数组中的值逆序重新存放

目录 1解题思路&#xff1a; 2代码 3运行代码如图&#xff1a; 4总结&#xff1a; 1解题思路&#xff1a; 首先学会如何利用循环输入位数和输入数值&#xff0c;然后再利用循环逆序即可 2代码 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { int…...

【C++心愿便利店】No.11---C++之string语法指南

文章目录 前言一、 为什么学习string类二、标准库中的string类 前言 &#x1f467;个人主页&#xff1a;小沈YO. &#x1f61a;小编介绍&#xff1a;欢迎来到我的乱七八糟小星球&#x1f31d; &#x1f4cb;专栏&#xff1a;C 心愿便利店 &#x1f511;本章内容&#xff1a;str…...

OpenCV检测圆(Python版本)

文章目录 示例代码示例结果调参 示例代码 import cv2 import numpy as np# 加载图像 image_path DistanceComparison/test_image/1.png image cv2.imread(image_path, cv2.IMREAD_COLOR)# 将图像转换为灰度 gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 使用高斯模糊消除…...

轻量封装WebGPU渲染系统示例<15>- DrawInstance批量绘制(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/DrawInstanceTest.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔离。…...

E: 仓库 “http://cn.archive.ubuntu.com/ubuntu kinetic Release” 没有 Release 文件。

sudo apt-get update时报以下错误&#xff1a; E: 仓库 “http://cn.archive.ubuntu.com/ubuntu kinetic Release” 没有 Release 文件。 N: 无法安全地用该源进行更新&#xff0c;所以默认禁用该源。 N: 参见 apt-secure(8) 手册以了解仓库创建和用户配置方面的细节。 E: 仓库…...

【VR开发】【Unity】【VRTK】3-VR项目设置

任何VR避不开的步骤 如何设置VR项目,无论是PC VR还是安卓VR,我在不同的系列教程中都说过了,不过作为任何一个VR开发教程都难以避免的一环,本篇作为VRTK的开发教程还是对VR项目设置交代一下。 准备好你的硬件 头盔必须是6DoF的,推荐Oculus Quest系列,Rift系列,HTC和Pi…...

git log 用法

git log --format"%s" -n 1在 Git 中&#xff0c;您可以使用 git log 命令来查看提交历史&#xff0c;其中包含每个提交的详细信息&#xff0c;包括提交消息。如果您只想提取提交信息而不是完整的 git log 输出&#xff0c;可以使用 git log 命令的 --format 选项来指…...

Linux学习---有关监控系统zabbix的感悟

监控系统 监控系统就像咱们日常生活中小区监控(Monitor)&#xff0c;用于及时发现问题(PROBLEM)&#xff0c;根据相应的规则可以触发警告(Media)&#xff0c;在后台显示屏(Dashboard)上以某种方面显示出来,高级的报警系统也许还能实现电话通知等功能&#xff0c;目的是为及时发…...

apollo云实验:定速巡航场景仿真调试

定速巡航场景仿真调试 概述启动仿真环境仿真系统修改默认巡航速度 实验目的福利活动 主页传送门&#xff1a;&#x1f4c0; 传送 概述 自动驾驶汽车在实现落地应用前&#xff0c;需要经历大量的道路测试来验证算法的可行性和系统的稳定性&#xff0c;但道路测试存在成本高昂、…...

基于RK3568的新能源储能能量管理系统ems

新能源储能能量管理系统&#xff08;EMS&#xff09;是一种基于现代化技术的系统&#xff0c;旨在管理并优化新能源储能设备的能量使用。 该系统通过监测、调度和控制新能源储能设备来确保能源的高效利用和可持续发展。 本文将从不同的角度介绍新能源储能能量管理系统的原理、…...

dockerfile避坑笔记(VMWare下使用Ubuntu在Ubuntu20.04基础镜像下docker打包多个go项目)

一、docker简介 docker是一种方便跨平台迁移应用的程序&#xff0c;通过docker可以实现在同一类操作系统中&#xff0c;如Ubuntu和RedHat两个linux操作系统中&#xff0c;实现程序的跨平台部署。比如我在Ubuntu中打包了一个go项目的docker镜像&#xff08;镜像为二进制文件&am…...

Qt 使用QtXlsx操作Excel表

1.环境搭建 QtXlsx是一个用于读写Microsoft Excel文件&#xff08;.xlsx&#xff09;的Qt库。它提供了一组简单易用的API&#xff0c;可以方便地处理电子表格数据。 Github下载&#xff1a;GitHub - dbzhang800/QtXlsxWriter: .xlsx file reader and writer for Qt5 官方文档…...

canal+es+kibana+springboot

1、环境准备 服务器&#xff1a;Centos7 Jdk版本&#xff1a;1.8 Mysql版本&#xff1a;5.7.44 Canal版本&#xff1a;1.17 Es版本&#xff1a;7.12.1 kibana版本&#xff1a;7.12.1 软件包下载地址&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1jRpCJP0-hr9aI…...

【力扣】面试经典150题——双指针

文章目录 125. 验证回文串392. 判断子序列167. 两数之和 II - 输入有序数组11. 盛最多水的容器15. 三数之和 125. 验证回文串 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字…...

6-8 最宽层次结点数 分数 10

文章目录 1.题目描述2.本题ac答案2.1法一: 代码复用2.2法二: 顺序队列实现层序遍历 3.C层序遍历求最大宽度3.1层序遍历代码3.2求最大宽度 1.题目描述 2.本题ac答案 2.1法一: 代码复用 //二叉树第i层结点个数 int LevelNodeCount(BiTree T, int i) {if (T NULL || i < 1)re…...

Linux学习第28天:Platform设备驱动开发(二): 专注与分散

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、硬件原理图分析 四、驱动开发 1、platform设备与驱动程序开发 53 /* 54 * 设备资源信息&#xff0c;也就是 LED0 所使用的所有寄存器 55 */ 56 static str…...

postgresql数组重叠(有共同元素)查询

直接上最终代码&#xff1a; select distinct id from a where string_to_array(in_area,,) && (select ARRAY_AGG( code) from areas where code like 11% or code 100000)::TEXT[] pg语法&#xff1a; 表 9.48显示了可用于数组类型的运算符。 表 9.48。数组运算符…...

ubuntu系统 生成RSA密钥对

在Ubuntu系统上生成密钥对通常指的是生成SSH密钥对&#xff0c;它常用于安全的远程登录、数据通信和其他安全网络操作。以下是如何在Ubuntu系统上生成SSH密钥对的步骤&#xff1a; 打开终端&#xff1a;你可以使用快捷键 Ctrl Alt T 在Ubuntu上打开一个终端窗口。 运行ssh-k…...

【RtpSeqNumOnlyRefFinder】webrtc m98: ManageFrameInternal 的帧决策过程分析

Jitterbuffer(FrameBuffer)需要组帧以后GOP内的参考关系 JeffreyLau 大神分析 了组帧原理而参考关系(RtpFrameReferenceFinder)的生成伴随了帧决策 FrameDecisionFrameDecision 影响力 帧的缓存。调用 OnAssembledFrame 传递已经拿到的RtpFrameObject 那么,RtpFrameObject…...