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模拟操作系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【雕爷学编程】MicroPython动手做(27)——物联网之掌控板小程序3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

Stable Diffusion AI绘画学习指南【本地环境搭建win+mac】

一、硬件配配置要求 系统&#xff1a;windows 10 / Mac os 硬盘&#xff1a;C 盘预留 15GB 以上&#xff0c;其他盘 50GB 以上,Stable Ddiffusion的很多大模型都是以 GB 起步。 显卡&#xff1a;4GB 以上&#xff0c;建议 8GB, 效率高&#xff0c;能玩大尺寸的图 CPU&…

微信小程序(van-tabs) 去除横向滚动条样式(附加源码解决方案+报错图)

问题描述 今天第一次接触vant组件库。 ant官网地址适用于Vue3 支持Vue2、Vue3、微信小程序等 我在使用van-tabs组件时遇到了一个问题&#xff0c;如下图所示&#xff1a; 从图片上可以看到有个灰色的横向滚动条&#xff0c;一开始领导给我说这个问题&#xff0c;我反反复复都…

C++ ——stack、queue容器模拟实现及deque容器底层介绍

deque文档 stack文档 deque文档 文章目录 &#x1f345;1. deque容器&#x1f352;deque底层&#x1f352;deque的优势&#x1f352;deque的劣势 &#x1fad0;2. stack模拟实现&#x1f95d;3. queue模拟实现 &#x1f345;1. deque容器 查看文档可发现&#xff0c;栈和队列都…

Netty自定义消息协议的实现逻辑处理粘包拆包、心跳机制

Netty 自定义消息协议的实现逻辑自定义编码器 心跳机制实现客户端发送心跳包 自定义消息协议的实现逻辑 消息协议&#xff1a;这一次消息需要包含两个部分&#xff0c;即消息长度和消息内容本身。 自定义消息编码器︰消息编码器将客户端发送的消息转换成遵守消息协议的消息&…

Linux第一个小程序-进度条(缓冲区概念)

1.\r和\n C语言中有很多字符 a.可显字符 b.控制字符 对于回车其实有两个动作&#xff0c;首先换行&#xff0c;在将光标指向最左侧 \r &#xff1a;回车 \n&#xff1a;换行 下面举个例子&#xff1a; 把\n去掉会怎样 什么都没输出。为什么&#xff1f; 2.缓冲区概念 观察下两个…

网工内推 | 网络安全工程师,最高15K,有高温补贴

01 超圣信华 招聘岗位&#xff1a;网络安全工程师 职责描述&#xff1a; 1. 负责网络安全产品的售前沟通交流、现状调研、方案设计、产品测试、产品选型和招投标等工作。 2. 负责网络安全集成项目的实施管理、项目交付文档编制以及项目验收等工作。 3. 负责网络安全产品的售后…

在云服务器上,clone github时报Connection timed outexit code: 128

文章目录 问题解决方案 问题 在执行pip install安装依赖时&#xff0c;需要clone github代码&#xff0c;此时报了Connection timed out&exit code: 128错误&#xff0c;原因是访问超时了&#xff0c;此时需要使用代理 fatal: unable to access https://github.com/hugg…

【MATLAB第62期】基于MATLAB的PSO-NN、BBO-NN、前馈神经网络NN回归预测对比

【MATLAB第62期】基于MATLAB的PSO-NN、BBO-NN、前馈神经网络NN回归预测对比 一、数据设置 1、7输入1输出 2、103行样本 3、80个训练样本&#xff0c;23个测试样本 二、效果展示 NN训练集数据的R2为&#xff1a;0.73013 NN测试集数据的R2为&#xff1a;0.23848 NN训练集数据的…

解决Mysql报错2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)

1.找到mysql文件夹&#xff0c;将my,ini文件放入bin文件夹 2.管理员模式打开cmd 3.输入netstat -ano查看端口占用情况&#xff0c;这里我已经开启mysql应用&#xff0c;所以会有3306&#xff0c;如果没有开启是不会有的 4.输入sc delete mysql&#xff0c;删除mysql服务 5.将…

