Mybaiys源码赏析一:可以优化的查询方法

1.知识铺垫: 首先我们要了解Mybaits的缓存机制,一级缓存默认是SESSION级别的,所有的查询都是先查询一级缓存没有的话再去查询数据库,而且一级缓存不能关闭,二级缓存是默认不开启的,是mapper级别的,相同的namespace共用一个缓存(比较鸡肋),一般用redis去代替二级缓存。 2.问题描述及原因分析: 好了,咱们言归正传,直接上源码: 我给大家解释一下这段代码的含义就是判断resultHadnler等于null的情况下先从localCache里面根据key查询值,如果查询到了执行handleLocallyCachedOutputParameters()方法,这个方法主要是跟存储过程相关,一般用不到,重点来了!!!请看下面的图 这里往localCache里面,以key作为key存入了EXECUTION_PLACEHOLDER一个枚举值,如果两个线程同时执行这段逻辑的话,第一个线程到了doQuery()方法耗时比较久,迟迟没有执行localCache.removeObject(key);将key删除的话,那么第二个线程到达判断第一张图的判断resultHadnler等于null的情况下先从localCache里面根据key查询值,那么查询出的结果就是EXECUTION_PLACEHOLDER,此时强转为List 会报类型转换异常的错误 3.解决方案: 我在想mybaits源码作者为啥不再加一层判断,如果是从缓存取出的结果EXECUTION_PLACEHOLDER也去查询数据库,请注意:从缓存取出结果为EXECUTION_PLACEHOLDER的场景是发生在查询数据库耗时久的情况下,同一条SQL查询,如果第二个线程也去让他查,第三个也去查,那么数据库有可能在此时要是被黑客攻击利用的情况下就崩了。最好的解决方案是在从缓存取出结果为EXECUTION_PLACEHOLDER等待第一条线程取到的数据赋值给第二条线程,这里利用全局变量进行处理即可。

Maven编译时报致命错误: 在类路径或引导类路径中找不到程序包 java.lang[已解决]

项目场景: Maven项目编译报错 问题描述 Maven编译时遇到的错误,主要原因是maven在编译java类时,类文件的搜索路径有问题,错误信息如下: [INFO] 1 error [INFO] ------------------------------------------------------------- [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] athena-parent ...................................... SUCCESS [ 0.395 s] [INFO] athena-common ...................................... FAILURE [ 1.696 s] [INFO] athena-provider .................................... SKIPPED [INFO] athena-portal ...................................... SKIPPED [INFO] athena-weixin ...................................... SKIPPED [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.309 s [INFO] Finished at: 2023-06-12T10:37:25+08:00 [INFO] Final Memory: 17M/222M [INFO] ------------------------------------------------------------------------ [WARNING] The requested profile "test" could not be activated because it does not exist.

【Python】模块导入 ⑥ ( `__all__` 变量简介 | `__all__` 变量用法 | import 导入整个模块 - 执行阶段报错 | from 导入整个模块 - 编译阶段报错 )

文章目录 一、`__all__` 变量简介1、`__all__` 变量2、`__all__` 变量用法3、import 导入整个模块 - 执行阶段报错4、from 导入整个模块 - 编译阶段报错5、from 导入部分模块功能 - 编译阶段报错 二、代码示例1、代码示例 - 模块中定义 `__all__` 变量2、代码示例 - 使用 from 导入模块3、代码示例 - 使用 import 导入模块4、代码示例 - 使用 from 导入模块功能 一、__all__ 变量简介 1、__all__ 变量 Python 语言中的 __all__ 变量 是一个 列表 数据容器 , 用于控制 本应用 导入的 模块 中 可以使用 导入模块 的哪些 变量 / 函数 / 类 ; Python 模块 被 应用导入时 , 系统会检查该模块是否定义了 __all__ 变量 : 如果有 定义 __all__ 变量 , 那么导入 该 __all__ 变量 列表 元素 对应的 变量 / 函数 / 类 功能 ;如果没有 定义 __all__ 变量 , 那么导入该模块中所有功能 ; 2、__all__ 变量用法 在 模块 代码的 最上部定义 __all__ 变量 , 为其赋值一个 元素类型为 字符串类型 的 列表容器变量 ;

C++Qt 入门

目录 Qt 是什么 Qt 与 Qt Creator 的关系 暗黑主题音乐播放器界面 UI 设计。 简约的视频界面设计。 炫酷车载音乐 APP 主界面开发。 Qt/C++与 QML 如何选择 Qt 版本 Linux 下安装 Qt 配置中文输入法 Qt Creator 简单使用 第一个 Qt 程序 新建一个项目 ​编辑 项目文件介绍 项目文件*.pro 样式文件*.ui 头文件*.h 源文件*.cpp Qt 是什么 Qt 是一个跨平台的 C++ 开发库。主要用来开发图形用户界面( Graphical User Interface ,简 称 GUI )程序。 Qt 虽然经常被当做一个 GUI 库,用来开发图形界面应用程序,但这并不是 Qt 的全部; Qt 除了可以绘制漂亮的界面(包括控件、布局、交互),还包含很多其它功能,比如多线程、 访问数据库、图像处理、音频视频处理、网络通信、文件操作等,这些 Qt 都已经内置了。 Qt 还存在 Python 、 Ruby 、 Perl 等脚本语言的绑定, 也就是说可以使用脚本语言开发基 于 Qt 的程序。开源社区就是这样,好东西就会被派生扩展,到处使用,越来越壮大。 Qt 支持的操作系统有很多,例如通用操作系统 Windows 、 Linux 、 Unix ,智能手机系统 Android 、 iOS 、 WinPhone , 嵌入式系统 QNX 、 VxWorks 等等。 简单的来说, Qt 可以做很多东西,好比如 Windows 下的软件也有很多是 Qt 开发的,这里 我很喜欢它的一个特性就是跨平台使用,“跨平台”代表一份代码可以无需任何修改或者小修改 就可以在其他平台上运行。 Qt 与 Qt Creator 的关系 Qt 能做什么 Qt 能做什么?理论上来说,您能想到的 App , Qt 它都基本能做。像 WPS 这种大型的桌面 应用, Maya(3D 建模 ) ,一些游戏的内核都可以使用 Qt 来实现。甚至您能快速使用 Qt 来开发一 款像酷狗,网易云音乐这样的音乐播放器。在嵌入式里,使用 Qt 来开发界面已经是无可替代的 一种趋势。工控界面最常用,一些移动端的界面也开始使用 Qt 。像点菜机,温度采集数据显示, 汽车仪表,速度显示界面等。 Qt 能做优美的界面,所以推出了 QML (一种描述性的语言)。每 次 Qt 更新都有在 Quick ( QML 使用的模块)上优化或者添加功能,看来 Qt 打算在移动设备端 的开发市场端进军!呵呵,其实 Qt 早已经在这块发展了! 下面是本书开发的一些界面小例子,请欣赏。要想开发好的界面关键是要有想法。可以说 如果您是做界面其实大多数时间花在美化界面上,功能都是比较容易实现的。最好读者需要有 一定的美工基础,例如会基本的 PS ,在开发过程中就不用去麻烦公司的美工了,开发界面和程 序一起做。 暗黑主题音乐播放器界面 UI 设计。 简约的视频界面设计。 炫酷车载音乐 APP 主界面开发。 Qt/C++与 QML QML 是 Qt C++ 基础上拓展的。也就是说 Qt C++ 上所使用界面的类,基本都是可以拓展到 QML 上。如果不能拓展的,也可以直接 QML 与 C++ 一起使用。实际上 Qt C++ 效率更高。所 以本教程都是 Qt C++ 为基础做教程入门教程, QML 可以说是一个加分项。 Qt QML 模块提供 QML 语言开发应用程序和库提供了一个框架。 QML 本身不涉及显示部分的内容,所以 Qt Quick 模块充当了这部分的作用。至于他们三者的关系,我们就这样简单的了解一下就行了。 Qt C++ 在底层编写功能更突出,若要做好看的界面且功能强大, Qt C++ 与 QML 语言结合 是必不可少的。 QML 语言负责界面层,而底层调用 Qt C++ 。比如文件的读写、图像处理、多 线程通信等这些都是需要 C++ 来编写完成的。 在目前来说, Qt C++ 更成熟, QML 目前也比较成熟了,因为每次更新版本 QML 也有更新。 不过在低版本的 Qt (如 Qt5.

【Windows】Windows 如何查看已连接过WiFi的密码

文章目录 方式一、使用命令行查看方式二、使用PowerShell 查看方式三、使用网络适配查看 方式一、使用命令行查看 Ctrl+Shift+Esc 打开任务管理器 打开新建任务对话框 在任务管理器界面,找到第一个菜单文件(F)点击运行新任务(N)。 新建cmd任务 打开(O):cmd ▼ 以系统管理权限创建此任务。 输入下面指令查询密码 netsh wlan show profiles name=[你连接过的Wifi名称] key=clear netsh wlan show profiles name=CMCC-PS7c key=clear 方式二、使用PowerShell 查看 运行Windows PowerShell 在底部搜索框中输入:power 🔍power 选择Windows PowerShell,点击以管理员身份运行 2. 输入下面指令查询密码 netsh wlan show profiles name=[你连接过的Wifi名称] key=clear netsh wlan show profiles name=CMCC-PS7c key=clear 方式三、使用网络适配查看 打开网络和Internet设置 在下方状态栏右侧,找到wifi信号图标,点击网络和Internet设置 打开控制面板\所有控制面板项\网络连接 在状态页,点击更改适配器选项 打开当前连接Wifi的状态 选中WLAN鼠标右键,在右键菜单中选中状态(U) 查看WLAN的无线属性 在WLAN 状态界面,点击无线属性(W) 查看密码 进行如下操作,即可在 网络安全密钥(K) 选中安全页面 显示字符(H)

STM32F4_MPU6050六轴传感器详解

目录 前言 1. 姿态检测的基本概念 2. 传感器的基本概念 2.1 传感器原理 2.2 传感器参数 2.3 物理量的表示方法 3. MPU6050简介 4. 利用STM32F4读取MPU6050的姿态步骤 5. 硬件设计 6. 实验程序 6.1 ANO_Tech 匿名四轴上位机_V2.6.exe 6.2 main.c 6.3 MyMPU6050.c 6.4 MyMPU6050.h 前言 MPU6050是当下最流行的一款六轴(三轴加速度+三轴角速度(陀螺仪))传感器。该传感器广泛的用于四轴、平衡车和空中鼠标等设计,具有非常广泛的应用范围。STM32F4板载了MPU6050传感器,本节我们将使用STM32F4来驱动MPU6050读取其最原始的数据,并且利用其自带的DMP实现姿态解算,结合匿名四轴上位机软件和LCD进行显示。 1. 姿态检测的基本概念 在飞行器中,飞行姿态是非常重要的参数,以飞机自身的中心建立坐标系,当飞机绕坐标轴旋转的时候,会分别影响到偏航角、横滚角及俯仰角。 假设我们知道飞机初始时是左上角的状态,只要想办法测量出基于原始状态的三个姿态角的变化量,再进行叠加,就可以获知它的实时姿态了。 坐标系: 抽象的说,姿态是载体坐标系和地理坐标系之间的转换关系。 地球坐标系:以地球球心为原点,Z轴沿地球自转轴方向,X、Y轴在赤道平面内的坐标系。 地理坐标系:它的原点在地球表面,Z轴沿当地地理垂线的方向,也就是重力加速度的方向,XY轴沿当地经纬线的切线方向。跟我们说的东南西北是一样的。 载体坐标系:载体坐标系以运载体的质心为原点,一般根据运载体自身结构方向构成坐标系,如Z轴上由原点指向载体顶部,Y轴指向载体头部,X轴沿载体两侧方向。 其中,北轴、天轴、东轴对应的是地理坐标系。 使用陀螺仪检测角度: 陀螺仪是最直观的角度检测器,他可以检测物体绕坐标轴转动的角速度, 如同将速度对时间积分可以求出路程一样,将角速度对时间积分就可以计算出旋转的角度。 利用加速度计检测角度: 由于直接用陀螺仪测量角度在长时间测量时会产生累积误差,因而我们又引入了检测倾角的传感器。 测量倾角最常见的例子是建筑中使用的水平仪,在重力的影响下,水平仪内的气泡能大致反映水柱所在直线与重力方向的夹角关系,利用T字型水平仪,可以检测横滚角与俯仰角,但是偏航角是无法以这样的方式检测的。 在电子设备中,一般使用加速度传感器来检测倾角,他通过检测器件在各个方向的形变情况而采样得到受力数据,根据F=ma转换,传感器直接输出加速度数据,因而被称为加速度传感器。 由于地球存在重力场,所以重力在任何时刻都会作用于传感器,当传感器静止的时候(实际上加速度为0),传感器会在该方向检测出加速度g,不能认为重力方向测出的加速度为g,就表示传感器在该方向作加速度为g的运动。 磁场检测: 为了弥补加速度传感器无法检测偏航角的问题,我们再引入磁场检测传感器,它可以检测出各个方向上的磁场大小,通过检测地球磁场,它可以实现指南针的功能,所以也称为电子罗盘。由于地磁场与地理坐标系的 “南北” 轴固联,利用磁场检测传感器的指南针功能,就可以测量出偏航角了。 磁场检测器的缺陷: 与指南针的缺陷一样,使用磁场传感器会受到外部磁场干扰,如载体本身的电磁场干扰,不同地理环境的磁铁矿干扰等等。 GPS检测: 使用GPS可以直接检测出载体在地球上的坐标,假如载体在某时刻测得坐标在A,另一时刻测得坐标为B,利用两个坐标即可求出它的航向,即可以确定偏航角,且不受磁场的影响,但这种检测方式只有当载体产生大范围位移的时候才有效(GPS民用精度大概为10米级) 姿态融合: 可以发现,使用陀螺仪检测角度时,在静止状态下存在缺陷,且受时间影响,而加速度传感器检测角度时,在运动状态下存在缺陷,且不受时间影响,刚好互补。假如我们同时使用这两种传感器,并设计一个滤波算法,当物体处于静止状态时,增大加速度数据的权重,当物体处于运动状态时,增大陀螺仪数据的权重,从而获得更准确的姿态数据。 同理,检测偏航角,当载体在静止状态时,可增大磁场检测器数据的权重,当载体在运动状态时,增大陀螺仪和GPS检测数据的权重。这些采用多种传感器数据来检测姿态的处理算法被称为姿态融合。 四元数: 在姿态融合解算的时候常常使用 “四元数” 来表示姿态,它由三个实数及一个虚数组成,因而被称之为四元数。使用四元数表示姿态并不直观,但因为使用欧拉角(也就是前面说的偏航角、横滚角及俯仰角)表示姿态的时候会有 “万向节死锁” 问题,且运算比较复杂,所以一般在处理数据的时候会使用四元数,处理完毕后再把四元数转换成欧拉角。 也就是说,四元数是姿态角的另一种表达方式。 2. 传感器的基本概念 之前,我们学到的DS18B20温度传感器、DHT11温湿度传感器,以及我们本节学习的 MPU6050 六轴传感器都属于传感器中的一种。这一部分我们来总结何为传感器?

STM32MP157 AP6236 WiFi蓝牙模块

STM32MP157 AP6236 WiFi蓝牙模块 1. 介绍2. 修改设备树3. 配置Linux内核3.1 配置支持WiFi设备3.2 配置支持IEEE 802.113.3 配置支持蓝牙 4. 配置Buildroot5. 板子配置6. 验证6.1 WiFi6.2 蓝牙 移植参考开发板为100ASK_STM32MP157_V11。 1. 介绍 AP6236是采用BCM43430B0方案,2.4G单频单通道SDIO接口支持BT4.2单频蓝牙WiFi二合一模块。 2. 修改设备树 BCM43430B0 WiFi采用SDIO接口,蓝牙采用uart接口。下面我们给出必要配置,需要根据理解修改自己的设备树。SDIO接口使用的是sdmmc3, uart接口使用的是usart1 。因为i2c4的引脚和usart1 的引脚有重叠,所以我们先将其disabled以免影响。使能sdmmc3后mmc设备号发生了改变,sdmmc3对应0,sdmmc2(SD卡)对应1,sdmmc1(EMMC)对应2,所以后面需要修改Linux启动参数。 #include <dt-bindings/rtc/rtc-stm32.h> / { aliases { serial2 = &usart1; }; vdd_wifi: regulator-vdd-wifi { pinctrl-names = "default"; pinctrl-0 = <&vdd_wifi_pins_a>; compatible = "regulator-fixed"; regulator-name = "vdd_wifi"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; startup-delay-us = <70000>; regulator-boot-on; regulator-pull-down; }; wifi_pwrseq: wifi-pwrseq { compatible = "

STM32MP157 u-boot2021.10移植

STM32MP157 u-boot2021.10移植 1. 初次编译2. 移植2.1 添加自己的板子2.2 修改设备树2.2.1 修改串口Uart2.2.2 修改时钟2.2.3 修改电源2.2.4 修改DDR2.2.5 删除LCD HDMI和音频2.2.6 修改EMMC和SD卡2.2.6 修改USB2.2.7 修改ethernet2.2.8 修改LED 3. 编译下载3.1 编译3.2 下载 4. 总结 参考母板是STM32MP157D-DK1开发板,移植开发板为100ASK_STM32MP157_V11。 STM32MP157 tf-a2.6 optee3.16 u-boot2021.10 linux5.15移植STM32MP157启动流程STM32MP157 tf-a2.6移植STM32MP157 optee3.16移植STM32MP157 u-boot2021.10移植STM32MP157 linux5.15移植STM32MP157 buildroot-2022.02.5构建根文件系统 1. 初次编译 解压源码,并打补丁。可以参考README.HOW_TO.txt文件,里面说了怎么解压和打补丁,并且还说了如何编译。 #解压源码 $ tar -xvf u-boot-stm32mp-v2021.10-stm32mp1-r1-r0.tar.xz #进入源码目录 $ cd u-boot-stm32mp-v2021.10-stm32mp1-r1/ #打补丁 $ for p in `ls -1 ../*.patch`; do patch -p1 < $p; done 执行以下命令完成编译,DEPLOYDIR=$FIP_DEPLOYDIR_ROOT/u-boot是U-Boot编译结果存放的目录,如果不设置就会在上一级产生deploy目录存放编译结果,同级目录下生成的build目录存放编译中间文件。 #设置编译器 $ source ../../../../toolchain/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi #设置FIP目录 $ export FIP_DEPLOYDIR_ROOT=$PWD/../../FIP_artifacts #编译 $ make -f $PWD/.

STM32MP157 tf-a2.6移植

STM32MP157 tf-a2.6移植 1. 初次编译2. 移植2.1 添加自己的板子2.2 修改设备树2.2.1 修改串口Uart2.2.2 修改时钟2.2.3 修改电源2.2.4 修改DDR2.2.5 修改EMMC 3. 编译下载3.1 编译3.2 下载 4. 总结 参考母板是STM32MP157D-DK1开发板,移植开发板为100ASK_STM32MP157_V11。 STM32MP157 tf-a2.6 optee3.16 u-boot2021.10 linux5.15移植STM32MP157启动流程STM32MP157 tf-a2.6移植STM32MP157 optee3.16移植STM32MP157 u-boot2021.10移植STM32MP157 linux5.15移植STM32MP157 buildroot-2022.02.5构建根文件系统 1. 初次编译 解压之前准备好的源码,并打好补丁文件。可以参考README.HOW_TO.txt文件,里面说了怎么解压和打补丁,并且还说了如何编译。 #解压源码 $ tar -xvf tf-a-stm32mp-v2.6-stm32mp1-r1-r0.tar.xz #进入源码目录 $ cd tf-a-stm32mp-v2.6-stm32mp1-r1/ #打补丁 $ for p in `ls -1 ../*.patch`; do patch -p1 < $p; done 解压好源码,我们在源码目录执行以下命令完成编译。DEPLOYDIR=$FIP_DEPLOYDIR_ROOT/arm-trusted-firmware是TF-A编译结果存放的目录,如果不设置就会在上一级产生deploy目录存放编译结果,同级目录下生成的build目录存放编译中间文件。 #设置编译器 $ source ../../../../toolchain/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi #设置FIP目录 $ export FIP_DEPLOYDIR_ROOT=$PWD/../../FIP_artifacts #编译 $ make -f $PWD/../Makefile.sdk DEPLOYDIR=$FIP_DEPLOYDIR_ROOT/arm-trusted-firmware -j12 all $ make -f $PWD/.

STM32MP157 buildroot-2022.02.5构建根文件系统

STM32MP157 buildroot-2022.02.5构建根文件系统 1. 源码获取2. 源码解压3. 配置并编译3.1 配置3.1 编译 4. 下载验证4.1 下载4.2 验证 5. 总结 移植参考开发板为100ASK_STM32MP157_V11。 STM32MP157 tf-a2.6 optee3.16 u-boot2021.10 linux5.15移植STM32MP157启动流程STM32MP157 tf-a2.6移植STM32MP157 optee3.16移植STM32MP157 u-boot2021.10移植STM32MP157 linux5.15移植STM32MP157 buildroot-2022.02.5构建根文件系统 1. 源码获取 到Buildroot官网下载最新的长期支持版本,这里下载buildroot-2022.02.5。 2. 源码解压 在sources/arm-ostl-linux-gnueabi目录下新建一个buildroot目录,将源码拷入进行解压。 $ mkdir buildroot #将源码拷入 $ cd buildroot/ $ tar -xvf buildroot-2022.02.5.tar.xz 3. 配置并编译 3.1 配置 进入源码目录,执行make menuconfig进行配置。 $ cd buildroot-2022.02.5/ $ make O="$PWD/../build" menuconfig $ cd ../build $ make menuconfig 配置Target options,如下图。 配置Toolchain,如下图。C库选择glibc,GCC版本选择11.x,选择支持C++。 配置 System configuration,如下图。设置hostname和欢迎语,使能密码但不设置(可以设置自己的密码)。 配置Filesystem images,如下图。设置ext4根文件系统,并设置根文件系统的大小。

Skywalking安装、配置及简单应用

Skywalking 概念: 1.TraceId,即一次调用的链路的标识,链路中所有的调用节点都拥有相同的TraceId 2.SpanId,即每个被调用的节点的标识,如果一个调用链路中有5个节点的处理,那么就对应5个SpanId. 一、安装Docker Desktop略,也可以在VMWare上安装CentOS虚拟机,再安装Docker。 二、安装ES: 如下,需要先建三个文件夹和一个文件,如下: 注:如果布署到阿里云上,需要在网络安全组开放,9200和9300端口 docker run -d --name skywalking_es7 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx128m" -v F:/libin/dev/ideaprojects/centry/web/skywalking/data/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v F:/libin/dev/ideaprojects/centry/web/skywalking/data/es/data:/usr/share/elasticsearch/data -v F:/libin/dev/ideaprojects/centry/web/skywalking/data/es/plugins:/usr/share/elasticsearch/plugins elasticsearch:7.6.2 三、安装Skywalking服务端 docker run -d --name skywalking_oapserver --restart always -e TZ=Asia/Shanghai -p 12800:12800 -p 11800:11800 --link skywalking_es7 -e SW_STORAGE=elasticsearch7 -e SW_STORAGE_ES_CLUSTER_NODES=skywalking_es7:9200 apache/skywalking-oap-server:8.5.0-es7 --link表示连接skywalking_es7,可以互相访问,但是是单向的 四、安装Skywaling-UI docker run -d --name skywalking_ui --restart=always -e TZ=Asia/Shanghai -p 8080:8080 --link skywalking_oapserver -e SW_OAP_ADDRESS=skywalking_oapserver:12800 apache/skywalking-ui:8.5.0 五、探针(agent)在idea中的使用

线程池的使用

目录 一、线程池 1.1、线程池是什么? 1.2、为什么要使用线程池? 二、了解多线程场景 三、标准库中的线程池 3.1、系统自带的线程池种类 3.2、演示系统自带的线程池 四、自定义实现线程池 五、线程池的七个参数 5.1、线程池的工作流程 5.2、拒绝策略 5.3、演示拒绝策略 六、线程的优点总结 一、线程池 1.1、线程池是什么? 字面意思就是,一次创建多个线程,放在一个池子里(集合类),用的时候拿出来一个,用完了就放回池子里就可以了。 1.2、为什么要使用线程池? 首先使用多线程编程就是为了提高效率,那么就需要创建很多线程。创建的过程是JVM通过系统API调用来申请系统线程的过程,虽然创建线程的开销比创建进程的开销小的多,但是也顶不住频繁的创建和销毁。 池化技术可以减少线程频繁的创建和销毁,从而提高程序的性能。 二、了解多线程场景 1、用一个集合去组织任务 2、一次性创建多个线程,不停的扫描任务集合 3、如果集合中有任务,那么就执行任务 4、如果集合中没有任务那就等待 三、标准库中的线程池 *使用Executors.newFixedThreadPool(3)能创建出固定包含三个线程的线程池. *返回值类型为ExecutorService. *通过ExecutorService.submit可以注册一个任务到线程池中. ExecutorService pool = Executors.newFixedThreadPool(3); pool.submit(new Runnable() { @Override public void run() { System.out.println("hello"); } }); 3.1、系统自带的线程池种类 //1、用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存 ExecutorService cachedThreadPool= Executors.newCachedThreadPool(); //2、创建一个无界队列(没有大小限制)且固定大小的线程池 ExecutorService fixedThreadPool=Executors.newFixedThreadPool(3); //3、创建一个操作无界队列且只有一个工作线程的线程池 ExecutorService singleThreadExecutor=Executors.newSingleThreadExecutor(); //4、创建一个单线程执行器,可以给定时间后执行或定期执行 ScheduledExecutorService singleThreadScheduleExecutor=Executors.newSingleThreadScheduledExecutor(); //5、创建一个指定大小的线程池,可以给定时间后执行或定期执行 ScheduledExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(3); //6、创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行的处理任务,不保证处理顺序 Executors.newWorkStealingPool(); 3.2、演示系统自带的线程池 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.

linux常用命令(持续更新中)

1、查看防火墙状态 systemctl status firewalld 2、关闭开启防火墙 关闭防火墙 systemctl stop firewalld 开启防火墙 systemctl start firewalld 3、进入某个目录下面 进入根目录要加斜杠,比如进入home里面 命令:cd /home 进入其他目录直接跟上目录名称 命令:cd /home/data 退出这一目录,返回上一目录 命令:cd .. 4、查看目录下有什么文件或文件夹 1、ls ls直接把目录下有什么文件给显示出来 2、ll ll不仅会把目录下有什么文件给显示出来,还会把文件或文件夹的大小、创建用户,权限,时间等信息显示出来 5、对于文件或文件夹的操作 移动文件 mv 文件(夹)名称 + 移动后的文件(夹)路径 比如把/usr/local/server/hmkj/nonImg路径下的2021文件夹移动到/usr/local/server/hmkj这个路径下面,首先进入要移动的文件(夹)目录下,然后用命令 :mv 2021 /usr/local/server/hmkj 重命名文件或文件夹 还是使用mv命令,比如把2021这个文件夹重命名为2022,用命令:mv 2021 2022 6、文本编辑相关 两种方式 1).vi + 文本文件名称 2).vi + 文本文件名称 这两种区别主要就是vim可以对代码进行区别,用不同的颜色对代码进行高亮处理,而vi都是一种颜色;并且vim可以运行于多种系统里面;vim可以多次撤销。所以可以说vim是vi的升级版。 文件里面的编辑 1、按i键可以进入编辑模式,和windows的文本文件一样编辑,只是不能用鼠标进行控制,只能用键盘上的上下左右方向键。 2、编辑完成之后首先按键盘左上角的esc键进入命令模式 3、此时可以用‘:wq’保存退出,或者‘:q!’不保存退出 7、查看磁盘空间 我常用的就是两种 显示系统的总空间和已使用空间以及剩余空间 df -h 当前目录下各个文件或文件夹的大小 du -sh * 8、查看文件(夹)大小 第一种:ll 两个小写的L 第二种wc -c

