log4J2和logback冲突和共存解决方法

项目场景: 一个在线编辑器调试打印日志功能,需要提供logback和log4j2不同日志框架的日志功能供使用方自由选择 问题描述 本来logback和log4j2的冲突是经常发生的事,这件事很烦说实话,以前总是草草了事,随便排除一下就解决了,也没多管他,毕竟一直觉得为了个日志功能花太多时间不值当。 但是最近要做一个后台低代码平台,搞过的人都知道,动作大各种引用模块框框一堆,TMD到处是冲突,就很烦头很大特别是日志冲突。 本来不想写这个,毕竟一搜全是各种排除,也没毛病,只是大家各自需要排除的包不一样,这也是大部分时候的正确选择。但是也有我碰到的这种需求,需要在编译时两种框架的包都能引用到不至于报错,但是实际部署时只要其中一种,避免日志框架的冲突。 原因分析: 冲突原因就不分析了,大家自行百度吧 解决方案: 我们以使用log4j2不使用logback为例 maven引用的时候加上 <scope>provided</scope> 这个的作用就是在打包的时候不会将logback打入依赖包从而避免冲突 但是能在编译阶段提供jar包 保证引用到logback的类能通过编译 <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <scope>provided</scope> </dependency> 是不是很简单 本来到这里我以为就结束了 确实打包部署运行是没问题了 但是当我需要在本地idea调试时怎么也不行一直报冲突 Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/E:/xx/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.

python 本地时间与utc时间互转

本地时间字符串转成UTC时间 def local_str_to_utc_datetime(local_str, formatter='%Y-%m-%d %H:%M:%S'): u"""本地时间字符串转成UTC时间(datetime格式)。 :param local_str: 本地时间字符串 :param formatter: 字符串格式 :return: UTC时间(datetime格式) :rtype: datetime """ if local_str is None: return None # 将本地时间字符串转成datetime类型 local_dt = datetime.strptime(local_str, formatter) # 将本地时间(datetime类型)转成UTC时间(datetime类型) return local_dt.replace(tzinfo=tz.gettz()).astimezone( tz.gettz('UTC')).replace(tzinfo=None).strftime(formatter) utc时间戳转本地时间字符串 def timestamp_to_time(time_stamp): """utc时间戳转本地时间字符串""" # utc 时间转本地时间字符串 time_stamp_array = time.localtime(time_stamp) return time.strftime(DATETIME_FMT, time_stamp_array) UTC日期转utc时间戳 def times_to_timestamp(time_stamp): """utc日期转utc时间戳""" return int(calendar.timegm(time.strptime(time_stamp, DATETIME_FMT)))

Spring Cloud Alibaba 组件的介绍及使用方法

Spring Cloud Alibaba Spring Cloud Alibaba 是基于 Spring Cloud 的一套开源框架,它为开发者提供了一系列的分布式应用开发工具,包括服务注册与发现、配置管理、消息驱动等组件。Spring Cloud Alibaba 的出现,让开发者在使用 Spring Cloud 进行分布式应用开发时,更加便捷和高效。 组件介绍 Spring Cloud Alibaba 包含了多个组件,下面将对其中的几个核心组件进行介绍。 Nacos Nacos 是一个开源的服务发现、配置管理和服务管理平台,支持多种注册中心和服务发现协议。在 Spring Cloud Alibaba 中,Nacos 可以作为服务注册中心和配置中心使用,它提供了完备的服务发现和服务注册功能,并且还支持配置管理和 DNS 服务等功能。使用 Nacos 作为注册中心和配置中心,可以方便地进行服务注册和配置管理,同时还可以实现服务的高可用和负载均衡。 使用方法 添加依赖 在 Maven 项目中,需要添加以下依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.3.RELEASE</version> </dependency> 配置文件 在 application.properties 文件中,需要添加以下配置: # Nacos 配置 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.discovery.namespace=dev 代码实现 以下是一个简单的示例代码,演示了如何使用 Spring Cloud Alibaba 进行服务注册和配置管理: @RestController public class HelloController { @Value("${hello.message}") private String message; @GetMapping("/hello") public String hello() { return message; } } 在上述代码中,使用了 @Value 注解,从配置文件中获取了 hello.

JSP自定义标签