接口自动化报告,生成本地服务并自动打开时失败

错误原因&#xff1a; 端口号被占用 首先可以在cmd中调出命令窗口然后执行命令netstat -ano就可以查看所有活动的链接&#xff0c;找到被占用的端口号 1、通过命令taskkill /f /t /im "进程名称" &#xff0c;根据进程的名称杀掉所有的进程。或者taskkill /f /t /p…

嵌入式开发的学习内容和技能包括:

. 熟悉C语言编程 掌握基础电子知识&#xff0c;如数字电路、模拟电路和单片机 .熟练掌握嵌入式操作系统的原理、内核架构和应用&#xff0c;如Linux、RTOS等 了解各种外设接口及其驱动程序开发&#xff0c;如SPI、I2C、USART等 熟悉常用的嵌入式开发工具和软件工程流程&#…

如何通过 5 步激活策略扩大用户群

假设&#xff0c;你现在是一个“深藏功与名”的增长黑客。前期你表现非常好&#xff0c;做了一些拉新实验&#xff0c;每天都有上千用户进入到产品。团队成员和家人朋友都非常开心你们的产品增长终于有了起色。 然而&#xff0c;如果你不重视拉新&#xff08;acquisition&…

ES6系列之let、const、箭头函数使用的坑

变量提升块级作用域的重要性箭头函数this的指向rest参数和arguments 1.ECMAScript与Js的关系 2.Babel转码器 Babel是一个广泛使用的ES6转码器&#xff0c;可以将ES6代码转为ES5代码&#xff0c;从而在老版本的浏览器执行。这意味着&#xff0c;你可以用ES6的方式编写程序&…

【微服务】springboot整合redis哨兵集群使用详解

目录 一、前言 二、环境准备 三、安装redis 3.1 前置准备 3.1.1 下载安装包 3.1.2 准备依赖环境 3.1.3 上传并解压包 3.2 执行安装 四、搭建redis主从集群 4.1 环境准备 4.2 搭建过程 4.2.1 创建实例文件目录 4.2.2 修改redis.conf配置文件 4.2.3 拷贝配置文件 4…

喜讯! WorkPlus入选中国信通院数字产品“2023全景图”!

“2023数字生态发展大会”暨中国信通院“铸基计划” WorkPlus喜讯 7月27日&#xff0c;中国信息通信研究院&#xff08;下称“中国信通院”&#xff09;主办的“2023数字生态发展大会”暨中国信通院“铸基计划”年中会议在京召开&#xff0c;大会全面地总结了“铸基计划”上半…

Linux系统安装部署MongoDB完整教程(图文详解)

前言&#xff1a;本期给大家分享一下目前最新Linux系统安装部署MongoDB完整教程&#xff0c;我的服务器采用的是Centos7&#xff0c;在部署之前我重装了我的服务器&#xff0c;目的是为了干净整洁的给大家演示我是如何一步步的操作的&#xff0c;整体部署还是挺简洁&#xff0c…

JavaScript 手撕大厂面试题数组扁平化以及增加版本 plus

前言 现在的前端面试手撕题是一个必要环节&#xff0c;有点时候八股回答的不错但是手撕题没写出来就会让面试官印象分大减&#xff0c;很可能就挂了… 概念 数组的扁平化其实就是将一个多层嵌套的数组转换为只有一层的数组 比如&#xff1a; [1, [2, [3, [4, 5]]]] > [1…

机器学习十大经典算法

机器学习算法是计算机科学和人工智能领域的关键组成部分&#xff0c;它们用于从数据中学习模式并作出预测或做出决策。本文将为大家介绍十大经典机器学习算法&#xff0c;其中包括了线性回归、逻辑回归、支持向量机、朴素贝叶斯、决策树等算法&#xff0c;每种算法都在特定的领…