vue+elementUi+el-upload实现上传、获取本机服务器路径、URL、document、createObjectURL、getElementsByClassName

目录 HTMLJavaScriptcreateObjectURLgetElementsByClassNameHTMLCollectionURLdocument注意 HTML <el-upload action="" :limit="1" :on-change="handleChange" :auto-upload="false" :file-list="fileList" :show-file-list="false" > <span>选择文件</span> </el-upload> JavaScript export default { data() { return { fileList: [] }; }, methods: { // 选择文件 handleChange(file, fileLists) { console.log(file); console.log(fileLists); // 本地服务器路径 console.log(URL.createObjectURL(file.raw)); // 虚拟盘符 // JavaScript无法获取本地文件路径 // JavaScript不支持对本地资源的操作 console.log(document.getElementsByClassName("el-upload__input")[0].value); }, }, }; createObjectURL MDN URL.createObjectURL()静态方法会创建一个DOMString,其中包含一个表示参数中给出的对象的URL。这个URL的生命周期和创建它的窗口中的document绑定。这个新的URL对象表示指定的File对象或Blob对象。 getElementsByClassName 菜鸟教程 getElementsByClassName()方法返回文档中所有指定类名的元素集合,作为NodeList对象。 NodeList对象代表一个有顺序的节点列表。NodeList对象 我们可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始)。 你可以使用NodeList对象的length属性来确定指定类名的元素个数,并循环各个元素来获取你需要的那个元素。 MDN 返回一个包含了所有指定类名的子元素的类数组对象。当在document对象上调用时,会搜索整个DOM文档,包含根节点。你也可以在任意元素上调用getElementsByClassName()方法,它将返回的是以当前元素为根节点,所有指定类名的子元素。 HTMLCollection 定义 HTMLCollection对象是HTML元素的类似数组的列表。 诸如getElementsByTagName之类的方法会返回HTMLCollection。 属性和方法 属性/方法描述item()返回HTMLCollection中指定索引处的元素。length返回HTMLCollection中的元素数。namedItem()返回HTMLCollection中有指定ID或名称的元素。 URL MDN URL接口用于解析,构造,规范化和编码URL。它通过提供允许您轻松阅读和修改URL组件的属性来工作。通常,通过在调用URL的构造函数时将URL指定为字符串或提供相对URL和基本URL来创建新的URL对象。然后,您可以轻松读取URL的已解析组成部分或对URL进行更改。 如果浏览器尚不支持URL()构造函数,则可以使用Window中的Window.URL (en-US)属性。确保检查您的任何目标浏览器是否要求对此添加前缀。

SourceTree推送拉取的时候一直等待,转圈,不断尝试

SourceTree推送拉取的时候一直等待,转圈 1.推送拉去一直在等待状态转圈状态 2.git地址访问触发 点击远端,访问地址后,重新回到git提交页面提交或者拉取是否正常,应该也可以正常拉取提交(具体原因不知) 需要每次失败,都要访问远端git地址。 以上不行,原因大概如下: 80%那有可能是公司的gil平台t地址有问题,git平台内网部署导致的访问缓慢,找git维护人员反馈协助处理,就说平台地址有问题提交不了不下来。或者试试其他公共git地址是否正常

element-plus使用步骤

在 vite + create-vue + vue3 + ts 项目中使用element-plus步骤 1, 下载安装element-plus cnpm i element-plus / yarn add element-plus 2, 下载elment-plus按需导入插件 cnpm i unplugin-vue-components unplugin-auto-import 3, 配置vite.config.ts import { defineConfig } from 'vite' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' export default defineConfig({ plugins: [ // ... AutoImport({ resolvers: [ElementPlusResolver()], }), Components({ resolvers: [ElementPlusResolver()], }), ], }) 4, 在页面中直接使用组件库即可 <el-button type="primary" plain>Primary</el-button> 需要注意的问题: 1, 安装环境版本要求(此处环境): node: V18.

如何以0.9分识别所有reCAPTCHA类型,包括v2、v2隐形版、v2的企业版,以及v3和v3的企业版

本文将为您提供一种解决方案,如果您正在处理许多无效令牌的情况。只需三个简单的步骤,您就可以使用CapSolver轻松通过0.9分的reCAPTCHA Enterprise v2 / v2隐形和v3 / v3企业。 第一步:获取锚点的响应,转换为base64 打开您的网络浏览器,转到包含您要解决的reCAPTCHA的网站。使用右键菜单选择"检查元素"以访问控制台窗口。然后,点击"Network"选项卡。刷新当前网页以触发reCAPTCHA的重新加载过程。如果reCAPTCHA加载正确,将会出现一个包含"/anchor"请求的网络请求。右键单击它,选择"复制"然后"响应"。访问一个base64编码的网站,比如https://www.base64encode.org/,并将复制的内容转换为base64。最后,将这个编码后的内容保存在您的代码文件中。 第二步:获取reCAPTCHA-reload的fetch值,转换为base64 此步骤与第一步相似。根据第一步,如果您要解决的网站具有reCAPTCHA v2版本,您可能需要点击reCAPTCHA按钮。对于reCAPTCHA v3,它是隐藏的,通常在网站提交令牌时激活,比如在登录提交过程中。如果reCAPTCHA正确激活,您将在网络选项卡中观察到一个包含"/reload"的请求。现在,右键单击它,选择"复制",然后选择"复制为Fetch"。将复制的内容转换为base64并存储在您的代码文件中。 请记住,锚点请求和重新加载请求应该是连续的。这意味着锚点请求应该是重新加载请求之前的最后一个请求。 在创建任务CrateTask文档时,将先前存储的base64编码的锚点和重新加载参数作为参数添加进去。这个过程通常会得到一个有效和可信任的令牌。 第三步:以下面格式返回这两个base64值 "task":{ //必填 "type":"ReCaptchaV2Task",//总是优先考虑使用您自己的代理的任务类型,应该会大大提高通过率,无代理的不适用于高安全性 //必填 "websiteURL":"https://www.google.com/recaptcha/api2/demo", //必填 "websiteKey":"6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", //粘贴您保存的锚点和重新加载的base64内容 "anchor":"base64内容", "reload":"base64内容" } 中文交流群:497493756,有关详细的任务教程,请查阅reCAPTCHA 文档 通过采用上述策略,您可以轻松解决reCAPTCHA v2 / v3企业版的挑战。

[web]前端富文本编辑器

关于富文本编辑器 在HTML中,用于输入文本的只是<input type="text"/>和<textarea>这2种标签,这些标签都只能输入纯文本,不可以对输入的内容进行编排! 在实际应用时,例如发布文章,需要对输入的内容进行编排,例如调整字号、字体、颜色,添加表格、列表等等,就出现了许多第三方的自定义控件,这些能够现实图文混排的就称之为“富文本编辑器”。 以使用wangeditor的使用步骤为例,首先,需要安装它: npm i wangeditor -S 然后,需要在main.js中添加配置: import wangEditor from 'wangeditor'; Vue.prototype.wangEditor = wangEditor; 在具体应用时,你需要在视图设计中,添加一个标签,用于注入富文本编辑器,例如: 然后,在当前视图被初始化时,加载富文本编辑并注入到以上标签中: 至此,富文本编辑器就可以显示在页面上了! 在表单中用富文本编辑器: 下面的代码: 解释: 当把富文本编辑器放在某个表单中,且需要获取此富文本编辑中输入的内容时,首先,需要将以上创建出来的编辑器对象声明为全局的,即: 初始化时,创建出来的对象赋值到此全局的变量上,然后再执行创建: 接下来,就可以可以调用富文本编辑器变量的txt属性的html()方法,以获取编辑器中的内容所对应的HTML源代码,例如: 注意:由于富文本编辑器是通过多层实现的显示效果,在界面中,如果有其它弹出层的设计,可能会出现“遮挡”的问题!例如: 通常,富文本编辑器的Z轴值应该是较低的,例如: 就可以显示正常了:

Qt实现拖拽功能(支持拖放文件、拖放操作)

目录 拖放Qt程序接受其他程序的拖拽部件/控件之间相互拖放总结 拖放 拖放是在一个应用程序内或者多个应用程序之间传递信息的一种直观的现代操作方式。除了为剪贴板提供支持外,通常它还提供数据移动和复制的功能。 拖放操作包括两个截然不同的动作:拖动和放下。Qt窗口部件可以作为拖动点(darg site)、放下点(drop site)或者同时作为拖动点和放下点。 Qt程序接受其他程序的拖拽 我们经常将文本文件推拽到notepate++等类型文本编辑器软件中。那么如何让Qt程序也能够支持这种操作呢? 我们需要在主窗口重新实现了来自父类的dragEnterEvent()和 dropEvent()函数。 protected: virtual void dragEnterEvent(QDragEnterEvent* event) override; virtual void dropEvent(QDropEvent* event) override; 在构造函数中,创建了一个QTextEdit并且把它设置为中央窗口部件。默认情况下,QTextEdit可以接受来自其他应用程序文本的拖动,并且如果用户在它上面放下一个文件,它将会把这个文件的内容填充到QTextEdit部件中。 由于拖放事件是从子窗口部件传递给父窗口部件的,所以通过禁用QTextEdit上的放下操作以及启用主窗口上的放下操作,就可以在整个MainWindow窗口中获得放下事件。 #include <QMimeData> #include <QTextStream> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); textEdit = new QTextEdit(this); setCentralWidget(textEdit); textEdit->setAcceptDrops(false); setAcceptDrops(true); setWindowTitle("Text Editor"); } 当用户把一个对象拖动到这个窗口部件上时,就会调用dragEnterEvent()。如果对这个事件调用acceptProposedAction(),就表明用户可以在这个窗口部件上拖放对象。默认情况下,窗口部件是不接受拖动的。Qt会自动改变光标来向用户说明这个窗口部件是不是有效的放下点。 这里,我们希望用户拖动的只能是文件,而非其他类型的东西。为了实现这一点,我们可以检查拖动的MIME类型。 MIME类型中的 text/uri-list 用于存储一系列的统一资源标识符(Universal Re-source Identifier ,URI),它们可以是文件名、统―资源定位器(Uniform Resource Locator , URL,如 HTTP或者FTP路径),或者其他全局资源标识符。标准的MIME类型是由国际因特网地址分配委员会(Internet Assigned Numbers Authority , IANA)定义的,它们由类型、子类型信息以及分隔两者的斜线组·成。MME类通常由剪贴板和拖放系统使用,以识别不同类型的数据。可以从下面的网站得到正式的 MIME类型列表: http://www.iana.org/assignments/media-types/ void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if(event->mimeData()->hasFormat("

wangEditor5 富文本编辑器基于 vue3、Nuxt3

这是官方dome: https://www.wangeditor.com/demo/index.html 使用这个插件会遇到的一些问题 已解决: 1.使用5.1.23的最新的话:视频尺寸编辑会有问题 2.setHtml 不可以设置值 提示不存在 上传图片 上传视频 3.刷新页面 编辑器数据不存在 这篇文章主要讲一下创建 引入 图片上传 粘贴 视频上传等 在项目中安装 yarn安装 yarn add @wangeditor/editor yarn add @wangeditor/editor-for-vue@next npm 安装 npm install @wangeditor/editor npm install @wangeditor/editor-for-vue@next 这里我是通过创建组件来使用 你们也可以直接在想要的页面直接引入就好 这个是部分代码截图: 第一步:首先创建一个组件wangeditor.vue 这里讲一下vue3和nuxt引入 我们除了引入不同 其他的都是一样的 我们在wangeditor.vue组件里面引入wangeditor vue3的引入方法: import "@wangeditor/editor/dist/css/style.css"; import { Editor, Toolbar} from '@wangeditor/editor-for-vue' Nuxt的引入方法: 因为在Nuxt中是分服务端跟客户端的所以这里我们需要判断一下 方法1: if (process.client) { const { Editor, Toolbar } = await import("@wangeditor/editor-for-vue"); } 方法2:在父组件使用 <ClientOnly> <h-wangeditor />

【Android Framework系列】第3章 Zygote进程相关

1 Zygote简介 Zygote是Android中最重要的一个进程,Zygote进程和Init进程、SystemServer进程是Android最重要的三大进程。Zygote是Android系统创建新进程的核心进程,负责启动Dalvik虚拟机,加载一些必要的系统资源和系统类,启动system_server进程,随后进入等待处理app应用请求。 在Android系统中,应用程序进程都是由Zygote进程孵化出来的,而Zygote进程是由Init进程启动的。Zygote进程在启动时会创建一个Dalvik虚拟机实例,每当它孵化一个新的应用程序进程时,都会将这个Dalvik虚拟机实例复制到新的应用程序进程里面去,从而使得每一个应用程序进程都有一个独立的Dalvik虚拟机实例。 Zygote涉及的类: frameworks/base/cmds/app_process/app_main.cpp frameworks/base/core/jni/AndroidRuntime.cpp frameworks/base/core/java/com/android/internal/os/ - Zygote.java - ZygoteInit.java - ZygoteServer.java - ZygoteConnection.java 2 Zygote启动 本文基于Android10(Q)的源码做分析 2.1 init进程解析init.rc脚本 Zygote由init进程解析init.rc脚本启动的。脚本传入app_process的main方法做分割,根据字符串命令做相应逻辑。 现在机器分为32位和64位,Zygote的启动脚本init.rc也各有区别: init.zygote32.rc:zygote进程对应的执行程序是app_process(纯32bit模式)init.zygote64.rc:zygote进程对应的执行程序是app_process64(纯64bit模式)init.zygote32_64.rc:启动两个zygote进程,对应的执行程序分别是app_process32(主模式)、app_process64init.zygote64_32.rc:启动两个zygote进程,对应的执行程序分别是app_process64(主模式)、app_process32 zygote要执行的程序便是system/bin/app_process,它的源代码在app_main.cpp。我们先来看看app_main是如何处理脚本命令: frameworks/base/cmds/app_process/app_main.cpp 165 #if defined(__LP64__) 166 static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64"; 167 static const char ZYGOTE_NICE_NAME[] = "zygote64"; 168 #else 169 static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32"; 170 static const char ZYGOTE_NICE_NAME[] = "zygote"; 171 #endif 172 173 int main(int argc, char* const argv[]) 174 { .

JAVA生成唯一订单编号方案(两种方式)

方法一:使用UUID public static String getUUID() { String replaceUUID = UUID.randomUUID().toString().replace("-", ""); return replaceUUID; } 方法二:用时间(精确到毫秒)+随机数 /** * 生成订单号(20位):时间(精确到毫秒)+3位随机数 */ public static synchronized String getOrderNum() { //时间(精确到毫秒) DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); String localDate = LocalDateTime.now().format(ofPattern); //3位随机数 String randomNumeric = RandomStringUtils.randomNumeric(3); String orderNum = localDate + randomNumeric; log.info("订单号:{}", orderNum); return orderNum; } 参考博客: ​​​​​​fhttp://t.csdn.cn/lCQ47​​​​​​​

Android Studio——记事本案例

一、布局界面 1、记事本界面布局 main_notepad.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fefefe"> <TextView android:id="@+id/note_name" android:layout_width="match_parent" android:layout_height="45dp" android:background="@android:color/darker_gray" android:text="记事本" android:gravity="center" android:textStyle="bold" android:textColor="@android:color/black" android:textSize="20sp" /> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#00000000" android:divider="#E4E4E4E4" android:dividerHeight="1dp" android:fadingEdge="horizontal" android:listSelector="#00000000" android:scrollbars="none" android:layout_below="@+id/note_name"> </ListView> <ImageView android:id="@+id/add" android:layout_width="60dp" android:layout_height="60dp" android:background="@drawable/add" android:layout_marginBottom="30dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true"/> </RelativeLayout> 2、记事本Item布局界面 activity_item.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="12dp"> <TextView android:id="@+id/ietm_content" android:textColor="@android:color/black" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="2" android:ellipsize="end" android:lineSpacingExtra="3dp" android:paddingTop="10dp"/> <TextView android:id="@+id/item_time" android:textColor="#fb7a6a" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="5dp" android:paddingBottom="7dp"/> </LinearLayout> 3、添加、修改界面布局 activity_record.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="

(小程序)基于uniapp+vite4+vue3搭建跨端项目|uni-app+uview-plus模板

(小程序)基于uniapp+vite4+vue3搭建跨端项目|uni-app+uview-plus模板 版本信息: HBuilderX: 3.8.4 Vite: 4.2.1 uView-Plus: 3.1.31 一、创建uniapp+vue3项目: 点击编辑器的文件 > 新建 > 项目(快捷键Ctrl+N) 2.选择uni-app项目,输入项目名/路径,选择项目模板,勾选vue3版本,点击创建,即可成功创建。 3.点击编辑器的运行 > 运行到浏览器 > 选择浏览器 当然也可以运行到手机或模拟器、运行到小程序工具。 到这里一个简单的uniapp+vue3项目就搭建好了。 二、引入uniapp+vue3组件库uview-plus 和 uni-ui(略) 目前支持 uniapp vue3 组件库有uni-ui(官方),uview-plus等。 1.使用hbuilderx 导入uview-plus组件库 2.引入uview-plus及样式 (3个文件) // main.js import uviewPlus from '@/uni_modules/uview-plus' import { createSSRApp } from 'vue' export function createApp() { const app = createSSRApp(App) app.use(uviewPlus) return { app } } /* uni.scss */ @import '@/uni_modules/uview-plus/theme.scss'; /* app.vue */ <style lang="scss"> /* 注意要写在第一行,同时给style标签加入lang="

gdb调试正在运行的进程

gdb [exec_file] [core_file] #or gdb -c [core_file] [exec_file] #-c指定转储的core文件 #进入后输入bt查看调用栈 bt #显示所有帧栈 bt 10 #显示前面10个帧栈(感觉没啥用) bt -10 #显示后面10个帧栈(感觉没啥用) bt full #显示帧栈以及局部变量 首先 ps -aux| grep test 查看进程ID 方式一 通过–-pid参数来绑定指定的进程程序。 ~@hqlong gdb --pid 25552 方式二 通过程序和进程号来绑定。 ~@hqlong gdb test 25552 方式三 先启动gdb后,通过attach来绑定pid ~@hqlong gdb attach 25552 将pid和gdb绑定后,就可以来对每一段代码进行调试。 常用命令: 调试命令 (缩写) 作用 (gdb) break (b) 在源代码指定的某一行设置断点,其中xxx用于指定具体打断点位置 (gdb) run (r) 执行被调试的程序,其会自动在第一个断点处暂停执行。 (gdb) continue (c) 当程序在某一断点处停止后,用该指令可以继续执行,直至遇到断点或者程序结束。 (gdb) next (n) 令程序一行代码一行代码的执行。 (gdb) step(s) 如果有调用函数,进入调用的函数内部;否则,和 next 命令的功能一样。 (gdb) until (u) (gdb) until (u) location 当你厌倦了在一个循环体内单步跟踪时,单纯使用 until 命令,可以运行程序直到退出循环体。 until n 命令中,n 为某一行代码的行号,该命令会使程序运行至第 n 行代码处停止。 (gdb) print (p) 打印指定变量的值,其中 xxx 指的就是某一变量名。 (gdb) list (l) 显示源程序代码的内容,包括各行代码所在的行号。 (gdb) finish(fi) 结束当前正在执行的函数,并在跳出函数后暂停程序的执行。 (gdb) return(return) 结束当前调用函数并返回指定值,到上一层函数调用处停止程序执行。 (gdb) jump(j) 使程序从当前要执行的代码处,直接跳转到指定位置处继续执行后续的代码。 (gdb) quit (q) 终止调试。 (gdb) Backtrace(bt) 查看堆栈。 (gdb) info threads 显示当前可调试的所有线程 (gdb) thread ID 切换当前调试的线程为指定ID的线程 (gdb) attach process-id 在gdb状态下,开始调试一个正在运行的进程 (gdb) thread apply all command 所有线程执行command ———————————————— 版权声明:本文为CSDN博主「GS_Qiang」的原创文章,遵循CC 4.

[开发工具]STM32:keil的软件逻辑分析仪(logic analyzer)使用

在keil MDK中软件逻辑分析仪很强的功能,可以分析数字信号,模拟化的信号,CPU的总线(UART、IIC等一切有输出的管脚),提供调试函数机制,用于产生自定义的信号,如Sin,三角波、澡声信号等,这些都可以定义。 下面我们模拟一下普通GPIO口输出高低电平实验,以一个LED例成来进行测试。 软件环境设置 根据图中步骤进行设置,首先点击魔术棒弹出对话框,然后选择Debug,再点击Use Simulator。 第4步设置为关键 dialog dll默认配置为DCM.DLL,而parameter默认配置为-pCM3,该种配置无法进行正常的仿真调试。导致现象为程序会一直在SystemInit死循环。 正确配置应该为 弹出对话框,点击OK,然后弹出以下对话框 在Search中输入你MCU的型号,然后在下方选中具体型号后,最下面会有相关提示,SIM中的信息就是我们要输入的信息。 正确配置应该为最下面图中框选部分 dialog dll:DARMSTM. dll parameter:-pSTM32F103C 输入完毕后,点击CLOSE,点击仿真,可以全速运行,并且可以运行到设置断点位置。 目前F103系列在线仿真没有问题,F4系列这样设置目前没实现这样的仿真功能。 逻辑分析仪设置 点击View,找到Analysis Windows,然后找到Logic Analyzer,点击。 弹出窗口选择Setup 点击方框,输入要观察的端口比如端口PORTB则需要输入GPIOB_IDR ,Display Type选择BIt Shift right表示要偏移的量,即要监测的管脚号。我们这里设置了两个管脚。 设置好之后,我们程序全速运行监测。 波形正常监测出来,高低电平进行切换,并且高电平是低电平时长1的3倍左右,示波器波形也能正常表示出来。 以上就是对logic analyzer使用的基本教程,如有错误请大家指教。 --------------------- 作者:woai32lala 链接:https://bbs.21ic.com/icview-3284680-1-1.html 来源:21ic.com 此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

如何解决远程桌面无法连接问题?

远程桌面连接是一种方便快捷的远程访问技术,但在使用过程中,可能会遇到无法连接的问题。以下是一些可能的原因和对应的解决方案: 无法连接到远程桌面 远程桌面连接不上可能是由于远程计算机或服务器的防火墙设置、网络连接或安全策略等问题引起的。可以尝试通过以下方法解决: 检查防火墙设置,确保远程桌面端口(默认为3389)已经被允许通过防火墙。检查网络连接,确保本地计算机和远程计算机或服务器之间的网络连接正常。检查安全策略,确保没有使用不当的安全策略阻止了远程桌面的连接。 连接后出现延迟或卡顿 这种情况可能是由于网络连接不稳定、远程计算机或服务器的性能问题等原因引起的。可以尝试通过以下方法解决: 检查网络连接,确保本地计算机和远程计算机或服务器之间的网络连接稳定。检查远程计算机或服务器的性能,确保其能够承担远程桌面的负载。 总之,解决远程桌面无法连接问题需要先确定具体原因,然后采取相应的解决方案。在解决过程中,可以尝试一些常用的方法,如检查防火墙设置、网络连接、安全策略等。如果问题仍然存在,可以考虑使用其他远程访问工具或联系技术支持人员进行进一步排查和解决。

如何解决C语言浮点数精度丢失的问题?

测试网站:C语言在线运行,代码编译测试 - 在线编译器(nhooo.com) 1.循环加数据,误差越来越大: float a = 99.2f; //float a = 1.3f; float b = 0; for(int i =0; i<1000; i++){ b = b + a; } for(int i =0; i<10000; i++){ b = b + a; } printf("%f\n", a); printf("---%f\n", b); 输出: 99.199997 ---99200.695312 ---991913.875000 1000次的时候还好。 10000次的时候,误差已经到了100。 解决方法:1.转化成整数再运算;在进行大量的浮点数运算时,为了提高运算的速度和准确性,可以考虑将小数转换为整数进行计算,再将结果转换回小数。 2.看看开源代码中C语言的算法是怎么算的; 3.都转成double,这样10000次计算结果是---991999.969482。尽量避免使用float类型。虽然float类型能够节省内存空间,但是其精度不够高,容易导致精度丢失。在精度要求比较高或需要进行复杂计算时,建议使用double类型。 2.比较两个数的大小,必须用一个float.h的宏定义EPS最小误差来定。大概0.000001.精确到6位。 double test=0.1; if(fabs(test-(1-0.9))<0.0001) { printf("正常"); } else { printf("what!!!"); } 3.C语言发送双精度到Java语言,需要精确到前两位发送。具体思路是转换成字符。 float ddd = (float)( (a+0.001)*100) / 100; printf("

什么是远程桌面连接?

远程桌面连接是一种便捷的技术,它允许用户通过互联网或局域网远程访问另一个计算机或服务器。这种技术在现代工作中非常流行,因为它为远程办公、远程教育和远程医疗等场景提供了便利。 远程桌面连接的原理是,用户的计算机通过互联网或局域网连接到远程计算机或服务器,远程计算机或服务器的操作系统会开启一个特定的端口,等待用户连接。用户可以使用客户端软件(如AnyViewer、向日葵等)来连接远程计算机或服务器,并像在本地操作一样使用它们。 远程桌面连接的优点包括: 方便灵活:用户可以随时随地连接远程计算机或服务器,只要有网络连接即可。安全可靠:远程桌面连接通常使用安全加密协议(如SSH、SSL等),确保数据传输和交互过程的安全性。高效协同:多个用户可以同时连接到一个远程计算机或服务器,实现高效协同工作。维护简单:远程桌面连接的配置和维护可以在远程服务器上进行,减少了本地计算机的维护工作量。 如何使用远程桌面连接? 使用Windows远程桌面连接可以让你通过互联网或局域网连接到另一台计算机,并像在本地操作一样使用它的桌面和应用程序。以下是使用Windows远程桌面连接的步骤: 确保远程计算机或服务器已经开启了远程桌面功能。可以在Windows设置中启用远程桌面,或者在服务列表中找到Remote Desktop Services并启动。在本地计算机上打开开始菜单,搜索“远程桌面连接”并打开。也可以使用快捷键Windows + R,在运行中输入“mstsc”并按下回车键。在远程桌面连接对话框中,输入远程计算机或服务器的IP地址或域名。如果在本地计算机和远程计算机之间存在防火墙或路由器,还需要确保相应的端口转发已设置。点击“连接”按钮,输入用户名和密码进行身份验证。如果远程计算机或服务器需要使用证书进行身份验证,则需要选择相应的证书并输入密码。连接成功后,远程计算机或服务器的桌面将会显示在本地计算机的屏幕上。你可以像在本地操作一样使用它们,包括打开程序、浏览文件、登录操作系统等。 需要注意的是,远程桌面连接的安全性非常重要,因此建议使用安全加密协议(如SSH)来进行连接,并定期更换密码以增加安全性。

Centos安装IotDB(集群版)

文章目录 一、前置检查二、集群配置说明1、通用配置2、ConfigNode 配置3、DataNode 配置 三、集群操作1、启动Seed-ConfigNode2、增加ConfigNode(2个)3、增加DataNode(3个)4、验证集群 集群安装版本V1.0.0,相关下载地址可查看 单机版安装 集群官网说明文档 本次集群共3台机器,ip分别为:192.168.117.128,192.168.117.132,192.168.117.131,其中192.168.117.128作为seed-confignode 一、前置检查 ①JDK>=1.8 的运行环境,并配置好 JAVA_HOME 环境变量。 ②设置最大文件打开数为 65535。 ulimit -n 65535 最大连接 sysctl -w net.core.somaxconn=65535 ③关闭交换内存。 #方法1 # 先备份 cp /etc/selinux/config /etc/selinux/config.bak # 更改setlinux级别,enforcing代表打开,disabled代表关闭 sed -i 's/SELINUX=enforcing/\SELINUX=permissive/' /etc/selinux/config # 重启机器 reboot # 方法2 vi /etc/selinux/config # 设置SELINUX值如 SELINUX=permissive # 设置iptables iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -F iptables -L -n # 重启机器 reboot # 查看selinux状态,如下图则配置成功: getenforce ④首次启动ConfigNode节点时,确保已清空ConfigNode节点的data/confignode目录;首次启动DataNode节点时,确保已清空DataNode节点的data/datanode目录。 ⑤如果整个集群处在可信环境下,可以关闭机器上的防火墙选项。

antd a-select多选加搜索框

目录 antd a-select多选加搜索框 1.实现效果 :在多选框中输入内容会匹配符合条件的列表展示在下拉框中 <a-select :value="nowProduct" placeholder="查看全部" mode="multiple" @change="onProductChange" show-search :filter-option="filterOption" option-filter-prop="children" :autoClearSearchValue="false" > <a-select-option v-for="item in productType" :key="item.product_name" :value="item.product_id"> {{ item.product_name }} </a-select-option> </a-select> filterOption(input, option) { return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 }, 2.关键配置项 show-search 使单选模式可搜索 :filter-option="filterOption" 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 false。 option-filter-prop="children" 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索 :autoClearSearchValue="false" 最重要!!!!!!是否在选中项后清空搜索框,只在 mode 为 multiple 或 tags 时有效。(否则输入关键字后只能选择一个选项就被清空)

Nginx Rewrite(重写跳转)

文章目录 一.Nginx Rewrite概述1.Rewrite跳转场景2.Rewrite跳转场景3.Rewrite跳转实现4.Rewrite实际场景4.1Nginx跳转需求的实现方式4.2 rewrite放在 server{},if{},location{} 段中4.3对域名或参数字符串 5.nginx正则表达式5.1 常用的正则表达式元字符 6.Rewrite 命令6.1 Rewrite 命令语法6.2flag标记说明6.3last和break比较 二.location1.location分类1.1精确匹配1.2一般匹配1.3正则匹配 2.正则匹配的常用的表达式3.location优先级4.location示例5.实际网站使用中,至少有三个匹配规则定义5.1第一个必选规则5.2第二个必选规则5.3第三个规则就是通用规则 三.rewrite 实例1.基于域名的跳转2.基于客户端 IP 访问跳转3.基于旧域名跳转到新域名后面加目录4.基于参数匹配的跳转5.基于目录下所有 php 结尾的文件跳转6.基于最普通一条 url 请求的跳转 总 一.Nginx Rewrite概述 1.Rewrite跳转场景 rewrite功能: 使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。 比如: 更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。 rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用, 例如http://www.kgc.com/abc/bbs/index.php?a=1&b=2 只对/abc/bbs/index.php重写。 2.Rewrite跳转场景 (1)URL看起来更规范、合理 URL: 就是一个具体路径/位置URI: 指的是一个拥有相同类型/特性的对象集合URN:用名称定位 (2)企业会将动态URL地址伪装成静态地址提供服务 (3)网址换新域名后,让旧的访问跳转到新的域名上 (4)服务端某些业务调整 3.Rewrite跳转实现 4.Rewrite实际场景 4.1Nginx跳转需求的实现方式 (1)使用rewrite进行匹配跳转(例如防盗链) (2)使用if匹配全局变量后跳转(此匹配全局变量是nginx服务本身全局变量) (3)使用location匹配再跳转(匹配的访问URL路径,location可以匹配本地重写以及跨服务器跳转) 4.2 rewrite放在 server{},if{},location{} 段中 location只对域名后边的除去传递参数外的字符串起作用 4.3对域名或参数字符串 (1)使用if全局变量匹配 (2)使用proxy_pass反向代理 5.nginx正则表达式 5.1 常用的正则表达式元字符 字符说明^^匹配输入字符串的起始位置$匹配输入字符串的结束位置*匹配前面的字符零次或多次+匹配前面的字符一次或多次?匹配前面的字符零次或一次.匹配除“\n"之外的任何单个字符\将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用\d匹配纯数字{n}重复n次{n,}重复n次或更多次[c]匹配单个字符c[z-a]匹配a-z小写字母的任意一个[z-aA-Z]匹配a-z小写字母或A-Z大写字母的任意一个()表达式的开始和结束位置|或运算符 6.Rewrite 命令 6.1 Rewrite 命令语法 rewrite [fiag]; regex:正则 replacement:跳转后的内容 fiag:rewrite支持的flag标记(进行判断)

HBuilderX集成Git教程,需要安装TortoiseGit依赖

1、HBuilder安装git插件,需要提前安装好git客户端(略过) 点击 工具=》插件安装 此时还是不能提交代码的,右键选中我们需要的项目,点击 外部命令=》Git插件=》然后随便选择一个操作 会提示需要安装TortoiseGit,然后跳转到TortoiseGit的下载页面https://tortoisegit.org/download/,选择合适自己的版本下载,笔者选的是64位的 下载完成后,安装是一直next就可! 2、在资源管理器中,自己需要上传的目录下右键,创建本地仓库 3、回到Hbuilderx 右键 -> 点击提交,将文件提交到本地仓库 4、点击推送,将本地仓库的文件上传到gitee

jasny-bootstrap组件-文件上传

今天和大家分享jasny-bootstrap如何实现文件上传,以及同form表单同时提交处理。 目前各大网站关于jasny-bootstrap上传文件的案例demo少之又少,就连若依也只是一笔带过,只是做了一个纯效果展示。 经过博主的一番查阅文档,查找案例,终于给搞出来了,在这里呢和大家分享一下。 1:首先引入jasny-bootstrap的js和css。 js和css可以从jasny文档去引用,这里就不多说。 2:jasny关于文件上传的前端代码 按照文档给的demo案例,结合自己的情况进行改造即可 3:选择文件后触发事件,可以在这里进行业务,其中e.target.files会获取到文件数组。 选择文件后,我们通过 change.bs.fileinput事件进行上传文件的业务处理。 通过e.target.files获取文件数组,这样我们就拿到文件了,若是需要单独上传,则可以在这里写业务。 但我们要做的是同form表单一同提交,所以不在这里做处理。 4:关于提交form表单如何和文件一同提交 5:后端处理 ;通过HttpServletRequest接收文件 一个完整的流程就这样出来了,注意的是,jasny组件我这里是新增和修改是用的同一个页面, 所以做了jasny的回显图片处理。 当然若是有小伙伴需要设置上传文件类型,可以添加accept属性。 比如我们只想让它上传图片类型,那么我们可以这样写: <input type="file" id="photoID" name="file1" accept="image/*"> 这样,在选择文件时就只能选择图片了。(其它类型文件自动给你隐藏了) 好了,今天的分享到此结束了。欢迎大家留言互相交流讨论。

详解 欧拉角与四元数

一、欧拉角 1.1 静态的定义 对于在三维空间里的一个参考系,任何坐标系的取向,都可以用三个欧拉角来表现。参考系又称为实验室参考系,是静止不动的。而坐标系则固定于刚体,随着刚体的旋转而旋转。 如图所示。设定xyz-轴为参考系的参考轴。称xy-平面与XY-平面的相交为交点线,用英文字母(N)代表。zxz顺规的欧拉角可以静态地这样定义: α \alpha α 是 x-轴与交点线的夹角, β \beta β 是z-轴与Z-轴的夹角, γ \gamma γ 是交点线与X-轴的夹角。 很可惜地,对于夹角的顺序和标记,夹角的两个轴的指定,并没有任何常规。科学家对此从未达成共识。每当用到欧拉角时,我们必须明确的表示出夹角的顺序,指定其参考轴。 下面我们通过图例来看看欧拉角是如何产生的,并且分别对应哪个角度。 1.2 欧拉角的表示 1.3 作用 欧拉角Eulerian angles用来确定定点转动刚体位置的3个一组独立角参量,由章动角 θ、旋进角(即进动角)ψ和自转角j组成。 欧拉角包括3个旋转,根据这3个旋转来指定一个刚体的朝向。这3个旋转分别绕x轴,y轴和z轴,分别称为 Roll(翻滚),Pitch(俯仰) 和 Yow(偏航),如下图所示。旋转的遵循右手坐标系,欧拉角可以表示成z-x-z,x-y-x,z-y-z等形式,旋转的顺序影响结果。 欧拉角很重要的一个优点就是直观,容易理解。 欧拉角的优缺点 优点: 三个角度组成,直观,容易理解。可以进行从一个方向到另一个方向旋转大于180度的角度。 缺点: 欧拉角是不可传递的,旋转的顺序影响旋转的结果,不同的应用又可能使用不同的旋转顺序,旋转顺序无法统一;3个旋转的角度可以不受限制,即可以是10000度,也可以是-1500度;可能造成万向节死锁(Gimbal Lock) 1.4 万向锁问题 对于动态欧拉角,即绕物体坐标系旋转。(静态不存在万向锁的问题)无论heading和bank为多少度,只要pitch为±90°(即绕第二个轴的旋转),就会出现万向锁现象。 为了对这一现象有一个感性的认识,请拿起自己的手机(没有?不会吧)和一支笔(用作旋转轴), 亲手做如下的几个旋转。 首先确定手机的物体坐标系朝向,为了方便记忆,我们假设z轴与手机屏幕垂直(手机平放于桌面)指向上方, 手机较短的一条边为x轴,较长的一条边为y轴(方向由手机尾部指向头部),物体坐标系的原点是手机左下角的顶点。(注意旋转顺序为zyx)绕z轴旋转任意角度(注意x和y轴也跟着一起旋转),再绕y轴旋转90°,再绕x轴旋转任意角度。通过多次尝试, 你会发现一个共同点:z轴永远是水平的,通俗的说,手机永远也不会立起来!本来我们以为手机会指向任何方向,但实际上手机好像是被锁在桌面上,只能指向水平的某个方向,这个现象就称为万向锁。 而如果绕y轴旋转不等于90°(1°也好89°也好),只要选择适当的绕x和z的角度,就可以让手机指向三维空间中的任何一个方向,手机是自由的,也就不会遇到万向锁现象。 万向锁的避免问题:限制旋转的角度范围 heading-pitch-bankheading 绕Y轴 限制范围在±180°pitch 绕X轴 限制范围在±90°bank 绕Z轴 二、四元数 什么是四元数? 在计算机图形学中,四元数用于物体的旋转,是一种较为复杂,但是效率较高的旋转方式。在三种坐标变换:旋转,平移,缩放当中,旋转应该算是比较复杂的存在。平常我们接触的比较多的是矩阵变换和欧拉变换。 对于一个物体的旋转,其实我们只需要知道四个值:一个旋转的向量 + 一个旋转的角度。而四元数也正是这样的设计: 其中x,y,z 代表的是向量的三维坐标,w代表的是角度;同时我们也可以写成以下的形式方便我们计算和分析: q = ( x , y , z , w ) q=(x,y,z,w) q=(x,y,z,w)

看完这篇,你就了解了K8S的CKA认证考试的内容占比和具体考纲

如果你正好想要了解关于 Kubernetes (K8S) 的 CKA 认证考试的内容占比和具体考纲,那么你来对地方了!本篇文章将详细解析 CKA 认证考试的内容占比以及具体考纲,让你对考试有一个清晰的了解。 CKA(Certified Kubernetes Administrator)认证是云原生计算基金会(CNCF)推出的一项权威认证,目的是验证候选人在使用 Kubernetes 进行应用部署、调度、维护和管理方面的技能水平。 内容占比 集群架构,安装和配置:25%工作负载和调度:15%服务和网络:20%存储:10%故障排除:30% 具体考纲 CKA 考试的内容占比主要涵盖以下几个方面,每个方面的重要性不同: 集群架构,安装和配置 管理基于角色的访问控制(RBAC)使用Kubeadm安装基本集群管理高可用性的Kubernetes集群设置基础架构以部署Kubernetes集群使用Kubeadm在Kubernetes集群上执行版本升级实施etcd备份和还原 工作负载和调度 了解部署以及如何执行滚动更新和回滚使用ConfigMaps和Secrets配置应用程序了解如何扩展应用程序了解用于创建健壮的、自修复的应用程序部署的原语了解资源限制如何影响Pod调度了解清单管理和通用模板工具 服务和网络 了解集群节点上的主机网络配置理解Pods之间的连通性了解ClusterIP、NodePort、LoadBalancer服务类型和端点了解如何使用入口控制器和入口资源了解如何配置和使用CoreDNS选择适当的容器网络接口插件 存储 了解存储类、持久卷了解卷模式、访问模式和卷回收策略理解持久容量声明原语了解如何配置具有持久性存储的应用程序 故障排除 评估集群和节点日志了解如何监视应用程序管理容器标准输出和标准错误日志解决应用程序故障对群集组件故障进行故障排除排除网络故障 最后 总体而言,以上内容涵盖了 CKA 考试的主要知识点和技能要求。参加 CKA 考试的候选人需要熟悉 K8S 的架构和组件,掌握容器生命周期管理、安装与配置、调度、应用与资源管理、监控与故障排除以及安全等方面的技能。 看完本篇,可以全面了解 CKA 考试的内容占比和具体考纲,为你的备考提供有力的指导。最后,祝大家在 CKA 认证考试中取得优异的成绩! 【K8S(专注于深入研究K8S相关的各种技术和知识分享。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2474851867500544003&count=3#wechat_redirect 【Go&Py(涵盖了Go和Python两种流行的编程语言。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2869340550028771330&count=3#wechat_redirect 【Ops(运维领域的讨论和交流。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2869345486221262853&count=3#wechat_redirect

15款备受推崇的K8S可视化工具,你都玩过哪些?

对于那些热爱探索新技术、寻找简化操作方式的运维工程师来说,如何更好地管理和操作K8S集群?本篇将分享15款备受推崇的K8S可视化工具,让你轻松管理和操作集群中的各种资源。你可能已经玩过其中的一些工具,这将是一个与你分享经验的机会哦! 备受推崇的15款 Kubernetes Dashboard: https://github.com/kubernetes/dashboardKubeSphere: https://kubesphere.io/Rancher: https://rancher.com/Lens: https://k8slens.dev/Octant: https://octant.dev/K9s: https://k9scli.io/Shipyard: https://shipyard-project.io/Kontena Lens: https://www.kontena.io/lens/Kubernetic: https://kubernetic.com/Loodse Kubermatic: https://www.kubermatic.com/Portainer: https://www.portainer.io/Kubevious: https://kubevious.io/Kuboard: https://github.com/eip-work/kuboard-pressGrafana: https://grafana.com/Weave Scope: https://www.weave.works/oss/scope/ 每款工具的简述 K8S Dashboard: 作为K8S官方提供的仪表盘工具,它以简洁而直观的界面展示和管理K8S集群中的各类资源。 KubeSphere: 作为一款开源的K8S平台,KubeSphere为你提供了可视化的控制台和管理界面,助你轻松管理应用程序的部署、监控和日志查看等功能。 Rancher: 作为一个开源的容器管理平台,Rancher支持多个K8S集群的管理,具备强大的应用程序管理、监控和自动化部署等功能。 Lens: 作为一款跨平台的K8S可视化工具,Lens支持Windows、macOS和Linux操作系统,提供直观的界面,帮助你查看和操作K8S集群中的各种资源。 Octant: 作为一款开源的K8S可视化工具,Octant提供了简洁而功能丰富的用户界面,支持自定义插件和扩展,助你更好地查看和管理K8S集群。 K9s: 作为一款基于终端的K8S管理工具,K9s提供了交互式的界面,让你可以轻松查看和操作K8S资源,实时监控、日志查看、资源过滤等功能一应俱全。 Shipyard: 作为一款开源的容器管理平台,Shipyard提供了可视化界面,帮助你管理和监控K8S集群,支持应用程序部署、资源管理和事件触发等功能。 Kontena Lens: 作为一款跨平台的K8S管理工具,Kontena Lens提供了直观的用户界面,让你可以轻松查看和操作K8S集群中的资源,支持多集群管理、监控和日志查看等功能。 Kubernetic: 作为一款面向开发人员和运维人员的K8S可视化工具,Kubernetic提供了强大的功能和直观的用户界面,帮助你更好地管理和操作K8S集群,支持实时监控、事件触发、日志查看等功能。 Loodse Kubermatic: 作为一款开源的K8S管理平台,Loodse Kubermatic提供了可视化界面,帮助你管理多个K8S集群,具备应用程序部署、自动扩展、监控和日志查看等功能。 Portainer: 作为一款开源的容器管理工具,Portainer提供了可视化界面,支持管理Docker和K8S集群,实现应用程序部署、资源监控和日志查看等功能。 Kubevious: 作为一款开源的K8S可视化工具,Kubevious提供了直观的界面,帮助你查看和管理K8S集群中的资源,支持拓扑图展示、配置审计和资源关系分析等功能。 Kuboard: 作为一款开源的K8S可视化仪表板,Kuboard提供了用户友好的界面,帮助你监控和管理K8S集群,支持资源概览、事件查看和日志管理等功能。 Grafana: 虽然主要是一款监控和可视化工具,Grafana也可以与K8S集成,提供对集群的可视化展示。通过Grafana的仪表盘功能,你可以创建和定制自己的K8S集群监控视图。 Weave Scope: 作为一款开源的容器和微服务可视化工具,Weave Scope提供了直观的界面,帮助你查看和管理K8S集群中的资源,支持拓扑图展示、性能监控和流量分析等功能。 最后 这些仅仅是15款备受推崇的K8S可视化工具的一部分,它们都拥有独特的特点和功能,能够满足不同用户的需求。无论你是正在探索K8S的小鲜肉,还是已经熟练运用K8S的老腊肉,这些可视化工具都将成为你提升运维乐趣和效率的利器。那么,你已经尝试过其中的哪些工具呢?评论留言分享你的使用心得,和号主一起共同探索。 【K8S(专注于深入研究K8S相关的各种技术和知识分享。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2474851867500544003&count=3#wechat_redirect 【Go&Py(涵盖了Go和Python两种流行的编程语言。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2869340550028771330&count=3#wechat_redirect 【Ops(运维领域的讨论和交流。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2869345486221262853&count=3#wechat_redirect

React入门(B站李立超老师)

视频地址:https://www.bilibili.com/video/BV1bS4y1b7NV/ 课程第一部分代码: https://pan.baidu.com/s/16hEN7j4hLDpd7NoFiS8dHw?pwd=4gxv 提取码: 4gxv 课程第二部分代码:https://pan.baidu.com/s/1mDkvLqYVz1QGTV1foz5mQg?pwd=5zir 提取码:5zir 课程第三部分代码:https://pan.baidu.com/s/1JBaN4gSST_yXgHoIPfF5uw?pwd=ws8t 提取码:ws8t 前言(三大框架的诞生) 网页是B/S架构中最重要的信息载体,用户看到的所有信息都需要在网页中呈现。像商品信息、用户信息、新闻列表等一系列的内容都需要通过网页的形式呈现出来。在传统的网站中用户每点一次链接就会加载出一个新的页面。比如用户在网站的主页中看到了一个新闻的标题,点击标题网站会跳转到一个新的页面来展示新闻的具体内容。这样就导致呈现新闻的页面是从服务器中新加载出来的,新闻和首页是两个完全独立的页面。如果本来两个页面就没有什么太大的关系这么处理当然是没有问题的,但有些使用场景中却不能这样。 在有些场景中,用户在网页中发生了一些行为,比如登录、加购物车、添加删除等操作时,这些操作的确会使网页发生变化,但这些变化往往非常细微,比如购物车图标的产品数量发生了变化,登录按钮变成了用户头像,网页中增加或减少了一条数据等。如果仅仅因为这些小的变化就刷新了整个网页是有些划不来的。刷新整个网页一来会增加用户的等待时间,二来也会增加服务器的压力。于是我们就有了局部刷新网页的技术。 所谓的局部刷新指的是,当用户和网站发生交互时,我们不再是简单的直接通过浏览器进行页面的跳转,而是通过JS中的AJAX直接通过JS向后台服务器发送请求,请求过程用户毫无感知。响应数据会通过回调函数返回给JS,而不是直接返回给用户。JS中收到响应数据后,在根据不同的结果通过DOM来完成对页面的修改。它的优点就是,请求响应过程是异步的,用户是无感的,不会影响用户的其他操作。同时,通过DOM对页面刷新时只需刷新部分页面无需整体刷新,提高了访问速度。在服务器端,服务器只需提供数据接口,无需考虑页面的渲染,在降低服务器复杂度的同时也使得服务器压力降低提高了处理请求的速度。 AJAX + DOM使得局部刷新成为了可能,但一切似乎并不是那么的完美。发送请求加载数据问题不大,但数据一旦加载过来问题就出现了。数据并不能直接在网页中显示。我们需要通过DOM将数据转换为网页的中的各种节点,这就意味着我们必须反复的操作DOM,这其中的痛苦实在是一言难尽。一来DOM操作本身十分占用系统资源一不小心就会出现卡顿。二来DOM的API十分繁复,使得各种操作并不十分的优雅。换句话说,服务器的复杂度降低了,但是前端的复杂度提高了。 于是在前端开发中就急需一个框架来帮助我们解决这个问题,使我们可以比较轻松的根据不同的数据来快速构建用户界面(UI),与此同时还要在构建过程中确保其流畅度(不能出现卡顿)。于是React、Angular、Vue这些前端框架应运而生。 React简介 React 是一个用于构建用户界面的 JavaScript 库,用来为现代的网络构建用户界面。React起源于Facebook,由Facebook的软件工程师 Jordan Walke 开发,2012年部署于 Instagram,2013年开源。除此之外,React还有React Native框架,通过它让我们可以直接使用 JavaScript 来编写原生应用。 React的特点: 虚拟DOM -【相比较原生DOM,虚拟DOM的优点:1.api简单易学 2.解决了浏览器兼容性问题 3.实际操作上性能更好】声明式基于组件支持服务器端渲染快速、简单、易学 HelloWorld React的常规开发方式并不是通过浏览器引入外部js脚本来使用,但在入门阶段我们暂且先使用这种方式来简单体会一下React。 使用React开发Web项目,我们需要引入两个js脚本: react.development.js react 是react核心库,只要使用react就必须要引入下载地址:https://unpkg.com/react@18.0.0/umd/react.development.js react-dom.development.js react-dom 是react的dom包,使用react开发web应用时必须引入下载地址:https://unpkg.com/react-dom@18.0.0/umd/react-dom.development.js <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>Hello React</title> <script src="script/react.development.js"></script> <script src="script/react-dom.development.js"></script> </head> <body> <div id="root"></div> <script> const button = React.createElement('button', { onClick: (e) => { alert('你点了按钮!'); e.

基于SpringBoot的作业管理系统【附源码】

基于SpringBoot+Vue前后端分离的作业管理系统 开发语言:Java数据库:mysql技术:SpringBoot+MyBatis+Vue工具:IDEA/Ecilpse+mysql+Navicat 角色:老师、学生、管理员 管理登录本系统可以对个人信息、学生信息、教师信息进行管理;还可以对本系统的所有作业、以及批改的作业、提交的作业进行管理。学生注册登录本系统可以查看自己老师布置的所有作业、提交作业、查看自己的成绩。老师注册登录本系统可与对自己学生布置作业,批改自己学生的作业等。 国外的作业管理系统比较多,大部分都具有综合性、跨学科等特点,比较有代表性的有:WebAssign,它是由美国北卡罗来纳州立大学教学团队开发,它是由学生端、教师端和管理员端组成,教师在作业系统上布置作业,学生登录作业管理系统完成作业,管理员对作业系统进行全局的维护与管理;WebCT,它是由哥伦比亚大学计算机科学系开发的,学生登录该平台后,可以进行选课、测验、查询成绩等操作;OWL,它是由马萨诸塞大学计算机教学中心设计开发,它具有在线发布与批阅作业、导出学名册等功能;FernUniversityHagen,它是由德国开发的在线作业系统,它除了具有作业系统常规的功能外,还可以对数学公式进行编辑、绘制图表、实时信息反馈等功能。 在国内,“互联网+"的快速发展促进了教育信息化的发展,促进了高校对教学信息化的研究与建设,因此,作业管理系统成为校园信息化研究与建设的重点,例如华南师范大学袁媛认为,作业管理系统的功能设计要与时俱进,系统要融入当前新课程评定理念,开发出能够创建个性化学习环境的功能,以满足不同能力层次学生的需求,另外,作业系统能够对作业题分等级,并能设置不同层次的信息提示,这种分层提示机制为学生开展个性化学习提供了友好的支持。主观题的批改一直是在线作业管理系统研究的热点与难点,西南交通大学的杨宁学所设计的作业管理系统,依托电子计算机自动识别技术,提出主观题批阅的方法,具体的做法是先对作业题进行分解,形成答题的步骤节点,接着控制答题的步骤,并从题目参考答案中抽取出具有典型特征的数据作为识别依据,最后与学生的作答内容进行比较识别,利用这种方式,在一定程度上实现了主观题自动批改评分的间题。曲阜师范大学实验教学与设备管理中心李艳华所设计的网上作业批改与管理系统,实现了学生在系统提交作业,教师在系统上批改作业等基本功能,简化了发布与批改作业的环节,提了课堂教学的效率;江苏财经职业技术学院机械电子与信息工程学院朱士高的基千Web的学生作业系统,实现了学生提交作业与教师批改作业的一体化。 代码 package com.xyf.resolver; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import com.xyf.utils.AjaxResult; import com.xyf.utils.JsonUtils; /** * * @author 徐塬峰 */ @Component public class XyfHandlerExceptionResolver implements HandlerExceptionResolver { private static final Logger logger = LogManager.getLogger(XyfHandlerExceptionResolver.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { logger.error("服务器出错了!", ex); //如果是ajax请求,就返回�?个json格式的出错提示信�? if (request.getHeader("X-Requested-With") != null) { try { response.

npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! Vue开发中安装库经常报错

安装的依赖: npm add sass sass-loader stylelint postcss postcss-scss postcss-html stylelint-config-prettier stylelint-config-recess-order stylelint-config-recommended-scss stylelint-config-standard stylelint-config-standard-vue stylelint-scss stylelint-order stylelint-config-standard-scss -D 出现的错误: npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: project@0.0.0 npm ERR! Found: stylelint@14.16.1 npm ERR! node_modules/stylelint npm ERR! dev stylelint@"*" from the root project npm ERR! peer stylelint@">= 11.x < 15" from stylelint-config-prettier@9.0.5 npm ERR! node_modules/stylelint-config-prettier npm ERR! dev stylelint-config-prettier@"*" from the root project

【深度学习】经典案例:猫狗大战(kaggle实战完整流程:数据集分割、预处理、模型搭建、模型参数保存、acc/loss可视化)

环境:kaggle平台+python3.7+TensorFlow 完整代码、模型及参数、详细文档见:猫狗大战完整代码+详细文档+模型参数 文章目录 1.概述1.1 任务1.2 数据集1.3 解决方案 2 解决方案2.1 加载、查看训练集/测试集2.2 处理数据2.3 搭建模型2.4 设置优化器、损失函数2.5 存取模型、断点续训2.6 参数保存2.7 训练结果可视化2.8 预测测试集 3 总结 1.概述 1.1 任务 猫狗大战的实验目的是通过给定的猫狗图片数据集训练神经网络模型,通过CNN架构提取图片特征,实现模型对于猫狗两种动物的识别。 1.2 数据集 采用kaggle官方Cats VS. Dogs比赛数据集。该数据集是由 Microsoft Research Asia 发布的猫狗大战数据集。该数据集包括 25000 张猫和狗的图片,其中 12500 张是猫的图片,另外 12500 张是狗的图片。每张图片的大小不一,颜色、角度、光线等也有所不同。 1.3 解决方案 基于深度学习的解决方案:基于tensorFlow框架搭建神经网络,从零开始一步步完成数据读取、网络构建、模型训练和模型测试等过程,最终实现一个可以进行猫狗图像分类的分类器;并借助数据增强技术,例如旋转、翻转、缩放等,来增加数据集的多样性,从而提高模型的泛化能力和鲁棒性。 以下使用卷积神经网络来构建模型。在 CNN 中,通过卷积层、池化层、全连接层等结构,可以自动学习图像的特征,并将其转化为一个向量表示。通过这个向量表示,可以进行分类或者其他任务。 2 解决方案 2.1 加载、查看训练集/测试集 查看训练集/测试集大小,样例: os.listdir():返回指定目录中的所有文件和文件夹的列表。 #返回指定路径下的所有文件和目录的名称列表 train_path = '/kaggle/working/train' test_path = '/kaggle/working/test' train_file_names = os.listdir(train_path) test_file_names = os.listdir(test_path) print("训练集大小:{}".format(len(train_file_names))) print("测试集大小:{}".format(len(test_file_names))) print("训练集样例:{}".format(train_file_names[0:5]))#训练集文件名:标签+序号 print("测试集样例:{}".format(test_file_names[0:5])) #测试集文件名:序号 2.2 处理数据 训练集/测试集路径、标签存入DataFrame:

【数据增强】彻底搞懂数据增强做了哪些工作?

数据增强是数据预处理中的常用技巧。 例如使用图像增强技术来增加训练集的样本数量,从而提高模型的泛化能力。如以下代码所示: train_gen = ImageDataGenerator( zoom_range=0.1,#随机缩放图像的范围 rotation_range=10,#随机旋转图像的角度范围 rescale=1./255,#对输入图像进行缩放的因子 shear_range=0.1,#随机剪切图像的范围 horizontal_flip=True,#随机水平翻转图像的概率 width_shift_range=0.1,#随机水平平移图像的范围 height_shift_range=0.1,#随机垂直平移图像的范围 ) train_generator = train_gen.flow_from_dataframe( dataframe=train_set,#train_set原始数据 x_col='train_image_path', y_col='label', target_size=(200,200), class_mode='binary', batch_size=128, shuffle=False ) print(len(train_generator)) Q1:数据增强的对象? A1:通常情况下,数据增强是只针对训练集进行的,而验证集和测试集的数据不进行增强。 数据增强的主要目的是增加训练集的样本数量,从而提高模型的泛化能力和鲁棒性。在训练过程中,使用数据增强技术来生成更多的训练样本,并将其用于模型的训练。这样,模型就可以学习到更多的样本特征,从而提高其泛化能力和鲁棒性。 而验证集和测试集主要作用是评估模型的性能,如果对这些数据也进行增强,就会导致评估结果失真。此外,验证集和测试集的数据应该是从真实场景中抽样得到的,如果对其进行增强,就可能会导致模型在真实场景中的表现不如预期。 Q2:数据增强时候设置的batchsize和模型训练时中的batchsize需要相等吗? A2:不需要相等,它们是独立的参数。 在使用 ImageDataGenerator 类时,我们可以通过设置 batch_size 参数来指定每个生成的批次中包含的样本数量,影响的是数据生成的速度。 而在使用 fit() 方法训练模型时,我们需要指定训练数据集的 batch_size,以控制每个训练批次中包含的样本数量,影响的是训练速度。 Q3:为什么说数据增强可以增加训练样本数量,而在执行完数据增强后没有将其与原始训练样本合并? A3:本质上是可以合并的,但是合并后的结果是一个静态的DataFrame类型的对象,它包含了所有的图像数据和标签信息,需要一次性将所有的数据载入内存中。与train_generator生成器相比,这种方法需要较多的内存空间,并且可能会降低模型训练速度。一般不采取合并这种方式,因为train_generator就可以实现数据量扩增。 首先了解train_generator生成器这个东西!该生成器负责在训练过程中动态地生成经过增强后的图像数据和标签信息。什么是动态呢?即train_generator生成器在模型训练过程中才会发挥作用,伴随着每个epoch的进行,会生成一批又一批的数据,不需要事先将所有数据载入内存中。 至于每个epoch使用的训练集数量取决于设置的batchsize(如50个)和step_per_epoch(如100个),所以每个epoch使用的训练集数量(即为5000个)一般会大于原始训练集数量(如1000个)。如果没有设置step_per_epoch,则默认一个epoch数据量和原始数据量相同。 Q4:数据增强后的数量会大于原始数据集数量,所以一个epoch中的数据中有重复的吗?不同epoch的数据集一样吗? A4:不一定。第一个是因为对于单张图片,ImageDataGenerator对象会随机选择一些变换操作,而不是对每个图片都执行所有变化操作。 第二个是因为在每个epoch中,train_generator生成器会动态地从原始训练集(train_set)中生成新的训练样本,并将其用于模型训练。根据ImageDataGenerator对象生成数据的随机性,每个epoch中所生成的数据样本会不同,从而增加训练集的样本数量和多样性,提高模型的泛化能力。

系统集成项目管理工程师-学习笔记1-信息化知识

考点1 信息与信息系统 信息的概念 信息的定义: 是有别与物质与能量的第三种东西,是对事物运动状态或存在方式的不确定行的描述 信息是按特定方式组织在一起的客体属性的集合,具有超出这些客体属性本身之外的价值两层次 1.本体论层次 : 纯客观的层次,只与客体本身的因素有关,与主体的因素无关. 2.认识论层次: 是从主体立场来考察的信息层次,既与客体因素有关,也与主体因素有关 信息技术 为解决信息的采集,加工,存储,传输,处理,计算,转换,表现等问题而不断繁荣发展核心: 传输技术(通常指通信,网络等) 信息的质量属性 特点: 客观性,普遍性 属性: 1.精准性:对事物状态描述的精准程度 2.完整性: 对事物状态描述的全面程度.完整信息应包括所有重要事实 3.可靠性: 指信息的来源,采集方法,传输过程是可以信任的,符合预期 4.及时性: 指获得信息的时刻与事件发生时刻的间隔长短 5.经济性: 指信息获取,传输带来的成本在可以接受的范围之内 6.可验证性: 指信息的主要质量属性可以被证实或者证伪的程度 7.安全性: 信息可以被非授权访问的可能性,可能性越低,安全性越高 信息的传输模型 1.信源: 产生信息的实体,信息产生后,由这个实体向外传播 2.信宿: 信息的归宿或接受者 3.信道: 传送信息的通道,如TCP/IP网络 4.编码器: 如量化器,压缩编码器,调制器等 5.译码器: 包括解调器,译码器,数模转换器等 6.噪声(干扰) 包括信道中的噪声及分散在通信系统中的其他噪声的集中表示,无处不在,而为了抵抗噪音带来的失真,使用了编码,译码手段 信息系统特点(易考) 1.目的性: 定义一个系统,组成一个系统或者抽象出一个系统,都有明确的目标或者目的 2.可嵌套性: 系统可以包括若干子系统,系统之间也能够耦合成一个更大的系统 3.稳定性: 受规则的约束,系统的内部结构和秩序应是可以预见的 4.开放性: 指系统的可访问性,这个特性决定了系统可以被外部环境识别,外部环境或者其他系统可以按照预定的方法,使用系统的功能或者影响系统的行为. 5.脆弱性: 与系统的稳定性相对应,即系统可能存在着丧失结构,功能,秩序的特性,这个特性往往是隐藏不易被外界感知的 6.健壮性: 当系统面临干扰,输入错误,入侵等因素时,系统可能会出现非预期的状态而丧失原有功能,出现错误甚至表现出破坏功能 信息系统组成 1.硬件:由执行输入,处理和输出行为的计算机设备组成.输入设备包括键盘,自动扫描设备,语音识别设备等. 2.软件:由管理计算机运行的程序构成.包括设备驱动程序,系统软件,数据库管理软件,中间件,应用软件等. 3.数据库: 是经过机构化,规范化组织后的事实和信息的集合,是信息系统中最右价值和最重要的部分之一. 软件的生命周期 阶段 可行性分析与项目开发计划,需求分析,概要设计,详细设计,编码,测试,维护简化 1.立项:系统规划 2.开发:系统分析,系统设计,系统实施,系统验收 3.运维 4.消亡 信息化层次

C# wpf 附加属性实现任意控件拖动调整大小

第一节 Grid内控件拖动调整大小 第二节 Canvas内控件拖动调整大小 第三节 窗口拖动调整大小 第四节 附加属性实现拖动调整大小(本节) 文章目录 WPF拖动改变大小系列前言一、如何实现? 1.定义附加属性2.整合功能3.关联功能 二、完整代码三、使用示例 1.拖动控件大小2.拖动窗口大小 总结 前言 前面几节讲了控件拖动改变大小的几种方法,根据不同的布局可以有不同的实现方式。本节主要讲的是利用附加属性对这些方式进行封装,实现复用性,否则直接添加装饰器的方式需要写cs代码较为麻烦,且不方便移植,实现起来很不方便。通过将上述几节的所有功能整合到附加属性中,增加灵活度和适用性。 一、如何实现? 1.定义附加属性 定义附加属性IsResizeable,用于指示控件是否可调整大小,ResizeTemplate用指定拖动控件的样式,实现界面业务分离。 IsResizeable: public static bool GetIsResizeable(DependencyObject obj) { return (bool)obj.GetValue(IsResizeableProperty); } public static void SetIsResizeable(DependencyObject obj, bool value) { obj.SetValue(IsResizeableProperty, value); } // Using a DependencyProperty as the backing store for IsResizeable. This enables animation, styling, binding, etc… public static readonly DependencyProperty IsResizeableProperty = DependencyProperty.RegisterAttached(“IsResizeable”, typeof(bool), typeof(Resize), new PropertyMetadata(false)); ResizeTemplate: public static ControlTemplate GetResizeTemplate(DependencyObject obj) { return (ControlTemplate)obj.

使用postman实现文件上传与下载

文件上传: 1. 设置KEY值为Content-Type, VALUE值为multipart/form-data 2. 选择Body ,类型为form-data,KEY值下拉选择为file,这样VALUE就会出现选择按钮,最重要的是,KEY值的file需要手动添加,不然后台收到的为null 文件下载: 1. 设置为GET请求 2.将文件下载时Header的Content-Type取消勾选 3.Body选择none 4.send下拉选择Send and DownLoad

compose中实现拍照和选取相册功能兼容android 13+

compose中实现拍照和选取相册功能兼容android 13+ 效果图添加引用修改AndroidManifest.xml定义拍照和选取相册的ResultContract调用拍照和选择相册的compose方法使用 效果图 添加引用 //用于compose权限的使用 implementation("com.google.accompanist:accompanist-permissions:0.31.0-alpha") //闪光 implementation("com.google.accompanist:accompanist-placeholder-material:0.31.0-alpha") implementation("io.coil-kt:coil-compose:2.2.2") 修改AndroidManifest.xml 添加权限清单和provider <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="31" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.image.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider_paths" /> </provider> 添加路径文件file_provider_paths.xml: <?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="img_files" path="." /> <cache-path name="cache" path="." /> </paths> 定义拍照和选取相册的ResultContract 拍照和选取图片的intent在Android上是通用的,后面写的compose组合方法才是compose里面特有的,所以这里也可以拿来放到非compose里面使用。 添加选取图片intent: class SelectPicture : ActivityResultContract<Unit?, PictureResult>() { private var context: Context? = null override fun createIntent(context: Context, input: Unit?

2023单元测试利器Mockito框架详解(超详细~)

前言 Mockito 是当前最流行的 单元测试 Mock 框架。采用 Mock 框架,我们可以 虚拟 出一个 外部依赖,降低测试 组件 之间的 耦合度,只注重代码的 流程与结果,真正地实现测试目的。 正文 什么是Mock Mock 的中文译为仿制的,模拟的,虚假的。对于测试框架来说,即构造出一个模拟/虚假的对象,使我们的测试能顺利进行下去。 Mock 测试就是在测试过程中,对于某些 不容易构造(如 HttpServletRequest 必须在 Servlet 容器中才能构造出来)或者不容易获取 比较复杂 的对象(如 JDBC 中的 ResultSet对象),用一个 虚拟 的对象(Mock 对象)来创建,以便测试方法。 为什么使用Mock测试 单元测试 是为了验证我们的代码运行正确性,我们注重的是代码的流程以及结果的正确与否。 对比真实运行代码,可能其中有一些 外部依赖 的构建步骤相对麻烦,如果我们还是按照真实代码的构建规则构造出外部依赖,会大大增加单元测试的工作,代码也会参杂太多非测试部分的内容,测试用例显得复杂难懂。 采用 Mock 框架,我们可以 虚拟 出一个 外部依赖,只注重代码的 流程与结果,真正地实现测试目的。 Mock测试框架的好处 可以很简单的虚拟出一个复杂对象(比如虚拟出一个接口的实现类);可以配置 mock 对象的行为;可以使测试用例只注重测试流程与结果;减少外部类、系统和依赖给单元测试带来的耦合。 Mockito的流程 如图所示,使用 Mockito 的大致流程如下: 创建 外部依赖 的 Mock 对象, 然后将此 Mock 对象注入到 测试类 中;执行 测试代码;校验 测试代码 是否执行正确。 Mockito的使用 在 Module 的 build.

C++中的函数重载

函数重载:在C++中提出了用一个函数名定义多个函数即为函数重载 函数重载的规则:函数名必须相同、参数列表必须不同(体现在个数、类型、排列顺序等不同上)、函数的返回类型可以相同也可以不相同、仅仅返回类型不同不足以成为函数的重载

探秘安卓广播:揭秘Android广播机制的神奇之处

壹 广播机制 Android中的广播(Broadcast)机制用于进程/线程间通信,该机制使用了观察者模式。观察者模式是一种软件设计模式,该模式是基于消息的发布/订阅事件模型,该模型中的消息发布者是广播机制中的广播发送者,消息订阅者是广播机制中的广播接收者,广播机制的具体实现流程,如下图所示。 广播接收者通过Binder机制在AMS(Activity Manager Service)中进行注册广播发送者通过Binder机制向AMS发送广播。AMS查找符合相应条件(IntentFilter/Permission)的广播接收者(BroadcastReceiver),将广播发送到相应的消息循环队列中。执行消息循环时获取到此广播,会回调广播接收者(BroadcastReceiver)中的onReceive()方法并在该方法中进行相关处理。 Android系统中内置了很多广播,例如手机开机完成、电池电量不足时都会发送一条广播。为了监听来自系统或者应用程序的广播事件,Android系统提供了BroadcastReceiver(广播接收者)组件。 广播接收者的创建,具体如下:在应用程序的包中创建一个类继承BroadcastReceiver并重写onReceive()方法来实现的。 public class MyReceiver extends BroadcastReceiver { public MyReceiver() { } //在该方法中实现广播接收者的相关操作 @Override public void onReceive (Context context, Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } } 1.1 动态注册 创建完广播接收者之后还需要对广播接收者进行注册才可以接收广播[一般在MainActivity中注册]动态注册广播,动态注册的广播接收者是否被注销依赖于注册广播的组件,当组件销毁时,广播接收者也随之被注销。 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //实例化广播接收者 MyReceiver receiver = new MyReceiver(); //实例化过滤器并设置要过滤的广播 String action = "android.provider.Telephony.SMS_RECEIVED"; IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(action); registerReceiver(receiver,intentfilter);//注册广播 } protected void onDestroy() { super.onDestroy(); //当Activity销毁时,取消注册 unregisterReceiver(receiver); } 1.

LINUX - EFK(elastic + filebeat + kibana)日志审计系统小白构建过程 日记 手册

由于领导要求让我研究 efk 日志审计系统。我之前从未接触过,所以写这一篇文章作为研究和搭建过程的笔记 供自己以后参考,其中记录了我搭建过程中的遇到的各种问题,以及解决办法 包括常用到的指令。 一. 准备阶段 1.准备好elasticsearch ,filebeat ,kibana 的压缩文件(网上下载),并下载好Xftp用于文件上传,Centos镜像文件并用VMware创建虚拟机 (注意elastic,filebeat,kibana的版本号要一样 如下图版本号均为-7.3.1 避免发生兼容性问题) 2.VMware16创建虚拟机 (本人之前没怎么接触过 摸索【百度】了很久,会的这里可以跳过不看) 点击主页中的创建虚拟机 这边我直接点击的典型(推荐) 根据实际情况选择(一般默认就可以了) 点击完成 然后耐心等待机器加载 加载完毕后还有一些配置 需要处理 语言选择好之后 进行软件选择 选择GNOME桌面 和 开发工具 就可以了 点击左上角完成退出 第二步点击网络和主机名 链接网络 一样还是点击完成退出 最后点击安装位置 ,默认的就可以了 点击完成退出 再点右下角开始安装 这里设置root密码 开机用的 设置完后等待系统安装好就可以了 安装好效果图如下: 二.搭建EFK日志审计系统 打开终端:在根目录下创建一个存放 压缩包的文件夹 cd / <----------------- 到根目录下 mkdir mysoft <------------ 创建文件夹的指令 mysoft 是文件夹的名称 名称随意 使用 ifconfig 查看虚拟机的ip (这个ip之后会经常用到) 用xftp链接这台虚拟机需要用到 ifconfig 点开下载好的xftp 把你下载好的 压缩包 拉进来放在 你才创建好的文件夹内 这时我们在虚拟机中创建的文件夹中查看 现在开始对elastic,filebeat,kibana 三个压缩包进行解压

处理png图片毛边问题

/// /// 修复图片导入时白边问题 /// /// public static void FixTransparency(this Texture2D texture) { Color32[] pixels = texture.GetPixels32(); int w = texture.width; int h = texture.height; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int idx = y * w + x; Color32 pixel = pixels[idx]; if (pixel.a == 0) { bool done = false; if (!done && x > 0) done = TryAdjacent(ref pixel, pixels[idx - 1]); // Left pixel if (!

MobaXterm连接虚拟机不通的一个解决办法

最近刚用MobaXterm连接虚拟机,但发现每次刚开始的时候总是等待很久无法连接。后来一位同事说了他的经验,给分享一下。 首先,打开电脑网络设置“更改适配器选项”的功能,然后在WLAN右键“属性”,打开共享标签栏, 把上面的勾选先不选,确定之后再进行勾选(记得在下拉里选择正确的“家庭网络连接”),基本解决了这个问题。

python如何在一个py文件中调用另一个py文件中的方法

要在一个Python文件中调用其他Python文件中的方法,可以使用Python的模块导入功能。模块是一个包含Python定义和语句的文件,可以被其他Python程序导入和使用。 假设我们有两个Python文件,一个是file1.py,另一个是file2.py。如果我们想在file1.py中调用file2.py中的方法,我们可以按照以下步骤进行操作: 1. 在file2.py中定义一个或多个方法,例如: def my_function(): print("Hello from file2!") 2. 在file1.py中导入file2.py,例如: import file2 3. 现在,我们可以在file1.py中调用file2.py中的方法,例如: file2.my_function() 这将输出Hello from file2!。 请注意,当您导入一个模块时,Python会执行该模块中的所有代码。因此,如果您只想导入模块中的特定函数或变量,可以使用以下语法: from file2 import my_function 这将只导入my_function函数,而不是整个file2模块。然后,您可以在file1.py中直接调用my_function(),而无需使用file2.前缀。 希望这可以帮助您在Python中调用其他文件中的方法! 

用Keil5添加stm32103c8的步骤及Keil的调试模式

一、操作方式(两种) (1)通过寄存器的操作方式 1、首先在keil5中创建一个Start文件并导入以下内容: 2、为了让工程文件中能找到.h文件的路径(点开魔术棒) 根据以下步骤找到存放.h文件夹的Start目录 3、在工程文件中添加User文件,并在keil5中new group 命名为User ,创建一个main.c文件。(需要注意的是要将main函数的位置放进User文件里面,一般默认是放在User文件的外面的) 这样直接操作配置寄存器就完成了。 (2)通过库函数的操作方式 1、首先创建项目并选择型号。 2、导入Start、Lib、CMSIS、User下的文件。 3、点击魔术棒->C/C++ 在Define下添加定义 USE_STDPERIPH_DRIVER,并在Include Paths中添加文件路径 二、Keil5的调试模式 三、操作小细节 (1)ctrl+滚轮可以调节字体大小 当然也可以通过菜单页下的edit->configuratiation->colors&Fonts下的一系列操作修改 (2)当有时候代码出现乱码的现象也可以通过edit->configuratiation->根据以下的进行调整。 (3)右键可以跳转到查看函数的定义,另外选择需要查找的参数,ctrl+f可以进行查看 (4)ctrl+shift+n 快捷键创建文件夹 (5)ctrl+a 快捷键全选 (6)菜单栏中view中找到工具栏 (7)ctrl+alt+空格 代码提示栏 (8)有时候声明必须写在最前面就可以点击魔法棒->

Vue+element ui表单中省市区级联选择—v-distpicker/Cascader

v-distpicker组件或Cascader 级联选择器 1.页面 <el-form ref="form" :model="form" :rules="rules" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="姓名" prop="name"> <el-input v-model="form.name" placeholder="请输入姓名" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="联系电话" prop="telephone"> <el-input v-model="form.telephone" placeholder="请输入联系电话" maxlength="11" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="所在地区" prop="district"> <!--方式1:安装v-distpicker组件 使用 npm 安装:npm install v-distpicker --save--> <!-- <v-distpicker @selected="onSelected" :province="form.province" :city="form.city" :area="form.area" ></v-distpicker> --> <!--方式2:使用cascader组件--> <el-cascader v-model="form.district" placeholder="请选择" :options="districtOptions" clearable filterable style="width: 100%" @change="onChange" ></el-cascader> </el-form-item> </el-col> <el-col :span="24"> <el-form-item label="详细地址" prop="

如何自动识别reCAPTCHA v3隐形验证码, reCAPTCHA v3的分数代表什么?

"score" 在 V3 中代表什么,为什么没有验证码? reCAPTCHA V3 不是普通的验证码任务。它不是用于区分机器和人类的自动图灵测试。reCAPTCHA V3 是一个浏览器评分机制,用于识别操作浏览器的是人类还是程序。绕过 reCAPTCHA V3 的结果是一个 0.1 到 0.9 的得分,其中 0.1 表示“最可能是机器人”,0.9 表示“最可能是人类”。Capsolver 提供得分为 0.9 的令牌。 如何知道有一个 reCAPTCHA V3? reCAPTCHA V2:页面上有一个复选框。reCAPTCHA V2 隐形:没有复选框,但在右下角有一个 reCAPTCHA 徽标。有时,如果检测到您是可疑用户,您会被要求解决 reCAPTCHA。reCAPTCHA V3:没有复选框,但在右下角有一个 reCAPTCHA 徽标。您永远不需要解决 reCAPTCHA。 有时很难区分 reCAPTCHA V2 隐形和 V3。在这种情况下,只需在浏览器的控制台 Command+Option+C(Mac),或者 Control+Shift+C(Windows,Linux,Chrome OS)中打开,并检查发送到 google.com 的请求(在某些情况下为recaptcha.net)在 Network 标签页上。 找到请求 https://www.google.com/recaptcha/api2/reload?k= 是 reCaptcha v3 或 https://www.google.com/recaptcha/enterprise/reload?k= 是 reCaptcha v3 Enterprise 然后检查 https://www.google.com/recaptcha/api2/userverify?k= 第一个请求应始终存在。如果找不到它,请尝试将主机名更改为“recaptcha.net”,并继续查找,直到找到它。如果找不到第二个 userverify 请求,则是 reCAPTCHA V3。如果有一个向 userverify 的请求,则是 reCAPTCHA V2 隐形。

Sql Server:创建用户并指定该用户只能看指定的视图,除此之外的都不让查看

1,在sql server中选择好要操作的数据库 2,–当前数据库创建角色 exec sp_addrole ‘seeview’ --创建了一个数据库角色,名称为:[seeview] 3,–分配视图权限 GRANT SELECT ON veiw TO [角色] –指定视图列表 指定seeview这个角色可以查看的视图表名称;也就是这个角色可以查看下面赋予这些视图信息,除此之外的所有的东西都看不到 GRANT SELECT ON v_viewname1 TOseeview GRANT SELECT ON v_viewname2 TO seeview 4,–添加只允许访问指定视图的用户: exec sp_addlogin ‘登录名’,‘密码’,‘默认数据库名’ exec sp_addlogin ‘per’,‘p123’,‘oa’ 此处可能执行不了,要求密码强度,那就自己手工创建 5,–添加只允许访问指定视图的用户到rCRM角色中: exec sp_adduser ‘登录名’,‘用户名’,‘角色’ exec sp_adduser ‘per’,‘p123’,‘seeview’

【Android Framework系列】第2章 Binder机制大全

1 Binder简介 1.1 什么是Binder Binder是Android中主要的跨进程通信方式。Android系统中,每个应用程序是由Android的Activity,Service,BroadCast,ContentProvider这四剑客中一个或多个组合而成,这四剑客所涉及的多进程间的通信底层都是依赖于BinderIPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于BinderIPC。不仅于此,整个Android系统架构中,大量采用了Binder机制作为IPC(进程间通信)方案,当然也存在部分其他的IPC方式,比如Zygote通信便是采用socket。 Binder驱动和ServiceManager分别相当于网络协议中的路由器和DNS,并基于mmap实现了IPC传输数据时只需一次拷贝。Binder包括BinderProxy、BpBinder、BBinder等各种Binder实体,以及对Binder驱动操作的ProcessState、IPCThreadState封装,再加上Binder驱动内部的结构体、命令处理,整体贯穿Java、Native层,涉及用户态、内核态,往上可以说到Service、AIDL等,往下可以说到mmap、Binder驱动设备,是相当庞大、繁琐的一个机制。 1.2 为什么要使用Binder 为什么要用Binder???这个问题问得好。我们知道Binder是一种Android独有的跨进程通讯方式,而Android系统底层是Linux,所以Linux的跨进程通讯方式在Android里也是可以使用的。那还有其他方式可以实现Linux的跨进程通讯吗? 传统Linux进程间通信方式:管道、信号量、socket、共享内存,而Binder是android系统独有的通讯方式。 Binder:只需要拷贝一次,基于C/S架构,易用性高,系统为每个APP分配UID同时支持实名和匿名更安全共享内存:无需拷贝,控制复杂,易用性差,依赖上层协议,访问接入点是开放的不安全Socket:需要拷贝两次,基于C/S架构,作为一款通用接口,其传输效率低,开销大,以来上层协议,访问接入点是开放的,不安全管道:需要拷贝两次,非C/S架构,是一对一的通讯模型,把一个程序的输出直接链接另一个程序的输入。Linux下的管道主要分两种:无名管道(pipe)和有名管道(fifo)。无名管道只能用于具有亲缘关系的进程之间的通信(也就是父子进程或兄弟进程之间),是以半双工的一个通信方式,速度较慢,容量有限;有名管道是对无名管道的一种改进,可以让两个互补相干的进程之间进行通信。并且该管道在文件系统中可见,不过大小一直为0。信号量:与其他的进程间通信方式不太相同,它主要提供对进程间共享资源的访问机制,进程会根据它判定是否能够访问某些共享资源,同时进程也可以修改该标志。除了用于访问控制外,还可以用于进程同步,主要是用来解决进程线程之间同步与互斥问题的一种通信机制。 Android系统需要一种高效率、安全性高的方式,因此Binder最合适不过。Binder只需要拷贝一次,效率仅次于共享内存,而且采用传统的C/S结构 2 Binder 实现机制 2.1 内存概念 首先需要明确Linux系统关于内存的几个概念:虚拟内存,用户空间,内核空间、MMap 2.1.1 虚拟内存 虚拟内存简单来说,是一种内存管理技术,是虚拟的、逻辑上存在的存储空间;将物理上(不连续的物理)的内存(碎片)形成一个逻辑上连续完整的地址空间。虚拟内存初始化的过程,就叫做内存映射。我们的用户程序操作的内存实际上都是通过虚拟内存操作真正的物理内存。 简单理解:虚拟地址指向虚拟内存,虚拟内存指向对应的物理内存,物理内存会根据程序局部性原则,加载磁盘中的活跃程序到物理内存中。MMU将物理内存的地址转换为虚拟地址提供给外部(CPU)使用。虚拟内存与物理内存的映射以页为单位,常见的页大小为4KB 虚拟内存中有效位和磁盘地址可组成三种状态: 未分配(有效位0,磁盘地址null),磁盘上还不存在未缓存(有效位0,磁盘地址有值),磁盘上存在,但内存中不存在已缓存(有效位1,磁盘地址有值),磁盘、内存都存在 2.1.1.1 MMU MMU是Memory Management Unit的缩写,中文名是内存管理单元,有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线的仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。 如上图所示,MMU实际上是CPU和物理内存/磁盘之间的桥梁,主要职责是将物理地址转换为虚拟地址提供给CPU使用。物理内存和磁盘之间存在频繁的读写操作,因为根据程序局部性原则 2.1.2 用户空间、内核空间 虚拟内存被操作系统划分成两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方。为了安全,他们是隔离的,即使用户的程序崩溃了,内核也不受影响。 32位系统,即2^32,即总共可以访问地址为4G,内核空间为1G,用户空间为3G; 64位操作系统,低位2-47位是有效的可变地址,高位48-63位全补0对应用户空间,全补1是内核空间 2.1.3 MMap(Memory Mapping)内存映射 Linux通过将虚拟内存区域与磁盘上的空间关联起来,以初始化这个虚拟内存区域的内容,这个过程成为内存映射。具体一点来说,把一个文件或者其他对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间的映射关系。实现这种映射关系之后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写到对应的磁盘文件。 用户空间(虚拟内存)和磁盘文件(物理内存)存在映射关系,这样在虚拟内存中操作文件,就会自动回写到磁盘文件中。 2.2 Binder原理 Binder通信采用C/S架构,从组件视角来说,包含Client、Server、ServiceManager以及Binder驱动,其中ServiceManager用于管理系统中的各种服务。架构图如下所示: 可以看出无论是注册服务和获取服务的过程都需要ServiceManager,需要注意的是此处的ServiceManager是指Native层的ServiceManager(C++),并非指framework层的ServiceManager(Java)。ServiceManager是整个Binder通信机制的大管家,是Android进程间通信机制Binder的守护进程,要掌握Binder机制,首先需要了解系统是如何首次启动ServiceManager。当ServiceManager启动之后,Client端和Server端通信时都需要先获取ServiceManager接口,才能开始通信服务。 图中Client/Server/ServiceManage之间的相互通信都是基于Binder机制。既然基于Binder机制通信,那么同样也是C/S架构,则图中的3大步骤都有相应的Client端与Server端。 注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端。获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端。使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。 图中的Client,Server,ServiceManager之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过与Binder驱动进行交互,从而实现IPC通信方式。其中Binder驱动位于内核空间,Client,Server,ServiceManager位于用户空间。Binder驱动和ServiceManager可以看做是Android平台的基础架构,而Client和Server是Android的应用层,开发人员只需自定义实现Client、Server端,借助Android的基本平台架构便可以直接进行IPC通信。 3 Binder整体架构 Client:调用端(客户端)进程Server:被调用端(服务端)进程​BpBinder和BinderProxy:远程Binder实体,只不过一个Native层、一个Java层,BpBinder内部持有了一个Binder句柄值handle。BBinder:Server端接收来自Client端通过IPCThreadState传递过来的信息,然后回调onTransact实现方法。ProcessState:进程单例,负责打开Binder驱动设备及mmap;IPCThreadState:线程单例,负责与Binder驱动进行具体的命令通信。 ​ 通讯流程: 由Proxy发起transact()调用,会将数据打包到Parcel中,层层向下调用到BpBinder,在BpBinder中调用IPCThreadState的transact()方法并传入handle句柄值,IPCThreadState再去执行具体的Binder命令。由Binder驱动到Server的大概流程就是:Server通过IPCThreadState接收到Client的请求后,层层向上,最后回调到Stub的onTransact()方法。 Client通过ServiceManager或AMS获取到的远程Binder实体,一般会用Proxy做一层封装,比如ServiceManagerProxy、AIDL生成的Proxy类。而被封装的远程Binder实体是一个BinderProxy。 ​当然这不代表所有的IPC流程,比如ServiceManager作为一个Server时,便没有上层的封装,也没有借助IPCThreadState,而是初始化后通过binder_loop()方法直接与Binder驱动通信的。 4 Binder四层结构 Binder在整个Android系统中有这举足轻重的地位,在Native层有一套完整的binder通信的C/S架构图中红色代表整个framework层binder架构相关组件,Binder类代表Server端,BinderProxy类代码Client端;图中的蓝色代表Native层,BpBinder作为客户端,BBinder作为服务端。基于naive层的Binder框架,Java也有一套镜像功能的binder C/S架构,通过JNI技术与native层的binder对应,Java层的binder功能最终都是交给native的binder来完成。从kernel到native,jni,framework层的架构所涉及的所有有关类和方法见Binder类图。 上图为整个 Binder 从 kernel 至,native,JNI,Framework 层所涉及的全部类

Go项目配置管理神器之viper使用详解

作者:程序员CKeen 博客:http://ckeen.cn​​​​​​​​​​​​​​​​​​​​​ 长期坚持做有价值的事!积累沉淀,持续成长,升维思考!希望把编码作为长期兴趣爱好😄 目录 1. viper的介绍 2. viper的使用 2.1 Viper对象的创建 2.2 预设默认配置。 2.3 从命令行工具的选项参数Flags读取 2.4 从环境变量读取 2.5 从配置文件读取 2.6 从远程key/value存储读取 2.7 监听配置变化 2.8 写入配置到文件 3. 源码分析--配置读取的顺序 4. 参考资料​​​​​​​ 1. viper的介绍 viper是go一个强大的流行的配置解决方案的库。viper是spf13的另外一个重量级库。有大量项目都使用该库,比如hugo, docker等。 它基本上可以处理所有类型的配置需求和格式, viper支持功能 设置默认配置支持各种配置文件,如JSON,TOML, YAML, HCL, envfile和Java属性配置文件支持监听文件变化以及重新读取配置支持从环境变量读取配置支持从远程配置系统(etcd或Consul)读取配置,并能监听远程配置修改支持从命令行标志Flag读取配置,比如搭配cobra使用支持读取缓冲区数据 Viper主要为我们做以下工作: 查找、加载和解组JSON、TOML、YAML、HCL、INI、envfile或Java属性格式的配置文件。提供一种机制来为不同的配置选项设置默认值。提供一种机制来为通过命令行标志指定的选项设置覆盖值。提供别名系统,以便在不破坏现有代码的情况下轻松重命名参数。当用户提供了与默认值相同的命令行或配置文件时,很容易区分它们。 viepr的安装很简单,直接再工程中使用go get命令安装即可 $ go get github.com/spf13/viper 2. viper的使用 2.1 Viper对象的创建 Viper的是viper库的主要实现对象, viper提供了下面的方法可以获取Viper实例: func GetViper() *Viper func New() *Viper func NewWithOptions(opts ...Option) *Viper func Sub(key string) *Viper 使用viper.GetViper()获取的为全局的Viper实例对象,默认使用viper包使用也是该全局Viper实例。查看viper的源码,可以看到viper默认提供了一个全局的Viper实例: var v *Viper func init() { v = New() } // New returns an initialized Viper instance.

HTTP、HTTPS、FTP 和 TCP 详细讲解:协议的功能和特点

目录 一、HTTP(Hypertext Transfer Protocol)二、HTTPS(Hypertext Transfer Protocol Secure)三、FTP(File Transfer Protocol)四、TCP(Transmission Control Protocol) 在互联网中,HTTP、HTTPS、FTP 和 TCP 是常用的网络协议,它们在数据传输和通信中发挥着重要作用。 一、HTTP(Hypertext Transfer Protocol) HTTP 是一种用于在 Web 浏览器和 Web 服务器之间传输数据的协议。它使用明文传输,通常在 TCP/IP 协议栈上运行。HTTP 是一种无状态协议,每个请求都是独立的,不会记住之前的请求状态。HTTP使用请求-响应模型,客户端发送 HTTP 请求,服务器返回 HTTP 响应。HTTP 默认使用端口号 80。 HTTP 的特点: 简单易用:HTTP 的语法相对简单,易于理解和使用。无状态性:HTTP 是无状态协议,服务器不会保留客户端的状态信息。明文传输:HTTP 的数据传输是明文的,不进行加密,存在安全性问题。支持多媒体:HTTP 可以传输多种类型的数据,包括文本、图像、音频和视频等。请求方法:HTTP 定义了多种请求方法,如 GET、POST、PUT、DELETE 等。 二、HTTPS(Hypertext Transfer Protocol Secure) HTTPS 是在 HTTP 的基础上添加了安全性的协议。通过使用 SSL(Secure Sockets Layer)或 TLS(Transport Layer Security)协议对通信进行加密和认证,保护数据的安全性。HTTPS 默认使用端口号 443。 HTTPS 的特点: 数据加密:HTTPS 使用 SSL/TLS 协议对传输的数据进行加密,防止被窃听和篡改。身份认证:HTTPS 使用数字证书对服务器进行身份认证,确保通信的安全性和可信度。数据完整性:HTTPS 使用消息摘要算法对传输的数据进行校验,确保数据的完整性。 三、FTP(File Transfer Protocol) FTP 是一种用于在计算机之间传输文件的协议。它提供了文件的上传和下载功能,并支持文件的管理(如删除、重命名等)。FTP 使用客户端-服务器模型,客户端通过 FTP 客户端软件连接到服务器,并使用用户名和密码进行身份验证。FTP 默认使用端口号 21。

QT程序运行起来了但是没有显示窗口界面

在我的QT程序ui界面中,不小心修改掉了windowOpacity这个属性,把这个属性置0,然后后面运行程序的时候就显示不出程序的界面了。后面发现是误改了这个属性(windowOpacity,这个表示修改窗口的透明度,当为0的时候也就看不到了) (做的笔记,仅供自己参考)

一文搞懂redis的用户权限管理(ACL)功能

目录 前言 一、acl基本操作 1.1 、查看用户 1.2、创建用户 1.3、启用/禁用用户 1.4、设置密码/取消密码 1.5、删除用户 二、用户的权限操作 2.1 、查看所有命令集合 2.2、增加/取消指定命令集合的权限 三、ACL的持久化 3.1、持久化ACL配置 3.2、从配置文件中读取ACL配置 四、其它操作 4.1. ACL测试能否使用指定命令 前言 Redis在6.0之前基本没有用户权限的概念,只有一个连接认证密码,一旦通过了认证就可以随意操作任意的redis数据,无法对用户权限进行精确控制,很容易因为用户权限过大引发误操作。如果想禁用某些不安全的命令,比如flushdb,flushall,只能通过rename-command的方式来避免。 redis6.0发布了权限管理功能ACL(access control list 访问控制列表),可以对不同的用户设置不同的权限,限制用户可使用的命令,可访问的key等。 一、acl基本操作 1.1 、查看用户 [root@localhost bin]# ./redis-cli 127.0.0.1:6379> acl list 1) "user default on nopass ~* &* +@all" default 表示用户名,兼容以前的AUTH命令,如果执行AUTH命令时不写用户名,redis认为是在认证这个default用户 on 表示已启用该用户,off表禁用 nopass 表示没有密码 ~* 表示可访问全部的数据Key(正则匹配) &* 表示允许用户访问所有Pub/Sub频道(正则匹配)。 +@all 表示用户的权限, "+"添加权限;"-"删减权限;@为redis命令分类; 可以通过 ACL CAT 查询相关分类,all表全部的命令集合,最终 +@all 表示拥有所有命令集合的所有权限。 或者使用acl users查看,内容很简洁,只展示了用户名 127.0.0.1:6379> acl users 1) "default" ACL WHOAMI 查看当前使用的用户

Spring中的事务管理

一、事务管理 1.事务回顾 概念 事务是一组操作的集合,它是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败。 操作 开启事务(一组操作开始前,开启事务) : start transaction / begin ;提交事务(这组操作全部成功后,提交事务) : commit ;回滚事务(中间任何一个操作出现异常,回滚事务): rollback ; 2.Spring事务管理 1. 前言 假如有一个公司,我们在做部门调整时删除一个部门,就要删除部门下的所有员工,否则会有造成数据的不一致。 2. 处理之后的代码 顺带加上一个根据部门id删除员工的功能: Sevices代码: @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptMapper deptMapper; @Autowired private EmpMapper empMapper; @Override public void delete(Integer id) { deptMapper.deleteId(id); //根据id删除部门 empMapper.deleteByDeptId(id); ; //根据部门id删除该部门下的员工 } } Mapper层代码: public interface EmpMapper { /** * 根据部门Id删除员工信息 * @param deptId */ @Delete("delete from emp where dept_id = #{deptId} "

[JVM]再聊 CMS 收集器

题目之所以是再聊,是因为以前聊过: [JVM]聊聊 CMS 收集器 最近又看了下这块的知识,打算把 CMS/标记-清除/GC Roots/引用 这些知识串起来 我依旧可能写的不是很好,降低下期待 GC 算法 CMS 是基于 标记-清除 算法来做的,那我们就先从 GC 算法开始聊 GC 算法有: 标记-清除 标记阶段: 从 GC Roots 对象开始遍历对象图,将所有可达对象进行标记清除阶段: 堆中未被标记的对象进行清除,释放内存空间 标记-复制: 标记阶段: 从 GC Roots 对象开始遍历对象图,将所有可达对象进行标记复制阶段: 将所有标记的对象从 From 指针指向的区域,复制到 To 指针指向的区域,同时更新对象引用回收阶段: 清除未被标记的对象,同时更新 From 指针和 To 指针指向的区域,保持 From 指针指向的区域为空 标记-整理: 标记阶段: 从 GC Roots 对象开始遍历对象图,将所有可达对象进行标记整理阶段: 将所有标记的对象向一端移动,然后将未被标记的内存空间释放 标记-清除算法有两个缺点: 1 执行效率不稳定:大量对象需要大量被回收时,会导致标记 & 清除效率变低; 2 内存碎片化 标记-复制算法解决了内存碎片化的问题,但它是以牺牲空间来优化的(因为有一部分空间要留出来复制用) 标记-整理算法也解决了内存碎片化的问题,但它是以牺牲时间来优化的(因为要花时间将标记对象移动到一起) CMS 基于 标记-清除 算法来实现的,那就会有一个无法避免的缺点: 会有大量的空间碎片 CMS 进行垃圾回收时的整个过程 接下来聊一聊 CMS 进行垃圾回收时的整个过程,其实也就是 4 个过程啦:

【Python脚本】Python轻松爬取歌曲,小白也能轻松上手操作!

文章目录 前言一、准备工作二、编写代码三、总结 前言 音乐抓取是一种非常有趣和实用的技术,它可以让我们通过程序从互联网上获取音乐文件,比如MP3文件。在本案例文章中,我们将使用Python编写一个简单的音乐抓取程序,来演示如何使用Python进行音乐抓取。 >>领取Python学习大礼包<< 一、准备工作 在开始编写代码之前,我们需要安装一些必要的库。在Python中,有一些非常好用的库可供我们使用,比如requests和beautifulsoup4。 首先,我们需要安装这些库。打开你的终端或命令提示符,然后运行以下命令来安装它们: pip install requests beautifulsoup4 安装完成后,我们就可以开始编写代码了。 二、编写代码 首先,我们需要导入所需的库: import requests from bs4 import BeautifulSoup 接下来,我们可以定义一个函数,用于从互联网上的网站获取音乐文件的URL: def get_music_url(): url = 'https://music.163.com/' # 替换为你要抓取音乐的网站URL response = requests.get(url) if response.status_code == 200: soup = BeautifulSoup(response.text, 'html.parser') # 在这里使用BeautifulSoup解析页面,找到包含音乐文件URL的元素 # 进行相应的操作,提取音乐文件URL music_url = '' # 这里存储你获取到的音乐文件URL return music_url else: print('Failed to access the website.') return None 替换https://music.163.com/#/song?id=1876909269为包含你要抓取音乐的网站URL。然后,使用requests.get方法访问该网站,获取网页的内容。 接下来,我们使用BeautifulSoup库解析页面。你需要根据具体的网页结构,找到包含音乐文件URL的元素,可以通过查看网页源代码或者使用浏览器的开发者工具来查找。 一旦你找到了音乐文件URL所在的元素,你就可以进行相应的操作,提取音乐文件URL。将提取到的音乐文件URL存储在music_url变量中,并返回它。 接下来,我们可以编写一个函数来下载音乐文件: def download_music(music_url, file_name): response = requests.get(music_url) if response.

MySQL 语法SQL 命令解析

目录 一、数据库操作二、表操作三、数据操作四、数据过滤与排序五、数据聚合与分组六、连接操作七、索引与优化 MySQL 是一种常用的关系型数据库管理系统,使用 SQL(Structured Query Language)作为操作数据库的语言。 一、数据库操作 创建 database_name 数据库 CREATE DATABASE database_name; 删除 database_name 数据库 DROP DATABASE database_name; 选择要使用的数据库 USE database_name; 二、表操作 1.创建 table_name 的表,包含指定的列和约束 CREATE TABLE table_name ( column1 datatype constraint, column2 datatype constraint, ... ); 删除 table_name 的表 DROP TABLE table_name; 向 table_name 表中添加列、修改列定义或删除列 ALTER TABLE table_name ADD column_name datatype constraint, MODIFY column_name datatype constraint, DROP column_name; 三、数据操作 插入数据 INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, .

【大数据之Hive】十六、Hive-HQL函数之窗口函数(开窗函数)

1 概述 先定义了窗口的大小(按行来算),然后对窗口内的行的数据进行计算,再将计算结果返回给改行。 窗口函数包括窗口和函数两部分,窗口用于定义计算范围,函数用于定义计算逻辑,窗口函数只会在原来的表上增加一列结果列,不改变原来的数据。 1.1 窗口函数使用语法 --窗口函数使用语法 select ..., 函数(col_name) over (窗口范围) result_col_name -表示在窗口范围之上应用函数逻辑 from table_name; 函数: 绝大多数聚合函数都可以配合窗口使用,如max(),min(),sum(),count(),avg()等。 窗口: 分为两种,一种是基于行的,一种是基于值的。 基于行的:如每行数据的窗口为上一行到当前行:对于第1行来说,处于窗口内的行为第0行和第1行;对于第2行来说,处于窗口内的行为第1、2行。 基于值的:如要求每行数据的窗口值位于当前值-1到当前值:对于值为1的数据来说,窗口范围的值为[1-1,1]即[0,1],此时只有1行数据;对于值为2的数据来说,窗口范围的值为[2-1,2]即[1,2],有第1、2、3行数据。 1.2 窗口语法(基于行row) 基于真正运算时的行,并不是基于看到的表数据,所以需要声明一个排序字段 order by ,在真正进行窗口计算时使用哪个窗口进行排序。 --基于行 函数(col_name) over (窗口范围) result_col_name --窗口范围(写在over后面的括号里): order by [col_name] rows between ***1 and ***2 ***1(窗口的起点):unbounded preceding / [num] preceding / current row / [num] following ***2(窗口的终点): 对于 unbounded preceding / [num] preceding 来说,终点可以写为 [num] preceding / current row / [num] following / unbounded following 对于 current row 来说,终点可以写为 current row / [num] following / unbounded following 对于 [num] following 来说,终点可以写为 [num] following / unbounded following (1)窗口起点(可以不包含当前行):

Beyondcompare比较时文件一样也标红的解决方法

一,简介 在使用beyondcompare时,有时会出现文件相同但是beyondcompare也同样标红的情况。 这种情况不方便快速找到两个文件夹有差异的地方。 二,解决办法 2.1 设置比较方式 点击“小人头”进行如下设置: 2.2 刷新结果 刷新之后,就会只显示差异项,相同项会被隐藏。 所以,完美解决。 三,总结 小问题也要刨根问底搞清楚,否则不仅会影响效率,积少成多对自己时间也是一种浪费。

使用构造函数对结构体进行初始化/构造函数重载

构造函数:用于初始化结构体的一种函数,直接定义在结构体中。 特点:不需要写返回类型,且函数名与结构体名相同 对于普通定义的结构体,其内部会生成一个默认的构造函数(不可见): struct studentinfo{ int id; char gender; //默认生成的构造函数 studentinfo(){} }; 如果想手动提供id和gender的初始化参数,则需要提供初始化参数对结构体中的变量进行赋值: struct studentinfo{ int id; char gender; //下面的参数用以对结构体内部变量进行赋值 studentinfo(int _id,char _gender){ //赋值 id=_id; gender=_gender; } }; ★构造函数也可简化为一行: struct studentinfo{ int id; char gender; studentinfo(int _id,char _gender):id(_id),gender(_gender){} }; 手动定义了构造函数就可以在需要时对结构体变量进行赋值: studentinfo stu=studentinfo(10086,'M'); 如果自己重新定义了构造函数,则不能不经初始化就定义结构体变量,默认生成的构造函数此时被覆盖了。添加studentinfo() {}后即可直接定义结构体变量。 只要参数个数和类型不完全相同,可以定义任意多个构造函数: struct studentinfo{ int id; char gender; //用以不初始化就定义结构体变量 studentinfo(){} //只初始化gender studentinfo(char _gender){ gender=_gender; } //同时初始化id和gender studentinfo(int _id,char _gender){ id=_id; gender=_gender; } }; 构造函数在结构体内元素较多的时候会显得代码简练且工整,推荐使用。

sass基础---选择器继承 @extend

//通过选择器继承继承样式 .error { border: 1px solid red; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } 以上的结果是在代码中样式写法为 class="seriousError", 但在html中展示的最终效果是 class="seriousError error" 1. css样式中使用 @extend 后,不仅会继承父类的样式 ,所有和父类组合在一起的样式也会被继承到子类中。 //.seriousError从.error继承样式 .error a{ //应用到.seriousError a color: red; font-weight: 100; } h1.error { //应用到hl.seriousError font-size: 1.2rem; } 2. 继承的高级用法 任何css规则都可以继承其他规则,几乎任何css规则也都可以被继承

全网最硬核解析!Maven进阶学习全解

前言 当我们在开发项目时,有时需要用到外部依赖组件,例如当我们需要Json序列化的时候需要用到FastJson组件,我们可以通过下载对应jar包加载到项目中。但当一个大的项目同时需要依赖各种各样的外部服务,就存在着配置繁琐、依赖冲突等问题,因此可以通过maven来完成对应的依赖管理功能。 一、Settings配置 settings.xml用来配置maven项目中的各种参数文件,包括本地仓库、远程仓库、私服、认证等信息。 1.1 配置概述 1.1.1 全局settings、用户setting、pom的区别 全局 settings.xml 是 maven 的全局配置文件,一般位于${maven.home}/conf/settings.xml,即maven文件夹下的conf中。用户 setting是maven的用户配置文件,一般位于${user.home}/.m2/settings.xml,即每位用户都有一份配置文件。pom.xml 文件是项目配置文件,一般位于项目根目录下或子目录下。 配置优先级从高到低:pom.xml > 本地 settings > 全局 settings 如果这些文件同时存在,在应用配置时,会合并它们的内容,如果有重复的配置,优先级高的配置会覆盖优先级低的。 1.1.2 仓库【重要】 如前言所述,我们依赖的外部服务是需要有地方进行存储的,而存储的地方就称之为仓库。其中仓库又分为本地仓库、中央仓库、镜像仓库、私服。 其对应关系为: (1)本地仓库 当项目在本地编译或运行时,直接加载本地的依赖服务无疑是最快的。默认情况下,不管在Window还是Linux下,每个用户在自己用户目录下都有一个路径名为.m2/repository/的仓库目录。 而原始的本地仓库是为空的,因此maven需要知道一个网络上的仓库,在本地仓库不存在时前往下载网络上的仓库,也就是远程仓库。 (2)中央仓库 当maven未配置时,会默认请求maven的中央仓库,中央仓库包含了这个世界上绝大多数流行的开源java构件,以及源码、作者信息、SCM,信息、许可证信息等,每个月这里都会接受全世界java程序员大概1亿次的访问,它对全世界java开发者的贡献由此可见一斑。 但是由于最常见的例如网络原因等,国外的中央仓库使用起来并不顺利,因此就有了下载地址为国内的中央仓库,也就是镜像仓库。 (3)镜像仓库 总结来说,镜像仓库就是将国外的中心仓库复制一份到国内,这样一来下载速度以及访问速度都将很快。 (4)私服 一般来说中央仓库或者镜像仓库都能满足我们的需求,但是当我们在公司内合作开发代码时,可能因为系统保密性原因,有一些其他同事开发的外部依赖只希望能够被本公司的人使用,而如果上传到镜像仓库则保密性就不复存在了。因此私服最主要的功能时存储一些公司内部不希望被公开的依赖服务。 1.2 settings配置详解 settings.xml配置了本地全局maven的相关配置。 以下是一份seetings.xml的文件配置顶级元素。 xml 复制代码 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository> <interactiveMode> <usePluginRegistry> <offline> <pluginGroups> <servers> <mirrors> <proxies> <profiles> <activeProfiles> </settings> 1.2.1 localRepository 用来标识本地仓库的位置 javascript 复制代码 D:/Maven/Repository 1.2.2 interactiveMode maven 是否需要和用户交互以获得输入。默认为true。

sass 基础

sass为css引入了变量,可以将反复使用得css属性值定义为变量,然后通过变量命名来引用它们。 1. sass使用 $ 符号来标识变量,在css中不会于现存或未来的css语法冲突。只声明变量无用,需要引用,使用他们才有用。反复声明同一个变量,后来的变量内容会覆盖之前的内容 1.变量声明(变量名使用中划线和下划线效果一样,互通,经常使用中划线) $sidebar-width: 30px; 2.变量引用 $highlight-color: #F90; .selected { border: 1px solid $highlight-color; } //编译后 .selected { border: 1px solid #F90; } 2. css 可以嵌套,父选择器标识符 & 1.遇到伪类时可以用& 标识出来使用父选择器,而不是以后代连接器的方式连接 article a { color: blue; &:hover { color: red } } //编译后为: article a { color: blue } article a:hover { color: red } 2.群组选择器 , .container { h1, h2, h3 {margin-bottom: .8em} } 编译为css后是: .container h1, .

ARM指令汇总

学习ARM指令汇编时,发现很多博客的都不全,因此在学习过程中完善一下,没有按照任何顺序,本文会在接下来一段时间内不定期更新。 ARM指令集 AREA: 伪操作,用来标识一个段的起始、段名和段的读写属性。 eg: AREA COPY,CODE,READONLY ;段名为COPY,属性为代码段,只读 AREA COPYDATA,DATA,READWRITE ;段名为DCOPYDATA,属性为数据段,读写 S: 指令后面加S,表示影响标志位 eg: SUBS R2,R2.#1 ;R2的值减1后存入R2,S代表影响标志位 ENTRY / END: ENTRY 伪操作用来标识汇编程序的运行入口, END伪操作用来标识汇编程序的结束。 使用 ; 注释代码 局部标号 引用格式:%{F|B|A|T} N{routname} %: 引用符号,对一个局部标号产生引用。 F:指示编译器只向前搜索。B:指示编译器只向后搜索 A:指示编译器搜索宏的所有宏命令层。T:指示编译器搜索宏的当前层 N:局部标号的名字。routename:局部标号的作用范围名称,使用ROUT定义 eg: BNE %B0 ;跳转到局部标号0处 GBLA / GBLL / GBLS /LCLA / LCLL / LCLS 定义数据 eg: GBLA a ;定义一个全局算术变量a, 并初始化为0 GBLL a ;定义一个全局逻辑变量a, 并初始化为{false} GBLS a ;定义一个全局字符串变量a,并初始化为0 LCLA a ;定义一个局部算术变量a,并初始化为0 LCLL a ;定义一个局部逻辑变量a,并初始化为{false} LCLS a ;定义一个局部字符串变量a,并初始化为0

我心中的TOP1编程语言—JavaScript

作为一名研发工程师(程序员),平时工作中肯定会接触或了解很多编程语言。每个人都会有自己工作中常用的语言,也会有偏爱的一些编程语言。而我心中的最爱,毫无疑问,就是 JavaScript。 JavaScript 是一门编程语言,可为网站添加交互功能(例如:游戏、动态样式、动画以及在按下按钮或收到表单数据时做出的响应等)。 个人认为,一门好的编程语言,要从易用性、执行效率、语言特性、工具生态环境、开发者社区等等多方面来衡量。而,对于 JavaScript,在这些方面都表现的很出色: 衡量标准 易用性 JavaScript 的语法非常简单,尤其对有编程经验的程序员来说。 相较于其他编程语言,JavaScript 结构简单、可读性强,其语法清晰明了,易懂易学。 // 在网页上显示 “Hello, World!” 的弹出窗口 alert("Hello, World!"); 同时,市面上现存大量的稳定高效的 JavaScript 框架及第三方库,可以根据个人喜好选择,从而帮助我们提高开发效率。(开源项目和库的火爆程度虽有降温,但常年持续第一,23年才被 Python 超过) 语言功能特性 JavaScript 是一门高级编程语言,提供了大量优秀的特性。JavaScript 作为一种事件驱动的编程语言,开发人员可以轻松地通过 JavaScript 代码处理各种事件(如页面加载、鼠标单击、键盘输入等)。 整个过程无需独立编译,在浏览器中即可运行。同 HTML、CSS 更能做到所见即所的开发体验。 // HTML 文档被完全加载和解析完成 document.addEventListener('DOMContentLoaded',function(){}); // 监听鼠标click事件 dom.addEventListener('click', (event) => {}); 工具生态环境 JavaScript 生态环境相当完备,包括很丰富的工具、第三方库和框架。从代码编辑、依赖管理、自动化构建、到测试和调试,使得开发人员可以更快、更高效地开发复杂的web应用程序。 工具/框架应用场景代码编辑工具Visual Studio Code、Sublime Text、Atom 等包管理器npm、Yarn、pnpm构建工具Webpack、Parcel、Rollup前端框架React、Vue、Angular应用程序框架Express.js、Koa、Nest.js 开发者社区 JavaScript 拥有非常活跃的社区,这不仅有助于 Javascript 在新技术和开发模式方面保持领先地位,还有助于其稳健性和可靠性。 其中:MDN 提供了非常详细的 API 文档、操作指南以及各种示例代码。是更加详细了解和学习 JavaScript 不错的平台。 未来发展趋势 近年来,JavaScript 的应用场景越来越广泛,从web开发、到移动端/各种小程序、再到服务端、硬件编程等均有 Javascript 的身影。随着 WebAssembly的普及、IoT应用场景落地,Javascript 仍在不断发展和演变中,未来仍将有巨大潜力。

java与javac常用指令

java 用法: java [-options] class [args...] (执行类) 或 java [-options] -jar jarfile [args...] (执行 jar 文件) 其中选项包括: -d32 使用 32 位数据模型 (如果可用) -d64 使用 64 位数据模型 (如果可用) -server 选择 "server" VM 默认 VM 是 server. -cp <目录和 zip/jar 文件的类搜索路径> -classpath <目录和 zip/jar 文件的类搜索路径> 用 ; 分隔的目录, JAR 档案 和 ZIP 档案列表, 用于搜索类文件。 -D<名称>=<值> 设置系统属性 -verbose:[class|gc|jni] 启用详细输出 -version 输出产品版本并退出 -version:<值> 警告: 此功能已过时, 将在 未来发行版中删除。 需要指定的版本才能运行 -showversion 输出产品版本并继续 -jre-restrict-search | -no-jre-restrict-search 警告: 此功能已过时, 将在 未来发行版中删除。 在版本搜索中包括/排除用户专用 JRE -?

git命令合并分支代码

合并步骤: 例:dev分支合并到master分支 1、git checkout master 【进入要合并的分支】 2、git pull 【拉取最新代码】 3、git branch -a 【查看所有分支是否都pull下来了】 4、git merge dev 【使用merge合并开发分支】 5、git status 【查看合并之后的状态】 注:此时有冲突的话,解决冲突 git add 冲突文件 继续提交代码 6、git commit 【如果不是使用git commit -m '备注',那么git会自动将合并的节骨作为备注,提交本地仓库】 7、git push 【本地仓库代码提交到远程仓库】

QCustomPlot的安装与使用

一、QCustomPlot介绍 QCustomPlot 是一个基于Qt的画图和数据可视化C++控件,类似的有QChart、Qwt。 以下使用的QCustomPlot版本为2.1.1,QT Creator版本为6.4.3 二、QCustomPlot下载与安装 下载地址 需要下载QCustomPlot.tar.gz和QCustomPlot-sharedlib.tar.gz两个文件。 把QCustomPlot.gz解压后如下: 把QCustomPlot-sharedlib.tar.gz解压后如下: 2.1 直接使用h和c文件 将QCustomPlot中的qcustomplot.c和qcustomplot.h文件直接放进项目内,然后在项目.pro文件中头部QT += core gui 后面添加printsupport,修改后为QT += core gui printsupport。 在需要使用qcustomplot的项目文件中添加头文件qcustomplot.h。 优点:导入快捷,使用方便 缺点:每次编译项目文件时,会编译qcustomplot.c,因为qcustomplot.c很大,导致每次项目编译时速度很慢。 为了提高项目编译速度,可以使用下面的方法。 2.2 编译为动态库然后导入项目 使用QT Creator打开QCustomPlot-sharedlib/sharedlib-compilation中的sharedlib-compilation.pro,代码如下: 如图所示,将首行修改为 QT += core gui printsupport 即添加printsupport。 然后查看末尾两行,即 SOURCES += ../../qcustomplot.cpp HEADERS += ../../qcustomplot.h …/…/表示目前.pro文件的上两级目录,此时需要将QCustomPlot文件夹中的qcustomplot.c和qcustomplot.h粘贴到与QCustomPlot-sharedlib同一级的目录,即qcustomplot.c和qcustomplot.h与QCustomPlot-sharedlib文件夹放到同一个文件夹内。 之后编译.pro打开的工程,会在debug和release文件夹内分别生成如下文件 此时打开需要导入qcustomplot的项目文件夹,新建一个qcustomplot文件夹,将sharedlib-compilation工程文件内release中的libqcustomplot2.a和qcustomplot2.dll;debug中的libqcustomplotd2.a和qcustomplotd2.dll;QCustomPlot.tar.gz解压后的qcustomplot.qch、qcustomplot.c和qcustomplot.h放到项目qcustomplot文件夹内,如下图所示: 右键项目->添加库,弹出如下界面: 选择外部库,然后库文件选择项目文件夹qcustomplot内的libqcustomplot2.a;包含路径选择为项目文件夹qcustomplot;平台根据需要选择;链接类型选择为动态。如下为windows平台示例: 点击下一步,点完成。 此时就可以使用qcustomplot库,并且编译速度很快。 To Be Continue。。。

在windows11环境下安装CUDA11.6+Anaconda3+pyToach1.13搭建炼丹炉

0.电脑环境 系统:win11 显卡:NVIDIA GTX1650 还有一个pyCharm,其他也用不到了,需要的文章中会进行说明 1.安装CUDA11.6 目前2023.03出来的pyToach2.0是用不到了,因为最低版本支持CUDA11.7。我的显卡是1650,驱动达不到CUDA11.7的要求,因此安装不了11.7。(主要原因是和女朋友端午旅游把我计划要买的4060TI 16G钱花掉了/(ㄒoㄒ)/~~,只能继续压榨我的我的小显卡了)。 pyToach2.0看说明是比1.13快很多,但是安装方式一样的,有好显卡的一定要安装CUDA11.7进而支持pyToach2.0 PyTorch的官网:官网 可以看的具体的依赖 显卡驱动和cuda对照 首先打开 cmd 命令窗口,输出如下命令: nvidia-smi 可以看到,此时显示的表格中,有一个字段叫 CUDA Version,像我的界面是这样的: 在这个官方网站:老黄的CUDA网站 找到11.6,下载它,三个都可以下载,随便选一个 说明: 安装cuda时,第一次会让设置临时解压目录,第二次会让设置安装目录; 临时解压路径,建议默认即可,也可以自定义。安装结束后,临时解压文件夹会自动删除; 安装目录,自定义最好; 注意:临时解压目录千万不要和cuda的安装路径设置成一样的,否则安装结束,会找不到安装目录 选择自定义安装 安装完成后,配置cuda的环境变量; 命令行中,测试是否安装成功;下面是具体安装步骤: 1)双击“exe文件”,选择下载路径,换一个其他的盘也可以。 一直确定 2)自定义安装,精简版本是下载好所有组件,并且会覆盖原有驱动,所以在这里推荐自定义下载 3)如果电脑上没有visual studio,后面会让下载,所以可以取消这个复选框 4)下面是比较重要的安装路径选择,建议先在自己电脑上安装软件的盘中先建立两个文件夹: 4.1) 然后将第一个和第三个目录更换为上面的CUDAToolkit,第二个目录更换为CUDASamples。记住安装目录 后面一直向下,然后就是查看一下环境变量了。点击设置–>搜索高级系统设置–>查看环境变量 上面的环境变量是自己生成的,无需手动配置。之后在cmd下查看是否可以使用命令:注意是大写V哦 这样就可以确定安装成功了。要注意自己的显卡驱动版本和cuda版本的对应,我的1650就可以安11.6了,显卡比我高的如果驱动版本不高可以升级驱动版本。 2.安装Anaconda3 下载官网:Anaconda官网,或者是清华镜像源镜像源,我感觉都可以下载 双击exe安装包,进行安装, 1)一直下一步到这里,选择所有用户 2)安装路径,还是推荐自定义 3)只选择第二项,第二项是说要默认使用python的版本,后期手动添加环境变量 4)安装完成 5)配置环境变量,点击path 5.1) 在编辑环境变量里,点击新建 5.2)新建下面这五个变量:xxx是自己的路径 D:\xxx\xxx\Anaconda3 D:\xxx\xxx\Anaconda3\Scripts D:\xxx\xxx\Anaconda3\Library\bin D:\xxx\xxx\Anaconda3\Library\mingw-w64\bin D:\xxx\xxx\Anaconda3\Library\usr\bin 6)安装完成,验证,同时按 win + r ,输入cmd,在弹出的命令行查看anaconda版本,输入 : conda --version和python 可以看的正确的版本号以及python已托管至Anaconda。可以在电脑屏幕左下角的Windows徽标键这里,选择点击绿色圈圈Anaconda Navifator将其打开 7)接下来是镜像源的配置,这里踩坑很多,花了好几个小时才搞定,其他博客有通过命令配置的源的,然后一些包总是无法使用。这里提供一个简单的方式。进入c盘的用户路径下,点击.condarc文件,可以用记事本方式打开。 然后内容修改为如下内容,注意envs_dirs: D://DeepLearingEnvironment//envs是自己的路径哦。 channels: - defaults show_channel_urls: true default_channels: - https://mirrors.