前言:已经有好久没有和大家分享知识,今天我要与大家分享的知识是继反射之后的JSP自定义标签知识。 上面三张图是自己绘制的三张的思维导图。可以通过思维导图来进入我要跟大家分享的知识。 一、JSP的特点: 1、jsp的构成:开始标签、标签主体、结束标签 例如: <z:demo1>demo1</z:demo1>2 2、标签的分类:标签的分类主要是有四种 第一种:空标签 例如:<br>、<hr> 第二种:数据标签 例如:<c:set var="name" value="zs"></c:set> <c:out value="${ name }"></c:out> 第三种:控制标签:<c:forEach items="" var=""></c:forEach> <c:if test=""></c:if> 第四种:UI标签:<table><tr></tr></table>、<input> 二、自定义标签的步骤: 第一步:自己创建一个tld类,把跳转的域名改成自己想要跳转的路径。 第二步:新建一个tld助手类,这里面要写标签对应的属性。 第三步:引用自己创建的JSP标签。 三:JSP生命周期: JSP标签生命周期一共有三条路线: 1、 路线一:doStartTag--->返回值是(SkipBody)--->doEndTag 2、 路线二:路线二:doStartTag--->返回值是(EAVL_BODY_INCLUDE)--- >doAfterBody--->返回值是(EAVL_PAGE)--->doEndTag 3、路线三:doStartTag--->返回值是(EAVL_BODY_INCLUDE)--->doAfterbody--->返回值(EAVL_Body_Again)--->doAfterBody(死循环,退出条件是案列五的foreach退出)--->doEndTag 证明路线一的正确性:只要在jsp界面上打出了Demo1_doStartTag进来了以及Demo1_doEndTag进来了,就可以说明路线一正确。 验证路线二:只要jsp界面上打印出了Demo2_doStartTag()进来了、Demo2_doAfterBody()进来了以及Demo2_doEndTag()进来了就可以验证路线二的正确性 验证路线三: 只要jsp界面上打印出了Demo3_doStartTag()进来了、Demo3_doAfterBody(),一直点循环按钮就一直是doafterbody() 结果在下面: 验证路线三的结果:因为EVAL_BODY_AGAIN, 所以一直输出Demo3_doAfterBody()进来了,只有当自己按红按钮时,才会停止。 接下来有六个案列,其中有五个是来验证三条路线的; 1、案例一与案例二:验证路线一和路线二,开发if标签。 下面是index界面中的代码: <z:if test="true">输出</z:if> <z:if test="false">不输出</z:if> 新建一个IfTag类,里面写一个验证test属性。 下面是在tld类中的写的if标签以及if标签的属性。 输出结果在上面,证明路线一正确。 2、 接下来是案例三和案例四:目的:验证路线一(开发数据标签set/out标签),需要借 助jspwrite来输出。 1、out类: public class OutTag extends BodyTagSupport { private Object value; public Object getValue() { return value; } public void setValue(Object value) { this.

echarts实现横向和纵向滚动条、dataZoom

文章目录 前言1、横向滚动条2、纵向滚动条 前言 使用echarts会遇到这种情况,以柱状图为例子,当数据过多时,echarts图就会堆叠在一起,看起来十分难看。通常解决办法是通过减小barWidth值来缩小柱子宽度,但是若数据达到上百条,这场面是相当壮观。另一个很常用的就是在外部容器div添加overflow: scroll;,这确实能解决一些问题,但是若是数据量过少,就会显的非常稀疏,经历过的都懂。言归正传,以上都不是最佳解决方式,echarts其实已经为提供好相应的API配置了,无论是横向滚动还是纵向滚动,dataZoom都能满足。 1、横向滚动条 dataZoom: [ { // 设置滚动条的隐藏与显示 show: true, // 设置滚动条类型 type: "slider", // 设置背景颜色 backgroundColor: "rgb(19, 63, 100)", // 设置选中范围的填充颜色 fillerColor: "rgb(16, 171, 198)", // 设置边框颜色 borderColor: "rgb(19, 63, 100)", // 是否显示detail,即拖拽时候显示详细数值信息 showDetail: false, // 数据窗口范围的起始数值 startValue: 0, // 数据窗口范围的结束数值(一页显示多少条数据) endValue: 5, // empty:当前数据窗口外的数据,被设置为空。 // 即不会影响其他轴的数据范围 filterMode: "empty", // 设置滚动条宽度,相对于盒子宽度 width: "50%", // 设置滚动条高度 height: 8, // 设置滚动条显示位置 left: "center", // 是否锁定选择区域(或叫做数据窗口)的大小 zoomLoxk: true, // 控制手柄的尺寸 handleSize: 0, // dataZoom-slider组件离容器下侧的距离 bottom: 3, }, { // 没有下面这块的话,只能拖动滚动条, // 鼠标滚轮在区域内不能控制外部滚动条 type: "

JavaScript随手笔记 --- 对数据进行判断最大位数是否超过八位

💌 所属专栏:【JavaScript随手笔记】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 文章目录 前言一、方法一:正则表达式1.匹配公式和单个数据2.对数据进行判断是否能展示 总结 前言 大家好,又见面了,我是夜阑的狗🐶,本文是专栏【JavaScript随手笔记】专栏的第6篇文章; 今天的需求是要判断字符串的位数是否超过八位,其中可以包括运算公式,而且现在最输入限制为 17 位,8位数字 + 运算符 + 8位数字(负数额外考虑); 专栏地址:【JavaScript随手笔记】 , 此专栏是我是夜阑的狗对JS数据处理的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。 如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。 一、方法一:正则表达式 要判断一个字符串输入的数据是否超过八位,需要用正则表达式来进行匹配,这里可以在线学习正则网站,可以练练,里面还有一些语法什么的。 毕竟比较赶时间,写的仓促,所以很多地方还是可以优化的。有什么不对的话还请大家多多体谅,谢谢啦 😀 😀 😀 。 1.匹配公式和单个数据 regexBit 用于匹配包含数字和运算符的字符串,例如 12345678 或者 12345678+12345678,不匹配数据超出八位数的情况。 var regexBit = /^[-]?(\d{8}|[\d\.]{9}|\d{8}[+\-*/]\d{8}|[\d\.]{9}[+\-*/][\d\.]{9})$/; 这里简单讲解一下该正则表达式各个部分的作用: /^[-]?)$/ : 字符描述^表示从匹配输入字符串的开始位置,除非在方括号表达式中使用, 当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合,$匹配输入字符串的结尾位置;[-]?表示匹配可选的负号(-) \d{8} : 字符描述\d{8}匹配任意的八个数字 [\d\.]{9} : 字符描述[\d\.]{9}匹配带有小数点的八个数字,加上小数点字符,所以长度为9, 用于匹配0.1234567,1234567.8 等情况; \d{8}[+\-*/]\d{8} : 字符描述\d{8}[+\-*/]\d{8}匹配八个数字+四个运算符中的一个+八个数字,例如:12345678+12345678 [\d\.]{9}[+\-*/][\d\.]{9} : 字符描述[\d\.]{9}[+\-*/][\d\.]{9}匹配带有小数点的八位数字+基础运算符之一+带有小数点的八位数字,例如:0.1234567+0.1234567 2.对数据进行判断是否能展示 使用上面正则表达式可以排除输入单个数据或者公式输入数据超过8位的情况,而只匹配包含八位数字、小数点和运算符的运算表达式,从而判断输入字符串是否为有效的运算表达式。 /** * @author CSH * @function 函数功能:对数据进行判断最大位数是否超过八位 * @param {string} displayNumber [需要判断的数据] */ function isCalcDataBit (displayNumber) { return regexBit.

JavaScript随手笔记 --- 用正则表达式匹配字符串是否为运算公式

💌 所属专栏:【JavaScript随手笔记】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 文章目录 前言一、方法一:正则表达式1.匹配数字和运算符2.匹配单个数字或者负数3.匹配多个数字4.对数据进行判断是否能展示 总结 前言 大家好,又见面了,我是夜阑的狗🐶,本文是专栏【JavaScript随手笔记】专栏的第5篇文章; 今天的需求是要对字符串进行判断是否能展示,其中要能匹配包含数字和运算符的字符串,不匹配单个数字或者负数的情况; 专栏地址:【JavaScript随手笔记】 , 此专栏是我是夜阑的狗对JS数据处理的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。 如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。 一、方法一:正则表达式 要判断一个字符串为一个运算公式,不包含单独的数字或者负数,可以使用正则表达式来进行匹配。这里默认大家都是学过正则表达式了哈,其实本人也没学过,就临时看看写了。这里在线学习正则网站,可以练练,里面还有一些语法什么的。 毕竟比较赶时间,写的仓促,所以很多地方还是可以优化的。有什么不对的话还请大家多多体谅,谢谢啦 😀 😀 😀 。 1.匹配数字和运算符 regexFormula 用于匹配包含数字和运算符的字符串,例如 “1 + 2 * 3”,但不匹配单个数字和负数的情况。 var regexFormula = /^(\d+|\d+[.]?\d+)([+\-*/](\d+|\d+[.]?\d+))+$/; 这里简单讲解一下该正则表达式各个部分的作用: /^...$/ : 字符描述^表示从匹配输入字符串的开始位置,除非在方括号表达式中使用, 当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合,$匹配输入字符串的结尾位置; (\d+|\d+[.]?\d+) : 字符描述\d+表示匹配一个或多个数字[.]?表示匹配可选的小数点(.)\d+[.]?\d+表示匹配小数(A|B)指明两项之间的一个选择 ([+\-*/](\d+|\d+[.]?\d+))+ 字符描述[+\-*/]表示匹配任意个运算符(+、-、*、/)(a)+表示匹配多个a 2.匹配单个数字或者负数 regexNumber 用于匹配包含单个数字或者负数的字符串,例如 “-3” 或 “42”,但不匹配包含多个数字和运算符的运算表达式。 var regexNumber = /^[-]?(\d+|\d+[.]?\d+)$/; [-]?(\d+|\d+[.]?\d+) 字符描述[-]?(\d+|\d+[.]?\d+)表示匹配单个数字或者负数 3.匹配多个数字 ·regexIeger 用于匹配多个数字,这里好像第二步重复了,可忽略。 var regexIeger = /^\d+$/; 4.

L1-025 正整数A+B (15分) C语言详细版

● 题目如下: 题的目标很简单,就是求两个正整数A和B的和,其中A和B都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。 输入格式: 输入在一行给出A和B,其间以空格分开。问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。 注意:我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。 输出格式: 如果输入的确是两个正整数,则按格式A + B = 和输出。如果某个输入不合要求,则在相应位置输出?,显然此时和也是?。 输入样例1: 123 456 输出样例1: 123 + 456 = 579 输入样例2: 22. 18 输出样例2: ? + 18 = ? 输入样例3: -100 blabla bla...33 输出样例3: ? + ? = ? ● 简单分析:) 题目有如下几点要求: ◆ A和B的的范围要在[1,1000] ◆ A和B是超出范围的数字、负数、带小数点的实数时不符合规定。 ◆ A和B之间用空格隔开,但是B可能还包含空格。(所以需要用到gets) 在这里补充一个知识点:当输入时,我们通常使用scanf,但是scanf是不能读取空格的,所以在有空格的字符串的输入,我们用gets。 ● 代码如下: #include <stdio.h> #include <string.h> int main(){ char c[500]; gets(c); int i,j,m1=1,m2=1,t1=0,t2=0;//m1,m2用来判断ab是否符合规定 //t1,t2分别记录ab的值 for(i=0;i<strlen(c);i++){ if(c[i]==' '){ if(i==0){ //如果开头为空格,那么a不符合规定。 m1=0;//表示a不符合规定 } j=i+1; //为了在第二个循环从空格开始 break; }else if(c[i]>='0' && c[i]<='9'){ t1=t1*10+c[i]-'0'; //a符合规定时,将数组转换为具体数值 }else{ m1=0; //不为0-9时,不符合规定 } } for(j;j<strlen(c);j++){ //j为1,是因为b内存储了a与b之间的空格 if(c[j]>='0' && c[j]<='9'){ t2=t2*10+c[j]-'0'; }else{ m2=0; break; } } if(m1==0 || t1<1 || t1>1000){ m1=0; printf("

Django Rest Framework中Restful请求中包含关联模型要怎么处理

Django Rest Framework中Restful请求中包含关联模型要怎么处理 update或者create请求更详细的解释粘贴上代码 update或者create请求 在django rest framework中,当您使用Serializer类来序列化或反序列化数据时,如果您的模型中有关联的模型字段,比如外键或多对多字段,那么Serializer类会默认使用PrimaryKeyRelatedField来处理这些字段¹。这意味着在序列化时,这些字段会被转化为它们关联的模型对象的主键值(pk),而在反序列化时,这些字段需要接收它们关联的模型对象的主键值(pk)作为输入²。如果您在反序列化时传递了一个字典(dict)而不是一个主键值(pk),那么您就会遇到这个错误:Incorrect type. Expected pk value, received dict. 要解决这个错误,您有两种方法: 一种是在反序列化时确保传递正确的主键值(pk)而不是字典(dict)。比如,如果您的模型中有一个countries字段,它是一个多对多字段,关联到Country模型,那么您在反序列化时需要传递一个包含Country对象的主键值(pk)的列表,而不是一个包含Country对象的字典(dict)的列表³。例如: { "countries": [1, 2, 3] // 正确 } { "countries": [{"id": 1, "name": "China"}, {"id": 2, "name": "India"}, {"id": 3, "name": "USA"}] // 错误 } 另一种是在Serializer类中自定义关联的模型字段的处理方式,使用其他类型的字段来代替PrimaryKeyRelatedField。比如,如果您想在反序列化时接收一个字典(dict),并根据字典中的数据创建或更新关联的模型对象,那么您可以使用Nested Relationships⁴。例如: class CountrySerializer(serializers.ModelSerializer): class Meta: model = Country fields = ('id', 'name') class MenuInfoSerializer(serializers.ModelSerializer): countries = CountrySerializer(many=True) # 使用嵌套的Serializer来处理countries字段 class Meta: model = MenuInfo fields = ('id', 'user_id', 'countries') 更详细的解释 在django rest framework中,Serializer类是用来将Python对象和JSON数据之间进行相互转换的工具。Serializer类有两个主要的功能:序列化和反序列化。序列化是指将Python对象转换为JSON数据,反序列化是指将JSON数据转换为Python对象。在这个过程中,Serializer类需要知道如何处理不同类型的字段,比如字符串、数字、日期、布尔值等。Serializer类提供了一些内置的字段类型,比如CharField, IntegerField, DateTimeField等,来处理这些基本的数据类型。

记录el-table出现滚动条,表头会有留白现象

有时候table加上个别min-width时候,会出现留白现象 解决办法: 方法1:直接修改表头th背景色 .el-table th.el-table__cell { background-color: pink; } 如果有时候设置了不生效,那就是没有设置在全局下面,可能设置进了某个类下面 方法2:找到对应的dom修改背景色 .gutter { background-color: #ededed !important; } 如果我们隐藏了table的滚动条,这时候我们看见下面会有留白现象 这是因为下面的body宽度写死了,没有100%适应 添加css .el-table__body-wrapper { .el-table__body { width: 100% !important; } }

如何5分钟快速搭建一套JVM线上监控工具

一、Springboot项目配置 1. pom文件中导入如下依赖 <!--实现JVM数据监控--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--prometheus实现jvm数据采集--> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> 2. 配置application.properties文件或者application.yml文件 2.1 配置application.properties文件 spring.application.name=springboot server.port=8080 management.endpoints.web.exposure.include=* management.metrics.tags.application=${spring.application.name} 2.2 配置application.yml文件 application: name: springboot management: endpoint: web: exposure: include: * metrics: tags: application: ${spring.application.name} 3. 添加监控JVM的bean配置,或者重新创建一个配置类 @SpringBootApplication public class JvmMonitorDemoApplication{ public static void main(String[] args) { SpringApplication.run(JvmMonitorDemoApplication.class, args); } /**监控jvm的配置*/ @Bean public MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName) { return registry -> registry.config().commonTags("application", applicationName); } } 创建配置类如下: @Configuration public class JvmMonitorConfig { /**监控jvm的配置Bean*/ @Bean public MeterRegistryCustomizer<MeterRegistry> configurer(@Value("

Webstorm使用git(windows10)

因为经常改代码有时候改的自己一脸懵逼直接重来,所以使用git就很便利了. 而网上大多都是苹果的分享… 相关版本: windows10 WebStorm 2022.3.4 git version 2.29.2.windows.2 1.安装git及简单使用 安装链接: Git 详细安装教程(详解 Git 安装过程的每一个步骤)–mukes 简单使用: 史上最详细Git使用教程–最近比较烦。 2.Webstorm安装gitee插件 然后登录自己的gitee账号,这里我己经登录了,懒得退 点击第一个你就会跳出一个网页,正常登录授权就可以了 3.push项目 在Git下选择Gitee,也就是刚刚下载好的插件,然后选择Share Project on Gitee. 然后Webtorm就会帮我们自动建立好本地仓库、添加远程链接(其中远程仓库名称为项目名称) 然后马上会弹出一个窗口 第一次commit,在Message窗口写内容 去gitee就可以看到push成功了,如果后面要pull或者push直接用右上角三个按钮就可以了 ✔是commit,建议取消勾选分析代码这些,这些耗损时间长且会报莫名其妙的错 然后,push到远程仓库去 点击三个按钮里面最右边的 最后就上传成功了! 4.总结 以gitee为例,github其实是一样的。熟悉掌握Webstorm中git运用,将会大大提高我们的效率。 最后,如果有错误,请在评论区指出,欢迎大家一起学习。 编辑于2023.4.10 修改与2023.4.11,找到了webstorm直接上传项目,而不是手动git。

el-upload 二次上传没有反应,clearFiles不起作用

element Upload 上传文件只能上传一次 ,再次点击上传无反应的问题的坑,clearFiles()也不起作用 <el-upload class="upload-btn ml10 mr10" ref="uploadfile" action :limit="1" accept=".xls, .xlsx" :show-file-list="false" :auto-upload="false" :on-change="file => importTable(file, row)" :file-list="fileList"> data() { return { fileList:[] } } importTable(file,item) { var data = new FormData(); data.append("file", file.raw); data.append("activityId", item.activityId); this.fileList = []//这里是重点,替换这个方法(this.$refs.uploadfile.clearFiles()) importUser(data).then(res => { this.$message.success("文件导入成功"); this.getlist()//更新列表 }) },

uniapp 设置底部不被覆盖

中间列表部分,开启绝对定位,设置一下位置,并且overflow:auto 就可以滑动 .cartList { position: absolute; bottom: 80rpx; overflow: auto; } 底部位置 .total{ z-index: 999; position: fixed; bottom: 0; height:80rpx; } 效果

Flutter基础入门

文章目录 一、Flutter基础知识1.Flutter简介和发展历史2.Flutter安装和配置3.Dart语言基础知识Dart语言特性Dart基本语法空安全 Null safetyDart异步原理 4.Flutter项目结构和文件组织方式5.Flutter Widgets和布局基础 二、Flutter进阶知识1.Flutter状态管理和数据传递2.Flutter动画和过渡效果隐式(全自动)动画AnimatedContainerTweenAnimationBuilder 显示(手动控制)动画自定义显示动画:AnimatedBuidler 3.Flutter网络请求和数据解析网络请求框架数据解析 4.Flutter本地存储和数据缓存5.Flutter渲染和性能优化渲染流程常见的内存溢出和内存泄漏的场景优化检测工具Flutter布局优化常规优化深入光栅化优化 Flutter内存优化 6.Flutter代码结构和代码质量把控 三、常用插件和第三方库好用的状态管理好用的网络请求好用的图片加载好用的音视频好用的控件好用的工具类好用的动画好用的数据存储好用的事件传递好用的三方sdk好用的编译器插件 四、可能有用的小技巧 一、Flutter基础知识 1.Flutter简介和发展历史 Flutter是一款由Google开发的移动应用程序开发框架,可用于开发高性能、跨平台的移动应用程序。Flutter使用Dart编程语言,并提供了丰富的UI组件和工具,使得开发者可以快速构建漂亮、响应式的用户界面和高质量的应用程序。 Flutter的发展历史可以分为以下几个阶段: 2011年,Dart语言项目启动,旨在提供一种适用于Web开发的高性能编程语言。 2015年,Flutter项目启动,旨在使用Dart语言构建高性能、跨平台的应用程序。 2017年,Flutter的第一个Alpha版本发布,开发者可以开始尝试使用Flutter构建应用程序。 2018年,Flutter的第一个稳定版本发布,得到了广泛的认可和采用。 2019年,Flutter 1.5发布,增加了对iOS13和Android Q的支持,以及许多其他改进和 新功能。 2020年,Flutter 1.20发布,引入了新的Web支持和iOS14和Android 11的支持,以及其他改进和新功能。 2021年,Flutter2.0发布,引入了许多重要的新功能,包括全新的Web支持、桌面应用程序支持、Flutter for Windows等。 2023年,Flutter3.0发布,引入了许多重要的新功能,包括全新的Web支持、桌面应用程序支持、Flutter for Windows等。 截止到2023年3月,由于Flutter生态系统的不断发展,Flutter在Google Play Store和Apple App Store上已经有超过400,000款应用程序上线。同时,Flutter还正在扩展到其他领域,例如Web开发和桌面应用程序开发,这些领域的应用程序数量也在不断增长。由于Flutter是一个开源框架,许多公司和个人也在使用Flutter构建自己的应用程序,并且Flutter的生态系统也在不断扩大,因此Flutter上线的应用程序数量可能会随着时间的推移而继续增长。 2.Flutter安装和配置 以下是安装和配置Flutter的步骤,以Windows为例: 下载Flutter SDK 可以在Flutter的官方网站上下载Flutter SDK。下载完成后,将其解压到您选择的目录中,例如在Windows上,您可以将其解压到 C:\src\flutter。 配置Flutter环境变量 将Flutter SDK的路径添加到PATH环境变量中,以便在终端中可以使用flutter命令。例如,在Windows上,您可以将C:\src\flutter\bin添加到系统环境变量的PATH变量中。 下载开发工具并安装Flutter插件 如果您使用的是Android Studio或IntelliJ IDEA,您需要安装Flutter插件以便在IDE中开发Flutter应用程序。打开IDE,进入插件设置,搜索“Flutter”,然后安装并重启IDE即可。 运行Flutter Doctor 打开终端或命令提示符,并输入“flutter doctor”命令,以检查Flutter环境的配置情况。Flutter doctor会检查您的环境并给出建议以解决任何缺失的依赖项或配置问题。 配置Android开发环境 如果您要在Flutter中开发Android应用程序,您需要安装并配置Android开发环境。您可以在Android开发者网站上获取有关如何安装和配置Android开发环境的更多信息。 以上是在Windows上安装和配置Flutter的基本步骤。完成这些步骤后,您就可以开始使用Flutter构建应用程序了。 3.Dart语言基础知识 Dart语言特性 Dart 的特性 Dart 是少数同时支持 JIT(Just In Time,即时编译)和 AOT(Ahead of Time,运行前编译)的语言之一。语言在运行之前通常都需要编译,JIT 和 AOT 则是最常见的两种编译模式。

SCADE Display(OpenGL)软件设计文档生成工具的设计考虑

SCADE Display(OpenGL)软件设计文档生成工具的设计考虑 2018年6月 1 引言 本文档描述在SCADE Display软件设计文档生成工具(以下简称为SDYSDDGEN)的设计过程中考虑到的一些问题及其解决方案。 2 目标 SDYSDDGEN的目标设定为: 生成SCADE Display软件模型的软件设计文档(以下简称为SDYSDD)SDYSDD要符合DO-178B/C或GJB438B对软件设计文档的要求SDYSDD要符合用户单位的软件设计文档模板的要求SDYSDD使用中文或英文SDYSDD的文件格式是MS OFFICE的word或excelSDYSDD易于导入到DOORS 3 术语 SCADE Display的官方工具SDYReporter生成的文档使用表1中的术语。 表1 术语 定义 SGFX file A file that corresponds to a display specification. OGFX file A file describing a part of a display specification and that can be used as a reference object. layer A layer is composed of a set of objects and has a transparent background. Superimposing layers allows to display complex images.

GitHub中图片无法正常显示

修改host文件内容 。C:\Windows\System32\drivers\etc 目录下 修改host权限,使能够编辑 将所有关于GitHub的注释掉 # GitHub Start 192.30.253.112 github.com 192.30.253.119 gist.github.com 151.101.184.133 assets-cdn.github.com 151.101.184.133 raw.githubusercontent.com 151.101.184.133 gist.githubusercontent.com 151.101.184.133 cloud.githubusercontent.com 151.101.184.133 camo.githubusercontent.com 151.101.184.133 avatars0.githubusercontent.com 151.101.184.133 avatars1.githubusercontent.com 151.101.184.133 avatars2.githubusercontent.com 151.101.184.133 avatars3.githubusercontent.com 151.101.184.133 avatars4.githubusercontent.com 151.101.184.133 avatars5.githubusercontent.com 151.101.184.133 avatars6.githubusercontent.com 151.101.184.133 avatars7.githubusercontent.com 151.101.184.133 avatars8.githubusercontent.com 151.101.208.133 user-images.githubusercontent.com # GitHub End 将上诉内容编辑到host当中, 其中github.com,gist.github.com的IP需要在https://www.ipaddress.com/ 中获取,

IDEA工具避坑指南(十一):git导入SpringBoot后|不识别依赖 |大量爆红 | 无法启动

一、前言 使用在IDEA2019中,使用Git工具导入SpringBoot项目后,java类的依赖包大量爆红、不能启动SpringBoot,不能自动识别启动类。 提示:如果刚拉取的项目,只有.git和.idea文件,没有src或java目录,点击进入! 二、错误描述 2.1 启动图标是灰色的,不能启 2.2 启动入口类不被识别,没有启动的绿色图标 2.3 配置启动入口时,报错,无法配置,无法点击确定按钮 点击IDEA右上角的,依次点击Add Configuration,在弹出窗口依次点击Templates,在下拉列表中找到SpringBoot选项 2.4 java、resource、test文件不被识别为不同的资源文件类型 2.5 各种神操作后,大量引入包爆红,不被识别 不忍直视(略过~~) 三、成果展示 再点开Add Configuration看一下配置,也正常了 四、解决方案 热身动作 1、配置Maven和Maven的setting.xml配置文件(不要使用IDEA默认的) 快捷键:ctrl+Alt+s,打开设置,修改maven的安装位置 更多maven配置,如需帮助,点击下方链接 点击进入:Maven环境配置、Maven在IDEA中的配置(参考一、1.2章节) 2、在工程目录下,鼠标右键pom.xml,Add as Maven Project 操作后,一定要先Reimport一下 3、给工程本身配置各种JDK 快捷键:Ctrl+Alt+Shift+s 提示:不局限于以下两处,JDK配置比较简单,自己脑补一下 ---------------¥¥¥¥¥¥¥¥¥如果热身动作不能解决,继续向下看 ¥¥¥¥¥¥----------------- 务必知晓,上面的热身动作都处理过了,再看下面的方案,否则下面方案可能不适合你!!! 方案一(推荐) 做完上面的热身 Ctrl+Alt+Shift+S,打开Project Structure项目结构,不出意外会看到下面的目录结构: 问题根源就在这里,需要删除一套,分析如下: 分别点击两个模块,看到两个模块下都有一套相同的java代码 此时,需要删除一套,我这里删除待项目名称的这套(本质上,它不属于模块,是模块的领导层),移除时,会有提示,直接确定即可。 最后,点击弹出框底部的确定按钮 特别提示:如果你的资源文件图标,没有特别标注,按如下步骤,自己标注一下。 操作步骤: 1)先点击下面的java文件夹,然后点击中间的源码图标; 2)再点击下面的resources,然后点击中间的Resources图标; 3)最后点击下面的test文件夹,然后点击中间的test图标; 4) 点击该窗口的“确定”按钮。 至此,一般情况下,步骤进行到这里,问题就完全解决了,效果如下: 选择启动模块,没有这个操作,启动时会提示找不到启动模块。 如下图所示,勾选一下需启动的模块 同时,勾选下面的小对钩 拓展1:如果启动项目时,遇到如下错误,解决步骤如下 IntelliJ IDEA Debug时报错 Cannot start compilation: the output path is not specified for module “NewFrameWork2023"

mac 远程连接windows系统

目录 mac 远程连接windows系统 下载地址安装 mac 远程连接windows系统 微软官方专门为Mac用户提供了一款类Windows mstsc的远程桌面工具——Microsoft Remote Desktop for mac,专门用于远程控制Windows桌面。 但是。苹果Appstore中国区无法搜索到该软件(不知道什么原因)。 基本上,大部分使用Microsoft Remote Desktop for mac的朋友,都是从第三方网站下载,其实,微软是提供了该软件的官方下载URL的。 下载地址 官网下载地址 安装 对与mac来说,是下载即可以使用的 把它挪到应用程序里,每次打开桌面就能直接使用了

运用Mybatis动态查询字段及表名

Mapper.java IPage<Map<String, Object>> getDyData(@Param("page") Page page, @Param("columns")String columns, @Param("tableName")String tableName); Mapper.xml <select id="getDyData" resultType="java.util.Map"> select ${columns} from ${tableName} dy </select> 使用场景: 1.我们必须知道查询的表名,可以通过表名查询字段及注释,然后把表名和字段传进mapper 2.如果知道具体查询哪些表,可以把这些表及表对应的字段配置进一张表和字段对应的表中,通过表名查询该表取出对应的字段及注释,此处的字段注释可以自己写相对比较灵活。 DROP TABLE IF EXISTS `table_colume_mapping`; CREATE TABLE `table_colume_mapping` ( `table_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表名', `column_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字段名', `column_comment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字段汉语名', `table_comment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表名注释', `sort` int(10) NULL DEFAULT NULL COMMENT '字段排序', `show_column` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '是' COMMENT '是否展示在列', `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '0存在1删除' ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '表字段注释映射' ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1; 调用 LambdaQueryWrapper<TableColumeMapping> wrapper = new LambdaQueryWrapper<>(); wrapper.

vue 启动项目报错Cannot read properties of undefined (reading ‘parseComponent‘)

如果出现如下报错大概率是因为install时中途出现异常导致vue-template-compiler依赖没有正常安装导致的,重新安装即可 Syntax Error: TypeError: Cannot read properties of undefined (reading 'parseComponent') You may use special comments to disable some warnings. Use // eslint-disable-next-line to ignore the next line. Use /* eslint-disable */ to ignore all warnings in a file. 1、 yarn add vue-template-compiler 或 npm add vue-template-compiler 2、最后如果还是不行就再用 yarn upgrade –latest vue-template-compiler npm upgrade –latest vue-template-compiler

Java基础之回调

回调函数是一种函数指针,它指向了另一个函数的地址。回调函数通常会在某些特定事件发生时被调用,这些事件可以是用户输入、系统消息等等。在Java中,回调函数可以通过接口来实现。 下面是一个简单的Java回调函数示例: public interface Callback { public void execute(); } public class Caller { public void call(Callback callback) { // do something callback.execute(); } } public class Main { public static void main(String[] args) { Caller caller = new Caller(); Callback callback = new Callback() { @Override public void execute() { System.out.println("Callback executed"); } }; caller.call(callback); } } 在这个示例中,我们定义了一个接口Callback,并实现了一个实现它的接口Caller。Caller类有一个call方法,它接受一个Callback参数,并在该方法内部调用execute方法。在Main类中,我们创建一个回调函数对象callback,并将其传递给Caller类的call方法。 当Caller类的call方法被调用时,它会调用传递给它的回调函数,并执行回调函数中的代码。在本例中,回调函数只是简单地输出了一条消息,但在实际应用中,回调函数可以执行任何功能。 这个例子展示了回调函数的基本概念和用法。在Java中,回调函数通常用于实现异步事件处理和插件架构等功能。 控制台将输出以下结果: Callback executed 这是回调函数中定义的输出语句。当Caller类的call方法被调用时,它会调用传递给它的回调函数,也就是Callback.execute()方法,执行回调函数中的代码。在这个例子中,回调函数只是简单地输出了一条消息,因此控制台会输出这个消息。 回调函数的优点包括: 灵活性。回调函数允许应用程序在运行时动态地改变程序行为,而无需修改代码。解耦性。通过使用回调函数,应用程序的不同部分可以独立发展,而不会相互影响。代码复用。回调函数可以被多个应用程序共享,以实现相似的行为。 常用于异步事件触发。当异步事件完成时,回调函数被调用。例如,当文件下载完成时,回调函数可以用来通知应用程序。 还有使用mq的时候当消息出错时,例如,如果使用MessageListenerOrderly接口,当消息消费出错时,会调用MessageListenerOrderly接口的onMessage方法的ConsumeOrderlyContext#setSuspendCurrentQueueTimeMillis方法,该方法可以设置消息暂停消费的时间,然后进行重新消费。如果多次消费仍然出错,则可以将消息写入死信队列进行处理。

单片机实现非阻塞延时

非阻塞式延时是指程序在执行延时函数时可以继续执行其他任务,不会一直等待。 E_Bool Ticker_Out(u32 *pTicker, u32 uCompareValue) { u32 uTicks = 0; uTicks = BSP_Get_SysTick(); if(0 == uCompareValue) { *pTicker = uTicks; return True; } else { if(uTicks >= (*pTicker)) { uTicks = uTicks - (*pTicker); } else { uTicks = (U32_MAX_VALUE - (*pTicker)) + uTicks; } if (uTicks >= uCompareValue) { return True; } } return False; } 上述代码中,BSP_Get_SysTick()是得到在滴答定时器中断函数中计数的值: u32 BSP_Get_SysTick(void) { return gSystickTimes; /* 获取系统心跳 */ } void SysTick_Handler(void) { gSystickTimes++; /* 系统心跳计数 */ } 具体使用:

[STM32F103C8T6] 串口

1.非中断串口发送数据 串口发送/接收函数: HAL_UART_Transmit(); 串口发送数据,使用超时管理机制 HAL_UART_Receive(); 串口接收数据,使用超时管理机制 HAL_UART_Transmit_IT(); 串口中断模式发送 HAL_UART_Receive_IT(); 串口中断模式接收 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) 作用:以阻塞的方式发送指定字节的数据 形参 1 :UART_HandleTypeDef 结构体类型指针变量 形参 2:指向要发送的数据地址 形参 3:要发送的数据大小,以字节为单位 形参 4:设置的超时时间,以ms单位 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) 作用:以中断的方式接收指定字节的数据 形参 1 是 UART_HandleTypeDef 结构体类型指针变量 形参 2 是指向接收数据缓冲区 形参 3 是要接收的数据大小,以字节为单位 此函数执行完后将清除中断,需要再次调用以重新开启中断。 代码实现 #include <stdio.h> #include <string.h> unsigned char ch[20] = {0}; int fputc(int ch, FILE *f) { unsigned char temp[1]={ch}; HAL_UART_Transmit(&huart1,temp,1,0xffff); return ch; } main函数里: unsigned char ch[20] = {0}; HAL_UART_Transmit(&huart1, "

openpyxl使用方法

1.创建Excel文档 首先我们需要安装openpyxl库: pip install openpyxl 然后使用下面代码创建一个新的Excel文档: import openpyxl workbook = openpyxl.Workbook() workbook.save('test.xlsx') 这样我们就创建了一个名为test.xlsx的Excel文档。 2.打开Excel文档 下面是打开一个已有的Excel文档的代码: import openpyxl workbook = openpyxl.load_workbook('test.xlsx') 这里我们打开了之前创建的test.xlsx文档。 3.获取工作表 Excel文档中可以包含多个工作表,我们首先需要获取到指定的工作表,才能对其进行操作。 获取工作表的代码如下: import openpyxl workbook = openpyxl.load_workbook('test.xlsx') worksheet = workbook['Sheet1'] # 获取名为“Sheet1”的工作表对象 这里我们获取了名为Sheet1的工作表对象。 4.读取单元格数据 我们可以通过工作表对象的cell()方法获取单元格对象,然后获取该单元格对象的value属性,即可读取该单元格的值。这里我们读取A1单元格的数据: import openpyxl workbook = openpyxl.load_workbook('test.xlsx') worksheet = workbook['Sheet1'] cell = worksheet.cell(row=1, column=1) print(cell.value) 5.写入单元格数据 我们同样可以通过工作表对象的cell()方法获取单元格对象,并给该单元格对象的value属性赋值,即可写入数据。 import openpyxl workbook = openpyxl.load_workbook('test.xlsx') worksheet = workbook['Sheet1'] cell = worksheet.cell(row=1, column=1) cell.value = 'Hello, World!' workbook.save('test.xlsx') 这里我们将A1单元格的值改为Hello, World!

SpringSecurity简介

一、什么是Spring Security? springsecurity是一个功能强大且高度可定制的身份验证和访问控制框架。springsecurity是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring安全性的真正威力在于它可以很容易地扩展以满足定制需求。 实际上,在Spring boot出现之前,Spring security已经发展了很多年,到那时由于强大的shiro,它一直不温不火。因为相对于Shiro,在SSH/SSM中整合Spring Security都是比较麻烦的操作,然而自从有了 Spring Boot 之后,Spring Boot 对于 Spring Security 提供了 自动化配置方案,可以零配置使用 Spring Security。 所以一般的推荐方案是: SSM + ShiroSpring boot/Spring Cloud + Spring Security 二、Spring Security 原理解析 Spring Security对Web资源的保护是靠Filter实现的。当初始化Spring Security时,会创建一个名为 springSecurityFilterChain 的Servlet过滤器,类型为org.springframework.security.web.FilterChainProxy,它实现了javax.servlet.Filter,因此外部的请求会经过此 类,下图是Spring Security过虑器链结构图: filter实现的security 这里FilterChainProxy是一个代理,真正起作用的是FilterChainProxy中SecurityFilterChain所包含的各个Filter,同时 这些Filter作为Bean被Spring管理,它们是Spring Security核心,各有各的职责,但他们并不直接处理用户的认 证,也不直接处理用户的授权,而是把它们交给了认证管理器(AuthenticationManager)和决策管理器 (AccessDecisionManager)进行处理。 所以spring Security功能的实现主要是由一系列过滤器链相互配合完成,如下图: Spring Security Filters SecurityContextPersistenceFilter :这个Filter是整个拦截过程的入口和出口(也就是第一个和最后一个拦截 器),会在请求开始时从配置好的 SecurityContextRepository 中获取 SecurityContext,然后把它设置给 SecurityContextHolder。在请求完成后将 SecurityContextHolder 持有的 SecurityContext 再保存到配置好的 SecurityContextRepository,同时清除 securityContextHolder 所持有的 SecurityContext。UsernamePasswordAuthenticationFilter :用于处理来自表单提交的认证。该表单必须提供对应的用户名和密码,其内部还有登录成功或失败后进行处理的 AuthenticationSuccessHandler 和 AuthenticationFailureHandler,这些都可以根据需求做相关改变。FilterSecurityInterceptor: 是用于保护web资源的,使用AccessDecisionManager对当前用户进行授权访问 这里需要重点讨论的有两个概念,身份认证和授权。这也是Spring Security的主要职责。

论文pdf高清图必看,Word 转PDF图片不清晰解决方法

符合期刊要求且可编辑的图 找了好多攻略发现word很清晰的图,到pdf就不清楚了试了很多方法 发现把图片导出为emf格式插入word,在转pdf后放大就非常高清 放下对比图 之前的方法设置Word 转PDF图片不清晰解决方法 - 知乎 保存为pdf还是很糊 

typescript 交叉类型

一,前言 1,交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性 二,交叉类型使用 1.我们可以使用type来声明一个新的交叉类型 interface A{ a:number } interface B{ b:string } type C = A & B //C 同时拥有A和B的所有属性 2.接口的交叉类型生成一个新的接口类型,含有两者的所有属性,在使用时,也要满足新的接口的形状。 三,注意事项 1.并不是所有类型都适合交叉类型,例如原子类型的交叉是没有意义的,string & number 是没有意义的,没有一种类型既是string也是number 2.对于两个接口类型的交叉类型,当两个接口含有相同的属性时,若这两个属性的类型相同,则合并为这一个类型,若不同,那么整个交叉类型返回never interface A{ a:number } interface B{ a:string } type C = A & B //C 是never类型 3.注意和联合类型区分开,一个是既是也是,一个是或者

数据库系列之MySQL线程ID和操作系统线程ID对应关系

在日常运维工作中,MySQL数据库服务器出现SQL语句执行导致服务器CPU使用率突增,如何通过现有手段快速定位排查到哪个SQL语句,并采取应急措施。本文介绍基于传统的操作系统线程的CPU使用监控手段入手,利用操作系统线程ID和MySQL线程ID对应关系,逐步定位到异常SQL和事务。 1、操作系统进程和线程ID 1.1 MySQL单进程和多线程关系 MySQL是一个单进程多线程数据库,进程是正在运行的程序的实例,线程是操作系统能够进行运算调度的最小单位。 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程并行执行不同的任务。 MySQL数据库选择单进程多线程,是因为进程同一时间内并发很多线程给不同的CPU,线程共享相同的内存单元/内存地址空间, 由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就使得通信更简便而且信息传递的速度也更快。 上图是MySQL存储引擎InnoDB的后台线程,在“InnoDB存储引擎解密”中详细介绍了。InnoDB后台线程主要用于维持服务器的正常运行和完成用户提交的任务,主要包括:master thread、page cleaner thread、purge thread、read thread、write thread、redo log thread、insert buffer thread、monitor thread、error monitor thread、lock monitor thread等。 1.1.1 Master Thread Master thread是核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、undo页的回收等。Master thread内部由多个循环组成,包括主循环、后台循环、刷新循环和暂停循环,master thread会根据数据库运行的状态在不同的循环之间切换。在InnoDB 1.0.x版本之前的主循环中,分两大部分操作:每秒钟的操作和每10秒钟的操作。 1)每秒一次的操作包括: 日志缓冲刷新到磁盘,即使这个事务还没有提交(总是),这点解释了为什么再大的事务commit时都很快合并插入缓冲(可能),合并插入并不是每秒都发生,InnoDB会判断当前一秒内发生的IO次数是否小于5,如果是,则系统认为当前的IO压力很小,可以执行合并插入缓冲的操作。至多刷新100个InnoDB的缓冲池的脏页到磁盘(可能),这个刷新100个脏页也不是每秒都在做。 即使某个事务还没有提交,InnoDB存储引擎仍然每秒会将重做日志缓存中的内容刷新到redo log中。 2)每10秒一次的操作包括: 刷新100个脏页到磁盘(可能);合并至多5个插入缓冲(总是);将日志缓冲刷新到磁盘(总是);删除无用的undo页(总是);产生一个检查点(checkpoing); 在以上过程中,InnoDB存储引擎会先判断过去10s内的磁盘IO操作是否小于200次,如果是InnoDB存储引擎认为当前有足够的磁盘IO操作能力,因此将100个脏页刷新到磁盘。接着,InnoDB存储引擎会合并插入缓冲,之后再将日志缓冲刷新到磁盘。最后InnoDB存储引擎会执行full purge操作,删除无用的undo页,它会先去判断当前系统中已被标记为删除的行是否可以删除,如果可以则可以立即将其删除。 在InnoDB 1.0.x版本之前,InnoDB存储引擎对于IO是有限制的,缓冲池向磁盘刷新做了一定的硬编码,随着磁盘硬件性能提高,这种方式会限制InnoDB对磁盘IO的性能。因此在1.0.x版本之后,InnoDB提供了参数innodb_io_capacity,用来表示磁盘IO的吞吐量,默认值为200。对于刷新到磁盘页的数量,会按照innodb_io_capacity的百分比进行控制: 在合并插入缓冲时,合并插入缓冲的数量为innodb_io_capacity值的5%在从缓冲区刷新脏页时,刷新脏页的数量为innodb_io_capacity 命令show engine innodb status;可以查看master thread信息: ===================================== 2021-08-22 20:38:37 140186194323200 INNODB MONITOR OUTPUT ===================================== Per second averages calculated from the last 12 seconds ----------------- BACKGROUND THREAD ----------------- srv_master_thread loops: 1 srv_active, 0 srv_shutdown, 255 srv_idle srv_master_thread log flush and writes: 0 1.

基于Face++,使用Spring Boot+Elemnet-UI实现人脸识别登录。

上一篇文章只是封装了人脸检测的一些工具类,要实现刷脸登录,我们首先得思考一个问题,就是如何将我们的人脸和登录账户信息进行绑定,让它通过人脸就能识别到当前登录的账户是谁的账户。 这个问题我们可以这样解决,我浏览Face++的官网发现它还有人脸比对的一个API,我点进去一看,这不就是实现人脸登录的关键API吗? 继续查看它需要的参数。 我们可以看到它需要的是两个图片的face_token,用两个图片的face_token,进行对比,得出它是不是同一个人。那就简单多了。许多问题都迎刃而解。接下来就是我具体的实现过程,大家可以参考一下。 1.准备工作 首先,在我们封装的工具类中,添加人脸比对的方法: /** * 对比两个人脸的face_token * @param face_token1 * @param face_token2 * @return 如果为true则是同一个人 * @throws Exception */ public static boolean compareFace(String face_token1, String face_token2) throws Exception { String url = "https://api-cn.faceplusplus.com/facepp/v3/compare"; HashMap<String, byte[]> byteMap = new HashMap<>(); map.put("face_token1", face_token1); map.put("face_token2", face_token2); byte[] bacd = HttpUtils.post(url, map, null); String str = new String(bacd); System.out.println("str = " + str); //转为为对象,获取检索的置信度 if (str.indexOf("error_message") != -1) { return false; } JSONObject jsonObject = JSONObject.

Jmeter常用断言之响应断言详解

响应断言是最常用的一种断言方法,主要是对响应结果中的文本内容进行断言,比如响应结果是否包含指定的值,或者是否等于指定的值。响应断言可以适用各种返回类型的响应结果,如:Test、html、application/json、application/xml等。 一、断言添加方式 根据需要可在【测试计划】、【线程组】、【线程请求】下添加断言,一般在对应的【线程请求】下添加,如下图所示,即本文所介绍的。 添加路径:【线程请求-点击右键-添加-断言-对应的断言形式】 二、断言结果查看 2.1.【断言结果】看断言结果 添加路径:【测试计划-点击右键-添加-监听器-断言结果】 整个测试计划下所有请求的所有断言结果报错信息均会在此显示,如下图所示,将所有断言结果的报错信息直接展示出来。 2.2.【查看结果树】看断言结果 添加路径:【测试计划-点击右键-添加-监听器-查看结果树】,整个测试计划下所有请求的所有断言结果报错信息均会在此显示,如下图的形式,切换查看。 三、响应断言 响应断言界面设置,如下图: 如上图所示,响应断言分为【Apply to】【测试字段】【模式匹配规则】【测试模式】【自定义失败信息】五个部分。 3.1.Apply to 断言的作用域。 通常使用默认的【Main sample only】(比如给HTTP请求新增断言,选择了Main sample only,那么这个断言的作用域只针对此HTTP请求),没有对其他作用域有过深入的研究。 【Main sample and sub-samples】与【Sub-samples only】这两个作用域的场景是:部分请求一次会触发多个线程。 **【Main sample and sub-samples】**作用于主线程以及子线程, **【Sub-sample only】**只用作于子线程。 如果选择了【Main sample and sub-samples】,即使主线程成功,子线程失败,那么断言也是以失败做结果。 3.2.测试字段 这个模块,指的是我们使用哪一块的返回信息做断言。 【响应文本】指返回的【响应数据】的文本信息response body。 【响应代码】指Http响应码,如200、500等。 【响应信息】指的是http的【取样器结果】中的response message。 【响应头】指http【响应数据】的响应头信息response hearders。 【请求头】指http【请求数据】的请求头信息request hearders。 【请求数据】指http【请求数据】的请求头信息request body。 【URL样本】指断言的当前请求的URL地址,与http【请求数据】的请求头信息request body中的值做对比是否一致。注意:如果有重定向包含重定向url。 【文档(文本)】通过Apache Tika从各种的文档中提取的文本进行验证,包括响应文本,pdf、word等等各种格式。 【忽略状态(Ignore Status)】 一个请求多项响应断言时,忽略某一项断言的响应结果,而继续下一项断言。 注意:响应文本不等于响应信息。 以上测试字段的断言,可以随便找个接口尝试一下,在下图的结果中查找对应的字段值进行测试。。。 3.3.模式匹配规则 分为【包括】【匹配】【相等】【字符串】【否】【或者】 【包括】响应的结果中包含指定的文本或者字段值,支持正则表达式。 【匹配】完全匹配,期望值与实际结果必须完全一致,一般结合正则表达式使用。 【相等】完全匹配,响应结果与指定的内容完全一致,不支持正则表达式。 【字符串】返回结果,包含指定的字符串,不支持正则表达式。 【否】合并选择之后,断言结果true为false,false为true。 【或者】当有多个断言时,只要有一个断言成功,那么最终结果就是成功的。 3.4.测试模式 断言的内容。如果有多个,按照顺序执行,没有选择【或者】的情况下,所有的断言通过之后,取样器结果才是成功的。

2个int类型的数字拼接成1个long类型的数字

/**int型数字跟long型数字转行 * ID转换器 */ public class IDConverter { /** * 将2个int型数字拼接成一个long类型数字 */ public static long combineInt2Long(int high, int low) { return ((long) high << 32 & 0xFFFFFFFF00000000L) | ((long) low & 0xFFFFFFFFL); } /** * 将一个long类型数字,拆分成2个int型数字 */ public static int[] seperateLong2Int(long val) { int[] res = new int[2]; res[1] = (int) (0xFFFFFFFFL & val);//低位 res[0] = (int) ((0xFFFFFFFF00000000L & val) >> 32);//高位 return res; } /**测试*/ public static void main(String[] args) { int high =1001; int low =200; long num = IDConverter.

mysql基于docker安装及连接

mysql简介 1、什么是数据库 ? 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。 主流的数据库有:sqlserver,mysql,Oracle、SQLite、Access、MS SQL Server等,本文主要讲述的是mysql 安装 mysql 启动docker systemctl start docker 下载MySQL 默认最新版本(如果对版本没有要求的话可以直接下载最新版) docker pull mysql 等一会儿就下载好了,然后我们看一下docker中的镜像 docker images 启动MySQL docker run --restart=always --name test_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e TZ=Asia/Shanghai -d mysql:latest --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-time_zone='+8:00'//以下是注释 不要复制--restart=always:设置为开机启动--name test_mysql:自定义的名称-p 3306:3306:端口映射-e MYSQL_ROOT_PASSWORD=设置密码-e TZ=Asia/Shanghai:设置时区-d mysql:指定镜像--character-set-server=utf8mb4:指定字符集--collation-server=utf8mb4_unicode_ci:指定字符集--default-time_zone='+8:00':默认时区 启动之后我们看一下运行情况 docker ps 远程连接 首先我们去配置一下云服务器安装组,开放3306端口,然后docker中也要开启3306端口 //开启3306端口firewall-cmd --zone=public --add-port=3306/tcp --permanent//重启防火墙firewall-cmd --reload 因为我们安装的是最新版,而最新版的mysql密码验证有更改,Navicat如果不是最新版的话,就验证不过去,这个时候我们要进入MySQL中设置一下 //进入test_mysql 的命令行模式 这里的test_mysql 就是刚刚起的那个名字docker exec -it test_mysql bash//默认进入root用户下root@xxxxxx:/#//进入mysql命令,回车输入docker-mysql密码mysql -u root -p//进入mysql数据库表use mysql;//修改密码方式alter user 'root'@'%' identified with mysql_native_password by '这里是你的密码';//完事 Ctrl+D连按两次回到主界面

Docker 镜像加速

前言 大家好,本文是对 Docker 镜像的详细讲解,讲解了如何安装 Docker、配置 Docker 镜像加速以及操作 Docker 镜像。希望对大家有所帮助~ 一、为什么要配置Docker镜像加速器 因为我们默认pull的docker镜像是从Docker Hub来下载,由于其服务器在国外,速度会比较慢。因此我们可以配置成国内的镜像仓库,这样可以加速镜像的上传/下载,比如阿里云,网易云,docker中国等。 二、准备: aliyun账号(淘宝、阿里云邮箱、1688账号均可)DockerCentOS 或 Ubuntu 三、获取加速地址 (1)登录阿里云:阿里云-为了无法计算的价值 (2)右上角进入【控制台】 (3)左上角点击【产品与服务】 (3)输入关键字【容器镜像服务】并点击进入 这一步需要注册Registry实例密码,因为在拉取私有镜像或者上传镜像前,需要docker login输入您的凭证信息。 (4)选择镜像加速器即可看到个人专属阿里云镜像加速地址 四、配置镜像加速器(Docker版本1.10.0以上) 使用阿里云提供的镜像加速器或者使用网易云提供的镜像加速器,下面以阿里云为例。 自己的测试环境:Centos7,docker版本如下: (2)安装/升级Docker客户端 推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce (2)配置镜像加速器 针对Docker客户端版本大于 1.10.0 的用户 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"] # 其中xxxx为自己的加速器地址 } EOF sudo systemctl daemon-reload sudo systemctl restart docker

CSS设置背景background

background-image ◼ background-image用于设置元素的背景图片  会盖在(不是覆盖)background-color的上面 ◼ 如果设置了多张图片  设置的第一张图片将显示在最上面,其他图片按顺序层叠在下面 ◼ 注意:如果设置了背景图片后,元素没有具体的宽高,背景图片是不会显示出来的 background-repeat ◼ background-repeat用于设置背景图片是否要平铺 ◼ 常见的设值有  repeat:平铺  no-repeat:不平铺  repeat-x:只在水平方向平铺  repeat-y:只在垂直平方向平铺 background-size background-size用于设置背景图片的大小  auto:默认值, 以背景图本身大小显示  cover:缩放背景图,以完全覆盖铺满元素,可能背景图片部分看不见  contain:缩放背景图,宽度或者高度铺满元素,但是图片保持宽高比  :百分比,相对于背景区(background positioning area)  length:具体的大小,比如100px background-position ◼ background-position用于设置背景图片在水平、垂直方向上的具体位置  可以设置具体的数值 比如 20px 30px;  水平方向还可以设值:left、center、right  垂直方向还可以设值:top、center、bottom  如果只设置了1个方向,另一个方向默认是center background-attachment ◼ background-attachment决定背景图像的位置是在视口内固定,或者随着包含它的区块滚动。 ◼ 可以设置以下3个值  scroll:此关键属性值表示背景相对于元素本身固定, 而不是随着它的内容滚动  local:此关键属性值表示背景相对于元素的内容固定。如果一个元素拥有滚动机制,背景将会随着元素的内容滚动.  fixed:此关键属性值表示背景相对于视口固定。即使一个元素拥有滚动机制,背景也不会随着元素的内容滚动。 background ◼ background是一系列背景相关属性的简写属性 ◼ 常用格式是

Redis的过期策略

Redis中缓存的数据是有过期时间的,当缓存数据失效时Redis会删除过期数据已节省内存,那Redis是怎么删除过期数据的?删除过期数据的策略是什么?Redis过期策略 Redis为什么这么快,原因之一是Redis的操作是基于内存的,既然基于内存的,而内存的大小是有限的,当内存不足或占用过高时,怎么办?Redis的内存淘汰机制 一、Redis过期策略 Redis在设置缓存数据时指定了过期时间,到了过期时间数据就失效了,那Redis是怎么处理这些失效的数据的呢?用到Redis的过期策略----“惰性删除+定期删除”。 1. 定期删除 定期删除是指Redis默认每隔100ms就随机抽取一些设置了过期时间的key,检测这些key是否过期,如果过期就将其删除。 100ms怎么来的? 在Redis的配置文件redis.conf中有一个属性“hz”,默认设置为10,表示每1s执行10次定期删除,即每隔100ms执行一次,可以修改这个配置值。 随机抽取一些检测,一些是多少? 同样是由redis.conf文件中的maxmemory-sample属性决定的,默认为5。 为什么随机抽取部分检测而不是全部? 因为如果Redis里面有大量的key都设置了过期时间,全部去检测一遍的话CPU负载会很高,会浪费大量时间在检测上面,甚至导致redis挂掉。所以只会抽取一部分而不会全部检测。 正因为定期删除只会随机抽取部分key来检测,这样的话就会出现大量已经过期的key并没有被删除,这就是为什么有时候大量的key明明已经过来失效时间,但是Redis的内存还是被大量占用的原因,为了解决这个问题,Redis又引入了“惰性删除策略”。 2. 惰性删除 惰性删除不是主动的去删除,而是在你要获取某个key的时候,redis会先去检测一下这个key是否已过期,如果没有则返回给你,如果已经过期,就将该key删除,并不返回给你。 “定期删除+惰性删除”就能保证过期的key最终一定能被删除,但是只能保障最终一定会被删除,要是定期删除遗漏的大量过期key,我们在很长的一段时间内也没有再访问这些key,那么这些过期key不就一直在内存中吗?不就一直占着内存吗?这样依然会导致Redis内存耗尽,由于存在这样的问题,所有Redis又引入了“内存淘汰机制”来解决。 二、Redis内存淘汰机制 内存淘汰机制能保证Redis内存占用过高的时候,去进行内存淘汰,也就是删除一部分key,保证redis的内存占用率不会过高,那么淘汰那些key?Redis目前提供了8种内存淘汰策略,含Redis 4.0版本之后又新增的两种LFU模式:volatile-lfu和allkeys-lfu 策略描述no-eviction当内存不足以容纳新写入数据时,新写入操作会报错,无法写入数据,一般不采用allkeys-lru当内存不足以容纳新写入数据时,移除最近最少使用的key,这个是最常用的allkeys-random当内存不足以容纳新写入数据时,随机移除keyallkeys-lfu当内存不足以容纳新写入数据时,移除最不经常(最少)使用的keyvolatile-lru当内存不足以容纳新写入数据时,在设置了过期时间的key中,移除最近最少使用的keyvolatile-random当内存不足以容纳新写入数据时,在设置了过期时间的key中,随机移除keyvolatile-lfu当内存不足以容纳新写入数据时,在设置了过期时间的key中,移除最不常用(最少)使用的keyvolatile-tll当内存不足以容纳新写入数据时,在设置了过期时间的key中,优先移除过期时间最早(剩余存活时间最短)的key 什么时候会执行内存淘汰策略,内存占用率高的标准是什么? redis.conf配置文件中的maxmemory属性限定了Redis最大内存使用量,当占用内存大于maxmemory的配置值时会执行内存淘汰策略,默认68%。 内存淘汰策略的配置 内存淘汰策略由redis.conf配置文件中的maxmememory-policy属性设置,没有配置时默认是no-eviction模式。 内存淘汰的执行过程 客户端执行一条命令,导致Redis需要增加数据(比如 set key value); Redis会检测内存使用情况,如果内存使用超过maxmemory,就会按照配置的过期策略maxmemory-polic删除一些key; 再执行新的数据的set操作; 三、其他场景对过期key的处理 快照生成RDB文件时 过期的key不会保存在RDB中。 服务重启载入RDB文件时 Master载入RDB时,文件中的未过期的键会被正常载入,过期键则会被忽略。Slave载入RDB时,文件中的所有键都会被载入,当主从同步时,再和Master保持一致。 AOF文件写入时 因为AOF保存的是执行过的Redis命令,如果Redis还没有执行del,AOF文件中也不会保存del操作,当过期key被删除时,del命令也会被同步到AOF文件中去。 重写AOF文件时 执行BGREWRITEAOF时,过期的key不会被记录到AOF文件中。 主从同步时 Master删除过期key之后,会向所有Slave服务器发送一个DEL命令,Slave收到通知之后,会删除这些key。 Slave在读取过期键时,不会判断删除操作,而是继续返回该键对应的值,只有当Master发送DEL通知,Slave才会删除过期key,这是统一、中心化的键删除策略,保证主从服务器的数据一致性。

STM32程序占用的内存容量计算

MKD编译完成后查看以下数据的大小: Code:表示程序所占用 FLASH 的大小( FLASH)。 RO-data:即 Read Only-data, 表示程序定义的常量,如 const 类型( FLASH)。 RW-data:即 Read Write-data, 表示已被初始化的全局变量( SRAM) ZI-data:即 Zero Init-data, 表示未被初始化的全局变量(SRAM) 占用的Flash=Code + RO Data + RW Data; 运行消耗的最大RAM= RW-data+ZI-data; 可以计算出占用的FLASH = 23204+1428+380=24.42kB,占用的RAM=380+1836=2.16kB STM32F103芯片的内存资源如下: 从这个表里可以看到ROM SIZE里包含了Code RO-data RW-data,但是没有zi-data。是因为zi-data的值没有在程序里进行初始化,所以上电运行后会直接被赋值为0,所以这个值也就没有必要保存的ROM空间里了。 程序空间大小计算: 7828byte=0x1E94byte; 那么数据存储从0x800 0000+0x1E94=0x800 1E94开始都是安全的。

Python学习+PTA习题练习

目录 Python第2章 序列 PTA get()函数 index()函数 keys() eval python中pop()函数 extend() 函数 split()函数 Python中的切片 python基础知识 strip()函数功能 isalpha()函数 islower() round()函数 选择与循环 字符串与正则表达式 Python第2章 序列 PTA 列表对象是可变对象。列表是动态数据结构,因此可以添加元素或者删除已有的元素。 空列表对象的布尔值是False。 列表中索引值为-1的元素指的是最后一个元素。 list("abcd")的结果是? ['a', 'b', 'c', 'd'] 要把5加到列表lst的末尾,用的是___ lst.append(5) list(range(2,12,2))[:-2].pop()的结果是:_。6 lst=[3,4,5,6,5,4,3],执行lst.remove(3)后,lst[0]的值是4 “[3] in [1, 2, 3, 4]”的值为False 创建只包含一个元素的元组时,必须在元素后面加一个逗号,例如(3,) Python支持使用字典的“键”作为下标来访问字典中的值。 在字典中,允许存在键值相同的多个键值对 False 集合中的元素是无序的,并且不允许重复。 集合中可包含任意类型的元素。False get()函数 在这里有两个参数,第一个是确定要分配值的键,第二个是拟定给键分配一个初值,但实际要给键赋值仍需要get赋值语句 index()函数 1.描述 index()函数可用于查找列表中对应函数的索引值并输出 2.index()函数的用法 list.index(object) 另外index()函数还可以范围查找: list.index(object,start,stop) keys() 获取当前字典中所有的键( key ) eval 比如字符串里面包含的字典就输出字典,包含的列表就输出列表,但是字符串相应的格式一定要输入正确,否则会报错 python中pop()函数 用法:pop()函数用于移除列表中的一个元素(默认最后一个元素),并且返回从列表中移除的元素对象。函数语法:【list.pop(ojb=list[-1])】。 extend() 函数 功能:用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) split()函数 它主要是切割字符串,结果返回由字符串元素组成的一个列表,当没有参数的情况下,函数会默认以空格

Misc Linux命令

1、unshadow命令 基本上会结合/etc/passwd的数据和/etc/shadow的数据,创建1个含有用户名和密码详细信息的文件。 root@kali:unshadow /etc/passwd /etc/shadow > shadow 2、unique unique工具可以从一个密码字典中去除重复行,为我们使用密码字典进行爆破提供了很大的便利。 root@kali:~# unique -v -inp=allwords.txt uniques.txt Total lines read 6089 Unique lines written 5083 (如有侵权请联系删除) 

Vue中this.$refs的使用

this.$refs在vue中ref可以以属性的形式添加给标签或者组件, ref 写在标签上时:this.$refs.ipt 获取的是添加了ref="ipt"标签对应的dom元素, ref 写在组件上时:this.$refs['component'] 获取到的是添加了ref="component"属性的这个组件 <template> //给标签使用 <input type="text" ref="ipt"/> //给组件使用 <comp-detail ref="component"></comp-detail> <button @click="confirm">确定</button> </template> methods:{ confirm(){ console.log(this.$refs.ipt.value) //打印出输入框中的value值 this.$refs['component'].init() //调用组件comp-detail中的init()方法 } } $refs 是所有注册过 ref 的集合(对象);若是遍历的ref,则对应$refs是个数组集合 注意:$ refs不是响应式的,只在组件渲染完成之后才填充。所以想要获取DOM数据的更新要使用 this.$nextTick() 总结: <!-- ref 写在标签上时:this.$refs.名字 获取的是标签对应的dom元素 ref 写在组件上(调用组件)时:这时候获取到的是 子组件(比如counter)的引用-->

LDPC的比特翻转算法与和积译码算法的python实现

- LDPC码简介 LDPC码即低密度奇偶校验码(Low Density Parity Check Code,LDPC),它由Robert G.Gallager博士于1963年提出的一类具有稀疏校验矩阵的线性分组码,不仅有逼近Shannon限的良好性能,而且译码复杂度较低, 结构灵活,是近年信道编码领域的研究热点,已广泛应用于深空通信、光纤通信、卫星数字视频和音频广播等领域。 LDPC码的校验矩阵只含有很少量非零元素,因此称为“低密度”奇偶校验码。LDPC码的译码方法和经典分组码不同,由于其码长较长,所以通常通过其校验矩阵的图像表达进行迭代译码。 - LDPC码编码原理 LDPC码的编码原理是将信息位按照一定的规则与校验位进行组合,形成一个码字。LDPC码的编码过程是将信息位按照一定的规则与校验位进行组合,形成一个码字。LDPC码的校验矩阵只含有很少量非零元素,因此称为“低密度”奇偶校验码。LDPC码的译码方法和经典分组码不同,由于其码长较长,所以通常通过其校验矩阵的图像表达进行迭代译码。以下是一个LDPC编码的例子。 A = np.array([[1,1,1,0],[0,1,1,1],[1,0,1,1]]) H = np.concatenate((A,np.eye(3)),axis=1)#校验矩阵 G = np.concatenate((np.eye(4),A.T),axis=1)#生成矩阵 Kdec = np.random.randint(0, 256,size=(1024))#产生随机符号 Kbin = np.array([int(_) for _ in ''.join(vec_dec2bin(Kdec))]) KbinRe = Kbin.reshape(-1, 4) encoded = np.mod(np.matmul(KbinRe, G), 2)#经过LDPC编码后的比特 - LDPC码译码原理 LDPC码的译码原理是基于迭代译码的思想,通过迭代计算来逐步减小误码率。LDPC码的译码过程是将接收到的码字与校验矩阵进行乘积运算,得到一个校验方程组。然后,利用迭代算法对这个方程组进行求解,得到一个估计值。如果估计值与接收到的码字不同,则将估计值作为新的输入,重新进行迭代。 - LDPC码比特翻转译码原理 LDPC码的比特翻转译码原理是指,当硬解调之后的比特信息不满足校验方程组时,统计所有比特不满足校验方程的个数,并翻转不满足个数最多的比特值,用更新之后的码组再次译码,直至所有校验方程均得到满足或者达到迭代次数的上限。以下代码可以实现比特翻转的功能。 def match_cols(H, C): #在H中匹配C校验和,返回匹配到的列数,该列对应需要翻转的比特 H_tmp = np.hstack((H,np.zeros((H.shape[0],1))))*2-1 C_tmp = C*2-1 maxMat = np.matmul(C_tmp, H_tmp) flip = np.argmax(maxMat,axis=1) return flip def flip_function(flip, modulatedRe): #根据翻转位进行翻转 flip_mask = flip!

七种方法实现异步编程

1.线程Thread 直接继承Thread类是创建异步线程最简单的方式。首先,创建Thread子类,普通类或匿名内部类方式;然后创建子类实例;最后通过start0方法启动线程。 2.Future Java 从1.5版本开始,提供了Callable和Future,可以在任务执行完毕之后得到任务执行结果。 3.FutureTask FutureTask 实现了 RunnableFuture 接口,则RunnableFuture 接口继承了Runnable 接口和Future接口,所以可以将FutureTask对象作为任务提交给ThreadPoolExecutor去执行,也可以直接被Thread执行;又因为实现了 Future接口,所以也能用来获得任务的执行结果。 4.异步框架 CompletableFuture JDK1.8中,Java 提供了 CompletableFuture类,它是基于异步函数式编程。相对阻塞式等待返回结果,CompletableFuture可以通过回调的方式来处理计算结果,实现了异步非阻塞,性能更优。 5.SpringBoot 注解 @Async 6.Spring ApplicationEvent 事件 ApplicationContext 通过 ApplicationEvent类和 ApplicationListener 接口进行事件处理。如果将实现 ApplicationListener 接口的bean 注入到上下文中,则每次使用ApplicationContext 发布 ApplicationEvent时,都会通知该bean。本质上,这是标准的观察者设计模式。 7.消息队列

STM32中文手册解读(1)

STM32中文手册的阅读 初学stm32,读手册是十分重要的。由于买了野火的开发板,最近也在学习,所以记录下学习的内容。 关于寄存器的描述: 首先对于STM32芯片基础知识的了解 STM32 芯片是已经封装好的成品,主要由内核和片上外设组成。若与电脑类比,内核与外设就如同电脑上的 CPU 与主板、内存、显卡、硬盘的关系。 STM32F103 采用的是 Cortex-M3 内核,内核即 CPU,由 ARM 公司设计。ARM 公司并不生产芯片,而是出售其芯片技术授权。芯片生产厂商(SOC)如 ST、TI、Freescale,负责在内核之外设计部件并生产整个芯片,这些内核之外的部件被称为核外外设或片上外设。如 GPIO、USART(串口)、I2C、SPI 等都叫做片上外设。 芯片(这里指内核,或者叫 CPU)和外设之间通过各种总线连接,其中驱动单元有 4个,被动单元也有 4 个,为了方便理解,我们都可以把驱动单元理解成是CPU 部分,被动单元都理解成外设。 1. ICode 总线 ICode 中的 I 表示 Instruction,即指令。我们写好的程序编译之后都是一条条指令,存放在 FLASH 中,内核要读取这些指令来执行程序就必须通过 ICode 总线,它几乎每时每刻都需要被使用,它是专门用来取指的。 2. 驱动单元 DCode 总线 DCode 中的 D 表示 Data,即数据,那说明这条总线是用来取数的。我们在写程序的时候,数据有常量和变量两种,常量就是固定不变的,用 C 语言中的 const 关键字修饰,是放到内部的 FLASH 当中的,变量是可变的,不管是全局变量还是局部变量都放在内部的SRAM。因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。 系统总线 系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通过这根系统总线来完成的。 DMA 总线 DMA 总线也主要是用来传输数据,这个数据可以是在某个外设的数据寄存器,可以在SRAM,可以在内部的 FLASH。因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。 3. 被动单元

Linux配置NTP时间同步

1. NTP NTP是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。 2. NTP服务端配置 2.1. 检查系统是否安装了NTP包 linux系统一般自带NTP4.2,没有安装我们直接使用yum命令在线安装 sudo apt install ntp 2.2. NTP服务端配置文件编辑 vim /etc/ntp.conf 结果 2.2.1. 新增-权限配置 restrict 127.127.1.0restrict 192.168.31.0 mask 255.255.255.0 nomodify notrap 2.2.2. 改动-注释掉上级时间服务器地址 #server 0.centos.pool.ntp.org iburst#server 1.centos.pool.ntp.org iburst#server 2.centos.pool.ntp.org iburst#server 3.centos.pool.ntp.org iburst 2.2.3. 新增-上级时间服务器 server 127.127.1.0 # local clockfudge 127.127.1.0 stratum 10 2.3. 启动NTP时间服务器 service ntpd start 2.4. 设置NTP开机自动启动 chkconfig ntpd on 2.5. 查看NTP是否正常运行 netstat -tlunp | grep ntp 2.6. 配置防火墙过滤规则 /sbin/iptables -I INPUT -p udp --dport 123 -j ACCEPT 2.

【Java字符串】

Java字符串 字符串是由数字、字母、下划线组成的一串字符。字符串是用于表示文本的数据类型,属于引用数据类型,在内存中的存储方式和数组类似,其中的每个字符都能够读取。 文章目录 Java字符串创建字符串字符串的操作字符串拼接字符串的长度字符串大小写转换字符串消除空格字符串截取字符串分割字符串替换字符串比较字符串查找 创建字符串 字符串是Java中较为特殊的类,由Java类库中提供一个String类用于创建和操作字符串,被广泛应用于Java编程中。在Java中定义一个字符串最直接的方法就是使用双引号将字符括起来,或者使用new关键字新建一个字符串对象。 常见构造字符串的方法 方法一:使用双引号(“”) String str = "Hello Java"; 使用双引号引起来的字符本身就是一个字符串对象,所以可以将其赋值给String字符串类型的变量。 方法二:使用new关键字创建一个字符串对象 String str = new String("Hello Java"); Java中的String类有11种构造方法可以构造字符串,根据传入的参数不同调用不同的构造方法去构造字符串,如传入字符数组作为参数。 方法三:传入字符数组作为参数创建对象 char[] ch = {'H','e','l','l','o',' ','J','a','v','a'}; String s = new String(ch); System.out.println(s); //执行结果 Hello Java 在Java底层中存储字符串的方式也是类似于存储字符数组的方法,所以其中的每个元素才能单独访问。 注意事项: 在java中,String类是不可变的,对String类的任何改变,都是返回一个新的String类对象。如"Hello Java"这样用双引号引起来的字面值常量,也是String类型的字符串对象。String是引用数据类型,所以其内存布局如下图所示。 【内部布局图片】 字符串的操作 Java中的String类提供了许多方便操作字符串的方法。 方法名说明char charAt(int index)返回指定索引位置的字符String concat(String str)拼接指定字符串到一个字符串的尾部boolean equals(Object anObject)将字符串与指定对象作比较boolean equalsIgnoreCase(String anotherString)将两个字符串作比较,不考虑大小写int indexOf(char ch / String str)查找指定字符/字符串在字符串中第一次出现的位置,并返回对应的索引值int indexOf(char ch / String str, int fromIndex)从指定索引开始查找字符/字符串第一次出现的位置,并返回对应的索引值int length()返回字符串的长度String replace(char oldChar, char newChar)将字符串中的所有oldChar字符替换成newChar字符,并返回替换后新字符串String replaceFirst(String regex, String replacement)使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串String replaceAll(String regex, String replacement)使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。String[] split(String regex)根据给定正则表达式的匹配拆分此字符串为字符串数组,不限制个数。String[] split(String regex, int limit)根据给定正则表达式的匹配拆分此字符串为字符串数组,限制字符串数组元素个数为limit个String subString(int beginIndex)从begineIndex索引开始截取字符串String subString(int beginIndex, int endIndex)从begineIndex索引开始截取字符串到endIndex索引为止char[] toCharArray()将字符串转换为字符数组String toLowerCase()将字符串中的字符全部转换为小写String toUpperCase()将字符串中的字符全部转换为大写String trim()去除字符串首尾的空格boolean isEmpty()判断字符串是否为空 字符串拼接 "

【Java基础语法】

Java基础语法 Java标识符 概念:标识符是用于给类、对象、方法、变量、接口以及自定义的数据类型命名的。在Java中,变量、常量、方法、接口等都有自己的名字,将这些名字统称为标识符 Java中的标识符由数字、字母和下划线(__),美元符( ) 或者人民币符号 ( ¥ ) 组成的, ∗ ∗ 而且还要求不能以数字或者除美元符 ( )或者人民币符号(¥)组成的,**而且还要求不能以数字或者除美元符( )或者人民币符号(¥)组成的,∗∗而且还要求不能以数字或者除美元符()、人民币符号(¥)的特殊字符开头**,最为重要的就是,不能使用Java中的关键字作为标识符 而既然要命名,那需要注意的就是命名的规则: 大小写敏感:Java是对大小写敏感的,这意味着"Hello"和"hello"是不同的类和接口名:对于类和接口,使用的是大驼峰的命名规则,即每个字的首字母大写,含有大小写。例如,MyClass,HelloWorld,Person等。方法名:对于方法,使用的是小驼峰的命名规则,即首字符小写,其余的首字母大写,含大小写。例如,myName,helloWorld等。常量名:基本数据类型的常量名使用全部大写字母,字与字之间使用下划线分隔。例如,MY_NAME,PORT等。变量名:变量名推荐的也是使用小驼峰命名,但并不是硬性要求,而最好可以做到见名知义,名字尽量有些含义。 Java关键字 Java关键字是Java语言中事先定义好的,对Java编译器具有特殊意义的标识符,可以使用这些关键字来告诉编译器这是一个类、一个方法或一个数据类型等,所以不能使用关键字作为标识符。 Java中定义了如下关键字: 类型关键字说明基本数据类型byte字节型char字符型short短整型int整型long长整型float单精度浮点型double双精度浮点型boolean布尔型权限修饰符public公共的protected受保护的default默认的private私有的类、方法和变量修饰符abstract声明抽象class定义类extends继承final不可改变的implements实现接口interface定义接口native本地方法(非Java实现)new创建static静态strictfp严格、精确synchronized线程,同步transient声明不用序列化的成员域volatile表明两个或者多个变量必须同步地发生变化void声明当前成员方法没有返回值程序控制break提前跳出一个代码块continue回到一个代码块的开始if表示条件语句结构else用在条件语句中,表明当条件不成立时的分支switch表示分支语句结构case用在switch语句之中,表示其中的一个分支do用在do-while循环结构中while表示循环语句结构for表示循环语句结构return返回instanceof用于检测一个对象是否为指定类型的实例对象异常处理try尝试一个可能抛出异常的程序块catch捕捉一个程序块可能抛出的异常finally无论是否捕捉到异常都会执行的代码块thorw抛出一个异常对象throws声明一个异常可能被抛出assert断言,主要用于调试引用super表明当前对象的父类型的引用或者父类型的构造方法this当前实例对象的引用保留字goto是Java中不起作用的关键字,一样不能作为标识符使用const 以上就是Java中的关键字,也就是具有特殊意义的标识符,他们用来表示一种数据类型,或者表示程序的结构等,null也属于保留字,和关键字一样,也不可以作为标识符使用。 Java注释 在编写Java程序期间,通常都需要对程序进行一定的注释,在方便别人阅读,让别人更好理解所编写的程序的同时,也方便自己阅读。 Java中的注释主要分为以下三种: 单行注释:// 注释内容(用的最多)多行注释:/* 注释内容*/(不推荐) 文档注释: /** 文档注释 */(常见于方法和类之上描述方法和类的作用),可用来自动生成文档 下面是演示: public class Test { /** * 这是一个文档注释 * @param args */ public static void main(String[] args) { // 这时单行注释演示 /* 这也是单行注释演示 */ /* * 这是一个多行注释 * 同时注释若干行 */ System.out.println("hello world"); } } 注释的作用是为了提高代码的可读性,使得Java程序逻辑条理清晰,使用注释修饰的字符会被编译器忽略。

Python变量命名5大规则!

Python变量名不是随便乱起,需要遵循以下规则: 1、只能字母、下划线开头,不能数字开头。变量用小写字母开头是 Python 的惯例,也是编码的好习惯,大家要养成好习惯哟。 大家可以动手试试上面4个变量名哪个是正确的,尝试打开编辑器定义变量输出,看看有什么提示。 实际上面4个变量名,只有第一个变量名是正确的,后面3个都是错误的。如果运行,将会有如下类似的错误提示: 2、变量名不能有空格,可以用下划线; 3、Python内置的关键字和函数不能用,比如说if、for、while、print、input等等; 4、变量名称对大小写敏感,比如:myname和myName不是同一个变量; 5、小写字母l和大写字母O尽量不要用于变量名,容易看成数字1和0 。 以上5条Python变量命名规则,请牢记! 最后,小编送给各位一句代码,试试打印输出效果是什么。 print("Hello World !\n"*500) 对于初学者想更轻松的学好Python开发,爬虫技术,Python数据分析,人工智能等技术,这里也给你准备了一套系统学习资源。 文中所展示的资料全部都是免费分享,点击下方链接添加微信即可免费获取! 戳这里 👉 【读者福利】Python经典学习资料免费分享,领走不谢! 👈 👉 1.确定好自己的学习路线 👈 无论做什么事,或者学什么技能,在一开始就要有所规划,所以我们要事先确定好自己的学习路线,这是非常重要的,能够在我们学习的时候使得我们的思路更为清晰。 👉 2.Python必备开发工具 👈 工欲善其事必先利其器,既然我们要学习Python,那么想与之的开发工具必须要先行安装好,利用好工具能让我们事半功倍。 👉 3、Python学习视频合集 👈 观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。 👉 4.实战案例 👈 光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。 👉 5.一百道Python练习题 👈 学而不练则罔,练而不学则殆,检查学习结果,是优秀人员必备的。 👉 资料领取 👈 文中所展示的资料全部都是免费分享,点击下方链接添加微信即可免费获取! 戳这里 👉 【读者福利】Python经典学习资料免费分享,领走不谢! 👈

git bash反应慢解决办法

方法来源于其他网友,感谢其他网友的尝试和分享。 方法众多,我试了一个比较有效的方法就是不使用git bash,而是使用没有爆露的bash.exe文件。 我们在windows下面一般用git bash的方法就是,在所在文件夹右键,选择git bash here,这样打开的就是一个类linux的命令行窗口,这种窗口,输入命令后反应速度就慢。要想快,就不要用这种方式输入git 命令,而是用安装目录下面bin/bash.exe文件。 可以给这个文件创建一个快捷方式,然后可以指定打开的快捷键和默认打开的路径。 这样以后使用git时,就双击这个快捷方式就可以打开bash.exe。 你会发现,使用bash.exe,那是真的快,纵享丝滑。

数据结构与算法入门(follow 左神)

文章目录 一. 认识时间复杂度和简单排序算法1.以选择排序为例2.异或运算3.插入排序4.二分查找5.对数器 二. 认识O(NlogN)的排序1.递归==栈的后序遍历2.归并排序3.快速排序 三.详解桶排序以及排序内容大总结1.堆结构(优先级队列)2.比较器3.桶排序4.排序总结 四.链表1.哈希表和有序表2.链表 五.二叉树1.哈希表和有序表2.BFS宽度优先遍历(层次遍历)3.套路题(可树型DP) 六.图1.定义好通用的图所需结构2.BFS和DFS + 拓扑排序3.kruskal算法(边)和Prim算法(点)【无向图】4.Dijkstra:单元最短路径 七.详解前缀树和贪心算法1.前缀树2.贪心算法3.字典序证明4.其他题目 八.暴力递归1.N皇后2.暴力递归冲冲冲 Ending 本文是跟着左程云老师在b站发布的视频教程所记录的算法入门笔记,左神算法班 总共分为八节,一些相关代码和重点思路分析 大多已在下文呈现 一. 认识时间复杂度和简单排序算法 1.以选择排序为例 第一遍的时候,查询了n次,比较了n次,交换了1次;第二遍,查询n-1次,比较了n-1次,交换1次;。。。所以时间复杂度是O(n) ^2 算法分析先看时间复杂度指标,再分析不同数据样本下的实际运行时间,也就是"常数项时间" 额外空间复杂度指的是除去存放必要数据外,所需的空间。 2.异或运算 不同为1,相同为0;同时可以理解成无进位相加 1)0^N=N; N^N=0 2)交换律:a^b = b^a;结合律 (a^b) ^c= a^(b ^c) 第一题:已知一个数组中,只有一种数出现了奇数次,其余都是出现偶数次,请问怎么找到这种数 第二题:如果两种数出现了奇数次呢,怎么找到? 要求O(N)时间,O(1)空间。 第一题int eor=0和数组中全部异或得到的数就是结果,因为偶数次的结果都没了;相当于消消乐 第二题先按照第一题得到int eor=a^b; 由于a!=b,所以eor!=0 ==> eor在32位比特位中至少有1位是1,假设是第8位,那么a和b的第八位一定一个是1,一个是0,不然得不到1这个异或结果 ==> int eor2去异或数组中所有第8位不是1/不是0的数,最后结果一定是a or b;相当于将整个数组根据第8位是否是1分成两部分,这两部分分别包含a和b以及其他偶数次的数字 ==> 最后再将eor^eor2得到另一个数 int rightOne = eor & (~eor + 1); //提取最右侧的1 eor和eor的补码进行 同1得1,有0则0 的与运算 int onlyOne = 0; for (int cur : arr) { if ((cur & rightOne) !

javaSE-值传递和引用传递

1、值传递和引用传递 当参数类型是基本数据类型时,传递的是实参的值,因此无法对实参进行修改。 当参数类型是非基本数据类型时,传递的是实参内存地址的拷贝,此时形参和实参都可以对此对象的字段进行修改,但是互相无法影响对方本身。 class Person { String name; int money; } class Client { public static void main(String[] args) { // Create a person named Bob and he has no money. Person person = new Person(); person.name = "Bob"; person.money = 0; // Check the person, if he has no money, set it as null check(person); // If the person turned to null, print he has no money, otherwise print he's rich if (person == null) { System.