谈谈静态代理和动态代理

目录 一、静态代理二、动态代理2.1、JDK代理2.2、CGLib动态代理2.2.1、定义实体2.2.2、被代理的类2.2.3、cglib代理 一、静态代理 在运行前,已经通过逻辑代码有了代理类的字节码文件,只能代理单一的服务对象,有多个服务对象的话每个对象都得创建自己的代理类 图中的 Subject 是程序中的业务逻辑接口,RealSubject 是实现了 Subject 接口的真正业务类,Proxy 是实现了 Subject 接口的代理类,封装了一个 RealSubject 引用。在程序中不会直接调用 RealSubject 对象的方法,而是使用 Proxy 对象实现相关功能。 Proxy.operation() 方法的实现会调用其中封装的 RealSubject 对象的 operation() 方法,执行真正的业务逻辑。代理的作用不仅仅是正常地完成业务逻辑,还会在业务逻辑前后添加一些代理逻辑,也就是说,Proxy.operation() 方法会在 RealSubject.operation() 方法调用前后进行一些预处理以及一些后置处理。这就是我们常说的“代理模式”。 使用代理模式可以控制程序对 RealSubject 对象的访问,如果发现异常的访问,可以直接限流或是返回,也可以在执行业务处理的前后进行相关的预处理和后置处理,帮助上层调用方屏蔽底层的细节。例如,在 RPC 框架中,代理可以完成序列化、网络 I/O 操作、负载均衡、故障恢复以及服务发现等一系列操作,而上层调用方只感知到了一次本地调用。 代理模式还可以用于实现延迟加载的功能。我们知道查询数据库是一个耗时的操作,而有些时候查询到的数据也并没有真正被程序使用。延迟加载功能就可以有效地避免这种浪费,系统访问数据库时,首先可以得到一个代理对象,此时并没有执行任何数据库查询操作,代理对象中自然也没有真正的数据;当系统真正需要使用数据时,再调用代理对象完成数据库查询并返回数据。常见 ORM 框架(例如,MyBatis、 Hibernate)中的延迟加载的原理大致也是如此。 /** * 代理接口 * @author xnn * @date 2021-09-30 10:58 */ public interface Subject { void doSomeThing(String thing); } /** * 真正执行任务的类 */ public class RealSubject implements Subject { /** * 执行任务。 * @param thing */ @Override public void doSomeThing(String thing) { System.

【Sortable】前端拖拽库 | 简洁 | 实用 | 强大

前言 官网 - http://www.sortablejs.com/index.html中文文档 - https://www.itxst.com/sortablejs/neuinffi.htmlnpm - https://www.npmjs.com/package/sortablejs npm下载 npm i sortablejs umd <script src="https://www.itxst.com/package/sortable/sortable.min.js"></script> 例子 const el = document.querySelector('.template-group')//拖拽的父元素 new Sortable(el, { group: { name: "z", pull: true, put: true }, filter: '.viz-group',// 过滤 draggable: ".viz-item",//拖拽的元素 animation: 300,//动画时间 handle: ".viz-move",//拖拽句柄 - 就是要拖拽的子元素 easing: 'cubic-bezier(0.16, 1, 0.3, 1)',//动效 ghostClass: 'drop-select',//拖拽class }) 拖拽句柄解释 如下图 假如设置了拖拽句柄,要拖拽红框的元素,黄框就是拖拽句柄。只有当拖拽句柄才能拖拽红框元素 Demo demo.html <style> .box { width: 200px; max-width: 220px; } .item, .title { display: flex; justify-content: space-between; height: 30px; align-items: center; border: solid 1px #ccc; border-style: none none solid solid; } .

mysql详解(全)

mysql存储引擎 库表基础属性 mysql操作 mysql表操作 mysql表内容操作 mysql查询流程 数据记录存储格式 系统表汇总 建表规范 建表约束 字段类型 sql函数 存储过程 sql关键字 sql空间数据 sql索引 sql行列互转 数据库视图 sql慢查询分析 sql优化思路 sql集合运算 sql表的联结 mysql事务 执行计划 分库分表 单表迁移分布式表思路 锁表以及解除方式 mysql存储引擎 MySQL主要存储引擎以及功能如下: MySQL5.5之前,默认存储引擎是MylSAM,5.5之后变成了InnoDB。 大多数情况下,使用默认的InnoDB就够了。如果要提供提交、回滚和恢复的事务安全(ACID 兼容)能力,并要求实现并发控制,InnoDB 就是比较靠前的选择了。 如果数据表主要用来插入和查询记录,则 MyISAM 引擎提供较高的处理效率。 如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存的 MEMORY 引擎中,MySQL 中使用该引擎作为临时表,存放查询的中间结果。 使用哪一种引擎可以根据需要灵活选择,因为存储引擎是基于表的,所以一个数据库中多个表可以使用不同的引擎以满足各种性能和实际需求。使用合适的存储引擎将会提高整个数据库的性能。 库表基础属性 数据库字符集 数据库变量 表字段属性 数据库字符集 Mysql默认的字符集编码是Latin1,其不支持中文,所以建库时需要进行设置charset=utf8 数据库变量 变量分为,系统变量和自定义变量两种。系统变量是由系统提供,不是用户定义,属于服务器层面;自定义变量则是用户自定义的。 系统变量下有全局变量和会话变量。服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启,而会话变量则仅仅针对于当前会话(连接)有效。 全局变量使用示例 语句内容show global variables;查看所有的系统变量show global variables like ‘%char%’;查看满足条件的部分系统变量select @@global.系统变量名;查看指定的某个系统变量的值set @@global.系统变量名=值;为某个系统变量赋值set global 系统变量名=值;为某个系统变量赋值 会话变量使用示例 语句内容show session variables;查看所有的会话变量show session variables like ‘%char%’;查看满足条件的部分会话变量select @@session.

VUE-Element组件(二)NavMenu导航菜单--层级关系

NavMenu第一篇的几个例子,固定的菜单中菜单层级是在<el-menu>只写死的,动态菜单权限中层级也是由后台代码排好的(父子关系),到前端接收的menuList可以直接循环渲染了。现在后端只传回有权限的菜单编码,层级关系放在前端路由配置,然后根据路由与后端返回的菜单编码过滤用户权限。 一、多级路由:之前的路由均为二级路由(当然也可以写成多级路由),如果需要配置多级路由,嵌套多层children就可以了,其次要注意component。最外层component指向导航页即NavMenu菜单页面,其他的父级路由component指向一个空的路由跳转页面(否则会出现多个菜单)。如三级菜单: children:[ { path: '/my/user', name: 'myUser', meta: { title: '用户', noControl: true, icon: 'el-icon-help', }, component: MultiLevelMenu, children: [ { path: '/my/user1', name: 'user1', meta: { title: '用户1页面', noControl: true, showAlways: true }, component: MultiLevelMenu, children: [ { path: '/my/user1/user11', name: 'overview', meta: { title: '用户11页面', headerConfig: { isStartFlag: true, isUserCenter: true }, }, component: resolve => require(['@/views/user/index11'], resolve) }, { path: '/my/user1/user12', name: 'overview', meta: { title: '用户12页面', headerConfig: { isStartFlag: true, isUserCenter: true }, }, component: resolve => require(['@/views/user/index12'], resolve) }, ] }, //详情页面 { path: '/my/userDetail', name: 'userDetail', meta: { title: '详情', headerConfig: { isStartFlag: true, isUserCenter: true }, noControl: true, hideInMenu: true, isDetailPage: true, }, component: resolve => require(['@/views/user/detail/index'], resolve) } ] } ] 空页面代码:

python字典:怎么取出key对应的值

目录 python中的字典是什么 怎么判断key是否在字典中 怎么取出key对应的值 总结 python中的字典是什么 在Python中,字典(Dictionary)是一种无序且可变的数据类型,用于存储键-值(Key-Value)对。字典通过键来访问和操作其对应的值,而不是使用索引。 字典的特点如下: 1. 键唯一性:字典中的键必须是唯一的,一个键只能对应一个值。如果重复添加相同的键,后面的值将会覆盖前面的值。 2. 无序性:字典中的键-值对没有固定的顺序,即使添加的顺序不同,字典的遍历顺序也可能不同。 3. 可变性:字典中的键-值对可以进行添加、删除和修改操作。 字典用大括号 `{}` 来定义,其中的每个键值对由冒号 `:` 分隔,键和值之间用逗号 `,` 分隔。示例: # 创建一个字典 person = {"name": "Alice", "age": 25, "city": "New York"} # 访问字典中的值 print(person["name"]) # 输出: Alice print(person["age"]) # 输出: 25 # 修改字典中的值 person["age"] = 26 print(person["age"]) # 输出: 26 # 添加新的键值对 person["gender"] = "Female" print(person) # 输出: {'name': 'Alice', 'age': 26, 'city': 'New York', 'gender': 'Female'} # 删除键值对 del person["

SpringBootAdmin介绍

一、SpringBootAdmin 简介 1.1 概述 SpringBootAdmin 是一个非常好用的监控和管理的开源组件,该组件能够将 Actuator 中的信息进行界面化的展示,也可以监控所有 Spring Boot 应用的健康状况,提供实时警报功能。 1.2 功能特性 显示应用程序的监控状态应用程序上下线监控查看 JVM,线程信息可视化的查看日志以及下载日志文件动态切换日志级别Http 请求信息跟踪… 二、Server端整合 2.1 添加pom配置 <!--Admin+Actuator 健康信息健康--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> </dependency> 2.2 配置yaml参数 # Boot参数配置信息 spring: application: name: xs-monitor-server profiles: active: dev boot: admin: monitor: default-timeout: 5000 client: url: http://localhost:${server.port}${spring.boot.admin.context-path} #注册实例 优先使用IP instance: prefer-ip: true # 监控访问前缀信息 context-path: /admin # Actuator 监控端点的配置项 management: health: mail: enabled: false endpoints: web: base-path: /actuator exposure: include: '*' endpoint: health: show-details: always logfile: external-file: ${user.

Redis的数据淘汰策略

目录 一、概念 二、redis有哪些数据淘汰策略 三、注意事项 四、怎么选择数据淘汰策略 五、总结 一、概念 Redis的数据淘汰策略指的是在内存不足的情况下,如何决定哪些数据需要被淘汰以释放内存空间,当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉。 二、redis有哪些数据淘汰策略 1、noeviction noeviction是Redis的默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。 2、allkeys-lru `allkeys-lru`策略会优先淘汰最近最少使用的键(Least Recently Used,LRU)。在内存不足时,Redis会从所有的键中选择最近最少使用的键进行删除,直到有足够的内存或者所有键都被删除。 3、allkeys-lfu `allkeys-lfu`策略会优先淘汰使用频率最少的键(Least Frequently Used,LFU)。在内存不足时,Redis会从所有的键中选择使用频率最少的键进行删除,直到有足够的内存或者所有键都被删除。 4、 volatile-lru `volatile-lru`策略与`allkeys-lru`类似,但是它只会淘汰设置了过期时间(TTL)的键。 5、volatile-lfu `volatile-lfu`策略与`allkeys-lfu`类似,但是它只会淘汰设置了过期时间的键。 6、volatile-random `volatile-random`策略会随机淘汰设置了过期时间的键。 7、allkeys-random `allkeys-random`策略会随机淘汰任意的键。 8、volatile-ttl 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰 三、注意事项 在Redis中,可以通过`maxmemory-policy`配置项来设置数据淘汰策略,默认策略是`noeviction`。需要注意的是,当Redis的`maxmemory`配置项为0时,表示Redis不限制内存使用,不会进行数据淘汰,这样可能会导致Redis使用过多的内存导致服务崩溃。因此,建议在生产环境中设置一个合适的`maxmemory`和`maxmemory-policy`来防止这种情况的发生。 四、怎么选择数据淘汰策略 在Redis中选择合适的数据淘汰策略需要根据具体的业务场景以及Redis的使用情况来确定。一般来说,可以基于以下几个方面来选择合适的数据淘汰策略: 1、数据类型和业务场景: 不同的数据类型和业务场景下,数据淘汰策略的选择不同。例如,在缓存需要快速响应并尽量减少淘汰操作的情况下,可以使用`volatile-lru`策略;在记录使用频率较低的长时间存在的监控数据时,可以使用`allkeys-lfu`策略。 2、内存使用情况: 数据淘汰策略的选择还受到内存使用情况的限制。如果Redis的内存使用率已经持续很高了,可以考虑使用`allkeys-lru`、`volatile-lru`或者`volatile-lfu`等策略来优先淘汰长时间未使用的键或达到过期时间的键。 3、数据规模和维护成本: 数据规模和维护成本也是影响数据淘汰策略的因素。当数据规模很大时,如果使用`allkeys-lru`或`allkeys-lfu`策略,可能会导致Redis频繁进行扫描,对性能造成影响。因此,对于数据规模较大的场景,建议选择`volatile-lru`或`volatile-lfu`策略。 五、总结 总之,在选择数据淘汰策略时,需要结合具体的业务场景、内存使用情况、数据规模和维护成本等多方面考虑,合理配置maxmemory和maxmemory-policy参数,以确保Redis的性能和稳定运行。同时,需要注意定期监控Redis的内存使用情况,及时进行调整和优化。

依葫芦画瓢-Kotlin --003.基本语法

文章目录 1、基本类型1.1 数字1.1.1 字面常量1.1.2 显式转换 1.2 字符串 2 变量与常量2.1 常量2.2 属性包装 3 函数3.1 函数声明单表达式返回值类型函数类型函数参数3.2 闭包3.3 lambda 表达式 1、基本类型 kotlin 的基本类型主要包括: 数字字符布尔数组 看起来与Java差不多,但是有一个根本的区别,kotlin 中的基本类型也都是面向对象的,而Java中的基本类型还区分包装类型和原始类型。 1.1 数字 Kotlin 对数字的处理与Java类似,但也有很大差异。 然而对于数字类型, Kotlin 却不兼容 Java 中的类型 例如,你不能这样在 Kotlin中声明和初始化一个 Java 中的整型类型: var a : Integer= Intege r(3) 同样,在 Kotlin 中,不能声明 Java 中其他的基本数字类型,例如: var b : Long = Long () 之所以会这样,是因为 Kotlin 有自己的一套基本类型,并且有重名的类,例如Kotlin 的长整型类型为 Long ,这与 Java 的长整型类型名称相同。 kotlin 一共提供了6种类型 Double、Float、Long、Int、Short、Byte var c='a' var a = c as Int val b = 1 1.

matlab遗传算法工具箱

以下内容大部分来源于《MATLAB智能算法30个案例分析》,仅为学习交流所用。 1理论基础 1.1遗传算法概述 遗传算法(genetic algorithm,GA)是一种进化算法,其基本原理是仿效生物界中的“物竞天择、适者生存”的演化法则。遗传算法是把问题参数编码为染色体,再利用迭代的方式进行选择、交叉以及变异等运算来交换种群中染色体的信息,最终生成符合优化目标的染色体。 在遗传算法中,染色体对应的是数据或数组,通常是由一维的串结构数据来表示,串上各个位置对应基因的取值。基因组成的串就是染色体,或者称为基因型个体(individuals)。一定数量的个体组成了群体(population)。群体中个体的数目称为群体大小(population size),也称为群体规模。而各个个体对环境的适应程度叫做适应度(fitness)。 遗传算法的基本步骤如下: 1.编码 GA在进行搜索之前先将解空间的解数据表示成遗传空间的基因型串结构数据,这些串结构数据的不同组合便构成了不同的点。 2.初始群体的生成 随机产生N个初始串结构数据,每个串结构数据称为一个个体,N个个体构成了一个群体。GA以这N个串结构数据作为初始点开始进化。 3.适应度评估 适应度表明个体或解的优劣性。不同的问题,适应性函数的定义方式也不同。4、选择 选择的目的是为了从当前群体中选出优良的个体,使它们有机会作为父代为下一代繁殖子孙。遗传算法通过选择过程体现这一思想,进行选择的原则是适应性强的个体为下一代贡献一个或多个后代的概率大。选择体现了达尔文的适者生存原则。 5.交叉 交叉操作是遗传算法中最主要的遗传操作。通过交叉操作可以得到新一代个体,新个体组合了其父辈个体的特性。交叉体现了信息交换的思想。 6.变异 变异首先在群体中随机选择一个个体,对于选中的个体以一定的概率随机地改变串结构数据中某个串的值。同生物界一样,GA中变异发生的概率很低,通常取值很小。 1.2谢菲尔德遗传算法工具箱 1.工具箱简介 谢菲尔德(Sheffield)遗传算法工具箱是英国谢菲尔德大学开发的遗传算法工具箱。该工具箱是用MATLAB高级语言编写的,对问题使用M文件编写,可以看见算法的源代码,与此匹配的是先进的MATLAB数据分析、可视化工具、特殊目的应用领域工具箱和展现给使用者具有研究遗传算法可能性的一致环境。该工具箱为遗传算法研究者和初次实验遗传算法的用户提供了广泛多样的实用函数。 2.工具箱添加 用户可以通过网络下载gatbx工具箱(官方github下载地址:gatbx)。然后把工具箱添加到本机的MATLAB环境中,该工具箱的安装步骤如下: (1)将工具箱文件夹复制到本地计算机中的工具箱目录下,路径为matlabroot\ toolbox。其中matlabroot为 MATLAB的安装根目录。 (2)将工具箱所在的文件夹添加到MATLAB的搜索路径中,有两种方式可以实现,即命令行方式和图形用户界面方式。 ①命令行方式:用户可以调用addpath命令来添加,例如: str = [matlabroot, '\toolbox\gatbx']; addpath(str) ②图形用户界面方式:在 MATLAB主窗口上选择主页→设置路径菜单项,单击“添加文件夹”按钮。找到工具箱所在的文件夹( gatbx),单击“OK”按钮,则工具箱所在的文件夹出现在“设置路径”的最上端。单击“保存”按钮保存搜索路径的设置,然后单击“关闭”按钮关闭对话框。 (3)批量修改后缀 该工具箱文件后缀为M,即*.M,matlab是区分大小写的,如果这一步没有操作,将会报错,在该文件路径下,新建txt,输入以下命令,并保存修改文件后缀为bat,点击运行: ren *.M *.m 如果文件夹中.M后缀的文件并未修改为.m的后缀,可以通过一个中间后缀名进行修改,先将其后缀名转为.txt,再转为.m,也就是先输入下面的命令,并保存修改文件后缀为bat,点击运行: ren *.M *.txt 所有.M后缀的文件都修改为了.txt后缀,然后再输入下面的命令并保存修改文件后缀为bat,点击运行: ren *.txt *.m 这样就把所有文件的后缀名都改成了.m文件。如果还是不行的话。。。。。就一个一个手动改吧。 2案例背景 2.1问题描述 1.简单一元函数优化 利用遗传算法寻找以下函数的最小值: 2.多元函数优化 利用遗传算法寻找以下函数的最大值: 2.2解题思路及步骤 将自变量在给定范围内进行编码,得到种群编码,按照所选择的适应度函数并通过遗传算法中的选择,交叉和变异对个体进行筛选和进化,使适应度值大的个体被保留,小的个体被淘汰,新的群体继承了上一代的信息,又优于上一代,这样反复循环,直至满足条件,最后留下来的个体集中分布在最优解周围,筛选出其中最优的个体作为问题的解。 3 MATLAB程序实现 下面详细介绍各部分常用的函数,其他的函数用户可以直接参考工具箱中的GATBXA2.PDF文档,其中有详细的用法介绍。 3.1 工具箱结构 遗传算法工具箱中的主要函数如表1所列。 表1 遗传算法工具箱的主要函数列表 3.2遗传算法常用函数 1.创建种群函数——crtbp功能:创建任意离散随机种群。调用格式:

【大数据】Hadoop概述

文章目录 一、大数据概论1. 大数据概念2. 大数据特点3. 大数据应用场景4. 大数据部门5. 大数据技术生态体系 二、Hadoop概述1. Hadoop是什么2. Hadoop发展历史3. Hadoop三大发行版本4. Hadoop优势5. Hadoop组成5.1 Hadoop1.x、2.x、3.x区别5.2 HDFS架构概述5.3 YARN架构概述5.4 MapRuduce架构概述5.5 HDFS、YARN、MapReduce三者关系 一、大数据概论 1. 大数据概念 大数据:指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。大数据主要解决海量数据的采集、存储和分析计算问题。按顺序给出数据存储单位: bit、byte、KB、MB、GB、TB、PB、EB、ZB、YB、BB、NB、DB 1Byte = 8bit 1K = 1024Byte 1T = 1024G 2. 大数据特点 Volume(大量) 数据的大小决定所考虑的数据的价值和潜在的信息Velocity(高速) 大数据区分于传统数据挖掘的最显著特征Variety(多样) 数据被分为结构化数据和非结构化数据Value(低价值密度) 价值密度的高低和数据总量的大小成反比 3. 大数据应用场景 抖音:推荐用户喜欢的视频电商站内广告:推荐给用户推荐可能喜欢的商品零售:分析用户消费习惯,为用户购买商品提供方便保险:海量数据挖掘及风险预测,精准营销,提升精细化定价能力金融:多维度体现用户特征,推荐优质客户人工智能+5G+物流网+虚拟与现实 4. 大数据部门 大数据部门间业务流程分析 大数据部门内组织架构 5. 大数据技术生态体系 二、Hadoop概述 1. Hadoop是什么 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。主要解决海量数据的存储和海量数据的分析计算问题。广义上来说,Hadoop通常是一个更广泛的概念——Hadoop生态圈。 2. Hadoop发展历史 Hadoop创始人Doug Cutting,为了实现与Google类似的全文搜索功能,他在Lucene框架基础上进行优化升级,查询引擎和索引引擎。2001年年底Lucene成为Apache基金会的一个子项目。对于海量数据的场景,Lucene框架面对与Google同样的困难,存储海量数据困难,检索海量速度慢。学习和模仿Google解决这些问题的办法:微型版Nutch。可以说Google是Hadoop的思想之源(Google在大数据方面的三篇论文) GFS -->HDFS、Map-Reduce —>MR、BigTable -->Hbase2003-2004年,Google公开了部分GFS和MapReduce思想的细节,以此为基础DougCutting等人用了2年业余时间实现了DFS和MapReduce机制,便Nutch性能飙升。2005年Hadoop作为Lucene的子项目Nutch的一部分正式引入Apache基金会。2006年3月份,Map-Reduce和Nutch Distributed File System(NDFS)分别被纳入到Hadoop项目中,Hadoop就此正式诞生,标志着大数据时代来临。名字来源于Doug Cutting儿子的玩具大象 3. Hadoop三大发行版本 Hadoop三大发行版本:Apache、Cloudera、Hortonworks。 Apache版本最原始(最基础)的版本,对于入门学习最好。Cloudera内部集成了很多大数据框架,对应产品CDH。Hortonworks文档较好,对应产品HDP。Hortonworks现在已经被Cloudera公司收购,推出新的品牌CDP。 4. Hadoop优势 高可靠性:Hadoop底层维护多个数据副本,所以即使Hadoop某个计算元素或存储出现故障,也不会导致数据的丢失。高扩展性:在集群间分配任务数据,可方便的扩展数以千计的节点。高效性:在MapReduce思想下,Hadoop是并行工作的,以加快任务处理速度。高容错性:能够自动将失败的任务重新分配。 5.

依葫芦画瓢-Kotlin --002.快速入门

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、编写第一个 Hello World 程序2、Kotlin源码结构3、包声明与导入4、后缀名5、Kotlin 标准库6、为什么要学Kotlin 1、编写第一个 Hello World 程序 与其他任何教程一样,在正式介绍 Koti in 之前,我们先通过一个“Hello World" 程序让大家认识一下 Kotlin 程序很简单,跑完后你会发现原来是如此简单。 在编辑器新建一个helloword.kt文件 ,在文件中编写如下: fun main(args: Array<String>) { println("Hello word") } 与其它语言一样,kotlin的主函数就是main() ,没有返回值,其入参是Array<String,对应Java 的String[]。 2、Kotlin源码结构 kotlin 的程序结构与Java 类似,但不完全相同。主要 有以下几个要素组成: 包声明 即package指令导入语句 即 import类定义 包括普通的类及其一切形式的变种,如接口、枚举、抽象类等函数定义 即顶级函数变量定义 即顶级变量 3、包声明与导入 kotlin 的源程序以包的声明开始,也可以省略,包声明的结构与源码所在目录相对路径并不需要完全一致。 导入一个单独的名字 如 import com.google.android.material.R导入一个作用域 import androidx.constraintlayout.*导入顶级函数和属性导入对象中声明的函数和属性重命名导入类 4、后缀名 kotlin 文件被编译后,生成JVM class字节编码文件,会在文件名上添加“kt"这个后缀。 5、Kotlin 标准库 主要包括以下几块: 注解容器并发枚举文件操作反射数学运算常用工具类 6、为什么要学Kotlin 现在的编程语言已经足够多了,为什么我们还需要更多的语言?Java已经足够强大了,为什么我们还需要Kotlin、Scala这样的语言呢? 1.java语言比较稳健,久经考验,有庞大的生产代码库。然而,java裹足不前,开发者喜欢的很多现代语言高级特性,它都没有,或者迟迟加入。 2.kotlin从这些经验中受益良多,而java中的某些早期设计却越来越陈旧。脱胎于旧语言,kotlin解决了很多痛点,进化成一门优秀的语言。相比java,kotlin进步巨大,带来了更可靠的开发体验。 3.最重要的一点,google推崇kotlin,将kotlin定性为android主要开发语言,很多优秀的开源源码库均是由kotlin编写并维护。 kotlin的跨平台特性 1.kotlin不仅支持编写代码在虚拟机上运行,而且是一门跨平台的通用型语言,我们可以用kotlin开发各种类型的原生应用,如Android,macOS,Windows,Javascript应用。 2.kotlin能脱离虚拟机层,直接编译成可以在Windows,LInux和macOS平台上运行的原生二进制代码。 深入学习,相信你会喜欢上Kotlin。

依葫芦画瓢-Kotlin --001. 简介

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并 开源。 Kotlin 可以编译成Java字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。 在Google I/O 2017中,Google 宣布 Kotlin 成为 Android 官方开发语言。 文章目录 kotlin 可以做什么?1.使用 Kotlin 进行服务器端开发2.使用 Kotlin 进行 Android 开发3.Kotlin JavaScript 概述4 Kotlin/Native 用于原生开发5 用于异步编程等场景的协程 kotlin 可以做什么? 1.使用 Kotlin 进行服务器端开发 Kotlin 非常适合开发服务器端应用程序,允许编写简明且表现力强的代码, 同时保持与现有基于 Java 的技术栈的完全兼容性以及平滑的学习曲线: 表现力:Kotlin 的革新式语言功能,例如支持类型安全的构建器和委托属性,有助于构建强大而易于使用的抽象。 可伸缩性:Kotlin 对协程的支持有助于构建服务器端应用程序,伸缩到适度的硬件要求以应对大量的客户端。 互操作性:Kotlin 与所有基于 Java 的框架完全兼容,可以让你保持熟悉的技术栈,同时获得更现代化语言的优势。 迁移:Kotlin 支持大型代码库从 Java 到 Kotlin 逐步迁移。你可以开始用 Kotlin 编写新代码,同时系统中较旧部分继续用 Java。 工具:除了很棒的 IDE 支持之外,Kotlin 还为 IntelliJ IDEA Ultimate 的插件提供了框架特定的工具(例如Spring)。

k8s安装配置nacos集群

1 在k8s中部署的难点 在k8s中部署nacos集群和在裸机器上直接部署nacos机器其实差别不大。 最主要的区别是k8s中部署的服务没有固定的ip地址,而nacos集群部署需要配置所有实例的ip 2 解决 在k8s中通过StatefulSet和Headless Service为每个nacos实例生成一个唯一的dns地址, 创建一个普通Service给可客户端使用 版本: nacos1.4.0 前提前提条件: mysql Ingress Controller (用于ingress暴露方式) 具体实现如下。 3 实现方式 3.1 创建数据库配置 vim nacos-mysql-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: nacos-uid data: mysql.host: "192.168.199.201" mysql.db.name: "nacos_config" mysql.port: "3306" mysql.user: "root" mysql.password: "mysqlpassword" kubectl apply -f nacos-mysql-config.yaml 注意:我是直接现有mysql的nacos库,如果要新建数据库必须先在数据库新建名称为nacos_config的库并导入对应nacos1.4.0下config/nacos-mysql.sql脚本导入到nacos_config库 3.2 部署Headless Service Headless Service为每个pod(nacos实例)生成一个DNS地址,用作NACOS_SERVERS配置 vim nacos-headless.yaml apiVersion: v1 kind: Service metadata: name: nacos-headless labels: app: nacos annotations: service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" spec: ports: - port: 8848 name: server targetPort: 8848 clusterIP: None selector: app: nacos kubectl apply -f nacos-headless.

Centos/7.9.2009/isos/x86_64/下载

环境: windows10 一、阿里云开源镜像站 centos-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿里云 二、各个版本的iso镜像说明

PDPS15(Tecnomatix_15.0)安装包及安装教程分享

上图为小编前阵子自己成功安装的PDPS仿真软件,安装过程相比DELMIA/CATIA复杂繁琐,容易出错,故作此安装教程及安装包分享。 一、确认安装包内容 1.Perl和Java软件文件 2.Oracle数据库安装文件 3.Tecnomatix_15.0安装文件 4.Tecnomatix许可文件 (如果许可文件过期,可修改电脑的时间来使用。) *安装包下载链接见文末* 二、Perl的安装 安装按照步骤一直下一步就可以,直到安装成功。其中安装位置location:C\Perl\,可变更安装路径。 三、Java的安装 双击程序,直接安装,可以选择其他安装位置,不受影响。 四、安装Oracle数据库 Step1:安装前先确认下计算机名字是可行的,不然无法进行。名字命名不能是中文,不能有下划线,最好不要空格! Step2:双击【setup】图标。 Step3:选择【是】 Step4:选择【仅安装数据库软件】,点击【下一步】 Step5:选择【单实例数据库安装】,点击【下一步】 Step6:【所选语言】选简体中文点到左侧,选择【下一步】 Step7:选择【企业版】,点击【下一步】 Step8:选择【使用Windows内置账户】,点击【下一步】 Step9:选择【是】 Step10:在想要存放的磁盘中创建D:\app\Oracle和D:\app\perl文件夹 Step11:选择刚创建好的D:\app\Oracle文件夹为Oracle基目录(后续要用到),点击【选择】 Step12:创建记事本记录上D: app\Oracle\product12.1.0\dbhome_1,便于后续使用。最后点击【下一步】 Step13:等待Oracle检查系统配置,配置完成后,进行Oracle安装,点击【安装】 Step14:等待安装完成,安装过程中如果出现下图提示,点击【继续】,完成安装并关闭。 五、制作Perl代码并修改注册表 Step1:将安装文件中的perl文件夹的文件,复制黏贴到D:\app\perl文件夹中 Step2:双击打开runInstall12.1_example - 副本 Step3:由于个人习惯安装在D盘,故要将记事本内的C盘改为D盘。接着将“kude-PC01”替换改成本机计算机名。然后在电脑开始键旁搜索cmd,以管理员身份运行。最后将上述记事本第一行粘贴到cmd窗口第一行,回车执行。 Step4:记事本第二行粘贴到cmd窗口上,回车,运行。 运行时间较长,耐心等待。 数据库创建完成。 Step5:修改注册表,WIN+R输入regedit,按【Enter】 Step6:选择【HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1】,选择【NLS_LANG】右键修改,键值为AMERICAN_AMERICA.UTF8,选择【确定】 六、Tecnomatix软件安装 Step1:选择【Tecnomatix 15.0】,以管理员身份运行安装程序 Step2:选择【Install Tecnomatix 15.0Products】,再选择【Install Tecnomatix 15.0】 接着选择【Next】 Step3:选择【Install eMServer and Client Applications】,点击【Next】 Step4:选择需要安装的产品、【Change】更改安装目录,或者直接选择【Next】 【Change】更改安装目录为D盘 选择需要安装的机器人控制器,再点击【Next】 点击【Next】 【Change】可更改安装目录为D盘,或直接选择【Next】 点击【Next】 点击【Instal】,直至Tecnomatix安装完成。 七、启动Oracle相关的服务程序 Step1:右键此电脑,选管理,找到服务和应用程序,双击服务,找到4个服务程序,逐一将其启动类型手动改成自动。 Step2:右键OracleJobSchedulerppdd,点击启动 八、开启监听 Step1:创建数据库实例,在cmd窗口输入CD D:\Program Files\Tecnomatix_15.0\eMPower\DBScripts按【Enter】 因为安装在D盘,而cmd窗口终端默认系统盘C盘,故需要先输入D:按【Enter】(安装在C盘,不做此步骤) 再输入CD D:\Program Files\Tecnomatix_15.

Python编程习题(14): 最大公约数和最小公倍数

本题要求两个给定正整数的最大公约数和最小公倍数。 输入格式: 输入在一行中给出两个正整数M和N(≤1000)。 输出格式: 在一行中顺序输出M和N的最大公约数和最小公倍数,两数字间以1空格分隔。 输入样例: 511 292 输出样例: 73 2044 解答代码: m,n = input().split() m = int(m) n = int(n) max_divisor = 0 min_multiple = 0 if m > n: num1 = m num2 = n else : num1 = n num2 = m lim1 = int(num2) lim2 = int(num1*num2) for i in range (1,lim1+1): if num1 % i == 0 : if num2 % i == 0: max_divisor = i flag = False for i in range (num1,lim2+1): if flag == False: if i % num1 == 0: if i % num2 == 0: min_multiple = i flag = True print("

VIT中的cls_token是如何获取图片的类别信息的?

VIT中的cls_token是通过Transformer的自注意力机制来学习图片的类别信息的。Transformer的自注意力机制可以让每个输入向量(包括cls_token和patch嵌入向量)与其他输入向量进行交互,从而获得全局的上下文信息。这样,cls_token就可以根据图片中所有patch的特征来更新自己的特征,从而反映图片的整体语义信息。在训练过程中,cls_token对应的特征向量会被送入一个分类头(一个全连接层),用于预测图片的类别。通过优化分类损失函数,cls_token就可以不断调整自己的特征向量,使其更能区分不同类别的图片

java可变字符序列:StringBuffer、StringBuilder

文章目录 StringBuffer与StringBuilder的理解StringBuilder、StringBuffer的API StringBuffer与StringBuilder的理解 因为String对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低,空间消耗也比较高。因此,JDK又在java.lang包提供了可变字符序列StringBuffer和StringBuilder类型。 java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。比如: StringBuffer与StringBuilder StringBuffer 不会出现线程不安全,而StringBuilder 会出现但是它的效率会高很多。 //情况1: String s = new String("我喜欢学习"); //情况2: StringBuffer buffer = new StringBuffer("我喜欢学习"); buffer.append("数学"); StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且提供相关功能的方法也一样。区分String、StringBuffer、StringBuilder String:不可变的字符序列; 底层使用char[]数组存储(JDK8.0中)StringBuffer:可变的字符序列;线程安全(方法有synchronized修饰),效率低;底层使用char[]数组存储 (JDK8.0中)StringBuilder:可变的字符序列; jdk1.5引入,线程不安全的,效率高;底层使用char[]数组存储(JDK8.0中) StringBuilder、StringBuffer的API StringBuilder、StringBuffer的API是完全一致的,并且很多方法与String相同。 (1)StringBuffer append(xx):提供了很多的append()方法,用于进行字符串追加的方式拼接 (2)StringBuffer delete(int start, int end):删除[start,end)之间字符 (3)StringBuffer deleteCharAt(int index):删除[index]位置字符 (4)StringBuffer replace(int start, int end, String str):替换[start,end)范围的字符序列为str (5)void setCharAt(int index, char c):替换[index]位置字符 (6)char charAt(int index):查找指定index位置上的字符 (7)StringBuffer insert(int index, xx):在[index]位置插入xx (8)int length():返回存储的字符数据的长度 (9)StringBuffer reverse():反转 当append和insert时,如果原来value数组长度不够,可扩容。 如上(1)(2)(3)(4)(9)这些方法支持方法链操作。原理: 2、其它API (1)int indexOf(String str):在当前字符序列中查询str的第一次出现下标

【C语言项目】多臂井径电子测井成像项目(一)

目录 1、目的和意义2、本章概述3、串口R2324、OpenGL5、开发环境6、环境配置6.1、VS安装OpenGL6.2、虚拟串口生成工具 7、成品速览参考文献 1、目的和意义 本项目为获取矿藏地层的油气当量和及时精确地测量含油、含气层的压力及温度值的需求,辅助生产管理人员完成对油井的温度、压强、流量监控功能。通过油井井压力器对地层进行探测,通过串口通信将数据从井温压力器发至解析中心端,解析中心解包完成后利用 Lagrange 插值算法对数据进行处理,让数据看着更加流畅。通过 OpenGl 图形技术将地层的数据模拟成折线图和柱形图呈现。 2、本章概述 本章主要介绍了多臂井径电子测井成像项目中的项目来源,应用场景。所需相关的技术栈及环境配置。 3、串口R232 1、 串口通讯协议简介 串口:串口是一个泛称,UART,TTL,RS232,RS485都遵循类似的通信时序协议,因此都被通称为串口。 串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。 2、RS-232标准接口 RS232:是电子工业协会(Electronic Industries Association,EIA) 制定的异步传输标准接口,同时对应着电平标准和通信协议(时序),其电平标准:+3V~+15V对应0,-3V~-15V对应1。rs232 的逻辑电平和TTL 不一样但是协议一样。 RS-232标准接口(又称EIA RS-232)是常用的串行通信接口标准之一,全名是“数据终端设备( DTE)和数据通信设备(DCE)之间串行二进制数据交换接口技术标准。 3、Rs-232 特点 信号线少使用3条~9条信号线就可以实现全双工通信,采用三条信号线(接收线、发送线和信号地)能实现简单的全双工通信过程 波特率是指从一设备发到另一设备的波特率,即每秒钟多少比特bits per second (bit/s)。典型的波特率是110, 300, 600, 1200, 2400, 4800,9600, 14400, 19200,等bit/s。一般通信两端设备都要设为相同的波特率,但有些设备也可以设置为自动检测波特率。 奇偶效验Parity是用来验证数据的正确性。奇偶校验一般不使用,如果使用,那么既可以做奇校验(Odd Parity)也可以做偶校验(Even Parity)。 停止位是在每个字节传输之后发送的,它用来帮助接受信号方硬件重同步。 字节大小 4、OpenGL OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形到比较复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。 OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台和Mac OS。这些实现一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。开放源代码库Mesa是一个纯基于软件的图形API,它的代码兼容于OpenGL。但是,由于许可证的原因,它只声称是一个“非常相似”的API。 当今,OpenGL是视频行业领域中用于处理2D/3D图形的最为广泛接纳的API,在此基础上,为了用于计算机视觉技术的研究,从而催生了各种计算机平台上的应用功能以及设备上的许多应用程序。其是独立于视窗操作系统以及操作系统平台,可以进行多种不同领域的开发和内容创作,简而言之,其帮助研发人员能够实现PC、工作站、超级计算机以及各种工控机等硬件设备上实现高性能、对于视觉要求极高的高视觉图形处理软件的开发。 5、开发环境 1、Windows10或更高 2、VS2019或更高 3、Virtual Serial Port Driver Pro 4、OpengGL 6、环境配置 6.1、VS安装OpenGL 1、创建任意一个项目,然后点击【项目】->【管理NuGet程序包…】。 2、在搜索框内搜索nupengl,然后点击右侧的安装,随便安装那一个另一个都会一起安装。 3、创建一个*.c文件,包含一下代码,编译看能够通过。则表示环境配置成功。

SpringBoot集成SpringSecurity5和OAuth2 — 2、OAuth2客户端【SSO单点登录时作为客户端】

相关代码:参考码云上的sso-client【仅供本人参考使用,不对外,但跟着本文也可实现】 注意:OAuth2的客户端和资源服务器是不同的概念,OAuth2的客户端类似于第三方应用,它对接OAuth2服务器主要是使用OAuth2服务器端提供的客户信息【此处是OAuth2给用户分配的token】来登录客户端自己的系统而非资源服务器,后续用户访问的资源也是客户端自己存的用户资源,所以使用客户端的code来请求token会报错;而资源服务器则需要单独获取code后再获取token,然后才能请求资源服务器上的资源。【资源服务器和认证授权服务器同属一方。】 获取授权码: http://localhost:8080/oauth/authorize?response_type=code&client_id=client&scope=read&redirect_uri=http://localhost:8090/callback 获取token令牌: http://localhost:8080/oauth/token?grant_type=authorization_code&code=F4eRew&client_id=client&client_secret=secret&redirect_uri=http://localhost:8090/callback 一、项目环境配置 1.1 、JDK8 1.2、Spring Boot: 2.3.0.RELEASE 1.3、spring-cloud.version:Hoxton.SR4 二、pom.xml 1、加入thymeleaf模板依赖(可选) <!-- thymeleaf模板--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> 2、加入starter-web依赖 <!-- starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 3、加入oauth2依赖 <!-- oauth2 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> 4、完整的pom.xml文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>security.oauth2</groupId> <artifactId>client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>client</name> <description>OAuth2的客户端</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR4</spring-cloud.version> </properties> <dependencies> <!

jwt在线解密工具分享

前言 之前调用一个第三方api的时候,看到需要在Authorization填写bearer + token,英文不好,看成了熊(bear),心里很疑惑? 实际上,“bearer”指的是持票人,Bearer Token用于授权访问资源。任何Bearer持有者都可以无需证明拥有加密密钥而访问相关资源。Bearer代表授权范围、有效期和其他授权信息 。 JWT介绍 JWT(JSON Web Tokens)是一种开放标准(RFC 7519),它定义了一种紧凑的,自包含的方法,用于以JSON对象的形式在各方之间安全地传输信息。这些信息可以得到验证和信任,因为它们经过了数字签名处理。 JWT其实就是一串字符,由 Header、Payload 和 Signature 三部分组成,然后用点号拼接。JWT 的数据结构如下图: Header Header 部分是一个 JSON 对象,包含了 JWT 的元数据,一般是这样: { "alg": "HS256", "typ": "JWT" } alg(algorithm)表示签名的算法,默认是 HS256。typ(type)表示这个令牌(token)的类型,JWT 令牌统一写为JWT。最后,将上面的 JSON 对象去除缩进然后压缩后,使用 Base64URL 算法转成字符串。Base64URL算法:跟 Base64 算法基本类似,Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。 Payload Payload部分也是一个JSON对象,用来存放实际需要传递的数据,编码方法和Header部分一致,例图上的文本解密后是这样的: { "iss": "yxy", "exp": 1690602421 } Signature Signature 部分是对前两部分的签名,防止数据被篡改。首先,需要指定一个密钥(secret)。这个密钥只存储在服务器上,不能泄露给用户。然后,使用 Header 里面指定的签名算法,按照下面的公式产生签名: HMACSHA256( base64UrlEncode(header)+"."+ base64UrlEncode(payload), secret) 在线工具 如果你需要使用JWT,有几个在线工具可以简化JWT解密和加密的过程。这些工具提供用户友好的界面和直观的功能,使您能够轻松生成,验证或解码JWT。一些值得一提的流行的在线JWT加解密工具包括: 1. JSON Web Tokens (JWT) 在线解密, 开发工具箱 - JWT 在线解密 。这个网页提供了jwt解密功能。功能比较简单,上手很容易。

计算机二级Python刷题笔记------基本操作题2、3、8、13、16、19、22、28(考察format格式化输出)

文章目录 第二题第三题第八题第十三题第十六题第十九题第二十二题-进阶第二十八题第三十一题第三十四题 这篇文章整理计算机二级Python中关于format格式化输出的例题,并给出详细解析与运行结果。 print(“{格式}”.format(内容)) 类型里面: x:十六进制小写 第二题 题目: 解析: n = eval(input(“请输入一个数字:”)) 如果键盘输入123,经过input—“123”,再经过eval—123。chr()函数是输入一个整数(0-255)返回其对应的ascii符号或者unicode编码,例如: >>> chr(100) 'd' >>> chr(53) '5' ord()函数是用来返回单个字符的ascii值(0-255)或者unicode数值()。例如: >>> ord('d') 100 >>> ord('5') 53 print(“{格式}”.format(内容)) 格式::+^11 。从左到右依次为引导符号、加号字符+填充、居中对齐、宽度为11个字符。 内容:chr(n-1)+chr(n)+chr(n+1) 。使用chr()将数字转为Unicode编码,并用加号把n-1、 n和n+1三个连接起来。 所以答案为: print(“{:+^11}”.format(chr(n-1)+chr(n)+chr(n+1))) 答案: # 请在______处使用一行代码或表达式替换 # 注意:请不要修改其他已给出代码 n = eval(input("请输入一个数字:")) print("{:+^11}".format(chr(n-1)+chr(n)+chr(n+1))) 运行结果: 第三题 题目: 解析: 这里考察格式: :->20, 从左到右依次为引导符号、字符-填充、右对齐、宽度为20个字符、千位分隔符。 答案: # 请在______处使用一行代码或表达式替换 # 注意:请不要修改其他已给出代码 n = eval(input("请输入正整数:")) print("{:->20,}".format(n)) 运行结果: 第八题 题目: 解析: 这里考察格式: :=^20 从左到右依次为引导符号、字符=填充、居中对齐、宽度为20个字符。 答案: # 请在______处使用一行代码或表达式替换 # 注意:请不要修改其他已给出代码 s = input("

java:方法、return关键字、返回值与返回值类型、注意事项

目录 1方法 1.1概念: 1.2定义 1.3位置 1.4方法的调用 1.5形参与实参 1.6 好处 2.return关键字 3、返回值与返回值类型 3.1 返回值 3.2 定义语法 3.3 调用语法 4.注意 1方法 1.1概念: 实现特定功能的一段代码,可反复使用。 1.2定义 1.3位置 方法定义在类的内部,与main方法并列。 1.4方法的调用 方法名(参数); ​ 注意:调用方法时,会优先执行方法内部代码,结束后,返回到方法调用处,继续向下执行。 1.5形参与实参 “形参”等价于“局部变量的声明”。 (方法声明的时候给的参数) ​ “实参”等价于“局部变量的赋值”。(方法调用的时候给的参数 ​ 作用: ​ 方法的参数可以让代码功能更灵活、普适性更高,易于修改及维护 1.6 好处 好处: ​ 减少代码冗余。 ​ 提高复用性。 ​ 提高可读性。 ​ 提高可维护性。 ​ 方便分工合作。 2.return关键字 return的两种用法: ​ 应用在具有返回值类型的方法中: ​ return value; 表示结束当前方法,并伴有返回值,返回到方法调用处。 ​ 应用在没有返回值类型(void)的方法中: ​ return; 表示结束当前方法,直接返回到方法调用处。 注意:一个类中可以定义多个方法,方法之间属于并列关系,不可嵌套。 3、返回值与返回值类型 3.1 返回值 概念:方法执行后的返回结果。 ​ 方法执行后,一些情况下无需返回结果;另一些情况下则必须返回结果。 ​ 例如: ​ 存款操作无需返回结果。 ​ 取款操作必须返回结果。 3.

py基础工具-路径:浅层路径 获取or分拣

# -*- coding: utf-8 -*- """ Created on Sat Jul 29 08:52:28 2023 1. 函数介绍 1.1 已有路径列表, 筛选 folder | file | str select_file, select_folder, classify_file_folder_else 注:以上函数: 输入list, 输出list 1.2 获取浅层路径列表 推荐函数(支持列表输入, 展开文件夹的浅层, 进行分类): get_shallow_files, (输入list|str, 输出list) get_shallow_folders, (输入list|str, 输出list) get_shallow_file_folder_else(输入list|str, 输出dict) 其它函数: get_shallow_paths(不分类, 输入:list|str, 输出list), get_shallow_paths_by_str(输入:str, 输出list) @author: zkding """ #%% import import os #%% com func - 路径列表 内容分拣 def select_file(pths): """in: 路径list, 元素str: 文件|文件夹|其它 out: 其中的file""" ret = [] for pth in pths: if os.

Redis哨兵模式

Redis哨兵模式 一、服务器准备二、安装redis1.Master服务器2.SlaveFirst服务器3.SlaveSecond服务器 三、依次开启Redis服务器四、开启哨兵1.修改Master哨兵配置文件2.修改SlaveFirst哨兵配置文件3.修改SlaveSecond哨兵配置文件4.开启哨兵5.验证是否开启成功6.主从配置如下五、挂掉Master的Redis服务器,看服务器变化 六、哨兵配置文件自动更改七、再次开启原先Master 一、服务器准备 Kali安装无法定位软件包问题 Kali防火墙开关 Kali开启ssh端口 安装VM虚拟机,准备三台服务器,这里kali我是之前装的,随便什么linux服务器都行 二、安装redis 没有下载权限看这篇 Redis安装参考这篇 CentOs7:systemctl stop firewalld.service(关闭)firewall-cmd --state(查看状态) 三台服务器需要开放对应的端口,或者简单点直接关闭防火墙 kaili:关闭见上文文章链接 1.Master服务器 首先安装主服务器,这里安装Redis,之后修改redis.conf配置文件,来开启服务 1.bind 192.168.1.7 //绑定监听ip 2.daemonize yes //开启后台运行 3.protected-mode no //关闭守护模式,允许外部访问 4.port 6379 //开启监听端口 2.SlaveFirst服务器 安装第一台从Redis服务器,修改Redis.conf的配置 slaveof 192.168.1.5 6379 //从服务器需要这里在redis.conf中加上这句话 1.bind 192.168.1.5 //绑定监听ip 2.daemonize yes //开启后台运行 3.protected-mode no //关闭守护模式,允许外部访问 4.port 6379 //开启监听端口 5.slaveof 192.168.1.7 6379 //配置从服务器的主服务器 3.SlaveSecond服务器 安装第一台从Redis服务器,修改Redis.conf的配置 slaveof 192.168.1.5 6379 //从服务器需要这里在redis.conf中加上这句话 1.bind 192.168.1.6 //绑定监听ip 2.daemonize yes //开启后台运行 3.protected-mode no //关闭守护模式,允许外部访问 4.

开发板 在虚拟机中 通过 wifi 联网

这篇博客记录开发板通过wifi连网的过程。 材料: 灵眸科技 EASY EAI开发板电源线ADB调试线开发板WIFI接收器 0、虚拟机必须连网(其实也不是必须): https://blog.csdn.net/weixin_45824067/article/details/131904810 1、通过ADB调试线连接,进入开发板 首先给开发板上电,将WIFI接收器、ADB调试线连接好。 VMare Workstation软件右下角第四个图标亮起来的时候,表示ADB调试线连接好了 进入EASY-EAI编译环境: ~/develop_environment/run.sh 新开一个终端,进入开发板: 2、/etc/wpa_supplicant.conf中加入你要连接的wifi信息 不要 修改 /etc/netpaln/99_config.yaml,用netplan来配置网络,我尝试了一晚上都没成功 还是按照这个博主的做法做 开发板linux连接wifi的方法(一)_wsx_iot的博客-CSDN博客 首先修改 /etc/wpa_supplicant.conf 文件内容,只修改该文件 network= 后面的内容即可 network={ ssid="wifi名字" psk="wifi密码" scan_ssid=1 proto=WPA RSN key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE pairwise=TKIP CCMP group=CCMP TKIP WEP104 WEP40 } 然后执行如下脚本,使得 wlan0 被分配 ip地址: #关闭有线连接 ifconfig eth0 down #打开无线连接 ifconfig wlan0 up #杀死以前配置进程 killall wpa_supplicant #启动wifi配置,使文件生效 wpa_supplicant -B -Dwext -iwlan0 -c/etc/wpa_supplicant.conf #启动有点慢,等一下启动完毕 sleep 3s #杀死以前的dhcp进程 killall udhcpc #启动dhcp获取ip udhcpc -b -i wlan0 #static ip #ifconfig wlan0 192.

小白入门:如何在docker中运行python程序

目录 摘要: 1,编写Dockerfile制作镜像 2,使用镜像创建容器 3,交互式运行容器/镜像修改 3.1 编辑 3.2保存 4,将镜像上传至DockerHub 5,从DockerHub拉取镜像 摘要: 本文仅涉及docker的基础使用。主要介绍如何在docker容器内运行python程序,以及一些相关问题及解决方法,例如:如何让容器启动后自动运行程序?如何二次修改镜像,如何进行文件挂载?如何将镜像上传至dockerhub?...... 本文涉及到与DockerHub/DockerDesktop相关的一些操作需要搭梯子。。。 1,编写Dockerfile制作镜像 为了在docker容器中运行python程序,首先要编写Dockerfile.txt文件,并以此来制作镜像。一般的我们将Dockerfile文件放置在python项目根目录下,如下图所示: 一个简单的Dockerfile文件内容是这样的: FROM python:3.7-slim WORKDIR /work COPY . /work RUN pip install --no-cache-dir -r requirements.txt # 如果不能自动运行请尝试加上:RUN chmod +x main.py CMD ["python", "main.py"] 第一行表示使用python:3.7-slim为基础镜像(可以在dockerhub中找到,dockerhub是一个存放镜像的云仓库,类似于github)。 第二行表示在docker容器根目录下创建一个名为work的工作目录。 第三行表示将本机当前目录下的内容复制到容器工作目录。 第四行使得创建容器时自动安装项目依赖,本例中我们安装numpy。 第五行使得容器启动后自动运行main.py。另外如果加了这句指令仍不能自动运行,请尝试加上我注释的代码RUN chmod +x main.py授予权限。 编写好Dockerfile后开始制作镜像。首先运行DockerDesktop程序(请事先安装),之后在终端打开项目文件。 可以看到python项目内容以及我们编写的Dockerfile正在此目录内。使用如下指令构建镜像: docker build -t <镜像名称> . -f Dockerfile.txt 可以使用docker images指令查看存在镜像的信息,可以看到我们新创建的镜像 2,使用镜像创建容器 如果需要进行数据卷挂载,需在这里进行。通俗的讲,数据卷挂载就是将容器中的一个文件(夹)和本机中的一个文件(夹)关联起来。例如容器中有一个文件夹A,本机中有一个文件夹B。那么B中内容同步在A中,容器内可见;容器中对A文件夹的内容进行修改也会同步在B文件夹,在本机可见。我们以挂载两个文件夹(input,output)分别用作程序输入输出为例。 使用如下指令构建容器(方括号指令可选) docker run [--rm] [--name <容器名称>] [-v <本机文件夹路径>:<容器文件夹路径>] <镜像名称> --rm 使得容器为一次性容器,程序运行结束后容器退出并销毁。如果需要容器后仍存在,请删除。

AUTOSAR Eth模块 以太网配置开发

一、EthGeneral 1、Development Error Detection Switches the development error detection and notification on or off. DET报错的开关信号 2、EthGetRxStatsApi Configure ON/OFF at the precompile for the funtion Eth_GetRxStats. 获取接收状态的API的开关,有的控制器不支持。 3、EthGetCounterValuesApi Configure ON/OFF at the precompile for the funtion Eth_GetCounterValues. Reads a list with drop counter values of the corresponding controller. 获取drop counter状态的API的开关,用来读取一些控制器相关的一些计数。 4、EthGetTxStatsApi Configure ON/OFF at the precompile for the funtion EthGetTxStats. 获取发送状态的API的开关,有的控制器不支持。 5、EthGetTxErrorCounterValuesApi Configure ON/OFF at the precompile for the funtion EthGetTxErrorCounterValuesApi.

基于javaweb+mysql的springboot新闻发布系统(java+springboot+ssm+mysql+maven+jsp)

基于javaweb+mysql的springboot新闻发布系统(java+springboot+ssm+mysql+maven+jsp) 运行环境 Java≥8、MySQL≥5.7 开发工具 eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练习,学习演示等 功能说明 基于javaweb+mysql的SpringBoot新闻发布系统(java+springboot+ssm+mysql+maven+jsp) 一、项目简述 功能: 区分为管理员用户和普通用户,管理员用户能删除评论, 调整新闻显示/隐藏,修改新闻,删除普通用户,普通用户能 登陆浏览,新用户可以注册基本功能实现了新闻增加,新 闻删除,新闻修改,新闻搜索其他功能:用户评论,管理 员删除差评,新闻分类,前台分类显示新闻,用户注册, 登录,个人信息修改等等功能。 二、项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe (IntelliJ IDEA,Eclispe,MyEclispe,Sts 都支持) 项目技术: JSP + SpringBoot + Servlert + htm l+ css + JavaScript + ECharts+ JQuery + Maven 等等 @RequestMapping("/queryByType") public String queryByType(){ String categoryid = request.getParameter("categoryid"); List<News> newsList = newsDao.queryAll(); request.setAttribute("list", newsList.stream() .filter(x -> x.getCategoryid().equals(Integer.parseInt(categoryid))).collect(Collectors.toList())); List<Category> categoryList = categoryDao.queryAll(); request.setAttribute("categoryList", categoryList.

关于质数筛——数论

埃式筛法 #include <bits/stdc++.h> using namespace std; bool vis[100000010]; //标记数组 int n; int main(){ scanf("%d",&n); vis[0]=vis[1]=1; for(int i=2;i*i<=n;i++){ //优化1 if(vis[i]!=1){ for(int j=i*i;j<=n;j+=i){ //优化2 vis[j]=1; //0是质数,1不是 } } } for(int i=2;i<=n;i++){ if(vis[i]==0){ cout<<i<<" "; } } return 0; } 欧拉筛 #include <bits/stdc++.h> using namespace std; bool vis[100000010]; int n,cnt=0,prime[10000000]; int main(){ scanf("%d",&n); vis[0]=vis[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]){ prime[++cnt]=i; } for(int j=1;j<=cnt&&i*prime[j]<=n;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0){ break; } } } for(int i=1;i<=n;i++){ if(prime[i]==0) break; printf("%d "

素数个数——数论

题目描述 求 1,2,⋯,N 中素数的个数。 输入格式 一行一个整数 N。 输出格式 一行一个整数,表示素数的个数。 样例 #1 样例输入 #1 10 样例输出 #1 4 提示 对于 100% 的数据,1≤1081≤N≤108。 本题时间限制在2秒以内。 因为题目时间限制是2秒,所以可以用埃式筛法 埃式筛法 埃式筛法的原理很简单 如果 i 是质数,那么把所有的小于 n 的 i 的倍数(不包括 i )标记 vis[j]=1; #include <bits/stdc++.h> using namespace std; bool vis[100000010]; //标记数组 int n,ans=0; int main(){ scanf("%d",&n); vis[0]=vis[1]=1; for(int i=2;i*i<=n;i++){ //优化1 if(vis[i]!=1){ for(int j=i*i;j<=n;j+=i){ //优化2 vis[j]=1; //0是质数,1不是 } } } for(int i=2;i<=n;i++){ if(vis[i]==0){ ans++; } } printf("%d",ans); return 0; }

解决wandb: Network error (ReadTimeout), entering retry loop.

一、问题描述 wandb: W&B API key is configured (use `wandb login --relogin` to force relogin) wandb: Network error (ReadTimeout), entering retry loop. wandb: Network error (ReadTimeout), entering retry loop 出现上面的原因:使用wandb在线模式运行代码,服务器是一边运行我们的代码一边向wandb官网上传我们的数据,导致服务器显卡占用比特别大。 wandb可以将我们模型中的一些参数(比如,loss函数值、AUC面积以及训练、验证和测试时一些数据)以图表的形式表示出来。 二、解决方案 import os os.environ["WANDB_API_KEY"] = '+++++++++++' # 将引号内的+替换成自己在wandb上的一串值 os.environ["WANDB_MODE"] = "offline" # 离线 (此行代码不用修改)

一文让你彻底搞懂Mybatis之缓存机制

编译软件:IntelliJ IDEA 2019.2.4 x64 操作系统:win10 x64 位 家庭版 Maven版本:apache-maven-3.6.3 Mybatis版本:3.5.6 文章目录 一. 缓存是什么?二. 为什么要使用缓存?三. Mybatis中的缓存分哪几种?3.1 Mybatis缓存机制之一级缓存3.2 Mybatis缓存机制之二级缓存3.3 Mybatis中缓存机制之第三方缓存【以EhCache为例】 一. 缓存是什么? 一说到缓存,我们可能都会想到Cashe,这里摘自百度百科对它的解释:它原本是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。它的工作原理是当CPU要读取一个数据时,首先从CPU缓存中查找,找到就立即读取并送给CPU处理;没有找到,就从速率相对较慢的内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存。 以上部分内容可能看不懂,没关系,你只需要知道正是由于这样的读取机制,使得CPU读取缓存的命中率非常高(大多数CPU可达90%左右),也就是说CPU下一次要读取的数据90%都在CPU缓存中,只有大约10%需要从内存读取。这样大大节省了CPU直接读取内存的时间,非常快捷!!! 简而言之,以cpu中的缓存举例,缓存其实就是数据交换的缓冲区【又称Cashe】,是存贮数据(使用频繁的数据)的临时地方。当用户查询数据,首先在缓存中寻找,如果找到了则直接执行。如果找不到,则去数据库中查找。 二. 为什么要使用缓存? 举个生活中的例子,当我们在线观看视频时,以哔哩哔哩网站为例,你会发现,底下的进度条会实时显示蓝色,白色等两种颜色。不难发现,蓝色代表的是视频实际播放的进度,而白色代表的是视频实时预先缓存的进度。如下所示。 这种让用户一边下载一边观看、收听,而不要等整个文件下载到自己的计算机上才可以观看的网络传输技术,就是鼎鼎大名的流媒体技术。该技术的原理是先在使用者端的计算机上创建一个缓冲区,在播放前预先下一段数据作为缓冲,在网路实际连线速度小于播放所耗的速度时,播放程序就会取用一小段缓冲区内的数据,这样可以避免播放的中断,也使得播放品质得以保证。该技术在很多音频影视网站上被大量使用,旨在丰富用户的使用体验并提高音频的播放性能。 而程序中的缓存【Mybatis缓存】,亦是如此,Mybatis使用缓存优势可以提高查询效率,并降低服务器的压力。它的本质就是用利用空间换时间,牺牲数据的实时性,以服务器内存中的数据暂时代替从数据库读取最新的数据,减少数据库IO,减轻服务器压力,减少网络延迟,加快页面打开速度。 三. Mybatis中的缓存分哪几种? 👉分类 一级缓存二级缓存第三方缓存 3.1 Mybatis缓存机制之一级缓存 👉概述 一级缓存【本地缓存(Local Cache)或SqlSessiona级别缓存】 🤔什么是SqlSessiona? SqlSession是一个会话,相当于JDBC中的一个Connection对象,是整个Mybatis运行的核心,它是MyBatis的关键对象,是执行持久化操作的独享,类似于JDBC中的Connection。它是应用程序与持久层之间执行交互操作的一个单线程对象,也是MyBatis的核心接口之一 👉特点 一级缓存默认开启不能关闭可以清空 💡 :有点类似于使用腾讯视频网站去看电影,电影观看进度条前的那一小段灰色的进度条 👉缓存原理 第一次获取数据时,先从数据库中加载数据,将数据缓存至Mybatis一级缓存中【缓存底层实现原理Map,key:hashCode+查询的Sqlld+编写的sal查询语句+参数】以后再次获取数据时,先从一级缓存中获取,如未获取到数据,再从数据库中获取数据 不信?请看如下测试代码的体现 代码示例如下: @Test public void test04(){ try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通过SqlSessionFactory对象调用openSession(); SqlSession sqlSession = sqlSessionFactory.

【JVM】详细解析java创建对象的具体流程

目录 一、java创建对象的几种方式 1.1、使用new关键字 1.2、反射创建对象 1.2.1、Class.newInstance创建对象 1.2.2、调用构造器再去创建对象Constructor.newInstance 1.3、clone实现 1.4、反序列化 二、创建对象的过程 2.1、分配空间的方式 1、指针碰撞 2、空闲列表 3、怎么选择分配方式 三、注意事项 一、java创建对象的几种方式 1.1、使用new关键字 调用类的构造方法创建对象 1.2、反射创建对象 1.2.1、Class.newInstance创建对象 1.2.2、调用构造器再去创建对象Constructor.newInstance 先通过反射获取类中无参构造器,然后通过newInstance()获取对象 1.3、clone实现 通过Clone创建对象,首先实体类中必须先实现Cloneable接口并复写Object的clone方法(因为Object的这个方法是protected的) 1.4、反序列化 序列化:指把 Java 对象转换为字节序列的过程; 反序列化:指把字节序列恢复为 Java 对象的过程; 此方式需要类先实现Serializable接口 public class TestStack { public static void main(String[] args) throws Exception { File file =new File("M:/Serializable.txt"); FileOutputStream fileOutputStream = new FileOutputStream(file); ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream); UserParam userParam =new UserParam("hello"); outputStream.writeObject(userParam); FileInputStream fileInputStream = new FileInputStream(file); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); UserParam userParam1 = (UserParam)objectInputStream.

第四篇:k8s之节点kubelet预留资源配置

第四篇:k8s之kubelet预留资源配置 1 前言2 预留资源Kube-reservedSystem-reservedEviction Thresholds实施节点可分配约束 3 Pod优先级4 生产应用配置文件重启kubelet服务查看节点资源 1 前言 最近k8s在使用过程中遇到这样一个问题 由于Pod没有对内存及CPU进行限制,导致Pod在运行过程中所需的内存超过了节点本身的内存(OOM),从而导致节点崩溃,使得运行在该节点上的所有Pod都失败了 为了解决这个问题以及提高节点的稳定性,综合k8s的一些特性,方案如下 每个节点为系统守护进程预留计算资源(CPU、内存、磁盘空间)Pod驱逐:节点资源到达一定使用量,开始驱逐 pod每个Pod需指定所需资源 2 预留资源 Kubernetes 的节点可以按照 Capacity 调度。默认情况下 pod 能够使用节点全部可用容量。 这是个问题,因为节点自己通常运行了不少驱动 OS 和 Kubernetes 的系统守护进程。 除非为这些系统守护进程留出资源,否则它们将与 Pod 争夺资源并导致节点资源短缺问题。 kubelet 公开了一个名为 ‘Node Allocatable’ 的特性,有助于为系统守护进程预留计算资源。 Kubernetes 推荐集群管理员按照每个节点上的工作负载密度配置 ‘Node Allocatable’。 Kubernetes 节点上的 ‘Allocatable’ 被定义为 Pod 可用计算资源量。 调度器不会超额申请 ‘Allocatable’。 目前支持 ‘CPU’、‘memory’ 和 ‘ephemeral-storage’ 这几个参数。 可分配的节点暴露为 API 中 v1.Node 对象的一部分,也是 CLI 中 kubectl describe node 的一部分。 在 kubelet 中,可以为两类系统守护进程预留资源。 Node Capacity:Node的所有硬件资源

机器学习中的数据预处理指南

在机器学习任务中,数据处理的相关工作常会占据整个项目近70%的时间,因为真实的数据质量往往具有参差不齐,噪音、缺失、不一致等问题,不利于算法模型的训练。 因此,数据处理是机器学习项目中至关重要的一步,数据质量决定着模型质量的上限。 在本文中,我们将着重讨论将原始数据转换为结构化数据处理中的所有数据预处理步骤。 什么是数据预处理 数据预处理是在进行主要处理之前的一些数据处理行为,是清理数据并使其适用于机器学习模型的必要任务。它是创建机器学习模型的第一步,也是至关重要的一步。 为什么要进行预处理 数据预处理的目的是消除数据中的噪声、处理数据缺失、解决数据不一致等问题,并将数据转化为可供机器学习算法使用的形式。通过数据预处理,可以增强模型的性能、提高准确度,减少模型在训练和预测过程中可能出现的错误。 同时,良好的数据预处理还可以降低机器学习模型过拟合的风险,提高模型的泛化能力,以更好地应用于未见过的数据。 总而言之,数据预处理是创建机器学习模型的关键步骤之一。通过适当的数据清洗、集成、转换和归一化,可以提高模型的性能和稳定性,使其更好地适应真实世界的数据,并产生准确可靠的预测结果。 数据预处理的常见步骤 数据预处理共包含四个步骤,即数据收集、数据清理、数据转换与数据准备。 在数据预处理的过程中,常见的任务包括数据清洗、数据集成、数据转换和数据归一化。 数据清洗主要是处理缺失值、异常值和重复值,以确保数据的完整性和一致性。如果用户认为数据较为脏乱,他们不太会相信基于这些数据的挖掘结果,即输出的结果的可靠性。 数据集成是将多个数据源中的数据合并为一个一致的数据集,以便进行分析和建模。数据分析任务多半涉及数据集成。数据集成将多个数据源中的数据结合成、存放在一个一致的数据存储,如数据仓库中。这些源可能包括多个数据库、数据方或一般文件。 数据转换包括对数据进行平滑、聚集或转换为可处理的数值形式,以适应机器学习算法的需求。 数据归一化则是将数据转化为相同的尺度,以消除不同特征之间的差异,确保模型对各个特征的权重进行合理分配。 总之,在机器学习项目中,数据预处理是不可忽视的重要环节。只有经过充分而准确的数据处理,才能得到高质量的训练数据,让模型具备良好的性能和泛化能力。 数据预处理的质量直接影响着后续模型的性能和准确度。 最后,数据预处理是一个迭代的过程,需要不断尝试和调整预处理步骤,以获得最佳的数据处理效果。因此,在项目中要充分重视数据预处理的工作,并不断探索和尝试不同的数据预处理方法,以找到最适合的处理方式。

QT 使用串口

目录 1.1.1 添加库,添加类 1.1.2 定义串口 1.1.3 搜索串口 1.1.4 设置和打开串口 1.1.5 读取数据 1.1.6 发送数据 1.1.7 关闭串口 1.1.1 添加库,添加类 首先,QT5 是自带 QSerialPort(Qt5 封装的串口类)这个类的,使用时需要在 pro 文件里面添加一行: QT += serialport 加入下面两个文件: #include <QSerialPort> #include <QSerialPortInfo> QT5 中,串口通信是借助一个 QSerialPort 的对象来实现的,在设置 QSerialPort 对象对串口的名称、波特率、 数据位、校验位、停止位等参数后,方能对串口进行读写。下面,我总结了一下借助 QSerailPort 对串口进行设 置、打开、读、写和关闭的过程。 1.1.2 定义串口 QSerialPort *uart; uart = new QSerialPort(this); 1.1.3 搜索串口 //availablePorts 是返回当前系统所有能用的串口,返回值是一个容器 //QList 是容器类,在此的容器里边装的是 QSerialPortInfo QList<QSerialPortInfo> info = QSerialPortInfo::availablePorts(); for(int i=0; i<info.size(); i++){ ui->uartNameCombo->addItem(info[i].portName()); //addItem 加入数据到下拉 菜单里 } 1.

给你推荐几个好用的Android Studio插件

给你推荐几个好用的Android Studio插件 1. CodeGlance(代码全景) 类似于Sublime或Xcode,此插件在您的编辑器中嵌入了一个代码迷你地图。滚动条也会变得稍大一些。CodeGlance预览了文件的代码模式,让您快速导航到所需的部分。 2. Rainbow Brackets(彩虹括号) 对于程序员来说,嵌套的括号和圆括号可能是一个麻烦,特别是当某些括号丢失时。它们在代码审查中可能会让人真正头疼。此插件为圆括号、方括号和花括号添加了可爱的彩虹颜色。对于刚开始入门的开发人员,或者那些发现自己陷入大块代码中的人,它是一个救星。 除了Java和Kotlin,此插件还支持其他十几种语言,如Objective-C、Scala、Python、HTML、SQL等。 3. ADB Wifi 与iOS开发人员不同,Android开发人员通常必须确保在设备调试期间不要断开USB连接。虽然有一组ADB shell命令可以通过WIFI建立连接,但使用GUI快捷方式会快得多。只需安装ADB Wifi插件,确保您的主机设备和手机连接到同一网络,然后转到“工具” → “android” → “ADB WIFI” → “ADB USB to WIFI”,开始连接 - 现在您可以在无需USB连接的情况下运行应用程序。 4. Atom One Dark Theme 现代化IntelliJ IDEA的推荐Atom One Dark主题,通过插件美化使用方式。 5. Material UI Theme Android Studio拥有适合暗黑模式爱好者的Dracula主题。但有时候,改变一下也是不错的选择,而Material UI Theme插件正是为此而设计。该插件提供了一系列令人印象深刻的主题调色板,支持大多数编程语言,还包含了材料图标、填充和许多自定义选项。 6. JSON To Kotlin Class 使用这个插件,将JSON字符串转换为Kotlin数据类将变得更加快捷。此外,它还支持: 多种JSON库的注解,包括Gson、Jackson、Fastjson、Moshi、LoganSquare等。初始化属性并允许它们具有默认值和可为空。将属性名称改为驼峰式样式,并生成内部类或单独的类。从本地文件/HTTP URL加载JSON,前提是JSON字符串是有效的。 7. Kotlin Fill Class 经常需要快速创建一个带有默认属性的Kotlin类。这个IntelliJ插件正是为此而设计的。它为您提供了用于空构造函数和函数的意图操作,让您快速初始化参数。 8. Clear Cache Plugin 通常情况下,当开发人员需要清除缓存时,他们必须遍历.gradle目录。这是耗时的。您可以创建一个Gradle脚本来加速这个过程,但是为什么要重复造轮子呢? 通过使用Clear Cache插件,我们可以检索具有给定前缀的所有包,并删除那些不再需要的包。以下是一个演示: 9. Material Design Icon Generator 这个插件帮助您在Android应用程序中添加Material Design图标。导入资源、指定颜色、大小和密度非常简单。

【Python】在PyCharm中安装 ChatGPT 插件,让 AI 帮助我们写代码,从此代码再无报错,小白也能轻易上手!!!

前言 ChatGPT是目前最强大的AI,不仅能够聊天、写小说,甚至码代码也不在话下。 但是在国内要使用chatgpt很麻烦,国内一家团队开发了一款idea插件NexChatGPT,用数据代理的方式,让我们在国内也能轻松的使用chatgpt。 没有安装pycharm的参考:python和pycharm的安装教程 一、插件安装 pycharm版本不低于2020.2 先选择设置Settings 再选择插件Plugins 在Plugins页面中将上方标签切换到Marketplace 在搜索框中输入nex 点击NexChatGPT后的Install 下载成功后,先点击ok,再点击Apply 二、使用步骤 1、点击打开,完成登录,即可使用 在Search栏输入需要想要问的问题,点击send,就会返回答案 轻轻松松就可以得到问题的答案

QT常用类型转换

QString -> QByteArray: QString str = "11"; QByteArray byte = str.toUtf8(); //转utf8格式字节数组 QString转为其他编码方式的字符数组,这里以本地编码方式为例: QByteString array = str.toLocal8Bit(); //转本地编码格式 QString -> std::string(C++标准字符串) -> char* QString str = "22"; String t1 = str.toStdString(); //转c++标准 string char *t2 = str.data(); //转char* QByteArray -> char* QByteArray arr = "33"; char *t = arr.data(); //转char* char -> QString* char *p = "44"; QString t = QString(p); int -> QString 与 QString->int int n1 = 55; QString str1 = QString::number(n1); QString str2 = "

【深度学习】基于YOLO-V3训练自己的数据与任务(套用已训练好的模型进行自己的数据训练+预测)

提示:此篇笔记是听B站唐宇迪老师的深度学习YOLO-V3课程实战部分所做笔记 文章目录 前言一、标注数据信息(训练自己的数据)1.1 Labelme工具安装1.2 数据信息标注(数据打标签)1.3 完成标签标注 二、写好模型所需要的配置文件2.1 找到配置文件所在位置2.2 运行sh文件 三、标签格式转换3.1 转换原理3.2 使用json2yolo.py文件进行转换 四、写好数据和标签路径4.1 路径4.2 decode_json函数4.3 convert函数(转换) 五、完成其他配置操作5.1 复制txt所对应的图片到data\custom\images5.2 修改classes.names5.3 在train.txt与val.txt写好对应的路径5.4 custom.data 六、训练代码更改6.1 train.py需要设置的参数(更改参数)6.2 代码中的参数default值修改 七、预测操作7.1 训练完成后7.2 配置detect.py参数7.3 检测结果 额外注意结束语 前言 此篇笔记记录的是:听B站唐宇迪老师的深度学习YOLO-V3课程部分实战所做笔记,是在已经训练好coco数据集的模型的基础上进行的,所以直接就是套用coco训练集训练出来的模型,使用自己的数据进行训练和预测操作流程(方便熟悉整个流程)。 相关课程视频参考:【百万播放】零基础、快速学YOLO目标检测算法!完整学习路线一条龙,无脑通关! 一、标注数据信息(训练自己的数据) 1.1 Labelme工具安装 进入GitHub后,搜索labelme 然后输入安装的命令: pip install labelme pip install pyqt5 pip install pillow=4.0.0 额外安装完上面三个工具包以后,会自动安装相应的环境变量 点击anaconda进入命令行窗口,输入命令labelme进入安装好的labelme工具 打开后的工具界面 1.2 数据信息标注(数据打标签) 选择矩形框标注:右击鼠标,然后选择矩形框 选择person标签 标注完成后,保存已标注好的文件 1.3 完成标签标注 随便打开一个标注好的json文件 label是类别,points里指的是[x1,y1]和[x2,y2],shape_type表示矩形框,后续转换需要用到。 shape_type中一对{}表示一个框。 最后有路径和大小 二、写好模型所需要的配置文件 2.1 找到配置文件所在位置 2.2 运行sh文件 由于windows不像linux可以直接运行此类文件,所以需要额外安装git https://git-scm.com/ 下载完git后就可以直接运行.sh文件 下载安装好,右击空白处,点击git bash here

浏览器消息通知代码

<script type="text/javascript"> function notify(title, options, callback) { // 先检查浏览器是否支持 if (!window.Notification) { console.log("浏览器不支持notify"); return; } console.log("浏览器notify权限:", Notification.permission); // 检查用户曾经是否同意接受通知 if (Notification.permission === "granted") { var notification = new Notification(title, options); // 显示通知 if (notification && callback) { notification.onclick = function(event) { callback(notification, event); } setTimeout(function () { notification.close(); },3000); } } else { Notification.requestPermission().then( (permission) =>function(){ console.log("请求浏览器notify权限:", permission); if (permission === "granted") { notification = new Notification(title, options); // 显示通知 if (notification && callback) { notification.

vue2中axiso的请求拦截封装

在src文件下新建axios的配置文件,我这里直接命名axios.js,然后配置 //导入axios和router import axios from "axios"; import $router from '@/router/index'; //引用elenmentui的组件 import { Message } from 'element-ui' import { Loading } from 'element-ui' let loadingInstance = null // 全局配置axios,并使用ajax作为别名 const instance = axios.create({ timeout: 3000, responseType: 'json', //公共地址 baseURL: "http://127.0.0.1:8081", responseEncoding: 'utf8' }); // 添加请求拦截器 instance.interceptors.request.use(function (config) { // 在发送请求之前做些什么 loadingInstance = Loading.service({ fullscreen: true }) // 配置 Token 认证 if (localStorage.token !== '') { config.headers.Authorization = localStorage.getItem("token") }

好用免费的api接口大全

API(Application Programming Interface,应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问原码,或理解内部工作机制的细节。 免费api访问网址(不需要注册) 一、教书先生 稳定、快速、免费的 API 接口服务 https://api.oioweb.cn/ ​ 二、UomgAPI 稳定、快速、免费的 API 接口服务 https://api.uomg.com/ 三、短网址API 稳定、快速、免费的 API 接口服务 https://api.d5.nz 四、韩小韩API 我好像在哪里见过你 https://api.vvhan.com 五、JSON API免费接口 各种提供JSON格式数据返回服务网站的API接口 http://www.bejson.com/knownjson/webInterface/ ​ 五、末日API http://api.weijieyue.cn/# 六、顾宇API http://47.94.135.214/ 七、free-api https://www.free-api.com/ ​ 免费api接口(需要注册) 一、聚合数据 https://www.juhe.cn/docs?bd_vid=12366660879320847918 二、万维易源 https://www.showapi.com/?renqun_youhua=259537 ​ 三、极速数据 https://www.jisuapi.com/api/?isfree=1 ​ 四、百度AI平台 https://ai.baidu.com/ ​ 五、阿里云免费api https://www.aliyun.com/?spm=a2c4e.11155472.1280361.1.3f665d02tWDTRR

前端开发必读!7个HTML属性助你提升用户体验

虚拟键盘的 enterkeyhint 属性 enterkeyhint 是HTML<input> 标签的一个新属性,这个属性会影响虚拟键盘的 enter 键的样式和行为,主要用于移动端和平板电脑等设备上,让用户清楚地知道 enter 键将执行何种动作。这个属性的典型值有 "enter", "done", "go", "next", "previous", "search", 和 "send" 等。 例如,如果你在一个搜索框中使用 enterkeyhint="search" 属性,当用户在移动设备上使用这个搜索框时,enter 键将会变为"搜索",用户点击这个键就能提交搜索。 ini复制代码<form action="/search"> <input type="text" enterkeyhint="search" name="q"> <input type="submit" value="Search"> </form> 在这个例子中,输入框的 enterkeyhint 属性设置为 "search",这样在移动设备的虚拟键盘上,enter 键的标签就会变为 "搜索"。 enterkeyhint 的可能取值及其含义如下: "enter":默认行为,一般表示一个换行的操作。"done":表示完成输入的操作,比如填写表单的最后一个字段后,虚拟键盘上的按钮可能会变为“完成”。"go":表示要导航到一个新的页面或视图,或开始一个过程。"next":表示用户将移动到下一个输入字段,适用于有多个输入字段的表单。"previous":表示用户将移动到上一个输入字段,适用于有多个输入字段的表单。"search":表示启动搜索操作,适用于搜索框。"send":表示将发送消息或其他类型的文本,适用于聊天或邮件应用。 记住,这些键盘提示的具体表现可能会因设备或浏览器的不同而略有差异,因为每个系统或浏览器可能会以自己的方式实现这些提示。 2. 自定义有序列表的属性 在使用有序列表时,我们可以利用一些较少为人知的属性来自定义编号的行为。这些属性包括: reversed 属性:它允许我们以相反的顺序对列表项进行编号,从高到低,而不是默认的从低到高。start 属性:它定义了列表应该从哪个数字开始。type 属性:它指定列表项使用数字、字母还是罗马数字。value 属性:它允许你为特定的列表项设置自定义编号。 less复制代码<ol reversed> <li>List item...</li> <li>List item...</li> <li>List item...</li> </ol> <ol reversed start="20" type="1"> <li>Typee: A Peep at Polynesian Life (1846)</li> <li>Omoo: A Narrative of Adventures in the South Seas (1847)</li> <li>Mardi: and aVoyage Thither (1849)</li> <li>Redburn: His First Voyage (1849)</li> <li value="

Python web实战 | 用 Flask 框架快速构建 Web 应用【实战】

概要 Python web 开发已经有了相当长的历史,从最早的 CGI 脚本到现在的全栈 Web 框架,现在已经成为了一种非常流行的方式。 Python 最早被用于 Web 开发是在 1995 年(90年代早期),当时使用 CGI 脚本编写动态 Web 页面。2004 年 Django 框架发布,它是一个高度模块化的框架,提供了许多开箱即用的功能,使得 Web 开发更加容易和快速。Flask 框架于 2010 年发布,是一个轻量级的框架,它提供了更少的默认功能,但也更灵活,允许开发者根据需要添加或删除功能。 1. 什么是 Flask? Flask 是一款 Python 的轻量级 Web 框架,它的特点是简单易用、灵活性高。Flask 框架可以快速搭建 Web 应用程序,是一个很好的选择。Flask 框架的核心思想是 WSGI(Web Server Gateway Interface),它定义了 Web 服务器和 Web 应用程序之间的通信协议。 1.1 Flask 的优势 简单易用:Flask 框架的 API 简单易用,开发者能够快速上手。MVC设计模式。 灵活性高:Flask 框架的扩展性高,可以根据实际需求进行扩展。 轻量级:Flask 框架的代码量小,运行速度快。 文档丰富:Flask 框架的文档非常详细,开发者能够轻松查找所需信息。 1.2 Flask 的缺点 轻量级:Flask 框架的轻量级也是它的缺点之一,它的功能相对有限,需要自己进行扩展。 不适合大型应用程序:Flask 框架适合小型应用程序,对于大型应用程序来说,可能会出现性能瓶颈。这时可以考虑Django。 1.3 Flask 的基础组件 Flask 框架由以下几个基础组件组成:

Autosar - 【4 AUTOSAR以太网通信架构】

AUTOSAR以太网通信架构中从最底层到最上层包含了Eth Driver,EthIf,TCPIP,SoAd等模块,下面分别介绍每个模块的作用: 4.1 Eth Driver 硬件驱动层的Eth Driver负责与外部PHY芯片的数据交互,实现了MAC 的初始化,内容主要包含了buffer的设置,中断的设置,部分芯片中还包含了复用的一些设置,该模块提供了相关的接口给EthIf模块进行调用实现对MAC的控制。 4.2 Eth Interface 硬件抽象层的Eth Interface实现了: 对底层MAC模块以及外设模块(TRCV,Switch)的控制接口的封装,向上提供了接口给TCPIP,EthSM模块;上层模块通过调用EthIf的接口来访问MAC模块以及外设模块(TRCV,Switch);EthSM模通过EthIf实现了相关的以太网状态控制; 实现VLAN的划分和管理。 4.3 TCP/IP 传输控制协议/互联网协议 (Transmission Control Protocol/Internet Protocol)(简称TCP/IP),是车载以太网最基本的协议之一。 TCP/IP由很多协议组成,其中包含了TCP(传输控制协议)、UDP(用户数据报协议)、IP(互联网协议)、ARP(地址解析协议)、ICMP(Interne控制报文协议)、DHCP等,ARP则使用了静态配置表。 在AUTOSAR(AUTomotive Open System ARchitecture)中,TcpIp(Transmission Control Protocol/Internet Protocol)模块是用于实现TCP/IP网络协议栈的模块之一。它提供了在汽车电子系统中进行网络通信的功能。 配置TcpIp模块需要以下几个方面的配置: IP地址和子网掩码:配置汽车电子系统的IP地址和子网掩码。IP地址用于唯一标识系统在网络中的位置,而子网掩码用于定义子网的范围。网关地址:配置网关地址,即将数据包从一个子网传输到另一个子网所需的路由器地址。网关充当两个不同网络之间的桥梁。DNS服务器地址:配置DNS(Domain Name System)服务器的地址。DNS用于将域名解析为IP地址,使得系统可以使用域名进行网络通信。TCP/IP协议栈参数:配置TCP/IP协议栈的相关参数,例如TCP最大连接数、TCP超时时间、IP数据包大小等。这些参数影响着网络通信的性能和可靠性。端口配置:配置TCP/IP协议栈中的端口号。端口号用于标识应用程序之间的通信端点,不同的应用程序使用不同的端口号进行通信。网络接口配置:配置网络接口的相关参数,包括接口名称、速度、工作模式等。这些参数与底层硬件相关,用于与网络接口进行通信。 配置TcpIp模块的具体方式和工具可能会因AUTOSAR软件供应商的不同而有所差异。一般情况下,可以通过AUTOSAR开发工具链提供的配置工具或编辑配置文件来进行TcpIp模块的配置。配置完成后,TcpIp模块就能够根据配置参数来建立和管理TCP/IP网络连接,并提供相应的网络通信功能。 4.4 SoAd 数据传输的TCP/IP概念,特别是使用以太网作为物理层,已经成为计算和电信环境中的事实上的标准。应用程序的寻址、端点的逻辑寻址和物理寻址都覆盖在一套分层的协议和数字分配中。动态配置和路由是实现这些概念的核心。 AUTOSAR遵循静态通信关系(static communication relations)的概念,该概念在编译时预先确定,在运行时严格执行。传输的数据被认为与它需要往返的源和接收一样是预先确定的。 Socket Adaptor模块旨在弥合这两个概念之间的差距。通过建立一个包含AUTOSAR所需信息的预先确定的配置,并保留一些项,以便在运行时进行更新,就可以利用相互冲突的概念。此外,SoAd将基于回调(call-back based)的软件体系结构与TCP/IP世界中的基于套接字(socket based)的通信处理解耦。 SoAd模块的主要目的是在使用PDU(如PDU Router)的AUTOSAR通信服务模块和基于socket的TCP/IP堆栈之间创建一个接口。它将I-PDU ID映射到socket连接,反之亦然。TCP/IP协议栈在TcpIp SWS中指定,如下图所示。为了便于了解,本文略示了TCP/IP堆栈的内部功能结构。 SoAd模块实现PDU和套接字转换的过程,包含了源端口,目的端口,源IP地址,目的IP地址等的设置。在SoAd配置中,首先需要定义发送和接收使用到的SoAdPduRoutes和SoAdSocketRoutes,这两个选项分别代表了发送和接收UDP报文的步骤。 Extended AUTOSAR Communication Stack. 扩展的AUTOSAR通信堆栈。 AutoSAR SoAd模块的配置参数关系图如下:

C#实现动态编程(即时编译JIT),执行本文代码,将文本转化为代码或者dll

什么是动态编程 顾名思义,动态编程就是动态的把程序代码编辑好,即时生成软件,立即使用。我们平时的编程都是静态编程,即将代码写好,生成软件之后使用。动态编程是软件写好之后,将部分代码灵活地加入到程序里面。这个就是动态编程。 动态编程可以运用在PAAS风格的产品里面,可以用于实现模态软件。 动态编程C#代码实例 string scriptstring = File.ReadAllText(@"Script\code.txt"); CodeDomProvider compiler = new CSharpCodeProvider(); //编译器 CompilerParameters comPara = new CompilerParameters(); //编译器参数 comPara.GenerateExecutable = false; // 生成exe文件 comPara.GenerateInMemory = true; // 是否在内存在输出 CompilerResults compilerResults = compiler.CompileAssemblyFromSource(comPara, scriptstring); if (compilerResults.NativeCompilerReturnValue == 0) { Assembly assembly = compilerResults.CompiledAssembly; object obj = assembly.CreateInstance("SCService.Busnisses." + request.Header.ToString()); } CodeDomProvider :编译器,所有的代码编译都是这个类完成;CompilerParameters :编译参数,可以设置生成执行文件是否内存输出等等; 编译的代码文本内容 code.txt文本内容 namespace SCService.Busnisses { public class Login { public string Execute(object data) { return null; } } } 动态编程主要是两个方向:

vs code连接wsl时,提示Connecting with SSH timed out

问题描述: 1:vs code 连接wsl时,提示WebSocket close with status code 1006。 2:使用cmd指令可以正常访问wsl中ssh服务,但是用vs code连接远程主机时,提示Connecting with SSH timed out。 解决方案: 按照网上各种方案进行修改,均无效,最终解决方案如下: 该文章纯粹为了记录该问题,防止之后遇到忘记如何解决,毕竟好记性不如烂笔头!!!

网络套接字(socket)编程,基于TCP协议写一个简单的C/S程序(附代码)

目录 简介 TCP协议(准备知识 想看代码可直接跳过 重在记录) TCP协议简介 TCP特性 1、确定应答机制(ACK) 2、超时重传 3、建立连接(三次握手) 4、断开连接(四次挥手) TCP可以做什么 简单TCP网络程序 服务端 创建服务端套接字函数 服务端绑定 服务端监听 服务端获取连接 服务端处理请求 客户端 创建客户端套接字函数 客户端连接服务器 客户端发起请求 代码 服务端代码 客户端代码 运行结果 编译代码 运行结果 服务端 客户端 结束语 简介 此篇文章是我用来记录学习网络套接字的过程,代码是在linux操作系统的vim界面下基于C++编写的,如果在VS或者其他编译器出现提示不包含一些头文件,是正常的现象,因为其中的一些头文件是linux操作系统才有的(自己踩过的坑hhhh)。 TCP协议(准备知识 想看代码可直接跳过 重在记录) TCP协议简介 TCP协议的英文全拼是Transmission Control Protocol,简称传输控制协议,与UDP相反,它是一种面向连接的、可靠的、基于字节流的传输层通信协议。(包含三次握手,四次挥手) 一般的通信步骤是: 1、创建连接:TCP不创建连接不传输数据,通信开始前一定要先建立好连接 2、传输数据 3、关闭连接 其余时间处于监听状态 TCP特性 通信双方必须先建立好连接才能进行数据传输,传输完数据的双方必须断开连接,不然会占用系统资源。主要的特性有 1、确定应答机制(ACK) TCP协议规定只有ACK=1时,才能建立连接,也规定连接建立后所有发送报文的ACK必须是1;发送方发送一个ACK信号后,接收方可以反馈一个应答报文(ACK),表示自己已收到; 为什么要用这种应答方式呢?是因为在网络传输过程中,传输的消息有可能会出现消息本身数据错误或者顺序消息传输的顺序错误,导致客户端和服务端之间传输的数据可靠性得不到保证,出现“后发先至”或“先发后至”的情况。TCP协议的应答机制可以有效避免改情况的发现,针对发送的请求进行编号,应答的时候也针对编号进行应答,既能保证数据传输没有错误,也能保证传输顺序。 上述情况不是很严谨,因为真实的TCP不一样,TCP是面向字节流的,此处的编号并不是按照一两条来编的,而是按照字节来编号的,每个字节有一个编号。 确认应答是一种特殊的报文(ACK),所谓的应答报文,本质上就是 ACK 字段为1 的报文,此时报头中的"确认序号"字段才是生效的; 初始序号是随机的,为了防止网络攻击;如果发送多个数据,每个数据都会带着一个序号 接收方收到数据后,是知道数据所带着的序号的,根据序号给出确认序号(告诉发送方下次给我发的序号),发送给发送方,发送方就知道接收方收到了哪些数据 2、超时重传 但如果我给你发送了好久的消息,问你出不出来玩,你可能意念回复了,实际上一直没回,我感到很伤心,所以决定再发送一次问你,出不出来玩,并且铁了心就是要问到你回为止,所以我设置一个固定的时间,隔一段时间就给你发送一次消息,直到你回我 为止(生气)!这就是超时重传。 在实际数据传输中,会出现丢包的情况,比如 一、B不想回A的消息; 二、B没收到A的消息(请求消息丢失) 三、B回复了,但A没收到(应答ACK丢失) 为了应对二和三的丢包情况,TCP协议对这两种情况做了统一处理,在内部设置启动一个定时器,达到一定时间没有ACK反馈,定时器就会自动触发重传消息的动作--超时重传。 假设是第二种丢包情况,请求消息丢失,重传是没有问题的;但假如是第三种ACK丢失,重传会导致接收方收到了相同的数据,所以TCP会在内部进行数据去重(以序号为 key 进行去重)保证应用层读到的数据不是重复数据。

Vue3使用codemirror

Vue3使用codemirror 设计说明后端接口的问题项目下载 设计说明 本意是打算搭建一个在线的代码运行编写平台,方便随时可以在手机上也测试一些简单的代码; 在集成这个插件的时候遇到了不少问题,主要是插件依赖的下载 npm install axios npm install vue-router@4 npm install element-plus --save npm install codemirror vue-codemirror --save npm install @codemirror/lang-javascript npm install @codemirror/lang-python npm install @codemirror/lang-cpp npm install @codemirror/lang-java import { createApp } from 'vue' import App from './App.vue' import router from './router' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import VueCodemirror from 'vue-codemirror' import { basicSetup } from "codemirror"; const app = createApp(App) app.use(router) app.use(ElementPlus) app.use(VueCodemirror, { autofocus: true, disabled: false, indentWithTab: true, tabSize: 4, placeholder: '在这里编写代码', extensions: [basicSetup], }) app.

python皮卡丘编程代码教程,用python画皮卡丘的代码

大家好,小编为大家解答用python画一只可爱的皮卡丘的问题。很多人还不知道python皮卡丘编程代码教程,现在让我们一起来看看吧! 1、我用python画皮卡丘,没有错误出现,我也打开才cmd窗口输入了page22.py,前面也加入了import turtle,求 命晌核则令行输入:python 如氏拦果python不是环境宴棚变量,请添加环境变量 2、怎么用python的turtle库画出这个图案,要代码? 命晌核则令行输入:python 如氏拦果python不是环境宴棚变量,请添加环境变量 import turtle as t def quad(color): 岩帆 t.begin_fill() 旦枣液t.color(color) t.forward(100) t.left(36) t.forward(100) t.left(36*4) t.forward(100) t.left(36) 模物t.forward(100) t.end_fill() t.left(36*3) for i in range(10): if i%2: quad('#99c8de') else: quad('#e5b9c4') 两三年没碰海龟了,觉得没啥用,看你赏金又提了就回去学了学 3、用Python画小车车 命晌核则令行输入:python 如氏拦果python不是环境宴棚变量,请添加环境变量 import turtle as t def quad(color): 岩帆 t.begin_fill() 旦枣液t.color(color) t.forward(100) t.left(36) t.forward(100) t.left(36*4) t.forward(100) t.left(36) 模物t.forward(100) t.end_fill() t.left(36*3) for i in range(10): if i%2: quad('#99c8de') else: quad('#e5b9c4') 两三年没碰海龟了,觉得没啥用,看你赏金又提了就回去学了学 你好,下辩枯面是一个对应的代码 import turtle

三元运算符引发的自动拆装箱问题

文章目录 问题背景问题排查排查过程问题扩展总结 问题背景 生产环境上出现空指针异常,追踪报错位置得知以下代码报错 if (isNull(aiGroup)) { return null; } aiGroup.setNum(isNull(param.getNum()) ? aiGroup.getNum() : param.getNum().doubleValue()); 问题排查 乍一看,真没有什么问题(当然可能是我经验不足),细看会发现自动装箱导致空指针异常,上边set方法代码可以拆分为两行: Double num = isNull(param.getNum()) ? aiGroup.getNum() : param.getNum().doubleValue(); aiGroup.setNum(num); 声明:属性类型:aiGroup#num类型是Double,param#num类型是BigDecimal 你可以自己单独写一个main方法,自行运行一下。 在这里我直接说出来,以上代码在获取num时,如果isNull()方法为true时,会从aiGroup获取num,但是aiGroup.getNum()的结果是null,理论是你直接给一个包装类型属性设置null是没有问题的,比如aiGroup.setNum(null),这样是正确的。 但是三元运算的时候,如果发现结果类型和表达式中的类型不一致,他会在最外层进行自动装箱,会执行Double.valueOf()的操作,所以会出现空指针的现象:Double.valueOf(null)。 反之会出现自动拆箱问题。 排查过程 许多人可能会不明白我是怎么知道为什么会有Double.valueOf(null)这一步,过程很简单,查看Java的字节码就可以看到,想看Java字节码更详细的点可以看:Java字节码介绍。 言归正传,在这里为了简单我又新建了一个简单Main类,使三元运算中表达式的类型不一致,代码如下: public class Main { public static void main(String[] args) { SdAiGroup aiGroup = new SdAiGroup(); // aiGroup#num是Double类型,aiGroup#test是double类型 Double test = Objects.isNull(aiGroup.getId()) ? aiGroup.getNum() : aiGroup.getTest(); aiGroup.setAcos(test); System.err.println(test); } } 生成class文件,然后执行Javap -c Main.class 结果如下: Compiled from "

Linux服务器增加虚拟交换内存

文章目录 swap分区的创建1、查看磁盘使用情况2、添加Swap分区3、对交换文件格式化并转换为swap分区4、挂载并激活分区5、查看新swap分区是否正常添加并激活使用6、修改 fstab 配置,设置开机自动挂载该分区7、查看是否已经使用了交换内存 更改Swap配置查看当前的swappiness数值修改swappiness值,这里以10为例设置永久有效,重启系统后生效 swap分区的删除1、停止正在使用swap分区2、删除swap分区文件3、删除或注释掉我们之前在fstab文件里追加的开机自动挂载配置内容 swap分区的创建 1、查看磁盘使用情况 free -h 2、添加Swap分区 使用dd命令创建名为swapfile 的swap交换文件(文件名和目录任意): dd if=/dev/zero of=/var/swapfile bs=1024 count=4194304 dev/zero是Linux的一种特殊字符设备(输入设备),可以用来创建一个指定长度用于初始化的空文件,如临时交换文件,该设备无穷尽地提供0,可以提供任何你需要的数目。 bs=1024 :单位数据块(block)同时读入/输出的块字节大小为1024 个字节即1KB,bs(即block size)。 count = 4194304 表示的是4G 具体计算公式为:1KB * 4194304 =1KB *1024(k)10244 = 4194304 =4G 如需要调整交换区的大小的话,可以自行设置其他的 执行完命令后,会进行4G读写操作,所以会有一些卡顿,请耐心等待! 3、对交换文件格式化并转换为swap分区 mkswap /var/swapfile 4、挂载并激活分区 swapon /var/swapfile 执行以上命令可能会出现:“不安全的权限 0644,建议使用 0600”类似提示,不要紧张,实际上已经激活了,可以忽略提示,也可以听从系统的建议修改下权限: chmod -R 0600 /var/swapfile 5、查看新swap分区是否正常添加并激活使用 free -h 6、修改 fstab 配置,设置开机自动挂载该分区 echo "/var/swapfile swap swap defaults 0 0" >> /etc/fstab 7、查看是否已经使用了交换内存 top 我们能够看到,交换空间已经成功被使用! 更改Swap配置 一般默认的情况,当我们开启交换虚拟内存空间后,默认好像是当内存使用百分50的时候,就会开始使用交换空间,这样就会造成一个情况,就是本身物理内存还没有使用完成, 就去使用虚拟内存,这样肯定会影响我们的使用效率,那么我们怎么避免这个情况的发生呢?

STM32自定义串口通信协议

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file usart.c * @brief This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS.

Compose 为什么可以跨平台

前言 Compose 不止用于 Android 开发,凭借 Kotlin 的语言优势,Compose 变身为一个极具潜力的跨平台 UI 解决方案。本文从 Compose Runtime 的视角出发,带我们一探 Compose 实现跨平台的底层原理。 1 Compose Architecture Compose 作为一个框架,在架构上从下到上分成多层: Compose Compiler:Kotlin 编译器插件,负责对 Composable 函数的静态检查以及代码生成等。 Compose Runtime:负责 Composable 函数的状态管理,以及执行后的渲染树生成和更新。 Compose UI: 基于渲染树进行 UI 的布局、绘制等 UI 渲染工作。 Compose Foundation: 提供用于布局的基础 Composable 组件,例如 Column,Row 等。 Compose Material:提供上层的面向 Material 设计风格的 Composable 组件。各层的职责明确,其中 Compose Compiler 和 Runtime 是支撑整个声明式 UI 运转的基石。 2 Compose Compiler 我们先看一下 Compose Compiler 的作用: 左边的源码是一个非常简单的 Composable 函数,定义了个一大带有状态的 Button,点击按钮,Button 中显示的 count 数增加。

SOLIDWORKS磁力配合工具

在我们平常的工作中,很多人都会面临大型装配体相互配合的问题。有很多用户,由于设计的产品体积很大,零件数量非常多。即使将设备分成不同的部件进行组装,不同的部件之间进行配合也非常困难。因为这种时候软件运行的速度会变得非常慢,做一个配合关系需要等待很长时间或者根本卡住不动。 另外还有一些用户,需要配合公司整体项目规划,建立工厂布局或者完整的产线规划,需要将大量的设备进行组合排布。这时候,整个布局装配体的性能就显得很难受,设备和设备之间的配合太艰难了...... 本篇文章小信为大家带来的是SOLIDWORKS装配功能中的磁力配合”工具。 磁力配合工具让我们可以脱离传统的配合关系,依靠类似“吸附”的动作将两个装配体快速配合。在解决工厂布局、工业组件或其他大型互联组件的配合问题时特别有利,再结合一些大型装配体的功能,可以让配合变得更加容易快速。 下面我们将通过一个滚筒输送带的配合安装为例进行演示。 图1 滚筒输送带布局 从SOLIDWORKS模型装配来看,这跟我们许多用户遇到的问题非常相似: 这种装配体有非常多的设备组成:这一个完整的输送带系统由控制系统、多个机械手、多个输送机单元组成很非常多的辊道输送单元组成,子装配体和零件数量非常多。 1、 整个布局装配体文件体量非常大:整个装配体涉及到的零件大概2G左右,装配体总体零件数量3千左右。(用户自己的装配体可能更大,比小生这个样本文件大很多!) 2、 这种在本身体积就很大的装配体中再去做配合或者添加新的设备,往往会让SOLIDWORKS运行的特别慢,特别卡。 下面我们用磁力配合尝试下: Step 1:零部件中发布资产。首先,做磁力配合之前需要在子装配体或者零件中发布资产,定义地面和吸附点。 打开零件或者装配体。SOLIDWORKS菜单栏:【工具】--【Asset Publisher】,如图2所示。 图2 进入“Asset Publisher”功能 根据面板上的提示,定义地面和连接点(就是总装中使用的吸附点),如图3。 图3 “Asset Publisher”编辑对话框 磁力配合中的连接点用于定义装配体中其他资产定义的点,选择不同的轮廓类型,定位点一般不同。 选择的几何图元连接点的位置顶点在顶点处线性边线在中点处圆形边线在中心点处 表1 在本例中我们为这个子装配体共创建5个连接点和一个地面。 创建完毕之后,可在模型的特征树中找到刚才的磁力特征。如图4所示。 图4 Published References 所有需要连接的组件均需要通过以上步骤。 Step 2:总装配体中定义地面基准。磁力配合的地面可以是多个地面,像这个例子中是有两层的平台可以作为地面基准的。使用“参考几何体-地面基准”增加两个地面基准。(这里因为做多层平台,所以有个作为地面的子装,如果没有特殊要求也可以将总装中的标准基准面作为地面) 图5 图6 发布的地面基准 Step 3:将设备插入到装配体中。对于所有已经在零部件中添加过连接点和地面的零部件在插入到总装中都可以自动识别地面,将地面重合。两个零部件接近时。磁力点会自动显示进行吸附。 图7 识别地面自动配合 图8 零部件之间依靠吸附点进行配合 所有零部件装配完成后产生整条产线。 图9 磁力配合可以在大型装配体的配合中有效提高装配性能,帮助我们实现更快速、更简便的配合。结合一些大型装配体的功能,改善大型装配体处理的性能,提高我们的工作效率。 小技巧: 1.对于特别大的模型,我们可以创建资产的 SpeedPak 配置,进一步提高大型装配体的性能。 2.在特征管理器设计树中,我们可以鼠标右键单击顶层装配体,树显示---将零部件实例分组。这可在众多相似的零部件中快速找到我们想要的零部件。 3.地面基准面可以设置多个。 4.已经配合结束的资产,可以直接拖动,重新与其他资产配合。 5.磁力配合点可以锁定或者解除锁定。已经锁定的配合点,无法通过鼠标拖拽的方式进行二次配合。 图10

超参数优化 - 贝叶斯优化基础方法

目录 1. 贝叶斯优化的基本流程 2. 贝叶斯优化用于HPO 在之前的学习中我们了解了网格搜索、随机网格搜索与Halving网格搜索,无论具体每种网格搜索的思想如何变化,网格优化都是在一个大参数空间中、尽量对所有点进行验证后再返回最优损失函数值的方法,这一类方法在计算量与计算时间上有着不可避免的缺陷,因此才会有随机、Halving等试图缩短训练时间、让整体网格搜索更加适合于大型数据和大型空间的手段。然而,尽管sklearn在提高网格搜索效率方面做出了种种优化,但上述方法仍然无法在效率和精度上做到双赢,若希望更快速的进行参数搜索、并且搜索出一组泛化能力尽可能强的参数,目前的常见做法还是选用一些带有先验过程的调参工具,即一些基于贝叶斯过程调参工具。 ps:先验过程是指在观测到任何数据之前,对模型参数或未知变量的分布进行建模。它是基于先前的经验或领域知识,以及模型的先验假设,来描述参数或变量的分布。先验过程可以帮助我们在没有足够数据时对模型进行初始估计,或者在数据不足或不完整的情况下提供一种合理的先验推断。在贝叶斯统计中,先验过程与后验过程共同构成了贝叶斯推断的基础。 1. 贝叶斯优化的基本流程 首先,假设现在知道一个函数𝑓(𝑥))的表达式以及其自变量𝑥的定义域,现在,我们希望求解出𝑥的取值范围上𝑓(𝑥)的最小值,你打算如何求解这个最小值呢?面对这个问题,无论是从单纯的数学理论角度,还是从机器学习的角度,我们都已经见过好几个通俗的思路: ① 对𝑓(𝑥)求导、令其一阶导数为0来求解其最小值。要求:函数𝑓(𝑥)可微,且微分方程可以直接被求解。 ② 通过梯度下降等优化方法迭代出𝑓(𝑥)的最小值。要求:函数𝑓(𝑥)可微,且函数本身为凸函数。 ③ 将全域的𝑥带入𝑓(𝑥)计算出所有可能的结果,再找出最小值。要求:函数𝑓(𝑥)相对不复杂、自变量维度相对低、计算量可以承受。 当我们知道函数𝑓(𝑥)的表达式时,以上方法常常能够有效,但每个方法都有自己的前提条件。假设现在函数𝑓(𝑥)是一个平滑均匀的函数,但它异常复杂、且不可微,我们无法使用上述三种方法中的任意一种方法求解,但我们还是想求解其最小值,可以怎么办呢?由于函数异常复杂,带入任意𝑥计算的所需的时间很长,所以我们不太可能将全域𝑥都带入进行计算,但我们还是可以从中随机抽样部分观测点来观察整个函数可能存在的趋势。于是我们选择在𝑥的定义域上随机选择了4个点,并将4个点带入𝑓(𝑥)进行计算,得到了如下结果: 当我们有了4个观测值,并且知道我们的函数时相对均匀、平滑的函数,那我们可能对函数的整体分布有如下猜测: 当我们对函数整体分布有一个猜测时,这个分布上一定会存在该函数的最小值。同时,不同的人可能对函数的整体分布有不同的猜测,不同猜测下对应的最小值也是不同的。 现在,假设我们邀请了数万个人对该问题做出猜测,每个人所猜测的曲线如下图所示。不难发现,在观测点的附近,每个人猜测的函数值差距不大,但是在远离远侧点的地方,每个人猜测的函数值就高度不一致了。这也是当然的,因为观测点之间函数的分布如何完全是未知的,并且该分布离观测点越远时,我们越不确定真正的函数值在哪里,因此人们猜测的函数值的范围非常巨大。 现在,将所有猜测求均值,并将任意均值周围的潜在函数值所在的区域用色块表示,可以得到一条所有人猜测的平均曲线。不难发现,色块所覆盖的范围其实就是大家猜测的函数值的上界和下界,而任意𝑥所对应的上下界差异越大,表示人们对函数上该位置的猜测值的越不确定。因此上下界差异可以衡量人们对该观测点的置信度,色块范围越大,置信度越低。 在观测点周围,置信度总是很高的,远离观测点的地方,置信度总是很低,所以如果我们能够在置信度很低的地方补充一个实际的观测点,我们就可以很快将众人的猜测统一起来。以下图为例,当我们在置信度很低的区间内取一个实际观测值时,围绕该区间的“猜测”会立刻变得集中,该区间内的置信度会大幅升高。 当整个函数上的置信度都非常高时,我们可以说我们得出了一条与真实的𝑓(𝑥)曲线高度相似的曲线𝑓*,此时我们就可以将𝑓*的最小值当作真实𝑓(𝑥)的最小值来看待。自然,如果估计越准确,𝑓*越接近𝑓(𝑥),则𝑓*的最小值也会越接近于𝑓(𝑥)的真实最小值。那如何才能够让𝑓*更接近𝑓(𝑥)呢?根据我们刚才提升置信度的过程,很明显——观测点越多,我们估计出的曲线会越接近真实的𝑓(𝑥)。然而,由于计算量有限,我们每次进行观测时都要非常谨慎地选择观测点。那如何选择观测点才能够最大程度地帮助我们估计出𝑓(𝑥)的最小值呢? 有非常多的方法,其中最简单的手段是使用最小值出现的频数进行判断。由于不同的人对函数的整体分布有不同的猜测,不同猜测下对应的最小值也是不同的,根据每个人猜测的函数结果,我们在𝑋轴上将定义域区间均匀划分为100个小区间,如果有某个猜测的最小值落在其中一个区间中,我们就对该区间进行计数(这个过程跟对离散型变量绘制直方图的过程完全一致)。当有数万个人进行猜测之后,我们同时也绘制了基于𝑋轴上不同区间的频数图,频数越高,说明猜测最小值在该区间内的人越多,反之则说明该猜测最小值在该区间内的人越少。该频数一定程度上反馈出最小值出现的概率,频数越高的区间,函数真正的最小值出现的概率越高。 当我们将𝑋轴上的区间划分得足够细后,绘制出的频数图可以变成概率密度曲线,曲线的最大值所对应的点是𝑓(𝑥)的最小值的概率最高,因此很明显,我们应该将曲线最大值所对应的点确认为下一个观测点。根据图像,最小值最有可能在的区间就在x=0.7左右的位置。当我们不取新的观测点时,现在𝑓(𝑥)上可以获得的可靠的最小值就是x=0.6时的点,但我们如果在x=0.7处取新的观测值,我们就很有可能找到比当前x=0.6的点还要小的𝑓𝑚𝑖𝑛。因此,我们可以就此决定,在x=0.7处进行观测。 当我们在x=0.7处取出观测值之后,我们就有了5个已知的观测点。现在,我们再让数万人根据5个已知的观测点对整体函数分布进行猜测,猜测完毕之后再计算当前最小值频数最高的区间,然后再取新的观测点对𝑓(𝑥)进行计算。当允许的计算次数被用完之后(比如,500次),整个估计也就停止了。 在这个过程当中,我们其实在不断地优化我们对目标函数𝑓(𝑥)的估计,虽然没有对𝑓(𝑥)进行全部定义域上的计算,也没有找到最终确定一定是𝑓(𝑥)分布的曲线,但是随着观测的点越来越多,我们对函数的估计是越来越准确的,因此也有越来越大的可能性可以估计出𝑓(𝑥)真正的最小值。这个优化的过程,就是贝叶斯优化。 2. 贝叶斯优化用于HPO 在贝叶斯优化的数学过程当中,我们主要执行以下几个步骤: ① 定义需要估计的𝑓(𝑥)以及𝑥的定义域 ② 取出有限的n个𝑥上的值,求解出这些𝑥对应的𝑓(𝑥)(求解观测值) ③ 根据有限的观测值,对函数进行估计(该假设被称为贝叶斯优化中的先验知识),得出该估计𝑓*上的目标值(最大值或最小值) ④ 定义某种规则,以确定下一个需要计算的观测点 并持续在②~④步骤中进行循环,直到假设分布上的目标值达到我们的标准,或者所有计算资源被用完为止(例如,最多观测m次,或最多允许运行t分钟)。 以上流程又被称为序贯模型优化(SMBO),是最为经典的贝叶斯优化方法。在实际的运算过程当中,尤其是超参数优化的过程当中,有以下具体细节需要注意: 当贝叶斯优化不被用于HPO时,一般𝑓(𝑥)可以是完全的黑盒函数(black box function,也译作黑箱函数,即只知道𝑥与𝑓(𝑥)的对应关系,却丝毫不知道函数内部规律、同时也不能写出具体表达式的一类函数),因此贝叶斯优化也被认为是可以作用于黑盒函数估计的一类经典方法。但在HPO过程当中,需要定义的𝑓(𝑥)一般是交叉验证的结果/损失函数的结果,而我们往往非常清楚损失函数的表达式,只是我们不了解损失函数内部的具体规律,因此HPO中的𝑓(𝑥)不能算是严格意义上的黑盒函数。 在HPO中,自变量𝑥就是超参数空间。在上述二维图像表示中,𝑥为一维的,但在实际进行优化时,超参数空间往往是高维且极度复杂的空间。 最初的观测值数量n、以及最终可以取到的最大观测数量m都是贝叶斯优化的超参数,最大观测数量m也决定了整个贝叶斯优化的迭代次数。 在第3步中,根据有限的观测值、对函数分布进行估计的工具被称为概率代理模型(Probability Surrogate model),毕竟在数学计算中我们并不能真的邀请数万人对我们的观测点进行连线。这些概率代理模型自带某些假设,他们可以根据廖廖数个观测点估计出目标函数的分布𝑓*(包括𝑓*上每个点的取值以及该点对应的置信度)。在实际使用时,概率代理模型往往是一些强大的算法,最常见的比如高斯过程、高斯混合模型等等。传统数学推导中往往使用高斯过程,但现在最普及的优化库中基本都默认使用基于高斯混合模型的TPE过程。 在第4步中用来确定下一个观测点的规则被称为采集函数(Aquisition Function),采集函数衡量观测点对拟合𝑓*所产生的影响,并选取影响最大的点执行下一步观测,因此我们往往关注采集函数值最大的点。最常见的采集函数主要是概率增量PI(Probability of improvement,比如我们计算的频数)、期望增量(Expectation Improvement)、置信度上界(Upper Confidence Bound)、信息熵(Entropy)等等。上方gif图像当中展示了PI、UCB以及EI。其中大部分优化库中默认使用期望增量。 在HPO中使用贝叶斯优化时,我们常常会看见下面的图像,这张图像表现了贝叶斯优化的全部基本元素,我们的目标就是在采集函数指导下,让𝑓*尽量接近𝑓(𝑥)。

复制Eclipse项目

复制Eclipse项目,然后直接打开路径时,项目路径是复制之前的,而不是复制之后的,可进行如下操作:先将原项目删除(本地项目文件不可删除,只是删除Eclipse上的),再将复制后的导入进来,就可以了。如果不做这样的操作,编辑的新项目将会把原文件修改掉。

使用Kmeans算法完成聚类任务

聚类任务 聚类任务是一种无监督学习任务,其目的是将一组数据点划分成若干个类别或簇,使得同一个簇内的数据点之间的相似度尽可能高,而不同簇之间的相似度尽可能低。聚类算法可以帮助我们发现数据中的内在结构和模式,发现异常点和离群值,简化数据表示,以及为进一步的分析提供基础。聚类任务在现实世界中有很多应用场景,以下是其中的一些例子: 市场细分:聚类可以帮助将市场分成不同的细分市场,以便更好地针对消费者需求制定营销策略。 图像分析:聚类可以用于图像分析,例如将相似的图像分组。 模式识别:聚类可以用于发现数据中的模式和关系,例如在医疗领域中,可以使用聚类来发现疾病之间的关系。 推荐系统:聚类可以用于推荐系统中,以将用户分组并向他们推荐相似的产品或服务。 K-Means算法 K-Means是一种基于聚类的无监督机器学习算法,其目的是将一组数据点分为k个不同的簇,使得每个数据点与其所属簇的中心点(也称质心)的距离最小化。以下是K-Means的工作原理: 初始化:随机选择k个数据点作为初始质心。 分配:对每个数据点,计算其与每个质心的距离,并将其分配给距离最近的质心所代表的簇。 重新计算质心:对于每个簇,重新计算其质心位置,即将该簇中所有数据点的坐标求平均。 重复执行第2,3步,直到所有数据点的簇分配不再改变或达到预设的最大迭代次数为止。 下面是用K-Means算法完成聚类的简单Demo,下面的demo中K设置为2. from sklearn.cluster import KMeans import numpy as np # create some sample data X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]) # create a KMeans object with 2 clusters kmeans = KMeans(n_clusters=2, random_state=0) # fit the KMeans object to the data kmeans.fit(X) # print the centroids of the two clusters print(kmeans.

【Docker】Docker 部署 Mysql 并设置数据持久化

文章目录 1. Docker持久化MySQL2. 测试删除MySQL容器后新建容器,数据还在不在3. 参考资料 我们使用Docker的目的就是图它方便下载部署,不用常规的经历下载、配置、安装等等繁琐的步骤。但是与此同时Docker也存在一些缺点,像删除容器后数据就都没有了。很显然,不能持久化对于需要数据持久化的MySQL数据库来说是不能接受的,那有没有方式可以解决。 有,通过挂载方式 1. Docker持久化MySQL 挂载最大的优点是在删除容器后,该文件依然存在与主机中,下次启动新容器依然可以使用这些数据而不用重新配置一遍环境和恢复数据,这对需要持久化的容器特别友好,如mysql。 至于使用,通过 -v 命令可以把主机中的文件挂载到容器中,在启动容器时指定,举例如下: docker run -p 3306:3306 --name mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:5.7 2. 测试删除MySQL容器后新建容器,数据还在不在 假设,存在名为 mysql_test 的容器中,创建了 spring_test 数据库 现在删除 mysql_test 容器(如果不挂载那么所有数据库都会被删除) docker rm mysql_test 重新安装挂载源文件到新的容器 mysql_test_new 中 docker run -p 3306:3306 --name mysql_test_new \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:5.

基于javaweb+SSM的实验室预订申请管理系统(java+ssm+layui+JSP+maven++mysql)

一、项目简述 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持) 项目技术: JSP +Spring + SpringMVC + MyBatis + html+ css + JavaScript + JQuery + Ajax + layui+ maven等等。 适用 课程设计,大作业,毕业设计,项目练习,学习演示等 private OperaterLogService operaterLogService; /** * 用户列表页面 * @param model * @param user * @param pageBean * @return */ @RequestMapping(value="/list") public String list(Model model,User user,PageBean<User> pageBean){ model.addAttribute("title", "用户列表"); model.addAttribute("username", user.getUsername()); model.addAttribute("pageBean", userService.findList(user, pageBean)); return "admin/user/list"; } @RequestMapping(value = "/updatePassword", method = RequestMethod.

java高频词汇

翻看源码时,最常出现的词汇汇总,持续更新中… trigger 触发器 触发器是数据库中的特殊对象,可在特定事件发生时自动执行操作或触发逻辑。它通常与数据库表相关联,可在满足条件时触发数据的增、删、改等操作。作用是自动触发预定义的操作或逻辑。 repository 仓库 在源代码中,"Repository"是一个类或模块,封装了数据访问逻辑并提供了操作接口。它简化了数据的访问和操作,使其他部分可以轻松地使用数据,而不必考虑底层细节。 其他词汇: 单词释义instance实例dynamic动态 corresponding对应的、相应的autodetected自动检测concrete具体的abstract抽象的extract提取populate

技巧大揭秘:如何巧妙绕过Cloudflare验证码?

作为一名爬虫工程师,我深知在当今互联网世界中,Cloudflare等验证码系统的出现,对我们获取数据和进行爬取工作带来了新的挑战。然而,作为遵纪守法的技术从业者,我们必须始终坚守合规原则。本文将着重探讨利用API技巧,以合法合规的方式绕过Cloudflare验证码的可能性。 Cloudflare旨在保护网站免受恶意爬取和其他网络攻击,因此,它可能会对频繁的请求进行拦截,要求用户进行验证码验证。对于爬虫工程师而言,这意味着我们不能简单粗暴地通过传统的爬取手段直接获取数据。 我们可以利用一些API技巧来合法绕行Cloudflare验证码。以下是一些实用的方法: 合理调整请求频率:降低请求频率,模拟真实用户的行为。这样做不仅可以减少验证码的触发,还有助于维护网站服务器的稳定性。使用代理IP:通过使用不同的代理IP地址轮流发送请求,可以分散访问来源,减少被拦截的可能性。多用户代理(User-Agent)设置:模拟多种不同的浏览器、设备和操作系统类型,使爬虫请求看起来更像是普通用户的行为。JavaScript渲染:某些网站的验证码是通过JavaScript生成的,使用Headless浏览器或类似的技术,让爬虫能够执行JavaScript代码,从而成功绕过验证码。 本文转载自穿云API官方博客: API技巧大揭秘:如何巧妙绕过Cloudflare验证码? – 穿云API帮助教程

准备面试 记录

一、toString()和String()方法的区别 简单来说对应引用类型 toString()会返回该对象类型的字符串,对象都会继承toString()方法 二、toString()和valueOf()的区别 valueOf() 它的作用是返回它相应的原始值 toString就是将一个对象转化为字符串类型,默认的toString方法会输出以下结果: toString Vs valueOf 1、js是弱语言进行比较或者计算是 假如valueOf()方法已定义,返回的是原始类型那么会优先调用, 2、如果不定义valueOf(或者valueOf返回的不是原始数据类型),并且定义了toString(且toString返回一个原始数据类型),调用toString 3、如果将toString和valueOf方法都设置为null,或者都没有返回原始数据类型,直接报错 4、Date对象,默认先调用toString方法 5、如果将toString方法的返回设置为非原始数据类型,也会调用valueOf 6、String()方法会优先调用toString方法,Number会优先调用valueOf方法

CentOS 搭建 GitLab && Git

本文目录 1. CentOS7 搭建 Gitlab1. 安装 sshd1. 安装 sshd 依赖2. 启动并设置开机自启3. 安装防火墙4. 开启防火墙5. 开放 ssh 以及 http 服务 2. 安装 postfix1. 安装 postfix2. 启动并设置开机自启3. 几个补充知识 3. 下载并安装 gitlab1. 在线下载安装包2. 安装 4. 修改 gitlab 配置5. 重载配置及启动 gitlab6. 把端口添加到防火墙7. 登录 GitLab 页面 2. CentOS7 安装 Git1. 安装 Git2. 验证是否安装成功3. 配置基本信息4. 验证配置是否成功 1. CentOS7 搭建 Gitlab 1. 安装 sshd 1. 安装 sshd 依赖 输入以下命令: yum install -y curl policycoreutils-python openssh-server 注:因为我之前已经装过了 sshd 依赖,所以就如上图所示。没装过的耐心等待就好。

两个瓶子倒水问题python版本

两个瓶子倒水问题 简单粗暴无脑法武功秘籍:实战:解析总结 扩展欧几里得算法及贝祖等式求解课前扩展题目解析扩展欧几里得算法代码实现总结 贝祖等式结合广度优先算法求最优解解题思路代码实现 问题:假设有一个3升的杯子和一个5升的杯子以及充足的水源,现在问如何使用这两个杯子精确的取出4升的水。 简单粗暴无脑法 武功秘籍: 第一式:先选择小杯子装满水然后倒在大杯子,直到大杯子装满 第二式:大杯子水倒掉,把小杯子剩下的水倒进大杯子 第三式:无限循环第一式和第二式,至此武功大成 实战: 假设3升的杯子为C1,5升的杯子为C2 第一步:C1装满倒入C2,此时C1=0,C2=3 第二步:C1装满导入C2,此时C1=1, C2=5 第三步:倒掉C2,然后C1倒入C2, 此时C1=0,C2=1 第四步:C1装满导入C2, 此时C1=0,C2=4 完成 解析 当两个杯子的容量数互质时(假设一个3升,一个5升),他们的最大公约数为1(Gcd(a,b)=1)。 第一次小杯子往大杯子倒水其实就等于C1对C2求余(即3 / 5 = 0…3) 第二次小杯子往大杯子倒水相当于2C1对C2求余(即 2*3 / 5=1…1) 第三次小杯子往大杯子倒水相当于3C1对C2求余(即3*3 / 5 =1…4) 注意余数就是最终想要获取的水的升数,商就代表大杯子会被装满几次 总结 根据解析求该问题的解其实就是在求 C1*X mod C2 = 4 (小的数的X倍对大的数求余等于想要的数) 看到这里就要开始我们的第二种方法了 扩展欧几里得算法及贝祖等式求解 课前扩展 贝祖定理: 如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b) 贝祖等式定义: ax + by = m 有整数解时,当且仅当m是 a和b的最大公约数的倍数。 贝祖等式逆命题: ax + by = m 当m为a,b最大公约数的倍数时,一定存在整数解使得等式成立【证明自行搜索】 欧几里得算法: 欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。计算公式gcd(a,b) = gcd(b,a mod b)

java 8 stream+lambda 简化集合操作

目录 1.利用stream创建集合 1.1 Stream.of 创建 1.2 利用 Stream.iterate 创建 2. 遍历 forEach 3.查找 find 4.匹配 match 5.筛选 filter 6.映射 map/flatMap 7.归约 reduce 8.排序 sorted 9.收集 collect 10.list转map 11.去重 12.分组 13.方法 13.1 map() 13.2 filter() 13.3 limit() 13.4 skip() 13.5 distinct() 13.6 peek() 13.7 collect() 14 map转 list 1.利用stream创建集合 1.1 Stream.of 创建 public static void main(String[] args) { Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5); List<Integer> collect = stream.collect(Collectors.toList()); collect.

【Solr】Solr搜索引擎使用

文章目录 一、什么是Solr?二 、数据库本身就支持搜索啊,干嘛还要搞个什么solr?三、如果我们想要使用solr那么首先我们得安装它 一、什么是Solr? 其实我们大多数人都使用过Solr,也许你不会相信我说的这句话,但是事实却是如此啊 ! 每当你想买自己喜欢的东东时,你可能会打开某宝或者某东,像这样一搜,就能搜到很多东西,你知道你看到的这些数据都来自哪儿吗?百度一下你就知道!这些数据来自哪儿吗?等你了解完Solr后你就知道答案啦! 现实生活中我们都知道大多数网站或应用都必须具有某种搜索功能,问题是搜索功能往往是巨大的资源消耗并且它们由于沉重的数据库加载而拖垮你的应用的性能。 这就是为什么转移负载到一个外部的搜索服务器是一个不错的主意,Apache Solr是一个流行的开源搜索服务器,它通过使用类似REST的HTTP API,这就确保你能从几乎任何编程语言来使用solr。 Solr是一个开源搜索平台,用于构建搜索应用程序。 它建立在Lucene(全文搜索引擎)之上。 Solr是企业级的,快速的和高度可扩展的。 使用Solr构建的应用程序非常复杂,可提供高性能。 为了在CNET网络的公司网站上添加搜索功能,Yonik Seely于2004年创建了Solr。并在2006年1月,它成为Apache软件基金会下的一个开源项目。并于2016年发布最新版本Solr 6.0,支持并行SQL查询的执行。 Solr可以和Hadoop一起使用。由于Hadoop处理大量数据,Solr帮助我们从这么大的源中找到所需的信息。不仅限于 搜索,Solr也可以用于存储目的。像其他NoSQL数据库一样,它是一种非关系数据存储和处理技术。 总之,Solr是一个可扩展的,可部署,搜索/存储引擎,优化搜索大量以文本为中心的数据。 二 、数据库本身就支持搜索啊,干嘛还要搞个什么solr? 其实正如上面solr的介绍中所说的那样,solr本身也可以看成数据库,(no sql类型),但它比数据库搜索速度更快,所以在项目中我们一般把搜搜的部分交给solr,就像我们在京东首页所看到的商品信息,并不是来自数据库,而是来源于sorl的索引库 数据库本身不能实现分词效果,而只能使用模糊查询,但是模糊查询非常低效,查询速度比较慢,由于在实际生活中,一般搜索是用的比较多的,这样数据库压力自然就很大,所以我们就让供专业的solr来做搜索功能 三、如果我们想要使用solr那么首先我们得安装它 由于solr是以java开发而成,所以必须在jdk环境中运行。(配置 JAVA_HOME 这里就不具体介绍了) 下载并解压 solr,官网 https://lucene.apache.org/solr,我们直接附上最新版链接( solr-8.6.1.zip ) 解压后打开solr文件夹进bin目录,在地址框输入cmd 回车 此时弹出命令行 输入solr.cmd start 命令开启solr服务 打开浏览器输入https://localhost:8983/solr 下文附上全部图解 创建 code 核心并添加 conf 配置文件 solr官网 解压后打开solr文件夹进bin目录,在地址框输入cmd 回车 此时弹出命令行 输入solr.cmd start 命令开启solr服务 看到下面这个界面说明solr安装成功啦! 创建 code 核心并添加 conf 配置文件 创建后找到 server\solr\ 创建核心新建的文件夹 从 solr-7.7.2\example\example-DIH\solr\solr 中找到配置文件复制到新建文件夹 7.重启服务 8.显示以下界面表示核心创建成功啦!

【FreeRTOS学习】第11章 FreeRTOS的启动流程

1. 启动方法1 第一种我称之为万事俱备,只欠东风法。这种方法是在main函数中将硬件初始化,RTOS系统初始化,所有任务的创建这些都弄好,这个我称之为万事都已经准备好。最后只欠一道东风,即启动RTOS的调度器,开始多任务的调度。 //伪代码 int main(void) { HardWare_Init(); //硬件初始化 RTOS_Init(); //RTOS系统初始化 RTOS_TaskCreate(Task1); //创建任务1,但任务1不会执行,因为调度器还没有开启 RTOS_TaskCreate(Task2); //创建任务2,但任务1不会执行,因为调度器还没有开启 //继续创建各种任务 RTOS_Start(); //启动RTOS,开始调度 } void Task1(void *arg) { while(1); { //任务实体,必须有阻塞的情况出现 } } void Task2(void *arg) { while(1); { //任务实体,必须有阻塞的情况出现 } } 2. 启动方法2 第二种我称之为小心翼翼,十分谨慎法。这种方法是在main函数中将硬件和RTOS系统先初始化好,然后创建一个启动任务后就启动调度器,然后在启动任务里面创建各种应用任务,当所有任务都创建成功后,启动任务把自己删除。 //伪代码 int main(void) { HardWare_Init(); //硬件初始化 RTOS_Init(); //RTOS系统初始化 RTOS_TaskCreate(AppTaskCreate); //创建一个任务 RTOS_Start(); //启动RTOS,开始调度 } void AppTaskCreate(void *arg) { RTOS_TaskCreate(Task1); //创建任务1,但任务1不会执行,因为调度器还没有开启 RTOS_TaskCreate(Task2); //创建任务2,但任务1不会执行,因为调度器还没有开启 //继续创建各种任务 RTOS_TaskDelete(AppTaskCreate); //当任务创建完成,删除起始任务 } void Task1(void *arg) { while(1) { //任务实体,必须有阻塞的情况出现 } } void Task2(void *arg) { while(1) { //任务实体,必须有阻塞的情况出现 } } 3.

Openssl版本升级

Openssl版本升级 定义CentOS 升级1.现有版本确认2.登录到OpenSSL官网查看最新版本3.在获取到下载地址后,使用wget命令下载最新文件4.编译安装OpenSSL,依次执行命令5.优化OpenSSL路径,依次执行下方命令6.查看OpenSSL版本信息 定义 在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。 CentOS 升级 背景:在进行对现有系统进行漏洞扫描时发现OpenSSL存在版本过低的情况。 1.现有版本确认 登录到CentOS系统并输入命令行进行版本查询 openssl version 2.登录到OpenSSL官网查看最新版本 官网地址: link 3.在获取到下载地址后,使用wget命令下载最新文件 wget https://www.openssl.org/source/old/3.1/openssl-3.1.0.tar.gz --no-check-certificate # --no-check-certificate 后缀表示不验证证书,避免使用wget命令下载hpps时失败 4.编译安装OpenSSL,依次执行命令 tar xf openssl-3.1.0-alpha1.tar.gz # tar xf 解压缩 cd _openssl-3.1.0-alpha1_ ./config && make && make install 5.优化OpenSSL路径,依次执行下方命令 echo "/usr/local/lib64/" >> /etc/ld.so.conf # echo命令用来打印信息,是一个最常用的命令。在命令行中常用来打印环境变量的值,已确定当前环境中是否设置了指定的环境变量。在shell脚本中,常用来打印信息和帮助调试程序。 ldconfig # ldconfig命令的作用主要是在默认搜寻目录/lib和/usr/lib以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库,进而创建出动态装入程序(ld.so)所需的连接和缓存文件 mv /usr/bin/openssl /usr/bin/openssl.old ln -sv /usr/local/bin/openssl /usr/bin/openssl # 为某一个文件在另外一个位置建立一个同步的链接,这个命令最常用的参数是-s,具体用法是:ln -s 源文件 目标文件 6.查看OpenSSL版本信息 openssl version

k8s集群的部署

【1】安装docker systemctl enable docker 所有节点均需要安装docker,并且使其开机自启,每个节点均部署镜像加速器 【2】配置k8s的yum文件 [root@k8s1 ~]# cd /etc/yum.repos.d/ [root@k8s1 yum.repos.d]# vim k8s.repo [root@k8s1 yum.repos.d]# cat k8s.repo [k8s] name=k8s enabled=1 gpgcheck=0 baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ [k8s@k8s1 ~]$ yum repolist Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager k8s 561/561 repo id repo name status HighAvailability HighAvailability 51 ResilientStorage ResilientStorage 56 docker-ce-stable/x86_64 Docker CE Stable - x86_64 79 dvd rhel7.6 5,152 k8s k8s 561 repolist: 5,899 【3】安装 kubelet、kubeadm 和 kubectl(所有节点执行) kubelet 运行在 Cluster 所有节点上,负责启动 Pod 和容器。

Vue 学习随笔系列一 -- Cascader 级联选择器

Vue 学习随笔 —— Cascader 级联选择器 前言 随笔一: 记录 Cascader 级联选择器使用 一、Cascader 级联选择器 二、使用步骤 1. 引入 代码如下: <el-form-item label="xxx" prop="item" > <el-cascader ref="cascader" clearable :props="props1" :value="id" // v-model 与 value 使用其中一个即可 :options="itemList" // 接口返回的树形字典数据 :show-all-levels="false" placeholder="请选择" @change="handleChange" > </el-cascader> </el-form-item> 2. 数据定义 代码如下: data() { return { props1: { value:'id', label:'label', }, id:[], form: { item: '', itemList: [], // 分类 }, releaseTime: "", } } } 3. 获取点击label的值 handleChange() { // 使用 getCheckedNodes 可以获取到数组 this.

SwipeDelMenuLayout失效:Could not find SwipeDelMenuLayout-V1.3.0.jar

一、问题描述 最近在工作上的项目中接触到SwipeDelMenuLayout这个第三方Android开发库,然后我就根据网上的教程进行配置。这里先说一下我的开发环境:Android Studio版本是android-studio-2020.3.1.24-windows,gradle版本是7.0.2。 首先是在settings.gradle文件中添加jitpack仓库,而不是build.gradle文件(这么做的原因是参考了别人的资料:https://www.jdk5.com/ask/34/build-was-configured-to-prefer-settings-repositories-over-project-repositories-b)。添加的这一行代码是 maven { url 'https://jitpack.io' } 然后整个settings.gradle文件变成 dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { url 'https://jitpack.io' } } } rootProject.name = "SwipeDelDemo" include ':app' 然后在build.gradle (Module)文件中添加依赖 implementation 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0' 该文件的依赖就变成如下 dependencies { implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0' } 之后就可以编译使用SwipeDelMenuLayout这个库了。但是,编译的时候却遇到了来自Android Studio的编译报错,说 Could not find SwipeDelMenuLayout-V1.3.0.jar (com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0). 然后我去访问地址:https://jitpack.io/com/github/mcxtzhang/SwipeDelMenuLayout/V1.3.0/SwipeDelMenuLayout-V1.3.0.jar,浏览器显示Build failed. See the log at jitpack.io。具体的报错信息如下: 上面的报错表明这个库确实引用不了。我以为是我配置错了,但跟着别人的方式配置,Android Studio报的编译错误会更加多。 如果我删掉 implementation 'com.

若依中使用zTree 添加复选框,并设置选中和回显功能示例

zTree 添加复选框,并设置选中和回显功能示例 zTree 是一个依靠 jQuery 实现的多功能 “树插件”,这篇文章主要介绍zTree添加复选框的使用方法,非常具有实用价值,需要的朋友可以参考下。 一、页面加载树,请求后台接口返回数据集,并加载到树中 加载js和css并添加树元素 <th:block th:include="include :: ztree-css"/> <th:block th:include="include :: ztree-js"/> <div id="tree" class="ztree"></div> 打开页面时,加载数据 $(function () { var url = ctx + "fdc/tree/getTree"; var options = { url: url, expandLevel: 0, check: { enable: true,//显示复选框 chkStyle: "checkbox" }, onCheck: zOnCheck, // 复选框选中方法 callBack: callBack // 回显回调方法 }; $.tree.init(options); }); 二、调用复选框方法,并获取选中值,以及取消选中如何移除 // 全局变量 var checks = []; // 复选框调用 function zOnCheck(event, treeId, treeNode) { if (treeNode.

Vulnhub靶机渗透之环境搭建及JIS-CTF入门

Vulnhub靶机渗透之环境搭建及JIS-CTF入门 目录 Vulnhub靶机渗透之环境搭建及JIS-CTF入门 一、JIS-CTF题目描述 二、Vulnhub环境配置 三、Vulnhub靶机渗透详解 1.信息收集 2.First flag 3.Second flag 4.Third flag 5.Fourth flag 6.Fifth flag 7.sudo提权管理员权限 8.无密码登录数据库 9.获取数据库数据 四.总结 一、JIS-CTF题目描述 靶场题目:JIS-CTF: VulnUpload 靶场地址:Vulnerable By Design ~ VulnHub entry/jis-ctf-vulnupload,228/ 难度描述:包含5个Flag,初级难度,查找所有Flag平均需要1.5小时 靶场作者:Mohammad Khreesha 靶场描述:Description: There are five flags on this machine. Try to find them. It takes 1.5 hour on average to find all flags. 下载地址: Download (Torrent):https://download.vulnhub.com/ jisctf/JIS-CTF-VulnUpload-CTF01.ova.torrent Download (Mirror):https://download.vulnhub.com/ jisctf/JIS-CTF-VulnUpload-CTF01.ova 打开网址显示的内容如下图所示,我们获取虚拟机格式的镜像,然后进行环境配置。 二、Vulnhub环境配置 第一步,下载资源 第二步,打开VMware虚拟机安装靶场 找到我们刚才下载的文件,导入虚拟机。 第三步,导入完成之后,设置NAT网络模式,内存设置为2G,硬盘设置为32GB 四步,点击开启虚拟机及配置过程 到开机页面选择第二个Ubuntu的高级选项,如果启动网络正常的话可以直接开机,如果网络不正常可以按下面步骤操作。

性能测试:压测中TPS上不去的几种原因分析&案例分析

一、常见原因 在进行压测时,如果遇到 TPS(Transactions Per Second,每秒事务处理量)无法达到预期的情况,可能有以下几个常见的原因: 1、服务器资源限制: 服务器的硬件资源(如 CPU、内存、磁盘)可能不足以处理大量的请求。在高负载情况下,服务器可能无法及时响应所有的请求,导致 TPS 上不去。解决方法可以考虑升级硬件资源或通过负载均衡将请求分散到多台服务器上。 2、网络带宽限制: 服务器的网络带宽可能成为瓶颈,在高负载压力下无法支持大量请求的传输。这会导致请求的传输速率受限,从而影响 TPS。此时可以考虑扩大网络带宽或优化网络传输方式,如使用 CDN、压缩数据等。 3、数据库性能问题: 如果应用程序依赖数据库,数据库性能问题也可能导致 TPS 不能达到预期。例如,数据库读写瓶颈、索引不合理、数据库连接池配置不当等都可能影响并发处理能力。可以通过优化 SQL 查询语句、增加数据库缓存、调整连接池大小等手段来提升数据库性能。 4、代码逻辑问题: 应用程序中存在低效、死循环、资源竞争等问题,都可能导致并发处理能力下降。检查代码逻辑是否存在性能瓶颈,优化关键路径,避免不必要的锁竞争和资源浪费。 5、压测配置问题: 压测工具的配置可能影响 TPS 的表现。例如,并发数设置过低、请求时间间隔不合理、持续时间过短等都可能导致 TPS 表现不稳定。确保压测配置合理,并根据实际情况进行调整。 6、第三方服务延迟: 如果应用程序依赖外部的第三方服务(如支付接口、消息队列、数据库等),这些服务的延迟或故障也可能导致 TPS 降低。可以通过监控和日志分析来确定是否存在第三方服务问题,并与服务提供商联系解决。 在分析 TPS 上不去的原因时,可以使用系统监控工具、日志分析、性能剖析工具等来收集相关数据,并结合压测结果进行综合分析。根据具体情况采取相应的优化措施,优化关键路径、增加资源、调整配置等都有助于提升 TPS 的性能。 二、案例讲解 2.1 压测配置/压测脚本问题 2.1.1 背景: 在一个登录的压测场景,登录接口,需要对登录密码在本地进行加密,同时在header里生成验签。 处理这一系列的逻辑,是一个js脚本。 在压测时发现: 在压测的时候,查看jmeter聚合报告,发现rt很小,但是tps也很小。 讲道理来说,响应时间越小,tps应该越大。 一共压测10分钟,发现jmeter请求的样本数量非常小,才8500个请求。 10分钟内,才打出了8500个请求。 tps= 总样本数量/总时间。 时间是固定的600s,总样本数量小,导致tps很小。 为什么10分钟才打出了8500个请求。 2.1.2 原因: 发现有一个前置处理器,处理验签的。 这个前置处理器这么复杂吗?这么消耗性能吗? 这个前置处理器,做验签处理,做加密都是用的js脚本。 我将前置处理器,换成了java语言。做了一个实现。 2分钟内,100并发,js脚本,打出了 8306 个请求。 2分钟内,100并发,java脚本,打出307,336 个请求。 结果相差了37倍。 2.1.3 解决办法: 将js脚本,换成了java脚本。 2.2 其他案例 并发连接数过高:在某个压测场景中,你可能设置了非常高的并发连接数,但服务器的最大并发连接数限制低于此数量。因此,当压测开始时,服务器无法处理所有的连接请求,导致 TPS 达不到预期。解决方法可以是增加服务器的最大并发连接数限制或者调整压测配置中的并发连接数。

(一)「消息队列」之 RabbitMQ 入门

0、引言 想要实现两个应用程序之间的通信,我们可以借助“消息队列”技术。本文将介绍使用 C# 语言在 .NET 下实现 RabbitMQ 消息队列;当然无论是哪种编程语言,要使用消息队列,都需要完成以下两个基本步骤: 下载并安装相应的消息队列服务器软件,并根据需要进行配置;在您的应用程序代码中引入相应的消息队列客户端库,并使用客户端库提供的API来建立与消息队列服务器的连接并进行通信。 这些步骤对于大多数消息队列中间件都是适用的。不同的消息队列中间件可能有不同的安装和配置方法,以及不同的客户端库和API,您可以根据自身需要阅读相应的官方文档即可。 本文主要参考: RabbitMQ TutorialsRabbitMQ使用教程(超详细)C# 消息队列之 RabbitMQ 基础入门消息队列常见的几种使用场景介绍!- 知乎分布式之消息队列的特点、选型、及应用场景详解消息队列漫谈:什么是消息模型?- 知乎 1、基础概念 消息队列 消息队列( Message Queue)是一种通信模式,用于在应用程序之间传递消息。它提供了一种异步的、可靠的通信方式,允许发送者(发送消息的应用程序)和接收者(接收消息的应用程序)能够独立地进行工作,而不需要彼此直接交互。 在消息队列中,消息是以队列的形式存储和传递的。发送者将消息放入队列的末尾,而接收者从队列的开头获取消息。这种队列的特性确保了消息的有序处理,并且允许多个发送者和接收者之间进行解耦,从而提高了系统的可伸缩性和可靠性。 消息队列的使用可以带来许多好处。首先,它允许异步处理,即发送者可以在发送消息后继续执行其他任务,而不需要等待接收者的响应。这种方式可以提高应用程序的性能和吞吐量,特别是在处理大量消息或处理延迟较高的操作时。 其次,消息队列可以解耦发送者和接收者之间的依赖关系。发送者只需将消息发送到队列中,而不需要知道具体的接收者是谁或接收者何时处理消息。这种松耦合的设计允许系统中的不同模块独立开发、部署和扩展,提高了系统的灵活性和可维护性。 此外,消息队列还提供了消息持久化的能力,确保即使在发送者和接收者之间发生故障或中断时,消息不会丢失。消息可以持久化到磁盘上,并在系统恢复后重新发送。这种可靠性保证了消息的传递不会因为故障而中断,使系统更加健壮和可靠。 常见的消息队列软件 RabbitMQApache KafkaApache ActiveMQAmazon SQSMicrosoft Azure Service Bus 中间件 中间件是指位于操作系统和应用程序之间的软件层。它充当了不同软件组件之间的桥梁,提供了通信和协调的功能,以便它们能够相互交互和协作。 中间件的主要目标是简化分布式系统的开发和管理。它提供了一组通用的功能和服务,使得不同的应用程序和系统可以进行互操作,并能够以可靠、安全和高效的方式进行通信。 中间件可以实现各种功能,包括但不限于以下几个方面: 消息传递:中间件提供消息传递机制,用于在分布式系统中传递和交换数据。消息队列就是一种常见的消息传递中间件。远程过程调用(RPC):中间件可以实现远程过程调用,使得应用程序能够在不同的计算机或进程之间调用和执行函数或方法。数据库连接和访问:中间件可以提供数据库连接和访问的功能,使得应用程序能够方便地操作和管理数据库。分布式事务处理:中间件可以支持分布式系统中的事务处理,确保多个操作在不同的计算机或进程之间具有原子性、一致性、隔离性和持久性。缓存管理:中间件可以提供缓存管理的功能,加速数据访问和提高系统性能。安全认证和授权:中间件可以实现安全认证和授权机制,保护系统免受未经授权的访问和攻击。 Erlang Erlang 是一种通用的编程语言,最初由爱立信(Ericsson)的开发团队在1980年代末创建。它是一种函数式编程语言,专门设计用于构建可扩展、并发和分布式的软实时系统。 RabbitMQ 服务是使用 Erlang 语言编写的。 AMQP ( Advanced Message Queuing Protocol) AMQP 即 高级消息队列协议:一种面向消息的网络协议(应用层协议),用于在应用程序之间传递消息。 RabbitMQ 是对 AMQP 0.9.1 协议的 实现。并在后续拓展了对 更多协议的支持。 RabbitMQ 介绍 RabbitMQ 是一个消息代理:它接受并转发消息。 你可以把它想象成一个邮局:当你把你想要邮寄的邮件放在邮箱里时, 您可以确定,邮递员最终会将邮件递送给您的收件人。 在这个类比中,RabbitMQ是一个邮政信箱,一个邮局和一个信件载体。 RabbitMQ 和邮局的主要区别在于它不处理纸张。相反,它接受、存储和转发二进制 blob 数据 —— 消息( Message)。 RabbitMQ,以及一般的消息传递,会使用一些术语: 生产 Producing 仅仅只是意味着发送。发送消息的程序被称为 生产者 Producer:

C#如何使用SQLite数据库?

文章目录 0.引言1.SQLite工具准备2.创建窗体项目并添加SQLite的命名空间3.编写使用SQLite代码4.结果展示 0.引言 SQLite是一个轻量级的嵌入式数据库,它的库文件非常小巧,不需要独立的服务器进程或配置。这使得它非常适合在资源受限的环境中使用,如移动设备、嵌入式系统等。与其他数据库管理系统相比,SQLite不需要进行繁琐的配置和管理。它只需要一个文件来存储整个数据库,无需单独设置用户、权限和网络连接等。无论是在移动设备上存储本地数据还是作为小型应用程序的后端数据库,SQLite都能够提供高效、可靠和易于使用的解决方案。本文记录使用SQLite数据库的基础方法。 1.SQLite工具准备 本文使用VisualStudio2022进行编程,安装SQLite工具步骤如下: 菜单【工具】→【NuGet包管理器】→【管理解决方案的NuGet程序包】→搜索sqlite,然后选择“System.Data.SQLite”进行安装。 2.创建窗体项目并添加SQLite的命名空间 using System.Data.SQLite; 3.编写使用SQLite代码 string connectionString = "data source=data.db"; SQLiteConnection con = new SQLiteConnection(connectionString); con.Open(); SQLiteCommand cmd = new SQLiteCommand(con); cmd.CommandText = "create table student(id int,name nvarchar(50))"; cmd.ExecuteNonQuery(); cmd.CommandText = "insert into student values(1,'stu1')"; cmd.ExecuteNonQuery(); cmd.CommandText = "select name from student where id=1"; var name = cmd.ExecuteScalar(); MessageBox.Show(name.ToString()); con.Close(); 4.结果展示 参考资料: [1] Fanstorm丶. C# 中使用sqlite; 2019-03-19 [accessed 2023-07-27]. [2] Risehuxyc. C# 使用SQLite; 2022-10-21 [accessed 2023-07-27].

每天一个linux小技巧

1.nohup no hang up,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系,例如我们断开SSH连接都不会影响他的运行,注意了nohup没有后台运行的意思。 加&的作用是将,命令放到后台运行,使得终端可以继续输入其他命令。 nohup python xx.py >> xx.log(脚本输出的内容重定向输入到xx.log) 2. conda虚拟环境 linux 安装conda ➡️ 🏠 安装成功后的命令: conda create -n 环境名 python=3.7(自选版本) 激活环境 conda activate 环境名 退出环境 deactivate 3.编写测试脚本 1. 创建.sh文件 sudo vim test.sh 2.往.sh文件中填写内容,下面这个例子是语音识别某一目录下所有的.mp3文件 #!/bin/bash for file in folder/*.mp3 do whisper "$file" --model small done 3.为脚本授予执行权限 chmod +x test.sh 4.执行脚本 ./test.sh 4.GPU 运行报错 torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 20.00 MiB (GPU 0; 14.76 GiB total capacity; 6.

嵌入式常用宏定义分析

宏定义1 #define writeb(reg, addr) (*((volatile unsigned char *)(addr)) = (unsigned char)(reg)) 这段代码定义了一个宏writeb(reg, addr),用于向给定地址addr处写入一个字节数据reg。 宏的定义如下: #define writeb(reg, addr) (*((volatile unsigned char *)(addr)) = (unsigned char)(reg)) 该宏的作用是将给定的地址addr转换为volatile unsigned char类型的指针,然后将字节数据reg转换为unsigned char类型,并将其写入该地址处。 需要注意的是,volatile关键字用于告诉编译器该地址处的数据可能会被外部因素改变,因此在写入数据时应该直接写入内存,而不是使用缓存的值。这对于向外设寄存器等需要实时更新的数据进行写入非常重要。 此宏可以用于向特定地址写入一个字节的数据。例如,writeb(0x55, 0x12345678)将向地址 0x12345678写入字节数据0x55。 宏定义2 define readb(addr) ((unsigned char)*((volatile unsigned char *)(addr))) 这段代码定义了一个宏readb(addr),用于读取给定地址addr处的字节数据。 宏的定义如下: #define readb(addr) ((unsigned char)*((volatile unsigned char *)(addr))) 该宏的作用是将给定的地址addr转换为volatile unsigned char类型的指针,然后解引用该指针,获取对应地址处的字节数据,并将其转换为unsigned char类型返回。 需要注意的是,volatile关键字用于告诉编译器该地址处的数据可能会被外部因素改变,因此在读取数据时应该每次都从内存中读取,而不是使用缓存的值。这对于访问外设寄存器等需要实时更新的数据非常重要。

MySQL - 死锁的产生及解决方案

MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件1.1 什么是死锁1.2 死锁产生的4个必要条件 2. 死锁案例2.1 表锁死锁2.2 行锁死锁2.3 共享锁转换为排他锁 3. 死锁排查4. 实例分析4.1 案例描述4.2 案例死锁问题复现4.3 死锁排查4.4 解决死锁 5. 如何避免死锁 1. 死锁与产生死锁的四个必要条件 1.1 什么是死锁 死锁是指2+的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 摘自:@百度百科 1.2 死锁产生的4个必要条件 虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件: 1)互斥条件: 指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。 2)请求和保持条件: 指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。 3)不剥夺条件: 指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。 4)环路等待条件: 指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。 我们强调所有四个条件必须同时成立才会出现死锁。环路等待条件意味着占有并等待条件,这样四个条件并不完全独立。 死锁的关键在于:2+ 的 session 加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的 session 加锁有次序。 2. 死锁案例 2.1 表锁死锁 产生原因: 用户A访问表A(锁住了表A),然后又访问表B;另一个用户B访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁就产生了。 用户A–》A表(表锁)–》B表(表锁) 用户B–》B表(表锁)–》A表(表锁) 解决方案: 这种死锁比较常见,是由于程序的 BUG 产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理, 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。 2.2 行锁死锁 产生原因1: 如果在事务中执行了一条没有索引条件的查询,引发全表扫描,把行级锁上升为全表记录锁定(等价于表级锁),多个这样的事务执行后,就很容易产生死锁和阻塞,最终应用系统会越来越慢,发生阻塞或死锁。 解决方案1: SQL 语句中不要使用太复杂的关联多表的查询;使用 explain “执行计划"对 SQL 语句进行分析,对于有全表扫描和全表锁定的 SQL 语句,建立相应的索引进行优化。

VUE开发神器-NVM nodejs版本控制工具nvm

前言 在学习前端框架或者是nodejs时,有时候某些框架对nodejs的版本有要求。但此时你的电脑上已经安装了10.x版本的nodejs,你不想直接更新到12.x,想同时保存10.x和12.x版本,在必要的时候还能随时切换nodejs版本。那么nvm工具你值得拥有。 一、首先要安装nvm 下载地址:Releases · coreybutler/nvm-windows (github.com) 备用下载地址 1、选择合适的安装包下载并安装 博主还是比较喜欢安装.exe的,这样在安装过程中手动选择安装路径啥的也还不错。 可以自行选择下载哪种类型的安装包。 下载好之后点击.exe文件进行安装。 这里需要注意:nvm安装路径最好不要有空格和中文,不然可能会出现问题! 2、配置在下载nodejs包的时候通过淘宝镜像,这样会快一些 root: D:\nvm-nodejs\nvm # 这是我安装nvm的目录 path: C:\Program Files\nodejs # 这是nvm控制当前nodejs版本包的目录 arch: 64 proxy: none node_mirror: http://npm.taobao.org/mirrors/node/ npm_mirror: https://npm.taobao.org/mirrors/npm/ 在安装nvm的目录下找到 settings.txt文件,写入红框中的内容。 二、使用nvm 1、查看nvm版本(显示版本号即为安装成功):nvm v 2、查看nvm可控制的node版本列表 :nvm list / nvm ls 3、到官网查看自己要安装的nodejs版本是否存在,需要安装什么版本都在官网看。 以往的版本 | Node.js (nodejs.org) 4、使用nvm安装nodejs版本:nvm install nodejs版本号 5、安装完所需nodejs版本后,可以切换到任意nodejs版本啦 使用 nvm use 版本号切换使用 nodejs 版本 注意事项 如果nvm use 命令不生效? nvm use 后执行nvm ls,正常情况下当前使用的版本前会有*号标注。 但是如果nvm use 之后所有版本前都没有*号,或者是*号没有变动到nvm use 的那个版本,那就是出现问题了!!

2023十大最牛编程语言排行榜以及各语言的优缺点

文章目录 ⭐️ 2023年7月十大编程语言排行榜⭐️ 十大值得学习编程语言概要🌟 Python🌟 C/C++🌟 Java🌟 C#🌟 JavaScript🌟 Swift🌟 Ruby🌟 GO(Golang)🌟 PHP🌟 MATLAB 该章节内容数据来自互联网真实信息收集以及编程语言排行榜。 ⭐️ 2023年7月十大编程语言排行榜 Tips:TIOBE排行榜 是根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube和Baidu(百度)统计出排名数据,只是反映某个编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言所编写的代码数量多少。 ⭐️ 十大值得学习编程语言概要 Python:AI(人工智能)、机器学习方向最佳的编程语言。C:迄今为止,最值得信任的编程语言。C++:最通用的编程语言。Java:服务器端最好的编程语言C#:微软最强有力的面向对象编程语言。JavaScript:客户端最常用的脚本语言。Swift:IOS 端最高效的编程语言。Ruby:数据科学方面最可靠的编程语言。GO(Golang):可扩展的编程语言,谷歌出品,世界级大厂背书。(云原生领域必学编程语言)PHP:世界上最好的编程语言,不,最好用的 Web 编程语言。(养活了世界上90%的黑客) 🌟 Python Python已经占据榜一多年,之所以如此无疑是 “人工智能” 大爆发所带来的正向影响。它通常被认为是最容易学习的编程语言,是一种快速、易于使用且易于部署的解释型编程语言,广泛用于开发可扩展的 Web 应用程序。YouTube、Instagram、Pinterest、SurveyMonkey 都是使用 Python 构建的。 如果说你正在寻找一种更易于学习和流行的编程语言来学习,绝对应该尝试 Python!许多初创公司、小型团队使用 Python 作为他们的主要后端开发,很多全栈开发工程师也是将 Python 作为自己的第一编程语言;如果说打算考研,进入数据科学或人工智能行业,可以肯定的是必须学习 Python。除此之外它还可以用于其他领域,例如 Web 开发、多功能性和可访问性使其成为初学者的绝佳选择。 优点: 由于 OOP 特性,创建和使用类和对象很容易广泛的库支持专注于代码可读性甚至能够扩展最复杂的应用程序非常适合更快地构建原型和测试想法开源与不断增长的社区支持为多种平台和系统提供支持非常容易学习和使用 缺点: 不适合移动计算由于是一种解释性编程语言,所以速度较慢(相对其他编程语言而言)数据库访问层有些不成熟由于 GIL(全局解释器锁),线程不好(这个是吉多都没解决的问题) 🌟 C/C++ C 和 C++ 在编程世界中占有重要地位。几乎所有的低级系统,例如操作系统和文件系统,都是用 C/C++ 编写的。如果您想成为系统级程序员,那么这些是您应该学习的编程语言。 C++ 也被有竞争力的程序员广泛使用,因为它非常快速和稳定。它提供了一种叫做 STL - 标准模板库的东西。这是一个用于各种数据结构、算术运算和算法的即用型库。该语言的库支持和速度使其成为高频交易社区的热门选择。 优点: 与 [C++] 一起使用的几个编译器和库通过其他编程语言轻松访问被阻止或隐藏的对象 [C]比大多数编程语言更快地执行程序 [C/C++]为理解更复杂的编程语言奠定了基础 [C/C++]多设备、多平台应用程序开发的首选语言 [C++]提供高度的可移植性 [C]具有一组功能模块和块的面向过程的语言。这些使调试、测试和维护程序更容易 [C]。程序更高效更容易理解[C/C++]丰富的函数库 [C++]靠近系统硬件运行,因此提供了低级别的抽象 [C/C++]支持异常处理和函数重载 [C++]广泛的应用领域,例如游戏、GUI 应用和实时数学模拟 [C++] 缺点: 复杂语法 [C/C++]不支持程序命名空间 [C]无法解决现代现实世界的编程挑战 [C]与其他基于 OOP 的编程语言相比,效率较低的面向对象系统 [C++]需要手动创建高级构造 [C]没有垃圾收集或动态内存分配 [C/C++]没有运行时检查 [C/C++]没有严格的类型检查 [C]学习编程不是一个简单的首选[C/C++]受到缓冲区溢出和内存损坏问题的困扰 [C/C++]更小的标准库 [C] 🌟 Java Java是大型组织中的另一种流行选择,并且几十年来一直如此。它广泛用于构建企业级 Web 应用程序。众所周知,它非常稳定,因此许多大型企业都采用了它。如果您正在大型组织中寻找软件开发角色,Java 是您应该学习的第一门语言之一。

HTTP协议各版本介绍

HTTP协议是一种用于传输Web页面和其他资源的协议。 下面详细介绍一下HTTP的各个版本: 1.HTTP/0.9 这是最早的HTTP版本,于1991年发布。它非常简单,只能传输HTML格式的文本,并且不支持其他类型的资源、请求头和状态码。 2.HTTP/1.0 于1996年发布。HTTP/1.0引入了请求头和响应头的概念,支持多种格式的资源(例如图片、音频等)。此版本还支持持久连接,以减少连接的建立和关闭开销。然而,对于每个请求,仍需单独的TCP连接,这在处理大量资源时效率不高。 3.HTTP/1.1 于1997年发布,目前是最广泛使用的HTTP版本。HTTP/1.1对上一版本进行了改进,并引入了一些重要的特性来提高性能和效率。持久连接成为默认行为,允许多个请求和响应在同一个连接上顺序传输。此外,HTTP/1.1还引入了管道化请求,允许客户端发送多个请求,而无需等待每个请求的响应。HTTP/1.1还支持虚拟主机,可在同一个IP地址下为多个域名提供不同的Web服务。 4.HTTP/2 于2015年发布,基于Google的SPDY协议。HTTP/2采用了二进制传输而非纯文本传输,引入了多路复用,允许多个请求和响应并行交错地在同一个连接上传输。头部压缩减少了请求头和响应头的大小,优先级设定允许客户端指定请求的优先级,服务器则可以相应地处理请求。所有这些特性共同提高了性能和效率,减少了延迟,更有效地利用了网络资源。 5.HTTP/3 HTTP/3是下一个主要版本的HTTP。HTTP/3是基于QUIC(Quick UDP Internet Connections)协议的,QUIC使用UDP传输数据,提供了更快的连接建立和更可靠的数据传输。HTTP/3在QUIC之上实现了HTTP的功能,通过减少延迟和改进传输机制,提供了更好的性能和效率。 6.总结 尽管HTTP的不同版本具有各自的特性和改进,但它们都遵循相同的基本原理和目标,即通过协议进行数据交换和通信。目前,HTTP/1.1和HTTP/2仍然是最常用的版本,而HTTP/3则在积极发展中,并为HTTP通信带来更多的优化和改进。

启动jar包报错: 找不到或无法加载主类

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <!--不打包资源文件--> <excludes> <exclude>static/**</exclude> <!--<exclude>db/**</exclude>--> <exclude>*.txt</exclude> <exclude>*.xml</exclude> <exclude>*.yml</exclude> </excludes> <archive> <manifest> <!-- 是否要把第三方jar加入到类构建路径 --> <addClasspath>true</addClasspath> <!-- 外部依赖jar包的最终位置 --> <classpathPrefix>lib/</classpathPrefix> <!--指定jar程序入口--> <mainClass>com.attanzai.wms.WmsApplication</mainClass> <!--SNAPSHOT版本问题--> <useUniqueVersions>false</useUniqueVersions> </manifest> <!--MANIFEST.MF 中 Class-Path 加入资源文件目录--> <manifestEntries> <Class-Path>./config/</Class-Path> </manifestEntries> </archive> </configuration> </plugin>

数据结构 | 单链表的基本实现

学习教材:《数据结构——从概念到C++实现》 分类专栏:数据结构与算法(C++) 目录 前言 全文 1 链表概述 2 单链表的基本实现 2.1 建立只有头结点的空链表 2.2 建立指定长度的链表 2.3 析构函数 2.4 求单链表长度 2.5 按位查找元素 2.6 按值查找元素,返回元素序号 2.7 插入操作 2.8 删除操作 2.9 判空操作 2.10 遍历操作 全部代码 前言 最近刚在学习《数据结构与算法》,单纯地跟课、看书觉得并不能很好的掌握好这些知识点,所以决定尝试将学习的知识点归纳总结,也将其进行代码实现,强化对知识点的理解。即作为笔记、实践,又作为我的思路分享。因为初学,难免有不正确、不恰当之处,敬请指正! 全文 1 单链表概述 单链表(singly linked list)是用一组任意的存储单元存放线性表的元素,这组存储单元可以连续也可以不连续,甚至可以零散分布在内存中的任意位置。 结点(node)是存放了数据元素和其后续元素所在的地址信息的存储映像。其中。data为数据域,存放数据元素;next为指针域,存放该结点的后继结点的地址。 单链表通过每个结点的指针域将线性表的数据元素按照其逻辑次序链接在一起,由于每个结点只有一个指针域,故称为单链表。 2 单链表的基本实现 先定义单链表的结点结构,包括数据域和指针域。 template<typename DataType> struct Node { // 数据域 DataType data; // 指针域 Node<DataType>* next; }; 定义单链表类,其中成员变量 first 表示单链表的头指针,成员函数实现线性表的基本操作。 template<typename DataType> class LinkList { public: // 建立只有头节点的空链表 LinkList(); // 建立n个元素的单链表 LinkList(DataType a[], int n); // 析构函数 ~LinkList() {}; // 求单链表长度 int Length(); // 按位查找元素 DataType Get(int i); // 按值查找元素,返回元素序号 int Locate(DataType x); // 插入操作,在第i个位置插入值为x的元素 void Insert(int i, DataType x); // 删除操作,删除第i个元素 DataType Delect(int i); // 判断是否为空表 int Empty(); // 遍历单链+表进行打印 void printList(); private: Node<DataType>* first; // 头指针 }; 2.

C语言:分支和循环_switch

1、switch语句 除了if语句外,C语言还提供了switch语句来实现分支结构。 switch语句是一种特殊形式的if....else结构,用于判断条件有多个结果的情况。它把多重的else if改成更易用、可读性更好的形式。 1 switch (expression){ 2 case value1: statement 3 case value2: statement 4 default:statement } 上面的代码中,根据表达式expression不同的值,执行相应的case分支。如果找不到对应的值,就执行default分支。 注: switch后的expression必须是整型表达式case后的值,必须是整型常量表达式 1.1、if语句和switch语句的对比 练习:输入任意一个整数值,计算除3之后的余数 如果使用if语句完成,如下: #include <stdio.h> int main() { int n = 0; scanf("%d",&n); if(n%3 == 0) printf("整除,余数为0\n"); else if(n%3 == 1) printf("余数是1\n"); else printf("余数是2\n"); return 0; } 如果使用switch语句改写,就可以写成这样的: #include <stdio.h> int main() { int n = 0; scanf("%d", &n); switch(n%3) { case 0: printf("整除,余数为0\n"); break; case 1: printf("余数是1\n"); break; case 2: printf("

Linux根目录扩容--两篇

Linux根目录扩容--两篇 1.命令汇总 // 首先查看根目录大小 # df -h / // 查看磁盘与挂载情况,可以看到磁盘的文件系统。 # lsblk # lsblk -f // 查看磁盘详细信息 # fdisk -1 // 对/dev/vda磁盘进行分区 # fdisk /dev/vda // m帮助命令 Command(m for help) :m // n添加新的分区 Command(m for help) :n Partition type: // 主要分区 p primary (2 primary, 0 extended, 2 free) // 扩展分区 e extended // 一路回车,采用默认配置 Select (default p) : // 分区编号,新创建的分区名称会在/dev/vda上追加这个编号 比如:/dev/vda3 Partition number (3,4, default 3) : First sector (20971520-419430399, default 20971520): last sector, +sectors or +sizefK M G] (20971520-419430399, default 419430399): // 保存并退出 Command(m for help) :w // 在不重启的情况下重读分区表,否则lsblk命令看不到新创建的分区 # partprobe // 再次查看磁盘与挂载情况,可以看到新创建的分区 # lsblk # lsblk -f // 开始扩容 # lvm // 创建物理卷 lvm> pvcreate /dev/vda3 Physical volume "

PCIE常用缩写及含义

1.Egress和Ingress 在Switch中,数据流出的端口被称为Egress端口,Ingress指的数据流入Switch使用的端口。 2.DSP(Down Stream Port)和USP(Upper Stream Port) 对每个功能设备来讲,用来连接上下游设备的端口统称为DSP或者USP(下图图例)。 在一个PCIe系统中,upstream port 和 downstream port是固定的,但是Ingress port 和 Egress port 是不固定的,和数据包的传输方向相关。 3.流量类别(TC) TC 是在数据包内发送的一个 TLP 头字段,在端到端通过结构时没有改变。本地应用软件和系统软件应根据性能要求确定某个 TLP 使用什么样的 TC 标志。TC 字段是一个 3bits 长的字段,可以将不同的流量分成 8 种流量类别(TC0~TC7)。设备必须实现 VCO。设备或交换器要实现 TC-VC 映射逻辑,把给定 TC 号的 TLP 使用特定的 VC 号的缓冲区通过链路转发。PCIe 具有映射多个 TC到一个 VC 的能力,因而可通过提供有限数目的 VC 缓冲区支持来降低设备成本。 4.VC:虚拟通道 VC 是物理缓冲区,它通过使用发送和接收器虚拟信道缓冲区,提供一种在物理链路上支持多个独立逻辑数据流的手段。PCIe 设备可以最多实现 8 个 VC 缓冲区(VC0~VC7)。Extended VCCount字段的数值是除了 VC0以外所支持的 VC数量,为0时,表示仅支持 VC0;为 1~7时,表示额外支持1~7个 VC。 5.相位(Phase): VC 仲裁表的每一项表示一个相位。规范定义了三种 WRR配置,分别有128、64、32个 表项数。具体设备所能支持的仲裁表项的个数由端口 VC能力寄存器2中的 VCArbitrationCapability字段 来报告,表的大小通过写入端口 VC控制寄存器中 VC ArbitrationSelect字段的值来选择(参见图下)。

ARM架构与编程——实战:按键控制LED

汇编实现按键控制LED 一、纯汇编点灯 1.1 程序流程图 Created with Raphaël 2.3.0 start 使能GPIO模块 设置引脚为GPIO功能 设置引脚为输出 设置引脚输出高电平 delay 设置引脚输出低电平 delay 1.2 delay函数流程图 Created with Raphaël 2.3.0 start R0减1 等于0? 返回LR所示地址 yes no 1.3 程序实现 寄存器操作 对于寄存器的操作,主要涉及读、修改、写。 读可以使用LDR指令,代码为LDR R1, [R0] 写使用STR指令,代码为STR R1, [R0] 修改稍微复杂,清除位使用BIC或AND指令,设置位使用ORR指令 LDR R0, =(1<<20) | (1<<21) BIC R1, R1, R0 ; 清除R1的bit20, bit21 LDR R0, =(1<<20) ORR R1, R1, R0 ; 设置R1的bit20 函数里的条件判断 比如减1操作,代码为SUB R0, R0, #1 但是顺便使用减1后的结果影响程序状态寄存器,代码为SUBS R0, R0, #1

ChatGPT 1.0.0安卓逆向分析,仅限中国分享

ChatGPT 1.0.0安卓逆向分析,仅限中国分享 本文将对ChatGpt Android版本1.0.0 APK进行静态解包分析和抓包分析,从ChatGpt Android APK功能的设计、校验过程和代码内包含的信息来预测OpenAI的大致走向。 Sensor Tower指出,在美国市场,iOS版ChatGPT应用下载量在6月份环比下降了38%;而根据Similarweb的数据,ChatGPT今年6月的全球桌面和移动设备流量较上月下降9.7%,其网站的独立用户访问量下降5.78%,6月的访客花在该网站上的时间也减少了8.5%。 《流量增长乏力 ChatGPT要进安卓 - 北京商报》 目前Android版本上线仅支持美国、印度、孟加拉国和巴西使用。但从今天应用上线的情况来看,截至7月26日早上,在Google Play上的下载数量为10+。然而,在几个小时后的下午,下载数量已经达到了100K+,这充分证明了AI的热度。尽管AI概念整体跌幅2%,但市场上对AI仍然持有浓厚兴趣。 Android版本目前还只处于灰度测试阶段,即在部分国家上线,一周内逐步覆盖其他可以使用Google Play的国家。目前需要强制绑定Google Play的服务,后文将介绍通过hook的方式解决这个问题,但不提供重打包APK的方法。 静态分析 这份分析报告提供了ChatGPT Android APK的各种信息,包括安全评分、文件信息、应用程序信息和活动等。其中,核心的内容包括: 安全评分:ChatGPT的安全评分为62/100,这意味着它在安全性方面存在一些潜在的风险。文件信息:APK文件的名称为base.apk,大小为5.42MB,MD5为5ed65284c0962370b9dc9030a7342e61,SHA1为62a64392bca4fa127c70a7231dd38c72025a663a,SHA256为f66c90fdc3863c30cdbda0d84675c2cddb60cfbf36744df4718bcf6ec53f3498。应用程序信息:ChatGPT的包名为com.openai.chatgpt,主要活动为com.openai.chatgpt.MainActivity,目标SDK为33,最小SDK为23。活动:ChatGPT包含4个活动、9个服务、2个接收器和0个提供程序。导出的组件:ChatGPT中有1个导出的活动、1个导出的服务和2个导出的接收器。文本信息:分析报告中还包含了一些文本信息,例如应用程序中使用的字符串和控件的名称。 支持最小Android版本为 6.0,对于首个版本而言,目标就是覆盖足够多的用户 权限分析 这个应用使用了以下权限: android.permission.RECEIVE_BOOT_COMPLETED 允许ChatGpt 应用开机自启,即系统开机后自动启动,不过国内的OS上面,这种自启行为不会被支持。 android.permission.RECORD_AUDIO 允许应用程序访问音频记录路径, 目前ChatGpt Android版本是支持语音输入。 android.permission.VIBRATE 允许应用程序控制振动器,用来优化语音输入的体验 android.permission.WAKE_LOCK 这个权限用于,防止手机在和Chatgpt 聊天的过程中进入睡眠状态(灭屏) com.android.vending.CHECK_LICENSE 用于 Android 应用程序中与 Google Play 商店(Google Play Store)的许可验证相关的广播。这个广播通常由 Google Play 服务自动发送,用于检查应用程序是否已经在设备上获得了有效的许可或授权。 当你在应用程序中集成了 Google Play 许可验证服务时,应用程序将使用这个广播来与 Google Play 商店进行通信,以验证用户是否已经购买了该应用程序或应用程序内购买的许可,这对于防止未经授权的使用、确保用户购买了正版应用或在应用内购买中获得许可等方面非常有用。 从这个权限上来看,目前ChatGpt的Android版本和Google Play的证书校验有一个强绑定关系,在短期内,Android市场上不会脱离Google Play,所以国内的用户想用上官方的Android 版本基本是不可能的。 com.openai.chatgpt.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION openai 自定义的权限 从定义的权限上来看,权限上中规中矩,没有涉及到信息的采集,强绑定了 Google Play服务,基础功能不多,但够稳定,属于稳定迭代的阶段,不足以看出 OpenAi 着急的情况。

Redis概述及安装、使用和管理

目录 一、NoSQL非关系型数据库 1.NoSQL概述 2.关系型数据库和非关系型数据库区别 (1)数据存储方式不同 (2)扩展方式不同 (3)对事务性的支持不同 3.非关系型数据库使用场景 二、Redis概述 1.简介 2.优点 3.Redis读写快的原因 4.适用场景 三、Redis安装配置 四、Redis的使用 1.命令行工具redis-cli(登录) 2.测试工具redis-benchmark(测试) 3.redis命令的使用 4.Redis多库常用命令 五、Redis性能管理 1.查看内存使用 2.清理内存碎片 (1)内存碎片如何产生 (2)内存碎片率 (3)清理内存碎片 3.内存使用率 4.内回收key 一、NoSQL非关系型数据库 1.NoSQL概述 NoSQL (Not Only SQL),是非关系型数据库的总称。除了主流的关系型数据库外的数据库,都认为是非关系型。 不需要预先建库建表定义数据存储表结构,每条记录可以有不同的数据类型和字段个数(比如微信群聊里的文字、图片、视频、音乐等)。 主流的 NoSQL数据库有 Redis、MongBD、Hbase、Memcached、ElasticSearch、TSD等。 2.关系型数据库和非关系型数据库区别 (1)数据存储方式不同 关系型和非关系型数据库的主要差异是数据存储的方式。 SQL数据库天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。 NoSQL型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。 (2)扩展方式不同 关系型和非关系型数据库最大的差别是在扩展方式上,要支持日益增长的需求当然要扩展。 SQL数据库是纵向扩展,也就是说提高处理能力,使用速度更快速的计算机,这样处理相同的数据集就更快了。因为数据存储在关系表中,操作的性能瓶颈可能涉及很多个表,这都需要通过提高计算机性能来克服。虽然sql数据库有很大扩展空间,但最终肯定会达到纵向扩展的上限。 NoSQL数据库是横向扩展的。因为非关系型数据存储天然就是分布式的,NoSQL数据库的扩展可以通过给资源池添加更多普通的数据库服务器:节点)来分担负载。 (3)对事务性的支持不同 如果数据操作需要高事务性或者复杂数据查询需要控制执行计划,那么传统的SQL数据库从性能和稳定性方面考虑是你的最佳选择。 SQL数据库支持对事务原子性细粒度控制,并且易于回滚事务。 虽然NoSQL数据库也可以使用事务操作,但稳定性方面没法和关系型数据库比较。所以它们真正闪亮的价值是在操作的扩展性和大数据量处理方面。 3.非关系型数据库使用场景 可用于应对web2.0纯动态网站类型的三高问题(高并发、高性能、高可用)。 High performance——对数据库高并发读写需求;Huge Storage——对海量数据高效存储与访问需求;High Scalability and High Availability——对数据库高可扩展性与高可用性需求。 关系型数据库和非关系型数据库都有各自的特点与应用场景,两者的紧密结合将会给web2.0的数据库发展带来新的思路: 关系型数据库关注在关系和对数据的一致性保障上; 非关系型数据库关注在存储和高效率上。 例如:在读写分离的Mysql数据库环境中,可以把经常访问的数据存储在非关系型数据库中,提升访问速度。 二、Redis概述 1.简介 Redis(远程字典服务器)是一个开源的、使用c语言编写的 NoSQL数据库。 Redis基于内存运行并支持持久化,采用key-value(键值对)的存储形式,是目前分布式架构中不可或缺的一环。 Redis服务器程序是单进程模型,也就是在一台服务器上可以同时启动多个Redis进程,Redis的实际处理速度则是完全依靠主进程的执行效率。

c语言的代码类型

C语言是一门广泛使用的编程语言,它以其高效性和灵活性而闻名。在C语言中,我们可以将所有的代码分为三种类型:分支、循环和顺序。在本文中,我将介绍这三种类型,并提供相关的代码示例。本文加入了一些自己的看法,会有些错误,见谅。 目录 一、分支语句 1. if语句 2. switch语句 二、循环语句 1. while循环 2. for循环 三、顺序语句 四、goto语句 五.结束语 一、分支语句 分支语句是一种基本的控制结构,它允许程序在不同条件下执行不同的代码块。C语言中有两种常见的分支语句:if语句和switch语句。 而在我自己的理解,分支就是人生之中的不同情况,在面对不同答案做出的选择,而代码也是在这个道理,在进入这个选择时看自己本身是什么,从而进行判断。 1. if语句 if语句用于测试一个条件是否为真,并根据该条件的结果来执行相应的代码块。以下是if语句的基本格式: 例如,下面的代码演示了如何使用if语句来检查一个数是否为正数: 当然一个数不是正数就是0或者负数,这时可以使用else语句 在配合 else if语句可以得到这样 #include <stdio.h> int main() { int num; printf("请输入一个整数:"); scanf("%d", &num); if (num > 0) { printf("这是一个正数\n"); } else if (num < 0) { printf("这是一个负数\n"); } else { printf("这是零\n"); } return 0; } 在这个示例代码中,首先定义了一个整数变量num,用于存储用户输入的整数。然后通过printf函数提示用户输入一个整数,并通过scanf函数将用户输入的整数存储在num变量中。 接下来,使用if语句来判断num的值。如果num大于0,则输出"这是一个正数";如果num小于0,则输出"这是一个负数";否则,输出"这是零"。 也同样可以结合循环做到多次判断。 2. switch语句 switch语句用于测试一个变量等于多个值中的哪一个值,并根据该变量的值来执行相应的代码块。以下是switch语句的基本格式: case 和后边的数字之间必须有空格 每⼀个 case 语句中的代码执⾏完成后,需要加上 break ,才能跳出这个switch语句。

VS构建项目报错信息及解决办法05

报错信息及解决8: 报错信息详情:无法解析的外部符号“__iob_func” 原因:因VS不同版本之间对stdin,stdout,stder的定义不同,导致不同VS版本之间无法正确的调用函数。 eg: * 当libjpeg-turbo为vs2010编译时,vs2015下静态链接libjpeg-turbo会链接出错:找不到iob_func, * 增加iob_func到__acrt_iob_func的转换函数解决此问题, * 当libjpeg-turbo用vs2015编译时,不需要此补丁文件 解决办法: 在自己的代码中增加了一个名为__iob_func转换函数: #if _MSC_VER>=1900 #include "stdio.h" _ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned); #ifdef __cplusplus extern "C" #endif FILE* __cdecl __iob_func(unsigned i) { return __acrt_iob_func(i); } #endif /* _MSC_VER>=1900 */ 报错信息及解决9: 报错信息详情:无法打开包括文件: “arpa/inet.h”: No such file or directory 原因:不同平台头文件有所不同 解决办法: 将 #include<arpa/inet.h> 用 #include <windows.h> #pragma comment(lib, “wsock32.lib”) 代替 报错信息及解决10: 报错信息详情:命令行错误: 指定的语言模式不兼容 原因:C/C++语言标准不对照 解决办法:属性>C/C++>语言>C/C++语言标准>更改为默认值 报错信息及解决11: 报错信息详情:fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "pch.h"”? 原因:此错误发生的原因是编译器在寻找预编译指示头文件(默认#include "stdafx.h")时,文件未预期结束。没有找到预编译指示信息的头文件"XXXX.h"。

synchronized是如何锁住对象的?

目录 一、什么是synchronized? 二、synchronized的三大特性 synchronized如何保证原子性? synchronized如何保证可见性? synchronized如何保证有序性? 三、synchronized的底层实现 1)对象头 2)偏向锁 3)轻量级锁 4)自旋锁 5)重量级锁 一、什么是synchronized? synchronized是Java中的关键字,synchronized可以保证方法或者代码块在运行时,同一时刻只有一个线程可以进入到被修饰的代码块中,同时它还可以保证共享变量的内存可见性,Java中每一个对象都可以作为锁,这是synchronized实现同步的基础。 它修饰的对象有以下几种: 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,此时synchronized锁住的则是()中的对象。修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,此时synchronized锁住的是方法所在类的对象。修饰一个静态的方法,其作用的范围是整个静态方法,此时synchronized锁住的是类的字节码文件。修饰一个类,其作用的范围是synchronized后面括号括起来的部分,此时synchronized锁住的是类的字节码文件。 注意:对象锁是可以有很多把的但是类锁只有一把,因为对象可以创建多个但是类的字节码文件只有一份。 二、synchronized的三大特性 原子性:一个或多个操作要么全部执行成功,要么全部执行失败。synchronized关键字可以保证只有一个线程拿到锁,访问共享资源。可见性:当一个线程对共享变量进行修改后,其他线程可以立刻看到。执行synchronized时,会对应执行 lock、unlock原子操作,保证可见性。有序性:程序的执行顺序会按照代码的先后顺序执行。 static final Object lock = new Object(); static int counter = 0; public static void main(String[] args) { synchronized (lock) { counter++; } } public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: getstatic #2 // <- lock引用 (synchronized开始) 3: dup 4: astore_1 // lock引用 -> slot 1 5: monitorenter // 将 lock对象 MarkWord 置为 Monitor 指针 6: getstatic #3 // <- i 9: iconst_1 // 准备常数 1 10: iadd // +1 11: putstatic #3 // -> i 14: aload_1 // <- lock引用 15: monitorexit // 将 lock对象 MarkWord 重置, 唤醒 EntryList 16: goto 24 19: astore_2 // e -> slot 2 20: aload_1 // <- lock引用 21: monitorexit // 将 lock对象 MarkWord 重置, 唤醒 EntryList 22: aload_2 // <- slot 2 (e) 23: athrow // throw e 24: return Exception table: from to target type 6 16 19 any 19 22 19 any LineNumberTable: line 8: 0 line 9: 6 line 10: 14 line 11: 24 LocalVariableTable: Start Length Slot Name Signature 0 25 0 args [Ljava/lang/String; StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 19 locals = [ class "

Docker 构建 Jar 镜像

一、创建 docker 目录 /usr/local/docker 二、将项目打包上传到目录 # Jar 包 /usr/local/docker/app.jar # 配置文件 /usr/local/docker/config/application.yml 三、在目录下创建 Dockerfile 文件 FROM openjdk:8-jre # 将 jar 包添加到容器中 , tar 类型文件会自动解压(网络压缩资源不会被解压) , 可以访问网络资源 , 类似 wget ADD app.jar /usr/local/app.jar # 功能和 ADD 相同 , 不会自动解压文件 , 也不能访问网络资源 # COPY ./config/ /usr/local/config # 配置环境变量 # ENV JAVA_HOME=/usr/local/java/jdk-8 # ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar # ENV PATH=$JAVA_HOME/bin:$PATH # 切换工作目录 , 相当于 cd WORKDIR /usr/local # 映射端口 EXPOSE 80 # ENTRYPOINT 或 CMD 只会执行一次 , 会覆盖之前的 ENTRYPOINT 或 CMD 命令 ENTRYPOINT ["