Tcp实现文件传输的一些问题

一. 粘包问题 1. 概述 Tcp粘包是指发送方发送的若干个数据包达到接收方时粘成一个包,从接收缓冲区来看,后一个数据包的头紧接着前一个数据包的尾。 Tcp接收到数据包时,不会马上交给应用层进行处理,而是保存在接收缓冲区里,然后由应用程序主动从缓冲区读取收到的分组。这时,如果Tcp接收数据包到缓存的速度大于应用程序从缓存读取数据包的数据,多个数据包会被缓存,应用程序就可能读取到多个首尾相连在一起的包。 2. 解决思路 由于Tcp是流式协议,内容与内容之间没有分界标志,我们可以自己人为地给这些数据划分边界,在接收方就可以根据边界分出一个一个的数据包。 可以定义一个结构体MyDataPack表示数据包的头部,其中DatapackFlag可以自己定义字符串表示头部,比如我用的"DAEH_ATAD_PCT_YM"(MY_TCP_DATA_HEAD)的反序,这个字符串要避免与发送的内容一样;jsonSize表示要发送的json内容的长度。 struct MyDataPack { char DatapackFlag[20]; int jsonSize; }; 对于要发送的内容,使用json格式进行发送,便于解析。流程图如下。 2. 文件传输的过程 在文件传输过程中,为了避免接收方的接收速度跟不上发送方的发送速度,这里采用应答方式进行传输。收发双方先验证文件的文件名和md5值,主要存在以下三种情况: 如果发送方想要发送的文件在接收方有同名文件,且md5值相同,说明接收方已经存有该文件,无需再次传输。如果接收方有文件名为md5值的文件,说明接收方接收不完整,可以根据文件名为md5的文件大小确定需要继续接收的为止(实现断点续传)。如果接收方没有同名文件且没有文件名为md5的文件,则此次接收的是新文件。 在发送文件之前,发送方发送一个json数据,格式为: { type: "md5", md5: "文件的md5值", file-path: "文件在发送方的路径" } 接收方收到json数据并解析,若接收方已有该文件,直接返回发送完成。否则返回这样的json数据(ack表示下一次接收的文件位置): { type: "ack", file-path: "文件在发送方的路径", ack: number(pos) } 然后,收发双方开始循环传输数据了。发送方发送数据块,其中发送方的seq和ack相对应。 { type: "file", content: { file-path: "文件在发送方的位置", file-size: "文件的总大小", file-content: "文件块数据", seq: "文件块起始位置" } is-end: flase/true } 其时序图如下:

InnoDB的三种行锁(提供具体sql执行案例分析)

InnoDB存储引擎有3种行锁的算法,其分别是: Record Lock(记录锁):单个行记录上的范围 (锁住某一行记录)Gap Lock(间隙锁):间隙锁,锁定一个范围,但不包含记录本身 (锁住一段左开右开的区间)Next-key Lock(临键锁):Gap Lock + Record Lock,锁定一个范围,并且锁定记录本身 (锁住一段左开右闭的区间) 在学习具体行锁加锁规则之前,小伙伴们需要记住加锁规则的两条核心: 1)查找过程中访问到的对象才会加锁 这句话该怎么理解?比如有主键 id 为 1 2 3 4 5 … 10 的10 条记录,我们要找到 id = 7 的记录。注意,查找并不是从第一行开始一行一行地进行遍历,而是根据 B+ 树的特性进行二分查找,所以一般存储引擎只会访问到要找的记录行(id = 7)的相邻区间 2)加锁的基本单位是 Next-key Lock 哪些语句上面会加行锁? 1.对于常见的 DML 语句(如 UPDATE、DELETE 和 INSERT ),InnoDB 会自动给相应的记录行加写锁 2.默认情况下对于普通 SELECT 语句,InnoDB 不会加任何锁,但是在 Serializable 隔离级别下会加行级读锁 上面两种是隐式锁定,InnoDB 也支持通过特定的语句进行显式锁定: 3.SELECT * FROM table_name WHERE … FOR UPDATE,加行级写锁 4.SELECT * FROM table_name WHERE … LOCK IN SHARE MODE,加行级读锁

