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…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...