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…...

Android系统的进程管理(创建->优先级->回收)
一、进程的创建 1、概述 Android系统以Linux内核为基础,所以对于进程的管理自然离不开Linux本身提供的机制。例如: 通过fork来创建进行通过信号量来管理进程通过proc文件系统来查询和调整进程状态 等 对于Android来说,进程管理的主要内容…...

C#界面美化小技巧
1.窗体设置为无边框 FormBorderStyle的属性设置为none 2.窗体无边框,可以拖拽 private Point mPoint new Point(); private void Download_MouseDown(object sender, MouseEventArgs e) { mPoint.X e.X; mPoint.Y e.Y; …...

‘vite‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。
1.切换到工程目录下 2.执行npm install(最关键的一步了!!) 3. 最后直接运行:npm run dev 4.浏览器直接打开就行了!...

Linux下查阅帮助文档必学命令 man
Linux操作系统的使用中,我们经常会遇到很多问题,这个时候查询文档的能力至关重要,黄老师来推荐大家使用man,这时我们必须掌握的查阅能力: 最常用的命令: man 名称 man 数字(1~9) 名称 这里的数字分别代表:...

uniapp scroll-view显示滚动条
在style中添加样式: ::v-deep ::-webkit-scrollbar {/* 滚动条整体样式 */display: block;width: 10rpx !important;height: 10rpx !important;-webkit-appearance: auto !important;background: transparent;overflow: auto !important;}::v-deep ::-webkit-scroll…...

15、PHP神奇的数组索引替代
1、有数字索引指定的数组元素时,以数字索引的为准。 <?php $aarray(a,b,1>c,5>"d","e"); print_r($a); ?> 输出结果:b的位置直接被c替代了,e 的值为最大的整数索引1。 PHP不这么搞,怎么可能成…...

同为科技(TOWE)带热插拔功能机柜PDU插座的应用
所谓热插拔(hot-plugging或Hot Swap),即带电插拔,指的是在不关闭系统电源的情况下,将模块、板卡插入或拔出系统而不影响系统的正常工作,从而提高了系统的可靠性、快速维修性、冗余性和对灾难的及时恢复能力…...

GR5526 128BIT UUID改16BIT UUID
以下两个宏定义是我添加的。其中USING_128BIT_UUID的条件编译部分是SDK原生部分,USING_16BIT_UUID条件编译部分则是由我修改,通过这样的修改,128BIT UUID就变更为16BIT UUID了。如果你的广播、扫描响应有涉及UUID,不要忘记更改它。…...

【Android】使用 CameraX 实现基础拍照功能
目录 目录 1. 基础开发环境 2. 添加相关依赖 3. APP 布局 4. 主流程逻辑 5. 调试或安装 APK 1. 基础开发环境 JDK:JDK17 Android Studio:Android Studio Giraffe | 2022.3.1 Android SDK:Android API 34 Gradle: gradle-7.2-bin.zip Ca…...

刷题笔记 day2
力扣 1089 复写零 思路:双指针 第一步:利用指针 cur 去记录最后一位要复写的数 , 利用指针 dest 指向最后一位数所要复写的位置; 实现过程:最开始 cur 指向0,dest 指向 -1 , 当arr[cur] ! …...