STM32L431RCT6的蜂鸣器的使用

在使用蜂鸣器之前,我们首先要了解蜂鸣器。蜂鸣器分 有源蜂鸣器和无源蜂鸣器,两者表面长相相同。 有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定 无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音 蜂鸣器有正负极,顶部印有+号的为正极,若蜂鸣器引脚没剪,则长的为正极。 有源蜂鸣器: 一种带有内置驱动电路的蜂鸣器。它只需要输入一个交替电压信号,就可以发出一定频率的声音。源蜂鸣器通常带有两个引脚,一个用于连接电源,另一个用于连接控制信号。当控制信号为高电平时,蜂鸣器发出声音;当控制信号为低电平时,蜂鸣器停止发声。源蜂鸣器具有驱动电路,因此其工作电压范围比无源蜂鸣器宽,可以直接连接到数字电路或微控制器的IO口上使用。 其单片机IO端口简单接法如下: R1起到限流保护作用,单片机IO端口输出低电平时有源蜂鸣器就响,反之不响。如果用三极管控制驱动有源蜂鸣器,常见接法如下,单片机IO端口输出低电平就响 无源蜂鸣器: 一种不带有内置驱动电路的蜂鸣器。它只是一个振动的电磁铁,需要外部驱动电路才能工作。无源蜂鸣器通常只有两个引脚,一个用于连接正极,另一个用于连接负极。在使用无源蜂鸣器时,需要外部电路提供一定频率的交替电压信号来驱动蜂鸣器发声。因此,无源蜂鸣器的驱动方式相对较为复杂,需要通过外部电路来实现。 总的来说,源蜂鸣器比无源蜂鸣器更容易使用,只需要提供简单的控制信号即可发出声音。而无源蜂鸣器需要外部电路的支持才能工作,使用起来相对较为复杂,但是其工作稳定性较高,可靠性也较强。 下面使用STM32L431开发板来对蜂鸣器进行开发。该开板上集成的是无源蜂鸣器,需要我们提供2KHz~5KHz的方波去驱动它。 首先根据蜂鸣器的电路图,可知蜂鸣器的管脚为PA11,可作为TIM1_CH4使用,因此使能定时器TIM1的CH4t通道,并使其输出PWM即可,对相应管脚进行设置,如下图所示: 蜂鸣器工作的频率在2KHz~5KHz,在这个频率范围内,频率越高,声音音色越清亮。因此需要设置其频率和占空比:(设定蜂鸣器的输出频率为2.5Khz,占空比为50%) 根据芯片的数据手册以及设置的时钟树可知,TIM2内部时钟来源是ABP2= 80Mhz ,对其进行与预分频处理: 计算器的时钟频率CK_CNT=fck_psc/(PSC+1)=80Mhz/(80-1+1)=1Mhz。因此所以预分频系数设置为80-1。 蜂鸣器想要工作在2.5Khz,则自动重装载值(Counter Period (AutoReload Register - 16 bits value ))ARR=1Mhz/2.5Khz=400. 占空比为50%,则Pulse=400/2=200。 为了防止蜂鸣器误发声音还需将GPIO设置为内部下拉,同时对管脚进行命名: 最后生成代码。 在tim.c相应位置添加如下代码: /*Ring_Times为蜂鸣器响几次,Interval_time为蜂鸣器响的间隔时间*/ void Beep_Start(uint8_t Ring_Times,uint16_t Interval_time) { while(Ring_Times--) { if(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } HAL_Delay(Interval_time); if(HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } HAL_Delay(Interval_time); } } 补充说明: HAL_TIM_PWM_Start() 函数 该函数的作用是启动PWM信号。 HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel) 函数参数:htim 是需要启动的PWM信号的时钟

