Java小型操作系统模拟(采用策略模式结合反射进行搭建,支持一些简单的命令)
Java小型操作系统模拟
- 项目说明
- 第一阶段:反射结合策略模式搭建基本的命令结构
- 第二阶段:注解结合反射与策略模式,将结构进一步规范
- 第三阶段:开启新的窗口,将控制台输入切换到新窗口中,同时创建右键菜单,使效果贴近命令行
- 第四阶段,发现IDEA的编译与命令行编译不一致且导致类装载出错的情况进行处理--重新编写初始化的装载方法
- 第五阶段,解决打包为jar后的装载问题及采用脚本自动编译
- 项目下载
项目说明
主要是为了学习Java反射的知识,以及对操作系统的一些概念进行回顾,搭建了一个小型的操作系统,包括基本的一些命令,如:clear、help、cd、mkdir、ls等;同时支持用户及角色创建,密码登录等,相关文件采用加密存储在本地;同时采用资源分配的形式设计了磁盘资源和内存资源,采用首次适应、循环首次适应、最佳适应、最坏适应等策略;采用Java的Socket通信设计了简单的socket通信模式
第一阶段:反射结合策略模式搭建基本的命令结构
采用配置文件的形式指定命令的名称、描述与对应类的全路径,采用反射的形式创建对象并装载到容器中;策略模式结合HashMap的形式,可以较为方便的获取到命令对象,并执行对应的策略方法。
策略模式的体现,采用Map进行命令策略的管理
package os.strategy;import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;/*** @author bbyh* @date 2023-07-27 21:19* @description*/
public abstract class BaseStrategy {private static final Map<String, BaseStrategy> STRATEGY_FACTORY = new HashMap<>(4);private static final Map<String, String> STRATEGY_DOC = new HashMap<>(4);private final String name;private final String doc;public BaseStrategy(String name, String doc) {this.name = name;this.doc = doc;}protected final void register() {STRATEGY_FACTORY.put(name, this);STRATEGY_DOC.put(name, doc);}public abstract void execute();public static BaseStrategy getStrategy(String name) {if (!STRATEGY_FACTORY.containsKey(name)) {throw new UnsupportedOperationException("该策略还不支持");}return STRATEGY_FACTORY.get(name);}public static Set<String> getCommandNameSet() {return new HashSet<>(STRATEGY_FACTORY.keySet());}public static Map<String, String> getCommandDoc() {return new HashMap<>(STRATEGY_DOC);}
}
采用配置文件结合反射装载对象;分为只装载指定目录,或装载指定目录及其子目录,要求都是基础策略类的子类
package os.util;import os.strategy.BaseStrategy;import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Properties;/*** @author bbyh* @date 2023/7/28 12:19*/
public class OsApplication {private static final String PACKAGE_PREFIX = "src/";private static final String DEFAULT_STRATEGY_PACKAGE = "strategy.impl";private static final String OS_COMMAND_PROPERTIES = "os-command-config.properties";private static final HashSet<Class<?>> CLASS_SET = new HashSet<>(4);private static void load() {for (Class<?> instance : CLASS_SET) {if (instance.getSuperclass() == BaseStrategy.class) {try (InputStream inputStream = Files.newInputStream(Paths.get(OS_COMMAND_PROPERTIES))) {Properties properties = new Properties();properties.load(inputStream);if (properties.containsKey(instance.getName())) {String[] split = properties.getProperty(instance.getName()).split(",");try {Constructor<?> constructor = instance.getConstructor(String.class, String.class);Object newInstance = constructor.newInstance(split[0], split[1]);Method register = newInstance.getClass().getSuperclass().getDeclaredMethod("register");register.setAccessible(true);register.invoke(newInstance);} catch (NoSuchMethodException | InvocationTargetException |IllegalAccessException | InstantiationException e) {throw new RuntimeException(e);}}} catch (IOException e) {throw new RuntimeException(e);}}}}public static void runWithSpecifiedDirectory(Class<?> application) {initSpecifiedDirectory(application.getPackage().getName() + "." + DEFAULT_STRATEGY_PACKAGE);load();}private static void initSpecifiedDirectory(String scanPackage) {File basePackage = new File(PACKAGE_PREFIX + scanPackage.replace(".", "/"));File[] files = basePackage.listFiles(file -> file.getName().endsWith(".java"));loadClasses(scanPackage, files);}private static void loadClasses(String scanPackage, File[] files) {if (files != null) {for (File file : files) {try {Class<?> instance = Class.forName(scanPackage + "." + file.getName().replace(".java", ""));CLASS_SET.add(instance);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}}}public static void runWithRecursiveDirectory(Class<?> application) {initRecursiveDirectory(application.getPackage().getName());load();}private static void initRecursiveDirectory(String scanPackage) {File basePackage = new File(PACKAGE_PREFIX + scanPackage.replace(".", "/"));File[] files = basePackage.listFiles(file -> {if (file.isDirectory()) {initRecursiveDirectory(scanPackage + "." + file.getName());}return file.getName().endsWith(".java");});loadClasses(scanPackage, files);}
}
配置文件
os.strategy.impl.ClearStrategy=clear,清屏命令,清空屏幕
os.strategy.impl.HelpStrategy=help,帮助命令,查看当前系统支持的命令
项目结构
第二阶段:注解结合反射与策略模式,将结构进一步规范
采用类似SpringBoot的启动方式,自动装载指定目录下的命令类,采用注解的形式设置命令的名称与描述
采用注解设置启动装载包目录名,以及各个策略类的目录名称与相关说明
package os.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author bbyh* @date 2023/7/2 15:29*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyScan {String value() default "strategy.impl";
}
help命令,简单输出系统支持的命令和说明
package os.strategy.impl;import os.annotation.StrategyAnnotation;
import os.annotation.StrategyDocAnnotation;
import os.strategy.BaseStrategy;import java.util.Map;
import java.util.Set;/*** @author bbyh* @date 2023-07-27 21:26* @description*/
@StrategyAnnotation(commandName = "help")
@StrategyDocAnnotation(commandDoc = "帮助命令,查看当前系统支持的命令")
public class HelpStrategy extends BaseStrategy {public HelpStrategy(String name, String doc) {super(name, doc);}@Overridepublic void execute() {System.out.println("系统支持的命令");Set<String> commandNameSet = BaseStrategy.getCommandNameSet();Map<String, String> commandDoc = BaseStrategy.getCommandDoc();for (String commandName : commandNameSet) {System.out.println(commandName + ":" + commandDoc.get(commandName));}}
}
同样加载指定目录下携带注解的策略子类,或者加载目录及其子目录的所有符合条件的类
package os.util;import os.annotation.StrategyAnnotation;
import os.annotation.StrategyDocAnnotation;
import os.annotation.StrategyScan;
import os.strategy.BaseStrategy;import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;/*** @author bbyh* @date 2023/7/28 12:19*/
public class OsApplication {private static final String PACKAGE_PREFIX = "src/";private static final HashSet<Class<?>> CLASS_SET = new HashSet<>(4);private static void load() {for (Class<?> instance : CLASS_SET) {if (instance.getSuperclass() == BaseStrategy.class) {try {StrategyAnnotation nameAnnotation = instance.getAnnotation(StrategyAnnotation.class);StrategyDocAnnotation docAnnotation = instance.getAnnotation(StrategyDocAnnotation.class);if (nameAnnotation != null && docAnnotation != null) {Constructor<?> constructor = instance.getConstructor(String.class, String.class);Object newInstance = constructor.newInstance(nameAnnotation.commandName(), docAnnotation.commandDoc());Method register = newInstance.getClass().getSuperclass().getDeclaredMethod("register");register.setAccessible(true);register.invoke(newInstance);}} catch (NoSuchMethodException | InvocationTargetException |IllegalAccessException | InstantiationException e) {throw new RuntimeException(e);}}}}/*** 加载配置目录下的添加了StrategyAnnotation注解的类** @param application 启动类*/public static void runWithSpecifiedDirectory(Class<?> application) {StrategyScan strategyScan = application.getAnnotation(StrategyScan.class);initSpecifiedDirectory(application.getPackage().getName() + "." + strategyScan.value());load();}private static void initSpecifiedDirectory(String scanPackage) {File basePackage = new File(PACKAGE_PREFIX + scanPackage.replace(".", "/"));File[] files = basePackage.listFiles(file -> file.getName().endsWith(".java"));loadClasses(scanPackage, files);}private static void loadClasses(String scanPackage, File[] files) {if (files != null) {for (File file : files) {try {Class<?> instance = Class.forName(scanPackage + "." + file.getName().replace(".java", ""));CLASS_SET.add(instance);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}}}/*** 加载配置目录及其子目录下的添加了StrategyAnnotation注解的类** @param application 启动类*/public static void runWithRecursiveDirectory(Class<?> application) {initRecursiveDirectory(application.getPackage().getName());load();}private static void initRecursiveDirectory(String scanPackage) {File basePackage = new File(PACKAGE_PREFIX + scanPackage.replace(".", "/"));File[] files = basePackage.listFiles(file -> {if (file.isDirectory()) {initRecursiveDirectory(scanPackage + "." + file.getName());}return file.getName().endsWith(".java");});loadClasses(scanPackage, files);}
}
项目结构
第三阶段:开启新的窗口,将控制台输入切换到新窗口中,同时创建右键菜单,使效果贴近命令行
经过测试发现,上面两个系统在初始化加载类时有一些小问题,因为在实际使用时都是执行class文件,而在IDEA里面的执行是以Java文件为路径的,需要进行一些简单的小修改,当前这个阶段主要以IDEA里面的运行为主,后面再对路径和初始化逻辑进行一些调整,来保证兼容性
主窗体
package os.util;import os.strategy.BaseStrategy;import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.*;
import java.io.IOException;/*** @author bbyh* @date 2023-07-29 15:51* @description*/
public class MainFrame extends JFrame {public static final JLabel DISPLAY = new JLabel();private static final String DEFAULT_WORD_DIR = "C:\\root>";public MainFrame() {setTitle("BBYH OS System");setSize(1000, 600);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);JScrollPane scrollPane = new JScrollPane(DISPLAY);DISPLAY.setOpaque(true);DISPLAY.setBackground(Color.WHITE);setLayout(new GridLayout(1, 1));add(scrollPane);setVisible(true);Font font = new Font("Consolos", Font.PLAIN, 24);DISPLAY.setFont(font);DISPLAY.setVerticalAlignment(SwingConstants.TOP);DISPLAY.setFocusable(true);init();// 右键菜单JPopupMenu rightMenu = new JPopupMenu();JMenuItem backgroundItem = new JMenuItem();JMenuItem fontItem = new JMenuItem();JMenuItem copyItem = new JMenuItem();backgroundItem.setFont(font);fontItem.setFont(font);copyItem.setFont(font);backgroundItem.setText("设置背景颜色");fontItem.setText("设置字体颜色");copyItem.setText("复制剪切版内容");rightMenu.add(backgroundItem);rightMenu.add(fontItem);rightMenu.add(copyItem);backgroundItem.addActionListener(evt -> {Color color = JColorChooser.showDialog(null, "设置背景颜色", Color.WHITE);if (color != null) {DISPLAY.setBackground(color);}});fontItem.addActionListener(evt -> {Color color = JColorChooser.showDialog(null, "设置字体颜色", Color.BLACK);if (color != null) {DISPLAY.setForeground(color);}});copyItem.addActionListener(evt -> {Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();Transferable transferable = clipboard.getContents(null);if (transferable != null) {if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {try {String data = (String) clipboard.getData(DataFlavor.stringFlavor);appendDisplay(data);} catch (UnsupportedFlavorException | IOException e) {throw new RuntimeException(e);}}}});DISPLAY.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {char keyChar = e.getKeyChar();if (keyChar == KeyEvent.VK_BACK_SPACE && !"".equals(getContent())) {DISPLAY.setText(getContent().substring(0, getContent().length() - 1));appendDisplay("");} else if (keyChar == KeyEvent.VK_ENTER) {appendDisplay("<br />");try {BaseStrategy.getStrategy(Context.getNextCommand()).execute();} catch (Exception ex) {appendDisplay(ex.getMessage() + "<br />");}appendDisplay(Context.getWorkDir());} else if (Character.isLetterOrDigit(keyChar)) {appendDisplay(String.valueOf(keyChar));}}});DISPLAY.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if (e.getButton() == MouseEvent.BUTTON3) {rightMenu.show(DISPLAY, e.getX(), e.getY() - 10);}}});}private static void init() {Context.setWorkDir(DEFAULT_WORD_DIR);appendDisplay(DEFAULT_WORD_DIR);}public static void appendDisplay(String content) {DISPLAY.setText("<html><body style='padding: 20px 10px'>" + getContent() + content + "</body></html>");}private static String getContent() {return DISPLAY.getText().replace("<html><body style='padding: 20px 10px'>", "").replace("</body></html>", "");}
}
Context上下文操作类
package os.util;/*** @author bbyh* @date 2023-07-27 22:23* @description*/
public class Context {private static String workDir;public static String getWorkDir() {return workDir;}public static void setWorkDir(String workDir) {Context.workDir = workDir;}public static String getNextCommand() {String text = MainFrame.DISPLAY.getText();return text.substring(text.lastIndexOf(getWorkDir()) + getWorkDir().length(), text.lastIndexOf("<br /></body></html>"));}
}
主程序
package os;import os.annotation.StrategyScan;
import os.util.MainFrame;
import os.util.OsApplication;/*** @author bbyh* @date 2023-07-27 21:18* @description*/
@StrategyScan
public class Main {public static void main(String[] args) {OsApplication.runWithRecursiveDirectory(Main.class);new MainFrame();}
}
测试运行效果展示
第四阶段,发现IDEA的编译与命令行编译不一致且导致类装载出错的情况进行处理–重新编写初始化的装载方法
采用getResource方法获取类路径,来装在class文件,同时采用脚本来解决javac命令行执行时无法编译不被别的文件依赖的策略实现类
重新编写的装载方法,采用递归装载,装载启动类目录下及其子目录中带有注解的策略实现类
package os.util;import os.annotation.StrategyAnnotation;
import os.annotation.StrategyDocAnnotation;
import os.strategy.BaseStrategy;import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Objects;/*** @author bbyh* @date 2023/7/28 12:19*/
public class OsApplication {private static final HashSet<Class<?>> CLASS_SET = new HashSet<>(4);private static String BASE_PATH;/*** 加载配置目录及其子目录下的添加了StrategyAnnotation注解的类** @param application 启动类*/public static void runWithRecursiveDirectory(Class<?> application) {BASE_PATH = Objects.requireNonNull(application.getResource("/")).getPath();initRecursiveDirectory(application.getPackage().getName());load();}private static void initRecursiveDirectory(String packageName) {File[] files = new File(BASE_PATH + packageName.replace(".", System.getProperty("file.separator"))).listFiles(file -> {if (file.isDirectory()) {initRecursiveDirectory(packageName + "." + file.getName());}return file.getName().endsWith(".class");});loadClasses(packageName, files);}private static void load() {for (Class<?> instance : CLASS_SET) {if (instance.getSuperclass() == BaseStrategy.class) {try {StrategyAnnotation nameAnnotation = instance.getAnnotation(StrategyAnnotation.class);StrategyDocAnnotation docAnnotation = instance.getAnnotation(StrategyDocAnnotation.class);if (nameAnnotation != null && docAnnotation != null) {Constructor<?> constructor = instance.getConstructor(String.class, String.class);Object newInstance = constructor.newInstance(nameAnnotation.commandName(), docAnnotation.commandDoc());Method register = newInstance.getClass().getSuperclass().getDeclaredMethod("register");register.setAccessible(true);register.invoke(newInstance);}} catch (NoSuchMethodException | InvocationTargetException |IllegalAccessException | InstantiationException e) {throw new RuntimeException(e);}}}}private static void loadClasses(String packageName, File[] files) {if (files != null) {for (File file : files) {try {Class<?> instance = Class.forName(packageName + "." + file.getName().replace(".class", ""));CLASS_SET.add(instance);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}}}
}
需要注意的一点是,目前采用getResource方法对于打包为jar包时则会报空指针错误,后续将考虑采用新方法装载来解决该问题
第五阶段,解决打包为jar后的装载问题及采用脚本自动编译
自动编译的脚本,Windows
mkdir out
cd src
javac -d ../out os/Main.java os/strategy/impl/*.java -encoding UTF-8cd ../outjava os.Main
自动编译的脚本,Linux
#!/bin/bash
mkdir out
cd src
javac -d ../out os/Main.java os/strategy/impl/*.java -encoding UTF-8
cd ../out
java os.Main
需要注意几点小问题,脚本.sh需要在Linux下创建使用,同时需要给它赋予x执行权限(chmod +x javac_os_java.sh);然后在执行时还需要对XShell安装一下图形服务x11,参考文章:xshell-linux 启动 jmeter 报 No X11 DISPLAY variable was set, but this program performed …;不过这个Xming对中文的显示有问题,有点难办
主函数(根据启动不一样采用不一样的装载策略)
package os;import os.annotation.StrategyScan;
import os.util.MainFrame;
import os.util.OsApplication;import java.util.Objects;/*** @author bbyh* @date 2023-07-27 21:18* @description*/
@StrategyScan
public class Main {public static boolean applicationRunning = true;private static final String FILE_PROTOCOL = "file";private static final String JAR_PROTOCOL = "jar";public static void main(String[] args) {String protocol = Objects.requireNonNull(OsApplication.class.getResource("")).getProtocol();if (Objects.equals(protocol, FILE_PROTOCOL)) {OsApplication.runWithRecursiveDirectory(Main.class);} else if (Objects.equals(protocol, JAR_PROTOCOL)) {OsApplication.runWithRecursiveJar(Main.class);}new MainFrame();}
}
装载工具类
package os.util;import os.annotation.StrategyAnnotation;
import os.annotation.StrategyDocAnnotation;
import os.strategy.BaseStrategy;import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;/*** @author bbyh* @date 2023/7/28 12:19*/
public class OsApplication {private static final HashSet<Class<?>> CLASS_SET = new HashSet<>(4);private static String BASE_PATH;public static final String FILE_SEPARATOR = "/";private static final String PREFIX_FILE = "file:";private static final String PREFIX_JAR = "jar:file:";private static final String SUFFIX_CLASS = ".class";/*** 加载配置目录及其子目录下的添加了StrategyAnnotation注解的类** @param application 启动类*/public static void runWithRecursiveDirectory(Class<?> application) {BASE_PATH = Objects.requireNonNull(application.getResource("")).toString().replace(PREFIX_FILE, "");String packageName = application.getPackage().getName();BASE_PATH = BASE_PATH.substring(0, BASE_PATH.lastIndexOf("/" + packageName + "/")) + FILE_SEPARATOR;initRecursiveDirectory(packageName);load();}private static void initRecursiveDirectory(String packageName) {File[] files = new File(BASE_PATH + packageName.replace(".", FILE_SEPARATOR)).listFiles(file -> {if (file.isDirectory()) {initRecursiveDirectory(packageName + "." + file.getName());}return file.getName().endsWith(SUFFIX_CLASS);});loadFileClasses(packageName, files);}private static void loadFileClasses(String packageName, File[] files) {if (files != null) {for (File file : files) {try {Class<?> instance = Class.forName(packageName + "." + file.getName().replace(SUFFIX_CLASS, ""));CLASS_SET.add(instance);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}}}private static void load() {for (Class<?> instance : CLASS_SET) {if (instance.getSuperclass() == BaseStrategy.class) {try {StrategyAnnotation nameAnnotation = instance.getAnnotation(StrategyAnnotation.class);StrategyDocAnnotation docAnnotation = instance.getAnnotation(StrategyDocAnnotation.class);if (nameAnnotation != null && docAnnotation != null) {Constructor<?> constructor = instance.getConstructor(String.class, String.class);Object newInstance = constructor.newInstance(nameAnnotation.commandName().split(" ")[0], docAnnotation.commandDoc());Method register = newInstance.getClass().getSuperclass().getDeclaredMethod("register");register.setAccessible(true);register.invoke(newInstance);}} catch (NoSuchMethodException | InvocationTargetException |IllegalAccessException | InstantiationException e) {throw new RuntimeException(e);}}}}public static void runWithRecursiveJar(Class<?> application) {BASE_PATH = Objects.requireNonNull(application.getResource("")).toString().replace(PREFIX_JAR, "");BASE_PATH = BASE_PATH.substring(0, BASE_PATH.lastIndexOf("!/" + application.getPackage().getName() + "/")) + FILE_SEPARATOR;initRecursiveJar();load();}private static void initRecursiveJar() {try (JarFile jarFile = new JarFile(BASE_PATH)) {Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();while (jarEntryEnumeration.hasMoreElements()) {JarEntry jarEntry = jarEntryEnumeration.nextElement();if (jarEntry.getName().endsWith(SUFFIX_CLASS)) {Class<?> instance = Class.forName(jarEntry.getName().replace(SUFFIX_CLASS, "").replace("/", "."));CLASS_SET.add(instance);}}} catch (IOException | ClassNotFoundException e) {throw new RuntimeException(e);}}}
运行效果
项目下载
Gitee链接–Java模拟操作系统
相关文章:
Java小型操作系统模拟(采用策略模式结合反射进行搭建,支持一些简单的命令)
Java小型操作系统模拟 项目说明第一阶段:反射结合策略模式搭建基本的命令结构第二阶段:注解结合反射与策略模式,将结构进一步规范第三阶段:开启新的窗口,将控制台输入切换到新窗口中,同时创建右键菜单&…...
VsCode与Idea编辑器更换背景图
目录 VsCode Idea VsCode 需要安装background插件 安装完成后,打开设置,搜索background 然后就可以在json文件进行图片设置,透明度等等 Idea 打开File -> Settings 然后找到Appearance , 往下滑,找到BackGround …...
Visual Studio 快捷键
记录一下VS的快捷键,用Xcode几个星期后回到VS一下子有点乱,还好有条件反射在,过了会就都恢复了 目录 跳转快捷键查找快捷键编辑快捷键代码折叠书签操作记忆来源VS一定要装VAssistX插件,下面的快捷键部分是VX提供的。 跳转快捷键 快速打开文件 Alt + Shift + O 快速打开对…...
IT技术面试中常见的问题及解答技巧
在IT技术面试中,面试官常常会问到一些常见的问题,针对这些问题,我们可以充分准备和提前准备一些解答技巧。下面我将分享一些我个人的经验和观察,希望对大家有所帮助。 请介绍一下你的项目经验。 在回答这个问题时,我们…...
Java使用hive连接kyuubi
一、Maven依赖 <dependency><groupId>org.apache.hive</groupId><artifactId>hive-jdbc</artifactId><version>2.3.9</version> </dependency> 二、相关配置信息 驱动类:org.apache.hive.jdbc.HiveDriver连接UR…...
性能测试基础知识(三)性能指标
性能测试基础知识(三)性能指标 前言一、时间特性1、响应时间2、并发数3、吞吐量(TPS) 二、资源特性1、CPU利用率2、内存利用率3、I/O利用率4、网络带宽使用率5、网络传输速率(MB/s) 三、实例场景 前言 性能…...
【 Redis】的乱码问题
问题描述: 使用RedisTemplate存储的数据,在 redis-cli 客户端查看时,key 和 value 都会携带类似\xac\xad\这样的字符串。 原因: 由于默认使用了 jdk 的序列化方式。以下是支持的序列化方式 项目一般都会有缓存,常常…...
虚拟机安装的问题
CentOS7报错: Host SMBus Controller not enabled! 1.在上图界面中直接输入root用户的密码登录到系统 2.输入命令,lsmod | grep i2c 3.输入命令,vi /etc/modprobe.d/blacklist.conf 创建黑名单,添加以下内容: blacklist i2c_piix…...
seldom之数据驱动
seldom之数据驱动 如果自动化某个功能,测试数据不一样而操作步骤是一样的,那么就可以使用参数化来节省测试代码。 seldom是我在维护一个Web UI自动化测试框,这里跟大家分享seldom参数化的实现。 GitHub:GitHub - SeldomQA/seld…...
设计模式:生成器模式
这个模式书上讲的比较简单,但是感觉精华应该是讲到了。 引用下其它博客的总结:生成器模式的核心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用。 【设计模式】建造者模式_鼠晓的博客-CSDN博客...
Gradle同步任务一直不动问题(非网络情况)
最近更新ComposeViews的Kotlin和Compose版本,升级到Kotlin1.9和Compose1.4.3时遇见一个问题,Gradle同步时始终会卡在一个位置,同步了一晚上也没用 然后又试了两次还是不行,猜测可能是Gradle的问题,于是使用命令行进行同步,并打印debug日志 ./gradlew -debug -refresh-dependen…...
STM32使用HAL库BH1750光照度传感器
开发环境 单片机:STM32F103C8T6 光照度传感器:BH1750 IDE:KEILSTM32CUBEMX 单片机配置 1、STM32CUBEMX BH1750代码 1、头文件 /* ************************************************* BH1750光照数据计算(LUX) …...
qt代码练习
计时器练习 namespace Ui { class third; }class third : public QWidget {Q_OBJECTpublic:explicit third(QWidget *parent nullptr);~third();QLabel *labth1 new QLabel(this);QTextEdit *txtth1 new QTextEdit("闹钟",this);QLineEdit *leth1 new QLineEdit(t…...
PoseiSwap:首个基于模块化设施构建的订单簿 DEX
在前不久,PoseiSwap 曾以1000万美元的估值,获得了来自于ZebecLabs基金会的150万美元的融资。此后 PoseiSwap 又以2500万美元的估值,从GateLabs、EmurgoVentures、Republic以及CipholioVentures等行业顶级投资机构中,获得了新一轮未…...
Linux NameSpace 虚拟化 资源隔离
NameSpace NameSpace介绍 在操作系统中命名空间命名空间提供的是系统资源的隔离,其中系统资源包括了:进程、网络、文件系统等等 实际上linux系统实现命名空间主要目的之一就是为了实现轻量级虚拟化服务,也就是我们说的容器,在同…...
【Android Framework系列】第9章 AMS之Hook实现登录页跳转
1 前言 前面章节我们学习了【Android Framework系列】第5章 AMS启动流程和【Android Framework系列】第6章 AMS原理之Launcher启动流程,大概了解了AMS的原理及启动流程,这一章节我们通过反射和动态代理对不同Android版本下的AMS进行Hook,实现…...
哪些行业需要连接云专线?
在诸多行业之中,有一些行业对数据安全性要求高、业务需要实时性、业务需求复杂,往往需要建立起私密、高速、安全的传输通道,云专线是他们经常采用的方案。具体来讲,都有哪些行业需要连接云专线呢?请见下方。 1、金融行…...
【Mysql】group语句删除重复数据只保留一条
【Mysql】group语句删除重复数据只保留一条 【一】案例分析 假如在数据初始化的时候,insert脚本执行了两次,导致表里的数据都是重复的(没有设置唯一键)。这个时候再加上mybatis-plus的selectOne方法,就会出现报错。因…...
Git详解和命令大全
目录 一、Git 的基本概念二、Git 的安装和使用三、Git 的版本分支管理四、Git 的命令大全1. 常用命令2. 命令大全 五、版本分支管理的最佳实践六、Git 实践七、高级特性八、Git 的未来发展 Git 是一款开源的分布式版本控制系统,可以有效地处理从小到非常大的项目版本…...
北漂Java程序员入职五个月的收获总结
👨💻博主主页:小尘要自信 👨💻本文专栏:Java程序员的成长 👨💻上一篇文章:告别过去,拥抱未来:一个Java开发者的成长之路 👨&a…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...