Linux ps 命令详解

文章目录 ps补充说明语法选项实例 ps 报告当前系统的进程状态 补充说明 ps命令 用于报告当前系统的进程状态。可以搭配kill指令随时中断、删除不必要的程序。ps命令是最基本同时也是非常强大的进程查看命令,使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等,总之大部分信息都是可以通过执行该命令得到的。 语法 ps(选项) 选项 -a:显示所有终端机下执行的程序,除了阶段作业领导者之外。 a:显示现行终端机下的所有程序,包括其他用户的程序。 -A:显示所有程序。 -c:显示CLS和PRI栏位。 c:列出程序时,显示每个程序真正的指令名称,而不包含路径,选项或常驻服务的标示。 -C<指令名称>:指定执行指令的名称,并列出该指令的程序的状况。 -d:显示所有程序,但不包括阶段作业领导者的程序。 -e:此选项的效果和指定"A"选项相同。 e:列出程序时,显示每个程序所使用的环境变量。 -f:显示UID,PPIP,C与STIME栏位。 f:用ASCII字符显示树状结构,表达程序间的相互关系。 -g<群组名称>:此选项的效果和指定"-G"选项相同,当亦能使用阶段作业领导者的名称来指定。 g:显示现行终端机下的所有程序,包括群组领导者的程序。 -G<群组识别码>:列出属于该群组的程序的状况,也可使用群组名称来指定。 h:不显示标题列。 -H:显示树状结构,表示程序间的相互关系。 -j或j:采用工作控制的格式显示程序状况。 -l或l:采用详细的格式来显示程序状况。 L:列出栏位的相关信息。 -m或m:显示所有的执行绪。 n:以数字来表示USER和WCHAN栏位。 -N:显示所有的程序,除了执行ps指令终端机下的程序之外。 -p<程序识别码>:指定程序识别码,并列出该程序的状况。 p<程序识别码>:此选项的效果和指定"-p"选项相同,只在列表格式方面稍有差异。 r:只列出现行终端机正在执行中的程序。 -s<阶段作业>:指定阶段作业的程序识别码,并列出隶属该阶段作业的程序的状况。 s:采用程序信号的格式显示程序状况。 S:列出程序时,包括已中断的子程序资料。 -t<终端机编号>:指定终端机编号,并列出属于该终端机的程序的状况。 t<终端机编号>:此选项的效果和指定"-t"选项相同,只在列表格式方面稍有差异。 -T:显示现行终端机下的所有程序。 -u<用户识别码>:此选项的效果和指定"-U"选项相同。 u:以用户为主的格式来显示程序状况。 -U<用户识别码>:列出属于该用户的程序的状况,也可使用用户名称来指定。 U<用户名称>:列出属于该用户的程序的状况。 v:采用虚拟内存的格式显示程序状况。 -V或V:显示版本信息。 -w或w:采用宽阔的格式来显示程序状况。 x:显示所有程序,不以终端机来区分。 X:采用旧式的Linux i386登陆格式显示程序状况。 -y:配合选项"-l"使用时,不显示F(flag)栏位,并以RSS栏位取代ADDR栏位 。 -<程序识别码>:此选项的效果和指定"p"选项相同。 --cols<每列字符数>:设置每列的最大字符数。 --columns<每列字符数>:此选项的效果和指定"--cols"选项相同。 --cumulative:此选项的效果和指定"S"选项相同。 --deselect:此选项的效果和指定"-N"选项相同。 --forest:此选项的效果和指定"f"选项相同。 --headers:重复显示标题列。 --help:在线帮助。 --info:显示排错信息。 --lines<显示列数>:设置显示画面的列数。 --no-headers:此选项的效果和指定"h"选项相同,只在列表格式方面稍有差异。 --group<群组名称>:此选项的效果和指定"-G"选项相同。 --Group<群组识别码>:此选项的效果和指定"-G"选项相同。 --pid<程序识别码>:此选项的效果和指定"-p"选项相同。 --rows<显示列数>:此选项的效果和指定"--lines"选项相同。 --sid<阶段作业>:此选项的效果和指定"-s"选项相同。 --tty<终端机编号>:此选项的效果和指定"

代码随想录算法训练营第十六天|二叉树part03| 104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 ● 222.完全二叉树的节点个数

104.二叉树的最大深度 (优先掌握递归)Maximum Depth of Binary Tree - LeetCode 后序遍历 根节点的高度就是这颗树的最大深度。 int getHeight(node) if (node == null) return 0; 左 int leftHeight = getHeight(node.left); 右 int rightHeight = getHeight(node,right); 中 int height = Math.max(leftHeight, rightHeight) + 1 return height; /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.

IDEA配置npm启动

1、打开项目,确认package.json文件存在 找到右上角的编辑按钮 打开后 然后点击添加npm ,并配置好package.json文件的路径 保存后可以看到启动面板

SEERC2022(E,F,H,K)

正题 比赛链接:https://codeforces.com/gym/104114 E-Exercise【dp,贪心】 题目大意 给出长度为 2 n 2n 2n 的序列 c i c_{i} ci​,将 1 ∼ 2 n 1\sim 2n 1∼2n 两两配对使得每一对 ( a i , b i ) (a_i,b_i) (ai​,bi​) 的 ∣ c b i − c a i ∣ |c_{b_i}-c_{a_i}| ∣cbi​​−cai​​∣ 总和最小且对于任意 i i i 不存在 2 i − 1 2i-1 2i−1 与 2 i 2i 2i 配对的情况。 1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1≤n≤105

常用的限流方案

第一,限流方案必须是可选的,没有任何方案可以适用所有场景。第二,限流策略必须是可配置的。 集中常见的限流方式: 通过限制单位时间段内的调用量来限流。通过限制系统的并发调用程度来限流。通过漏桶(Leaky Bucket)算法来限流。通过令牌桶(Token Bucket)算法来限流 限制单位时间的调用量 通过一个计数器来统计单位时间内某个服务的访问量。如果超过了阙值,则该单位时间段那不允许继续访问,或者把请求放入队列中等下一个时间段继续访问。 单位时间不能太长,太长将导致限流效果不够“敏感”。比如我们的监控系统统计的事服务每分钟的调用量,所以很自然我们可以选择 1 分钟作为时间片段。 对于限制单位时间段内调用量的这种限流方式,实现简单,适用于大多数场景,如果阀值可以通过服务端动态配置,甚至可以当作业务开关来使用 但是也有一定的局限性,如果设定的阀值在单位时间段内的前几秒就被流量突刺消耗完了,将导致该时间段剩余的时间内该服务“拒绝服务”,这种现象被称为“突刺消耗”,并不常见。 限制系统的并发调用程度 我们通过并发限制来限流,我们通过严格的限制某服务的并发访问速度,其实也就限制了该服务单位时间段内的访问量。 并发限流一般用于服务资源有严格的限制的场景,比如连接数,线程数等。但是也未尝不能用于通用的服务场景。 从表面上看并发限流似乎很有作用,但也不可否认,它仍然可以造成流量尖刺,即每台服务器上该服务的并发量从 0 上升到阀值是没有任何阻力的,因为并发量考虑的只是服务能力边界的问题。 漏桶(Leaky Bucket)算法 漏桶算法事流量整形或者限流的常用算法之一。它有点像我们生活中用到的漏斗,液体倒进去以后在小口中以固定速率流出。漏桶算法就是这样,不管流量有多大,漏桶都保证了流量的常速率输出。既然是一个桶,那么肯定有容量,由于调用的消费速率已经固定,那么当桶的容量堆满了,则只能丢弃了。 令牌桶(Token Bucket)算法 令牌桶算法中,桶中会有一定数量的令牌,每次请求调用需要去桶中拿取一个令牌,拿到令牌后才有资格执行,否则必须等待。 有的同学或许有些疑问,如果把令牌比喻成信号量,那么好像和并发限流没什么区别嘛。 其实不是,令牌桶算法的精髓在于拿令牌和放令牌的方式,这和单纯的并发限流有明显的区别,因为每次请求时需要获取的令牌数不是固定的,比如当桶中的令牌比较多时,每次调用只需要获取一个令牌,随着令牌数的逐渐减少,当令牌使用率(使用中的令牌数/令牌总数)达到某个比率时,可能一次需要获取两个令牌,获取令牌的个数可能还会升高。归还令牌有两种方法,第一种是直接放回,第二种是什么也不做,有另一个额外的令牌生成步骤将令牌允许放回桶中。

在KVM中通过导入qcow2镜像方式安装虚拟机(命令行)

注:本文在CentOS系统中安装,其他Linux基本类似,但命令稍不同 1、打开终端,使用超级权限运行命令,安装KVM及图形管理工具 yum install qemu-kvm qemu-kvm-tools virt-manager libvirt virt-install –y 2、将VM01.qcow2格式的文件导入CentOS系统 3、使用virt-install手动创建qcow2镜像 创建一个name为VM01,4G内存,2个CPU,qcow2所在磁盘目录及文件名,网络为默认,强制导入,并设置虚拟机为随宿主机自动启动 virt-install --name VM01 --vcpus 2 --memory 4096 --import --disk path=/images/VM01.qcow2,bus=virtio --network type=default,source_mode=NAT,model=virtio --force --import --autostart 4、命令行连接虚拟机 virsh console --domain VM01 --force

【Java项目中 利用Redis实现数据缓存】

文章目录 Java SpringBoot项目中 用Redis实现数据缓存1 环境搭建1.1 maven坐标1.2 配置文件1.3 配置类 2 实现缓存短信验证码3 缓存菜品数据4 Spring Cache 缓存框架4.1 Spring Cache介绍4.2 Spring Cache常用注解4.3 Spring Cache使用方式 Java SpringBoot项目中 用Redis实现数据缓存 1 环境搭建 1.1 maven坐标 在项目的pom.xml文件中导入spring data redis的maven坐标: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 1.2 配置文件 在application.yml 中添加redis配置 redis: host: 172.17.2.94 port: 6379 password: root@123456 database: 0 1.3 配置类 在项目中加入配置类RedisConfig: @Configuration public class RedisConfig extends CachingConfigurerSupport{ @Bean public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){ RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>(); //默认的Key序列化器为:JdkSerializationRedisSerializer redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.

【MySQL】引擎InnoDB和MyISAM的区别

功能MyISAMInnoDB支持事务NoYes支持全文索引YesNo支持数据缓存NoYes保存表的总行数根据where确定全表或全索引扫描确定存储限制256TB64TB支持树索引YesYes支持Hash索引NoNo 可以根据以下的原则来选择 MySQL 存储引擎: 如果要提供提交、回滚和恢复的事务安全(ACID 兼容)能力,并要求实现并发控制,InnoDB 是一个很好的选择。如果数据表主要用来插入和查询记录,则 MyISAM 引擎提供较高的处理效率。如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存的 MEMORY 引擎中,MySQL 中使用该引擎作为临时表,存放查询的中间结果。如果只有 INSERT 和 SELECT 操作,可以选择Archive 引擎,Archive 存储引擎支持高并发的插入操作,但是本身并不是事务安全的。Archive 存储引擎非常适合存储归档数据,如记录日志信息可以使用 Archive 引擎。提示:使用哪一种引擎要根据需要灵活选择,一个数据库中多个表可以使用不同的引擎以满足各种性能和实际需求。使用合适的存储引擎将会提高整个数据库的性能。

Swift一些处理方法(ChatGPT)

ChatGPT回答的 1. 字符串根据固定宽度计算高度或根据固定高度计算宽度 根据宽度计算高度 func getHeight(for text: String, withFixedWidth width: CGFloat, font: UIFont, lineSpacing: CGFloat) -> CGFloat { let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude) let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineSpacing let attributes: [NSAttributedString.Key: Any] = [.font: font, .paragraphStyle: paragraphStyle] let attributedText = NSAttributedString(string: text, attributes: attributes) let boundingRect = attributedText.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil) return ceil(boundingRect.height) } 根据高度计算宽度 func getWidth(for text: String, withHeight height: CGFloat, font: UIFont) -> CGFloat { let constraintRect = CGSize(width: .

ETH总线

ETH总线是一种基于以太网技术的汽车通讯协议,也称为以太网总线。它是一种高速、可靠、灵活的通讯协议,能够满足现代汽车对通讯速度和数据传输量的要求。 ETH总线的主要特点包括: 1. 高速传输:ETH总线的传输速度可以达到100Mbps,比传统的CAN总线快得多。 2. 大数据传输量:ETH总线可以传输大量的数据,可以满足现代汽车对数据传输量的要求。 3. 灵活性:ETH总线可以支持多种不同的通讯协议,可以适应不同的汽车系统和设备。 4. 可靠性:ETH总线采用了多种安全机制,可以保证数据传输的可靠性和安全性。 ETH总线在现代汽车中被广泛应用,包括车载娱乐系统、导航系统、车身控制系统、发动机控制系统等。

Qt报错 Could not create pixmap from 解决办法

笔者今天运行几年前的Qt文件时,发现背景图片没有显示出来,并且出现了一个报错: Could not create pixmap from :\icon\background.jpg Could not create pixmap from :\icon\background.jpg ui文件中的代码是: MainWindow.setStyleSheet(u"background-image: url(:/icon/background.jpg);") 它调用了我的icon.qrc文件中的一个资源图片。 几次试验后,我发现把ui文件中的qrc source资源路径改成直接文件路径(相对路径或绝对路径皆可),可以成功显示背景图片 MainWindow.setStyleSheet(u"background-image: url(icon/background.jpg);") 但是这明显不是个好办法。 经过查阅资料,我得知应当是python或者qt升级后的更新特性导致,笔者当前使用的是Qt6.5,之前用得是Qt5.15。现在的.qrc资源文件会被自动编译出一个py文件,例如我的icon.qrc就被编译成了rc_icon.py文件。 (某些情况下,如果Qt没有帮你自动编译,也可以在命令行中手动编译,例如:pyrcc5 icon.qrc -o rc_icon.py 。同理.ui文件也可以手动编译,即 pyuic5 mainWindow.ui -o ui_mainWindow.py 。) 该模块将icon.qrc文件中的资源写成二进制格式并初始化在项目中,使用时只需在主文件中import rc_icon.py即可。 import rc_icon # 该模块将icon.qrc文件中的资源写成二进制格式并初始化在项目中 之后再运行项目,背景图片就可以正常显示了。

【Java 基础篇】Java 日期类详解

文章目录 导言一、java.util.Date 类二、java.time 包1、LocalDate 类2、LocalTime 类3、LocalDateTime 类4、ZonedDateTime 类 三、日期格式化和解析总结 导言 日期和时间在软件开发中是非常常见且重要的概念。Java 提供了一套强大的日期和时间 API,用于处理日期、时间、时区等相关操作。本文将详细介绍 Java 日期类的概念、用法和常见操作,并提供一些示例代码。 一、java.util.Date 类 在早期版本的 Java 中,java.util.Date 类是处理日期和时间的主要类。然而,Date 类在设计上存在一些问题,因此在 Java 8 中引入了新的日期和时间 API,推荐使用新的 API 进行日期和时间处理。 尽管如此,我们还是先了解一下 Date 类的基本用法。 Date 类用于表示特定的时间点,它包含了从协调世界时(UTC)1970 年 1 月 1 日 00:00:00 开始经过的毫秒数。下面是一个简单的示例: import java.util.Date; public class DateExample { public static void main(String[] args) { Date now = new Date(); System.out.println("Current time: " + now); } } 在上述示例中,我们使用 new Date() 创建了一个表示当前时间的 Date 对象,并通过 System.

Linux之Centos7.6版本下载及安装Go语言环境配置,安装Go1.18版本教程笔记-2023版

文章目录 一、Linux下安装Go环境1.远程获取2.解压3. 添加环境变量5.Go环境配置图配置完成信息图 二、VsCode连接我们Go2.1安装对应的插件2.2进行连接3.相关配置4.成功连接 一、Linux下安装Go环境 推荐在linux下安装Go,因为windows配置的话有些运行不了,在我做Mit6.824时候遇到的,因此记录下linux环境下怎么安装go 1.远程获取 wget -c https://studygolang.com/dl/golang/go1.15.linux-amd64.tar.gz 这个可以直接在虚拟机中运行,或者可以在Go官网下载,然后上传这个进行解压操作 2.解压 tar -zxvf go1.15.linux-amd64.tar.gz -C /usr/local 3. 添加环境变量 需要添加GO的环境变量到系统$PATH中. GOPATH这个环境变量它指定了一个目录, 这个目录即工作目录,它包含了我们所有的go源码 。 我们写的代码可以放到这个目录下面 按下述代码执行就好 # 创建一个目录 mkdir -p /home/user/goproject #打开配置环境变量的文件 vim /etc/profile #设置 export GOROOT=/usr/local/go export PATH=$PATH:$GOROOT/bin export GOPATH=$HOME/goproject export GO111MODULE=on export GOPROXY=https://goproxy.cn # 使得配置文件生效 source /etc/profile # 查看是否生效 go version go env 5.Go环境配置图 配置完成信息图 二、VsCode连接我们Go 我们不可能在虚拟机中开发,因此选用一个IDE进行开发 详细文档参考官方网址: https://code.visualstudio.com/docs/remote/ssh#_connect-to-a-remote-host 2.1安装对应的插件 2.2进行连接 3.相关配置 4.成功连接

技术精讲 | BEVFusion: 基于统一BEV表征的多任务多传感器融合

观点摘要:该论文是BEV模型研究传感器融合中很重要的一个工作,其实现特征级融合的同时,利用预计算(precomputing)和间隙降低(interval reduction)在BEV模型重要的模块“视角转换”中实现了对特征聚合的BEV池化(pooling)操作大幅加速,便于BEV模型在客户端的部署。 arXiv上传于2022年5月26日论文“BEVFusion: Multi-Task Multi-Sensor Fusion with Unified Bird’s-Eye View Representation“,来自MIT韩松团队的工作报告(注:NeurIPS会议投稿格式)。 前不久介绍过一篇BEV多传感器融合的目标检测工作:“FUTR3D,一个统一的传感器融合3D检测框架”: https://zhuanlan.zhihu.com/p/499567644 还有CVPR 2022上的传感器融合工作 TransFusion (注:是在图像平面的特征融合,不是在BEV): https://zhuanlan.zhihu.com/p/485971924 将多传感器融合对于准确可靠的自动驾驶系统至关重要。最近提出的方法基于点级(point-level)融合:使用摄像头特征增强激光雷达点云。然而,摄像头到激光雷达的投影丢弃了摄像头特征的语义密度(semantic density),阻碍了此类方法的有效性,尤其是对于面向语义的任务(如3D场景分割)。 本文提出的BEVFusion是一种多任务多传感器融合框架,其统一BEV表征空间中的多模态特征,很好地保留了几何和语义信息。为实现这一点,优化BEV池化,诊断并解除视图转换中的关键效率瓶颈,将延迟减少了40倍。BEVFusion从根本上来说是任务无关的,无缝支持不同的3D感知任务,几乎没有架构的更改。 在nuScenes数据集的3D目标检测上实现1.3%的mAP和NDS提升,在BEV分割上实现了13.6%的mIoU提升,计算成本降低了1.9倍。代码将开源 https://github.com/mit-han-lab/。 自动驾驶系统配备了各种传感器。例如,Waymo的自动驾驶车辆有29个摄像头、6个雷达和5个激光雷达。不同的传感器提供互补信号:例如,摄像头捕捉丰富的语义信息,激光雷达提供精确的空间信息,而雷达提供即时速度估计。因此,多传感器融合对于准确可靠的感知具有重要意义。 来自不同传感器的数据以根本不同的方式表征:例如,摄像头在透视图中捕获数据,激光雷达在3D视图中捕获数据。为了解决这种视图差异,必须找到一种适用于多任务多模态特征融合的统一表征。由于在2D感知方面取得了巨大成功,自然的想法是将激光雷达点云投影到摄像头图像平面上,并使用2D CNN处理RGB-D数据。然而,这种激光雷达到摄像头的投影引入了严重的几何畸变,对于面向几何的任务(如3D目标识别)的效率较低。 最近的传感器融合方法遵循了另一个方向,用语义标注、CNN特征或2D图像中的虚拟点(virtual points)来增强激光雷达点云,然后应用现有基于激光雷达的检测器预测3D边框。尽管这些点级融合方法在大规模检测基准上表现出了卓越的性能,但几乎不适用于面向语义的任务,如BEV地图分割。这是因为摄像头到激光雷达的投影在语义上是有损的,而BEB Fusion就是想避免这个几何和语义的损失,建立BEV特征的融合表征,实现3D语义任务。 如图所示:对于典型的32线激光雷达扫描,只有5%的摄像头特征与激光雷达点匹配,而其他所有特征都将被删除。对于更稀疏的激光雷达(或成像雷达),这种密度差异将变得更加剧烈。 近年来,多传感器融合方法可分为提议级(proposal level)融合和点级融合方法。早期方法MV3D在3D中创建目标提议,并将其投影到图像以提取RoI特征。F-PointNet、F-ConvNet和CenterFusion都将图像提议提升到3D平截体(frustum)中。最近的工作FUTR3D和TransFusion定义了3D空间中的目标查询,并将图像特征融合到这些提议中。所有提议级融合方法都是以目标为中心的,不能简单地推广到其他任务,如BEV地图分割。另一方面,点级融合方法通常将图像语义特征绘制到前景FG激光雷达点上,并在修饰的(decorated)点云输入上做基于激光雷达的检测。因此,它们既以目标为中心,又以几何为中心。其中,PointPaint、PointAugmenting、MVP、FusionPaint和AutoAlign是(激光雷达)输入级修饰,而Deep Continuous Fusion和DeepFusion是特征级修饰。 多任务CNN在2D计算机视觉领域也得到了很好的研究,包括联合目标检测、实例分割、姿势估计和人机交互。最近同时出现的研究M2BEV和BEVFormer,联合执行3D目标检测和BEV分割。上述方法均未考虑多传感器融合。MMF同时使用摄像头和激光雷达输入进行深度图补全和目标检测,但仍然以目标为中心,不适用于BEV地图分割。 如图所示是BEVFusion流水线概览:给定不同的感知输入,首先应用特定于模态的编码器来提取其特征;将多模态特征转换为一个统一的BEV表征,其同时保留几何和语义信息;存在的视图转换效率瓶颈,可以通过预计算和间歇降低来加速BEV池化过程;然后,将基于卷积的BEV编码器应用到统一的BEV特征中,以缓解不同特征之间的局部偏准;最后,添加一些特定任务头支持不同的3D场景理解工作。 本文采用BEV作为融合的统一表征,该视图对几乎所有感知任务都很友好,因为输出空间也在BEV。更重要的是,到BEV的转换同时保持了几何结构(来自激光雷达特征)和语义密度(来自摄像头特征)。一方面,LiDAR到BEV投影将稀疏LiDAR特征沿高度维度(height dimension)展平,因此不会产生几何失真。另一方面,摄像头到BEV投影将每个摄像头特征像素投射回3D空间的一条光线中(ray casting),这可以生成密集的BEV特征图,并保留了摄像头的全部语义信息。 摄像头到BEV的变换非常重要,因为与每个摄像头图像特征像素关联的深度(depth)本质上是不明确的。根据LSS,明确预测每个像素的离散深度分布。然后,沿着摄像头光线将每个特征像素分散成D个离散点,并根据相应的深度概率重缩放(rescale)相关特征。这将生成大小为N*H*W*D的摄像头特征点云,其中N是摄像头数,(H,W)是摄像头特征图大小。此类3D特征点云沿x、y轴量化,步长为r(例如,0.4m)。用BEV池化操作来聚合每个r×r BEV网格内的所有特征,并沿z轴展平特征。 虽然简单,但BEV池化的效率和速度惊人地低,在RTX 3090 GPU上需要500毫秒以上(而模型的其余部分计算只需要100毫秒左右)。这是因为摄像头特征点云非常大,即典型的工作负载,每帧可能生成约200万个点,比激光雷达特征点云密度高两个数量级。为了消除这一效率瓶颈,建议通过预计算和间歇降低来优化BEV池化进程。 如图所示:摄像机到BEV变换(a)是在统一的BEV空间进行传感器融合的关键步骤。然而,现有的实现速度非常慢,单个场景可能需要2秒的时间。文章提出了有效的BEV池化方法(b),通过预计算使间歇降低和加快网格关联,视图转换模块(c,d)的执行速度提高了40倍。 1、预计算 BEV池化的第一步是将摄像头特征点云的每个点与BEV网格相关联。与激光雷达点云不同,摄像头特征点云的坐标是固定的(只要摄像头内参外参保持不变,通常在适当标定后)。基于此,预计算每个点的3D坐标和BEV网格索引。还有,根据网格索引对所有点进行排序,并记录每个点排名。在推理过程中,只需要根据预计算的排序对所有特征点重排序。这种缓存机制可以将网格关联的延迟从17ms减少到4ms。 2、间歇降低 网格关联后,同一BEV网格的所有点将在张量表征中连续。BEV池化的下一步是通过一些对称函数(例如,平均值、最大值和求和)聚合每个BEV网格内的特征。现有的实现方法首先计算所有点的前缀和(prefix sum),然后减去索引发生变化的边界值。然而,前缀和操作,需要在GPU进行树缩减(tree reduction),并生成许多未使用的部分和(因为只需要边界值),这两种操作都是低效的。为了加速特征聚合,文章里实现一个专门的GPU内核,直接在BEV网格并行化:为每个网格分配一个GPU线程,该线程计算其间歇和(interval sum)并将结果写回。该内核消除输出之间的依赖关系(因此不需要多级树缩减),并避免将部分和写入DRAM,从而将特征聚合的延迟从500ms减少到2ms。 3、总结 通过优化的BEV池化,摄像头到BEV的转换速度提高了40倍:延迟从500ms减少到12ms(仅为模型端到端运行时间的10%),并且可以在不同的分特征辨率之间很好地扩展。在共享BEV表征中,这是统一多模态感知特征的关键促成因素。两项并行化工作也发现了纯摄像头3D检测的这一效率瓶颈。假设均匀深度分布,或截断每个BEV网格内的点,可以近似视图transformer计算。相比之下,该技术在没有任何近似的情况下是精确的,但仍然更快。 实验结果如下: 深信科创:致力于自动驾驶工业软件 深信科创是一家专注于提供自动驾驶仿真及智慧交通解决方案的国家高新技术企业。公司基于人工智能、软件测试、数字孪生与大数据等技术,致力于自动驾驶工具链的研发,拥有一支高素质的研发团队,研发了国际领先的自动驾驶仿真及数据闭环工具链SYNKROTRON™ Oasis产品系列,能够提供高精度传感器模型、动力学模型及感知级交通环境仿真解决方案等,客户可以在仿真平台上对自动驾驶系统开展大规模的仿真测试和模型训练,提前识别自动驾驶系统缺陷、降低实车测试成本、消除场景端落地的安全隐患,加速自动驾驶技术在场景端的安全落地。

vue在移动端调用扫一扫功能

一、 uni.app 但是H5不支持 uni.scanCode(OBJECT) : 调起客户端扫码界面,扫码成功后返回对应的结果。 平台差异: 示例代码 // 允许从相机和相册扫码 uni.scanCode({ success: function (res) { console.log('条码类型:' + res.scanType); console.log('条码内容:' + res.result); } }); // 只允许通过相机扫码 uni.scanCode({ onlyFromCamera: true, success: function (res) { console.log('条码类型:' + res.scanType); console.log('条码内容:' + res.result); } }); // 调起条码扫描 uni.scanCode({ scanType: ['barCode'], success: function (res) { console.log('条码类型:' + res.scanType); console.log('条码内容:' + res.result); } }); 二、使用HTML5+ API barcode 创建扫码识别控件对象 Barcode plus.barcode.create(id, filters, styles, autoDecodeCharset); id: ( String ) 必选 扫码识别控件的标识

windows系统安装nvm 不成功

安装nvm时按照网上的教程安装,习惯性的将nvm安装到了专用的D盘,一切按步骤完成后打开cmd输入nvm - v 测试nvm是否安装成功,但是显示nvm不是内部指令,环境变量都是安装nvm时自动生成的无需手动添加。只有在管理员模式下才能使用nvm -v 。D盘内的nvm应用程序权限正常,尝试多种路径后依然无法直接在user用户下使用nvm指令。 因此,我再次卸载重装,此次安装路径全部使用默认值,安装完毕后nvm -v测试成功。 nvm 安装node指令 nvm install 版本号 nvm切换node版本 nvm use 版本号 删除不需要的版本 nvm install 版本号