numpy中对ndarray的拼接 numpy.concatenate
将多个矩阵沿着一个已经存在的维度进行拼接
需求:两个张量的维度的数量需要相同,同时除了拼接的维度,其它维度的形状需要相同。
np.concatenate((,),axis=) ''' 第一个参数为要拼接的矩阵组成的元组 第二个参数为要拼接的维度 ''' a = np.arange(3*3).reshape((3,3)) b = np.arange(3*4).reshape((3,4)) a,b (array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]), array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])) np.concatenate([a,b],axis=1) array([[ 0, 1, 2, 0, 1, 2, 3], [ 3, 4, 5, 4, 5, 6, 7], [ 6, 7, 8, 8, 9, 10, 11]]) numpy.stack
将具有相同维度和形状的矩阵,在一个新的维度上进行堆叠
需求:矩阵具有完全相同的尺寸
np.stack((,), axis=) ''' 参数和上面的函数相同 ''' x1 = np.
一些简单的过程就不详细写了,就写一些可能会遇到的问题。
我使用的是Setup Factory 9.0.3.0 汉化版,资源地址:
https://download.csdn.net/download/woaishapi/7789171
这个是我参考的打包教程:
https://dominick-li.blog.csdn.net/article/details/83149751(不是Java应用打包也可以用的,这里面的1、2、4、6可以参考,3和5我在下面用了别的方法,7写错了我下面会写正确的)
http://t.zoukankan.com/lidabo-p-9809757.html(里面有打包过程、设置安装序列号、“到期”属性等)
1.卸载程序 自带的卸载程序uninstall.exe双击会报错,所以自己写一个卸载程序。
在Setup Factory软件左侧列表中点击【操作】-【关于安装之后】,在【On Post Install】里写入以下代码:
Shell.CreateShortcut(SessionVar.Expand("%AppFolder%"), SessionVar.Expand("卸载%ProductName%"), SessionVar.Expand("%AppFolder%\\uninstall.exe"), SessionVar.Expand("%AppFolder%\\uninstall.exe \"/U:%AppFolder%\\Uninstall\\uninstall.xml\""), SessionVar.Expand("%AppFolder%"), SessionVar.Expand("%AppFolder%\\uninstall.exe"), 0, SW_SHOWNORMAL, nil, ""); 然后点击【卸载】-【操作】,在【On Post Uninstall】里写入以下代码:
resultF = Folder.DoesExist(SessionVar.Expand("%AppFolder%")); if (resultF) then Folder.DeleteTree(SessionVar.Expand("%AppFolder%"),nil); end 安装发布包后,生成的文件夹中的uninstall.exe还是不起作用的,起作用的是我们上面写的卸载项目名.exe。
2.开机自启动 以下两个方法都自测可用:
1)写入注册表的方式
点击【操作】-【关于安装之后】,在【On Post Install】里写入以下代码:
isExist = Registry.DoesKeyExist(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\windows\\CurrentVersion\\Run"); -- An if ... else statement that compares two numbers if (isExist) then -- Do something here Registry.SetValue(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\windows\\CurrentVersion\\Run","Message", SessionVar.Expand("%AppFolder%\\%ProductName%.exe"),REG_SZ); else -- Do something else here Registry.
大家好,欢迎来到专栏《百战GAN》,在这个专栏里,我们会进行GAN相关项目的核心思想讲解,代码的详解,模型的训练和测试等内容。
作者&编辑 | 言有三
本文资源与生成结果展示
本文篇幅:7000字
背景要求:会使用Python和Pytorch
附带资料:参考论文和项目,视频讲解
1 项目背景
作为一门新兴的技术,GAN在很多人脸图像任务中有着广泛的应用,下面列举了一些典型的方向。
比如使用SRGAN进行人脸超分辨,使用BeautyGAN进行人脸美颜,使用Deepfake进行换脸。如今,基于人脸属性编辑的技术在抖音快手等应用中都是非常受欢迎的技术,比如可以体验让人变老变小,如下图年龄的更改。
年龄编辑
这背后的核心技术之一就是在生成模型的Latent空间进行属性向量的编辑,然后通过生成模型来获取最终结果图,其中最典型的代表性框架就是StyleGAN,本次我们来实战使用StyleGAN进行人脸属性编辑。
在阅读接下来的内容之前,请大家务必回顾之前StyleGAN人脸生成的内容,没有这一部分内容基础,无法学习接下来的内容。
【百战GAN】StyleGAN原理详解与人脸图像生成代码实战
【项目实战课】基于Pytorch的StyleGAN v1人脸图像生成实战
2 原理简介
现在我们要使用StyleGAN进行真实人脸的编辑,需要解决2个关键问题。
(1) 如何获得真实人脸的潜在编码向量,它对应StyleGAN中的映射网络(mapping network)的输入Z或者输出W。
(2) 如何通过修改Z或者W向量,控制生成人脸图像的高层语义属性。
接下来我们重点介绍潜在编码向量的求解,并在下一节中实验基于潜在编码向量的属性编辑。
当前对真实人脸编码向量的求取基本上基于两种思路,一种是学习一个编码器来实现映射,一种是直接对向量进行优化求解。
2.1 基于编码器的求解
基于编码器的求解框架如下图所示,由两部分模块组成。
Encoder表示需要训练的编码器,Decoder表示已经训练完的生成模型,如StyleGAN的生成器部分。真实图像输入编码器得到Z或者W,再输入生成器得到生成的人脸,完成人脸图像的重建。
通过直接学习一个编码器,可以不需要对每一张图都进行优化,实现一次训练,对任意图像都能提取潜在编码向量,但是也容易在训练数据集上发生过拟合。
2.2 基于优化求解的方法
另外一种方法就是基于优化求解,直接对每一张图片优化出对应的W,在StyleGAN v2,Image2StyleGAN等框架中采用了这种方案,并且512维的W被拓展成W+, W+为18×512维的矩阵,这样就可以对每一个自适应实例归一化(AdaIN)风格模块都使用不同W,实现更自由的属性编辑。
基于优化求解的方法包括以下几步:
(1) 给定图片I,以及预训练好的生成器G。
(2) 初始化潜在编码向量,如W,其初始值可以使用计算得到的统计平均值。
(3) 根据优化目标进行反复迭代,直到达到预设的终止条件。
优化目标的常见形式为:
其中Lpercept为特征空间中的感知损失距离,是很通用的问题,具体形式不再赘述。lamda用于平衡感知损失和MSE损失之间的权重比。可以使用梯度下降算法进行求解。
基于优化求解方法的优点是精度较高,但是优化速度慢,而且对每一个图片都必须进行优化迭代。
在求解得到了潜在编码向量后,我们就可以通过编辑向量来编辑人脸的高层语义属性,对于StyleGAN架构来说,潜在编码向量可以是Z也可以是W,一般基于W进行编码会有更好的效果。
3 人脸属性编辑实战
接下来我们实践基于StyleGAN模型的人脸属性编辑。
3.1 人脸重建
要使用StyleGAN来进行人脸编辑,首先我们需要将人脸投射到潜在编码向量空间,下面我们采用的方法是基于优化的方法,即对每一张人脸图片,单独优化求解出潜在编码向量,基本思想前面已经介绍过。
接下来我们来看人脸重建的求解,核心代码如下:
if __name__ == "__main__":
## 预训练模型权重
parser.add_argument(
"--ckpt", type=str, required=True, help="path to the model checkpoint"
目录
容器技术产生的背景
虚拟化
虚拟化概述
总结(虚拟化的作用):
cpu的时间分片(cpu虚拟化)
CPU虚拟化瓶颈
虚拟化工作原理
虚拟化类型
虚拟化的优缺点
优势
劣势
Docker
什么是docker
使用docker的意义
docker的使用场景
docker引擎(Docker Engine)
docker三要素
六大名称空间
资源控制——cgroups
容器特性
容器小的架构体系
Docker和虚拟化的区别
问:dovker 和VM 解决了虚拟机的什么问题?
Docker有哪些优势?和虚拟化比有什么优势?
总结
什么是docker?docker原理?
简述Docker主要使用的技术?
简述Docker体系架构
如何把多个目录挂载到同一个目录下?
前言:
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
容器技术产生的背景 以linux而言,linux操作系统会有一个主进程pid=1派生出其他进程来控制不同服务例如: pid=2 ——> python pid=3——>java pid4——>php,三个服务可能会相互影响使用者期望将这三个不同的服务,跑在不同的运行时环境中实现相互不影响,同时不会增加服务器成本——> 延伸出——>能否将这三种服务分别封装起来——>KVM虚拟化技术,实现了一个操作系统模拟多个操作系统/不同的运行时环境随着技术发展——>虚拟化技术开销较大(例如:只 要运行一个py脚本,想要使用虚拟化方式实现,还需要安装一个操作系统,并不方便/合理)——>延伸出容器技术 虚拟化层的抽象层(用户层)剥离,使用docker engine来替代(来宾操作系统去除),只要通过引擎就可以直接连接到宿主机操作系统中,极大减小了开销
docker引擎对内核版本是有要求的(至少是3.8+)
docker 需要cgroups(Linux内核态中资源管理的模块) 的资源管理功能
虚拟化 虚拟化概述 通过虚拟化技术将一台计算机虚拟为多台逻辑计算机,在一台计算机上同时运行多个逻辑计算机,同时每个逻辑计算机可运行不同的操作系统。应用程序都可以在相互独立的空间内运行而互相不影响,从而提高计算机的工作效率。
在一个操作系统中(win10)模拟多个操作系统(centos、win10、suse),同时每个操作系统可以跑不同的服务(ngintx/tomcat),从而实现一台宿主机搭建一个集群(从整体)通过软件/应用程序的方式,来实现物理硬件的功能(ensp) 以软件形式实现物理设备的功能(二层交换机、路由器、三层交换机等)
总结(虚拟化的作用): 虚拟化将应用程序和系统内核资源进行解耦,以操作系统级别进行隔离,目的是提高资源利用率
cpu的时间分片(cpu虚拟化) 正常每个任务以轮询的方式去处理,这个时候一个CPU一个整体。以下是针对的CPU单位时间内的一个资源。按时间划分,1秒划分成10个0.1秒,每个0.1秒可以全力处理10单位的任务。在1秒内,都在全力工作。cpu 1s全力运转的性能——》逻辑分割成分成了10份,可以理解为在单位时间内可以处理10个任务,每一个0.1s cpu是满的。原先分片前100M以下的任务一次只可以处理1个,现在100M的任务一次可以处理10个。这就是时间分片的一个概念。虚拟化作用——》缓解/解决了资源利用率的问题(总结) CPU虚拟化瓶颈 cpu分片后每个任务处理性能会打对折
如果是50m及50m以下的任务的话,虚拟化后的,1s模拟10个cpu,可以处理10个。虚拟化后的性能更高。如果是50+m的任务的话,物理硬件的性能就会比虚拟化的性能高了。虚拟化的cpu会卡顿。所以在极度吃资源的情况下,例如mysql高并发这种,就不适合用虚拟化。 虚拟化工作原理 虚拟机管理器功能:调用资源
两大核心组件:QEMU、KVM
ansible实现管理的方式: 管理方式 含义 Ad-Hoc 利用ansible命令直接完成管理,主要用于临时命令使用场景 playbook ansible脚本,主要用于大型项目场景,需要前期的规划 Ad-Hoc:
playbook:
ad-hoc执行方式中获得帮助: ansible-doc 显示模块帮助的指令 -l 列出可用模块 -s 显示指定模块的playbook片段 ansible命令运行方式及常用参数: ansible +清单 +-m+模块+-a+模块参数 --version 显示版本 -m moudle指定模块,默认为command模块 -v 详细过程,-vv,-vvv更详细过程 --list 显示主机列表,也可用--list-hosts -k 提示输入ssh连接密码,默认key认证 -C 预执行检测 -T 执行命令的超时时间,默认10s -u 指定远程执行的用户 -b 执行sudo切换身份操作 -become-user=USERNAME 指定sudo的用户 -K 提示输入sudo密码 ansible-doc -l列出可用模块:
ansible-doc -s列出指定模块的常用参数:
语法格式:
ansible 清单 -m 模块 -a 模块参数
查看版本号:
-v显示命令行运行的详细过程:
-vv显示命令行运行的更详细过程:
-vvv显示命令行运行的更更更详细过程。
v越多,显示命令行运行的过程越详细。
-m表示指定模块,-k参数表示指定输入ssh连接时输入的密码:
-C 表示预执行检测,只检测命令运行的正确与否,但不会执行只做检测:
-b表示指定sudo切换用户身份操作,–become-user=USERNAME表示指定用户:
-u表示指定远程执行的用户:
ansible的基本颜色代表: 绿色 执行成功但对远程主机未作任何改变 黄色 执行成功并对远程主机做改变 红色 执行失败 ansible中的常用模块: 1.
➤ 人脸识别功能有哪些?
现在主流的人脸识别厂家基本上都能提供成熟的人脸识别服务,通常会包括人脸检测、活体检测、人脸比对、人脸搜索、人脸聚类、人脸关键特征点定位、人脸属性分析、人像色情鉴定等功能,除此之外还可以提供各种证件识别、通用图像识别等功能,接下来企业服务汇就来为你详细说明各种人脸识别功能。
1.人脸检测
人脸检测是在对应的图片或视频中检测并定位出人脸图像的人脸位置,也可以通过该项功能来区分哪些图片和视频中包含人脸图像,哪些不包含人脸图像。一般在使用相机或手机软件进行拍照、在公共场所统计人流量等情况时可以使用该项人脸检测功能。
2.活体检测
活体检测是利用人脸识别功能检测出在摄像头面前出现的人脸图像是否是真实的人脸,而非是人为的使用人脸照片或者是人脸动态视频。在手机软件注册登录、网上购物付款、ATM机人脸识别取款需要进行真人身份验证时可以使用该活体检测功能。
3.人脸比对
人脸比对主要是检测在两种人脸图像中出现的人脸的相似程度大小并据此判断二者是否是同一个人。该项人脸比对功能在需要核实证件照与本人是否是同一个人的可以使用。
4.人脸搜索
人脸搜索又称为人脸查找,它是在一个含有大量人脸图像的数据库中通过搜索查找出是否有与当前人脸图像相同或者是高度相似的人脸图像。通常在公司的门禁与考勤、大型公共场所安全监控等方面应用较多。
5.人脸聚类
人脸聚类是指通过识别人脸图像提取出含有相同或者相似的人脸图像并进行分类管理,这项人脸聚类功能在手机或者电脑中的相册分类管理中应用比较普遍。
6.人脸关键点定位
人脸关键点定位也可叫做人脸特征点定位,不论是静态还是动态的人脸图像都可以显示包含人脸轮廓、眼睛、眉毛、鼻子、下巴等在内的关键部位的位置信息,企业可利用人脸关键特征点的识别功能开发出人像的美颜特效功能并将其应用在类似直播软件之中。
7.人脸属性分析
人脸属性分析是指通过识别一张人脸图像就可以实时分析出人的属性特点,最常见的例如年龄、性别、头部姿态、脸部表情、情绪、颜值、皮肤、肤色、照片本身的质量与模糊程度等等,之前火爆一时的通过上传个人照片“猜年龄”的营销活动就是一个应用该项人脸属性分析的典型案例。
8.人脸色情鉴定
人脸色情鉴定是在静态或者动态的人脸图像中识别出是否出现了违规的色情人脸图像,在现在的一些视频或者照片分享网站、直播网站中可以使用该项人脸色情鉴定功能来加强平台对于用户的有效管理。
现在的人脸识别系统供应商也提供各种证件识别和通用图像识别功能,所谓证件识别就是识别出一张包含人脸图像的证件(例如身份证、社保证等)上的全部信息,通用图像识别就是在所有的照片中识别出含有某种物体(例如玫瑰花、猫等)的照片。
全栈工程师开发手册 (作者:栾鹏)
一站式云原生机器学习平台
volcano的基本原理和架构 Volcano是一个基于Kubernetes的云原生批量计算平台,也是CNCF的首个批量计算项目。
volcano是华为开源出的分布式训练架构,github官方网址:https://github.com/volcano-sh/volcano
volcano 多机分布式 有时候单台机器多进程也无法快速完成代码运行,这个时候就需要多机器实现:
1、单机器算力有限,核数不足
2、有些运行有机器白名单显示,需要多台机器ip增加并发处理
volcano主要为我们提供index job, 也就是启动多个pod,并为每个pod提供index,role,以及其他role的访问地址。这样我们就可以用这些信息来做事情。
分布式计算集群 为了方便的实现一个volcano多机分布式集群,这里直接使用
https://github.com/tencentmusic/cube-studio 开源的云原生一站式机器学习平台。
使用volcano这个模板,填上自己的worker数量,每个worker的镜像和启动命令就可以了
分布式原理和代码 基本原则 部署分布式volcano集群 平台已经我们实现了,我们只需要编写分布式的代码。 要想针对实现并发操作
1、通过环境变量VC_WORKER_NUM 有多少个worker
2、通过环境变量VC_TASK_INDEX实现当前pod是第几个worker
3、每个worker里面都判别一遍总共需要处理的数据,和当前worker需要处理的数据。
4、代码根据当前是第几个worker处理自己该做的工作。
用户代码示例 保留单机的代码,添加识别集群信息的代码(多少个worker,当前worker是第几个),添加分工(只处理归属于当前worker的任务),
import time, datetime, json, requests, io, os from multiprocessing import Pool from functools import partial import os, random, sys WORLD_SIZE = int(os.getenv('VC_WORKER_NUM', '1')) # 总worker的数目 RANK = int(os.getenv("VC_TASK_INDEX", '0')) # 当前是第几个worker 从0开始 print(WORLD_SIZE, RANK) # 子进程要执行的代码 def task(key): print(datetime.
vscode 安装code runner插件,然后就可以拥有右上角三角图标,点击就能运行程序了。
文章目录 基于C语言的ATM自动取款机系统项目设计与开发一、ATM自动取款机系统功能分析与介绍二、开发ATM自动取款机系统的工具以及创建项目的过程2.1、本项目使用Visual Studio 2019作为开发工具。2.2、项目创建的过程 ATM自动取款机系统的设计与开发的步骤一、设计登入页面的显示功能二、设计登入页面退出功能三、设计登入页面登入和系统主页面显示的功能3.1登入用户账号功能3.2登入用户密码功能3.3主页面显示功能 四、设计主页面修改用户密码的功能五、设计主页面查询用户余额的功能六、设计主页面用户取款的功能七、设计主页面用户存款的功能八、返回登入页面的功能 总结 基于C语言的ATM自动取款机系统项目设计与开发 一、ATM自动取款机系统功能分析与介绍 ATM自动取款机系统是银行业务流程中十分重要且必备的环节之一,在银行业务流程中起着承上启下的作用,其重要性不言而喻。但是,目前许多银行在具体的一此业务流程处理过程中仍然使用手工操作的方式来实施,不仅费时、费力,效率低下,而且无法达到理想的效果。
本应用主要模拟ATM设备的常用功能,如登录系统、身份验证、余额查询、取款、存款和修改密码等功能。
在设计的过程中也以此为依据,每一 种具体功能使用一 个或几个函数来实现。
该系统的主要功能如下几个要点所示:
1、显示登入页面功能:系统运行可以显示ATM自动取款机系统的登入页面,功能包括了登入和退出的两个功能。
2、登入页面的用户登入功能:用户可以用账号,根据相关的提示登入ATM自动取款机系统。
3、修改密码功能:用户可以更改自己登入ATM自动取款机系统账号的密码功能。
4、查询余额功能:用户可以查询自己账号的余额。
5、取款功能:用户可以将自己账号里面存放的钱取出来。
6、存款功能 :用户可以将自己的现金存入到自己的账号中
7、返回登入页面功能:用户可以返回登入页面,进而可以选择登入自己或其他的账号,或者选择退出ATM自动取款机系统。
二、开发ATM自动取款机系统的工具以及创建项目的过程 2.1、本项目使用Visual Studio 2019作为开发工具。 2.2、项目创建的过程 打开VS2019,选择语言为C++,所属平台为Windows,项目类型为控制台项目,并选择空项目,如下图所示
然后输入项目的名称和选择项目的路径如下图所示
创建好项目后,向项目中添加ATM.h头文件和ATM.c源文件如下所示
然后编写相关的代码如下
ATM.h头文件代码
#pragma once #include <stdio.h> // 包含相应的头文件 #include <stdlib.h> ATM.c源文件代码
#define _CRT_SECURE_NO_WARNINGS #include "ATM.h" int main() { system("color 3E"); system("pause"); return 0; } 现在ATM自动取款机系统项目就创建好了。
ATM自动取款机系统的设计与开发的步骤 一、设计登入页面的显示功能 在ATM.h头文件中定义一个账号的登入密码和账号登入之后的初始余额大小,如下所示
long int CODE = 123456; // 登入密码 long int balance = 10000; // 存款的数目 然后在ATM.
文件系统 文件类型文件操作文件系统如何存储数据inodeblock(块)superblock 一个进程已经被挂载,可执行文件可以删除吗? 文件类型 操作系统的基本文件类型有普通文件、目录文件、设备文件和链接文件。
普通文件:最常见的文件。目录文件:目录文件中保存着该目录下其他文件的inode号和文件名等信息,目录文件中的每个目录项都是指向某个文件inode号的链接,删除文件名就等于删除与之对应的链接。设备文件:操作系统把各种设备也抽象成文件,便于管理,如鼠标,键盘等。链接文件:多个文件名指向同一索引节点(inode index)是存在的,这时就会出现链接文件。 文件操作 文件操作分为以下几种:创建文件,删除文件,读文件,写文件等。
创建文件:在创建一个新文件时,系统首先要为新文件分配必要的外存空间,并在文件系统的目录中,为之建立一个目录项,目录项中应该记录新文件的文件名及其在外存的地址等属性。删除文件:当已不再需要某文件时,可将其从文件系统中删除,在删除时,系统应先从目录中找到要删除文件的目录项,使之成为空项,然后回收该文件所占用的存储空间。读文件:读文件时,须在相应系统调用中给出文件名和应读入的内存目标地址。此时,系统要查找目录,找到指定目录项,从中得到被读文件在外存中的位置。在目录项中,还有一个指针用于对文件进行读/写。写文件:写文件时,须在相应系统调用中给出文件名和其在内存源地址。此时,系统要查找目录,找到指定目录项,从再利用目录中的写指针进行写操作。 文件系统对文件进行操作的过程:
先进入目录,目录中有相应的目录项。目录项中有对应的文件名和inode号,根据文件名找到对应的inode号。再根据inode号读取到文件的inode,分析是否符合inode中记录的权限。如果符合权限,则可以读取到相应的data blocks。 文件系统如何存储数据 文件包括属性和内容两部分(当然,还包括文件名,不过文件名实质是其所属目录文件的内容,目录文件也有inode号)。其中属性信息放置于inode区(即元数据区)中,实际内容放置于data block区中,另外,还有一个superblock(超级块)会记录整个文件系统的整体信息。
inode inode存放文件的属性信息(如文件类型、大小、权限等)和文件内容所在的block编号。inode是文件惟一标识,系统根据文件名先找到inode,并首先分析是否符合inode中记录的权限,符合后根据block编号找到数据块读取内容。
block(块) block存放文件实际内容。每个block大小有1K,2K及4K三种,其大小也是在磁盘(或分区)格式化时就确定了。每个block内只能存放一个文件的内容。若文件内容大小大于单个block,则该文件会占用多个block;若占不满一个block,这个block中的剩余空间也将浪费。因此block大小的选取也很重要,若经常存储小文件,而block较大无疑会浪费很多空间;但block较小的话,大型文件会占用较多的block数,这样inode中也会记录更多的block编号,由此会降低系统读写性能。所以block大小的选取应根据实际情况权衡。
superblock superblock存放此文件系统的整体信息,包括inode/block大小、inode/block总量、使用量、剩余量、文件系统格式等。一个文件系统仅有一个superblock,位于组0中,这个块很重要,因此通常还有一个备份位于其它组中,其大小一般为1K。
一个进程已经被挂载,可执行文件可以删除吗? Linux系统你可以放心的删,因为引用计数,也就是说你把你能看到的文件删掉了,并不会影响已经打开此文件的进程对此文件的读写。但是,进程退出后,此文件的引用计数为0时,这个文件就真的被删除了。
窥探OKHttp+Gson Json 介绍创建对应格式化实体类安装插件GsonFormatPlus创建实体类踩坑笔记 Json数据解析引入依赖OkHttp封装JsonObject解析JsonArray解析回调完整封装 Json解析 Json 介绍 JsonObject 对应Json字符串中用{}包裹的数据,相当于一个实体类 JsonArray对应Json字符串中用[]包裹的数据,相当于一个数组 下面为从某个服务器中拉去的数据,其中data为数据核心部分,minfo为一个数组,其中包含所需要渲染的数据,filter为一个数据实体,包含筛选条件信息。
{ "status":"200", "msg ":"success", "source":"156", "data":{ "data_type":"2", "minfo":Array[30], "filter":{ "orderby":[ { "title":"Popular", "id":"1" }, Object{...}, Object{...} ], "genre":Array[27], "pub":Array[12], "type":Array[3], "country":Array[49] } } } 创建对应格式化实体类 从服务器端拉去的Json字符串,需要创建对应的实体类进行接收,本文介绍一种插件,用于Android端格式化建立实体类
安装插件GsonFormatPlus 点击设置->plugins->搜索并安装插件GsonFormatPlus插件
创建实体类 第一步,在需要创建实体类的地方右击空白处,在弹出的显示框中选择Generate
第二步,然后在选择刚才安装的插件GsonFormatPlus
第三步,最后将Json字符串复制上去,点击OK即可自动创建
踩坑笔记 如果你不想一次性创建所有的Json数据对于的实体类,也就是说,你所请求的Json字符串你不想创建在一个实体类中,比如下面Json字符串为例,下面的minfo是一个数组,如果你想把这个数组内的数据单独建立一个实体类,你需要把这个字段定义为JsonArray类型,注意不是全大写,全大写是另外一个类,会出错,JsonObject同理。这样可以让数据更加层次分明,在不同的地方引用时,较为方便。
private JsonArray orderby; { "status":"200", "msg ":"success", "source":"156", "data":{ "data_type":"2", "minfo":Array[30], "filter":{ "orderby":[ { "title":"Popular", "id":"1" }, Object{...}, Object{...} ], "genre":Array[27], "pub":Array[12], "type":Array[3], "country":Array[49] } } } Json数据解析 引入依赖 implementation 'com.
今天电脑的outlook一直登录不上,输入密码之后一直说是无法显示网页,仔细想想,应该是outlook默认浏览器除了问题,或者是什么网络协议不对。
最后解决的办法是,发现需要启用Internet属性->高级里面的几个TLS协议
然后重新登录,就可以用了:
目录
Keepalived工具介绍
Keepalived的作用
keepalived实现原理剖析
vrrp虚拟路由冗余协议
Keepalived体系主要模块及其作用
core模块
vrrp模块
check模块
LVS+Keepalived高可用群集的搭建
配置主负载均衡调度器(192.168.10.19)
关闭防火墙、增强机制和下载httpd服务
安装 ipvsadm和keepalived服务
修改配置文件keeplived.conf
启动服务、查看虚拟网卡VIP
调整proc响应参数,关闭Linux内核的重定向参数响应
配置负载分配策略,并启动服务
清空ipvsadm,并做策略
保存设置 配置备负载均衡调度器(192.168.10.20)
关闭防火墙、增强机制和下载httpd服务
安装ipvsadm、keepalived服务
修改配置文件keeplived.conf
启动服务、查看虚拟网卡VIP 编辑
调整proc响应参数,关闭Linux内核的重定向参数响应
配置负载分配策略,并启动服务
清空ipvsadm,并做策略
保存设置
配置节点服务器web1(192.168.10.21)
关闭防火墙、增强机制和下载httpd服务
编辑
配置站点文件
配置虚拟VIP
重启网络服务,开启虚拟网卡
设置路由
调整proc响应参数
刷新proc参数
配置节点服务器web2(192.168.10.22)
关闭防火墙、增强机制和下载httpd服务
配置站点文件
配置虚拟vip 重启网络服务,开启虚拟网卡
设置路由
调整proc响应参数 刷新proc参数
进行测试 主
断开主DR服务器的Keepalived测试 在客户端进行测试
Keepalived脑裂及解决办法
前言:
Keepalived一个基于VRRP 协议来实现的 LVS 服务高可用方案,可以利用其来解决单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。
Keepalived工具介绍 专为LVS和HA设计的一款健康检查工具
支持故障自动切换(Failover)
支持节点健康状态检查(Health Checking)
官方网站: http://www.keepalived.orgl
判断LVS负载调度器、节点服务器的可用性,当master主机出现故障及时切换到backup节点保证业务正常,当 master 故障主机恢复后将其重新加入群集并且业务重新切换回 master 节点
目录
1、下载PenAttention
2、安装
3、打开软件设置
4、其它
1、下载PenAttention 百度搜索PenAttention,或直接点击该网址:PenAttention - Highlight your pen or mouse cursor
2、安装 3、打开软件设置 效果:
4、其它 软件设置已经完成了,下面是关于鼠标的其它设置(可以不更改,根据个人喜好)
问题说明:xshell启动时候弹出如下界面
问题原因:此问题就是xshell的版本出现问题,不是最新版本,我当前的xshell版本是Xshell-7.0.0077p,我需要对xshell版本进行一下重新安装。
注意:此方法对xftp也一样适用。
处理方法:
1 卸载掉原来的xshell版本。
2 首先访问xshell和xftp官网(同一个地址)。找到“家庭/学校免费”,或者在浏览器里面直接输入如下地址;https://www.xshell.com/zh/free-for-home-school/
3 直接填写“姓名”,“邮件”,勾选“两者”,点击“下载”,
4 然后来到邮箱里,就会看到收到两封邮件,邮件里面带有软件的下载地址,直接用邮件里给的下载地址进行新版软件的下载即可。
5 测试成功
静态发布网站 tomcat的使用 在官网下载tomcat安装包之后,解压。
双击startup.bat文件,开启tomcat.(注意这里可能会出现闪退的情况,可能是我们之前配置换系统环境变量,只需要在配置环境变量里将之前的配置删除掉即可)
这时我们打开浏览器,输入localhost:8080/ 可打开tomcat官网,说明tomcat配置成功。
将前端html网页发布到本地浏览器 在webapps文件夹中创建一个文件夹,这里创建一个gouwuche的文件夹。
然后将购物车前端页面html网页复制到gouwuche文件夹中。
这时我们在我们的本机浏览器中输入localhost:8080/gouwuche/gouwuche.html 即可在浏览器上运行我们的前端网页。
其他小伙伴也可以通过你的端口号http://XXX.XXX.XXX.XXX:8080/gouwuche/gouwuche.html进行访问。(emmmm…这里我的访问不了!!!!! )
然后,我们双击shutdown.bat文件,关闭tomcat.
tomcat乱码的解决 乱码情况:
右键单击文件,选择打开方式,用EditPlus编译器软件,打开conf文件夹下的logging.properties.
打开如下:
(window系统下,编码修改为GBK)
我们将编码方式修改为GBK(注意:记得保存),重新打开tomcat。可以看到汉字正常显示。
修改端口号 找到conf文件夹找到server.xml文件,用EditPlus编译器软件打开,找到连接器Connector及对应的端口号。
将端口号改成8088。
重新打开tomcat,看细节。
用浏览器访问原本地8080端口号以及现在修改过之后的端口号8088,看访问结果。
虚拟目录的配置 虚拟目录:解决了处于不同盘/文件夹下的tomcat和(要被呈现在浏览器上的)项目/文件之间的访问问题。
找到conf文件夹找到server.xml文件,用EditPlus编译器软件打开,找到节点Valve,并在Valve节点外添加<Context docBase="d:/yzh7/" path="hahaha" reloadable="true"/>。(valve:管道)
通过访问 hahaha 来间接访问D盘下的yzh7文件夹( d:/yzh7/ )。
不能直接访问localhost:8088/yzh7/gouwuche.html来访问D盘下的yzh7文件夹( d:/yzh7/ ),因为需要配置在webapps文件夹下,才可直接展示在浏览器中。
将yzh7文件夹及gouwuche.html文件配置在webapps文件夹下,才可直接展示在浏览器中。
可以访问虚拟路径hahaha 来访问D盘下的yzh7文件夹( d:/yzh7/ )。具体需要访问localhost:8088/hahaha/gouwuche.html
端口号被占用(待完善) 将端口号及虚拟目录还原(建议) 将修改的端口号及虚拟目录还原成原始的状态:(怕后期忘记端口号)
注意:每次修改完成之后,记得ctrl+s保存!!!
用idea动态发布网站 创建建java项目 参考: 【学习笔记】 IDEA 社区版配置JavaWeb环境
导入Tomcat中的servlet-api.jar包 使用IDEA导入servlet-api.jar(该路径在我们下载的Tomcat的文件夹lib中)。
选中servlet-api.jar,点击ok。
Smart Tomcat插件的配置 Smart Tomcat插件的下载 首先我们在IDEA——Seting——Plugins ——Smart Tomcat下载该插件:
Smart Tomcat插件的配置 下载完毕后我们打开之前创建的Java程序,在右上边找到Smart Tomcat。
编写html文件进行验证。
概述: 硬件:基于stm32f767igt6水星板开发;
软件:使用了RT-Thread实时操作系统,两个空闲IO口。PE2用作串口TX端,搭配一个定时器控制发送时序;PE3用作串口RX端,并使能外部中断,触发外部中断则开启一个接收定时器。
GitHub代码下载地址
1 . UART简介: 1.1 UART协议: 空闲位:当uart处于空闲状态(线路没有数据传输)时,TX、RX线都处于高电平状态(逻辑“1”),一般需要把相应IO口配置为上拉。
起始位:由高电平跳变为低电平,且持续一个位宽度,表示触发起始信号。
数据位:数据位可以5、6、7或8位,从最低位开始一位接着一位的传送。
校验位:有奇、偶或无校验。
奇校验:数据位+校验位的“1”的位数总和为奇数;
偶校验:数据位+校验位的“1”的位数总和为偶数;
例如:奇校验中,数据位“1”的位数为偶数个,则此时校验位为“1”。
无校验:顾名思义就是没有校验位,数据位后面接停止位。(通常配置为无校验。)
停止位:将数据线拉为高电平,可以设置停止位宽度为1位、1.5位或者2位。
波特率:在串口中波特率为每秒传送的bit数;通信双方必须设置相同的波特率,否则接收的数据为乱码。波特率9600时,传输1bit所需时间为(1/9600)us,大约为104us。
1.2 UART工作原理: UART 为全双工通信,通常需要三条线: TX(发送)、 RX(接收)和 GND(地线)。数据串行一位一位的传送。
发送数据:空闲状态TX处于高电平,将TX拉为低电平,宽度为1bit时间,接着数据按低位到高位依次发送,数据发送完毕后,如果有校验位,则发送奇偶校验位,最后发送停止位,这样一帧数据就发送完成了。(若发送多字节数据时,就连续发送多帧数据即可。)
接收数据:RX线路处于高电平(空闲态)时,当RX检测到下降沿(高电平变为低电平)时,说明线路有数据要传输,按照约定的波特率从低位到高位接收数据,数据接收完毕后,如果有校验位,则接收奇偶校验位,最后接收停止位。
2 . IO模拟UART通信 2.1 模拟TX发送端 2.1.1 自定义发送数据结构体: 发送状态分为空闲和发送中;还有一个发送数据缓冲区。
typedef enum _TX_STATE_{ AUART_TX_IDLE = 0, //发送空闲 AUART_TX_SEND, //数据发送 }TX_STATE; typedef struct _AUART_TX_{ uint8_t tx_data_buffer[TX_DATA_MAX]; //发送数据缓冲区 uint8_t cur_bit; //当前数据字节位 volatile uint8_t start_flag; //启动位标志位 TX_STATE tx_state; //发送状态 uint32_t bound; //波特率 uint16_t one_bit_time; //发送1bit时间 uint16_t data_cur; //当前数据 uint16_t tx_data_len; //发送数据长度 }AUART_TX; 2.
java日期格式化为json字符串,看这个就够了。
不管是入参还是返参,原理都是一样的。
/**
* json格式化注解
* 1,pattern是转化成json的格式,
* 如果是入参,则把pattern格式的字符串转换成时间对象payTime。
* 如果是返参,则把时间对象payTime转换成pattern格式的字符串。
*
* 2,只能处理pattern格式的字符串/只能转化成pattern格式的字符串
* "payTime": "2022-07-26T07:24:03Z"
* * 3,要点:pattern和字符串格式必须一一对应
* 2022-07-26T07:24:03Z 对应 yyyy-MM-dd'T'HH:mm:ss'Z'
* 2022-07-26 07:24:03 对应 yyyy-MM-dd HH:mm:ss
*
*/
@ApiModelProperty("支付时间")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime payTime;
AUC 衡量模型对所有样本间的排序能力,没有考虑到群体的差异性
GAUC 衡量模型对不同group (user, search_query) 的排序能力
例子参考: https://blog.csdn.net/hnu2012/article/details/87892368 假如有两个用户,分别是甲和乙,一共有5个样本,其中+表示正样本,-表示负样本,我们把5个样本按照模型A预测的score从小到大排序,得到 甲-,甲+,乙-,甲+,乙+. 那么实际的auc应该是 (1+2+2)/(3*2)=0.833, 那假如有另一个模型B,把这5个样本根据score从小到大排序后,得到 甲-,甲+,甲+,乙-,乙+, 那么该模型预测的auc是(1+1+2)/(3*2)=0.667.
此处计算AUC的方法可以参考: 推荐系统评价指标:AUC和GAUC - 简书
三个正样本, 两个负样本。所以分母是 2*3
按照预测的score进行排序后,第一个甲+ 左边有 一个负样本, 第二个甲+左边有两个负样本, 第三个正样本 乙+ 左边有两个负样本, 所以分子是 1+2+2
论文 Optimized Cost per Click in Taobao Display Advertising 中的表述与公式: First, we aggregate all test data ac- cording to the user (u) and the particular position (p) of ad spot. Then, the AUC results are calculated in each single group (note that if there are all positive or negative samples in a group, we re- move the group from the data).
1 touch
1.1 创建一个文件 touch yyTest.ini 1.2 同时创建两个文件
touch test1.txt test2.txt
1.3 批量创建文件(如创建2000个文件)
touch test{0001..2000}.txt
1.4 更改文件 yyTest.ini时间为当前时间(yyTest.ini已存在)
touch yyTest.ini 2 vi和vim
vi test.txt
vim touch.txt
3 使用>、>>
3.1 > 直接覆盖原文件,不会有任何提示
3.2 >> 追加在原文件末尾,不会覆盖原文件的内容
3.3 直接用>创建空文件
> test.ini
3.4 ls 创建文件(将结果写入文件) ls > test.ini
ls >> test.ini
3.5 grep 创建文件(将结果写入文件)
ps -ef | grep java >test.ini
ps -ef | grep java >>test.ini
3.6 echo 创建文件(将结果写入文件)
echo $PATH > test.ini
token和session与cookie详解以及应用原理 一、我们先解释一下Token的含义 1、Token的引入: Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。 2、Token的定义: Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。 3、使用Token的目的: Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。 4.Token 的优点: 扩展性更强,也更安全点,非常适合用在 Web 应用或者移动应用上。Token 的中文有人翻译成 “令牌”,我觉得挺好,意思就是,你拿着这个令牌,才能过一些关卡。 5.Token一般用在三个地方: ①防止表单重复提交 ②anti csrf攻击(跨站点请求伪造) ③身份验证(单点登录) 了解了Token的意义后,我们就更明确的知道为什么要用他了。
二、如何使用Token? 这是本文的重点,在这里我就介绍常用的两种方式。 1、用设备号/设备mac地址作为Token(推荐) 客户端:客户端在登录的时候获取设备的设备号/mac地址,并将其作为参数传递到服务端。 服务端:服务端接收到该参数后,便用一个变量来接收同时将其作为Token保存在数据库,并将该Token设置到session中,客户端每次请求的时候都要统一拦截,并将客户端传递的token和服务器端session中的token进行对比,如果相同则放行,不同则拒绝。 分析:此刻客户端和服务器端就统一了一个唯一的标识Token,而且保证了每一个设备拥有了一个唯一的会话。该方法的缺点是客户端需要带设备号/mac地址作为参数传递,而且服务器端还需要保存;优点是客户端不需重新登录,只要登录一次以后一直可以使用,至于超时的问题是有服务器这边来处理,如何处理?若服务器的Token超时后,服务器只需将客户端传递的Token向数据库中查询,同时并赋值给变量Token,如此,Token的超时又重新计时。 2、用session值作为Token 客户端:客户端只需携带用户名和密码登陆即可。 客户端:客户端接收到用户名和密码后并判断,如果正确了就将本地获取sessionID作为Token返回给客户端,客户端以后只需带上请求数据即可。 分析:这种方式使用的好处是方便,不用存储数据,但是缺点就是当session过期后,客户端必须重新登录才能进行访问数据。 三、使用过程中出现的问题以及解决方案? 刚才我们轻松介绍了Token的两种使用方式,但是在使用过程中我们还出现各种问题,Token第一种方法中我们隐藏了一个在网络不好或者并发请求时会导致多次重复提交数据的问题。 该问题的解决方案:将session和Token套用,如此便可解决,如何套用呢?请看这段解释: session是一个在单个操作人员整个操作过程中,与服务端保持通信的唯一识别信息。在同一操作人员的多次请求中,session始终保证是同一个对象,而不是多个对象,因为可以对其加锁。当同一操作人员多个请求进入时,可以通过session限制只能单向通行 本文正是通过使用session以及在session中加入token,来验证同一个操作人员是否进行了并发重复的请求,在后一个请求到来时,使用session中的token验证请求中的token是否一致,当不一致时,被认为是重复提交,将不准许通过。 这就是解决重复提交的方案。 四、基于 Token 的身份验证方法 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 Token,再把这个 Token发送给客户端 客户端收到 Token 以后可以把它存储起来,比如放在Cookie 里或者 Local Storage 里 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
session和cookie session :就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。
cookie:非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求会把该cookie发送给服务器。
区别:cookie数据存放在客户的浏览器上,session数据放在服务器上。将重要信息存放在Session中,其他信息如果需要保留,可以放在cookie中。
session认证流程如下:
1、当用户首次访问服务器的时候,服务器为每个用户单独创建一个 Session 对象,并分配一个新的 SessionID,此时 SessionID 通过 cookie 保存在用户端。
我们在做产品0到1的时候,一定会涉及到产品的选型。现在市面上的产品主要有APP、小程序和网站/H5。每个产品形态的选型都为后面产品迭代和产品增长做了铺垫作用,产品形态选型会影响开发时间、资源成本的投入。
一.产品形态定义 产品形态在百度百科上定义是指通过设计、制造来满足顾客需求,最终呈现在顾客面前的产品状况,包括:产品传达的意识形态,视觉形态和应用形态。
意识形态:指产品传达的精神属性。
视觉形态:指产品传达的包装属性。
应用形态:指产品传达的使用属性。
一般互联网领域的产品形态包括APP,Web(PC端、移动端),第三方平台(公众号、小程序等),SDK等
二.产品形态背后的意义 产品形态主要由产品定位来决定。因为只有要做什么样的产品了, 才知道产品的形态最好是什么。产品定位是要确定用户的核心需求,我们就可以根据解决的需求来定位产品。
产品形态设计关键在于从业务层梳理清楚产品定位,产品形态、业务逻辑、业务流程之间的关系。
产品形态是产品解决需求的方法,业务逻辑是实现方法的途径,业务流程是途径上每一步具体要做的事情。对应的关系如下
产品形态的业务逻辑,梳理出用户系统等的流转关系。通过功能模块的组合,业务数据的流转,来传递产品的业务逻辑与业务流程。
产品逻辑是基于用户把产品形态提炼成业务逻辑的能力。
业务流程就是将产品的业务逻辑流程化,并以图表的形式表达。
梳理产品的业务流程可帮助产品经理了解业务如何运转,基于业务场景完整还原现有的业务流程。-----未完待续
程序界面通过 CogRecordDisplay 控件显示视觉运行结果图像。
按指定图像显示,代码如下:
using System; using System.Windows.Forms; using Cognex.VisionPro; using Cognex.VisionPro.ToolBlock; /// <summary> /// 显示指定视觉图像 /// </summary> /// <param name="cogdisplay">显示控件</param> /// <param name="cogImage">显示图像</param> public void ShowDisplayByImage(CogRecordDisplay cogDisplay, CogImage8Grey cogImage) { try { cogDisplay.Image = null; cogDisplay.StaticGraphics.Clear(); cogDisplay.InteractiveGraphics.Clear(); cogDisplay.Image = cogImage; cogDisplay.AutoFit = true; } catch (Exception ex) { MessageBox.Show("图像显示失败!"); } } 按指定VisionPro 工具包 CogToolBlock 内的工具序号显示该工具结果图像,代码如下:
using System; using System.Windows.Forms; using System.IO; using Cognex.VisionPro; using Cognex.VisionPro.ToolBlock; /// <summary> /// 显示工具图像 /// </summary> /// <param name="
一、概述 视觉定位工具包一般包含:
1.相机取像;
2.图像九点标定;
3.Mark点粗定位;
4.建立粗定位坐标系;
5.Mark点精定位
6.输出Mark点坐标,角度等信息。
二、分类 1.单特征定位,无角度 Tips:其中,最终输出(X,Y)采用的找圆工具应根据实际项目应用工具。
2.双特征定位,带角度 Tips:角度通过线与线的夹角工具计算,线1为调试时设置的基准线,线2为当前识别的线。
相互学习,共同富裕。
推荐好文~
MyBatis Plus 批量数据插入功能(https://cloud.tencent.com/developer/article/1883389)
拓展阅读:MyBatis原生批量插入的坑与解决方案(https://cloud.tencent.com/developer/article/1892141 )
使用 MyBatis-Plus(下文简称 MP)自带的 saveBatch 方法,来实现数据的批量插入功能,因为 MP 不是本文讨论的重点,所以这里咱们就不介绍了,如果有不熟悉的朋友可以去他的官方自行恶补:https://baomidou.com/guide/,咱们本文重点介绍一下 MP 实现批量插入的具体步骤。
1.引入 MP 框架
首先,打开您的 pom.xml 文件,在文件中添加以下内容:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>mybatis-plus-latest-version</version> </dependency> 注意:mybatis-plus-latest-version 表示 MP 框架的最新版本号,可访问 https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter 查询最新版本号,但在使用的时候记得一定要将上面的 “mybatis-plus-latest-version”替换成换成具体的版本号,如 3.4.3 才能正常的引入框架。
2.创建数据库和表
此步骤可省略,主要用于本文功能的实现,创建数据库和数据表的脚本如下:
-- ---------------------------- -- 创建数据库 -- ---------------------------- SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; DROP DATABASE IF EXISTS `testdb`; CREATE DATABASE `testdb`; USE `testdb`; -- ---------------------------- -- 创建 user 表 -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL, `createtime` datetime NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- 添加测试数据 -- ---------------------------- INSERT INTO `user` VALUES (1, '赵云', '123456', '2021-09-10 18:11:16'); INSERT INTO `user` VALUES (2, '张飞', '123456', '2021-09-10 18:11:28'); INSERT INTO `user` VALUES (3, '关羽', '123456', '2021-09-10 18:11:34'); INSERT INTO `user` VALUES (4, '刘备', '123456', '2021-09-10 18:11:41'); INSERT INTO `user` VALUES (5, '曹操', '123456', '2021-09-10 18:12:02'); SET FOREIGN_KEY_CHECKS = 1; 3.
1.需求 需要在表格中的实例名上添加鼠标悬停显示tooltip的效果;
2.遇到的问题 因为该表格中该列的实例名是超链接,且该超链接组件是我们自己封装的,代码如下
我在<opt-link></opt-link>标签的外面添加一个<el-tooltip></el-tooltip>标签,确实可以实现鼠标悬停展示tooltip的效果;
但是只要页面手动刷新,该tooltip就无法显示了。
我一开始还以为是在js中写了$set()方法导致<el-tooltip>组件加载有问题,所以我还给<el-tooltip>组件加了一个:key属性,该属性的值toRender是变化的,Js中每$set()一次,该toRender值就+1,保证每次$set(),该<el-tooltip>组件都重新渲染;
但是页面有时候刷新还是会出现没有展示tooltip的问题,时好时坏。
3.解决办法 将<el-tooltip>组件放到<opt-link></opt-link>标签的里面,给显示值{{ tableScope.row.name }}外面加一个<span></span>,代码如下
<span></span>组件一定要加,否则表格中无法显示该列的值;这样写,无论是否刷新页面都会显示tooltip,问题解决。
有许多的朋友问我:软件测试行业到底有没有前景和出路?
这个问题我还是很有发言权的,现35+,年收入百万+
先说一下我的工作路径:毕业进入HW,研发测试岗,从测试工程师,到测试经理,再到项目经理。HW工作十年后离职,与人合伙创业三年,这中间我主要负责项目和市场,现如今在鹅厂,主要从事管理相关工作。
这些年管理的测试团队也有几百人,面试的有上千人。
先说答案:软件测试行业一定是有前景的,自己的规划也同样重要。
一:先说收入 做测试那些年,对应的收入和同级别的开发不相上下,但这跟公司有关,
比如我之前在华为,我们做的是终端集成产品,一次质量问题的修复成本就非常高(库存成本,人力成本,客户罚款等),所以公司重视质量,测试就同样被重视。收入就也不错。
我现在在鹅厂,对应的产品,一次质量问题修复成本就很低,刷个版本就可以,所以质量远没有创新重要,测试就没有那么被重视,收入相对开发就低一些。
但只要自己有实力,年收入上百万没有什么问题。
二:测试的优势 很多人都是从技术上对比,觉得测试不如开发等等。但是大家都忽视了一个问题,测试作为最后一关,是很容易从全局来了解产品的,也是很容易接触到用户的。
所以测试转管理,远比开发转管理更有优势。
开发往往是一个模块的开发。
但是测试可以每个模块进行测试。
如果喜欢测试,不要轻易放弃。
三:个人成长和规划 无论什么岗位,如果自己长期没有成长,也没有规划,再好的岗位也没有用。
我是典型的测试转管理,甚至自己创业的
所以进入工作岗位,一定要有清晰的职业规划,测试最典型的是两种
1、一直在测试领域,从测试工程师到行业测试专家
这方面除了技术的提升,也要关注行业的发展,知识域要不断的提升。比如我们以前在华为,一个视频测试工程师,给猎头50w都很难招到一个。
2、测试走管理路线
我自己是走的这条路线,一个公司一般有多个开发小组,比如前端,后端,中台等等,但是测试组一般只有一个。
所以测试经理,就需要对产品全域都了解,那么转项目经理就很有优势。项目经理最重要的就是执行力,风险管控能力,推动能力等。这些测试经理都可以习得。
还有转产品经理的,由于测试最接近用户,所以测试最了解产品。
所以测试也是很不错的,如果你本身就喜欢,那就更好了,很容易做的很好,以后的路也很宽,掌握个人核心竞争力,即使35+一点也不怕的。加油!
3、学习路线和资源
为了助力【软件测试】的朋友们跳槽面试、升职加薪、职业困境,提高自己的技术,本文给大家整了一套涵盖测试所有技术栈的快速学习方法和笔记。目前已经收到了七八个网友的反馈,说是面试问到了很多这里面的知识点。
内容涉及:测试理论、Linux基础、MySQL基础、Web测试、接口测试、App测试、管理工具、Python基础、Selenium相关、性能测试、LordRunner相关等
大厂软件测试岗经验分享 通过大数据总结发现,其实软件测试岗的面试都是差不多的。常问的有下面这几块知识点:
全网首发-涵盖16个技术栈 第一部分:测试理论(测试基础+需求分析+测试模型+测试计划+测试策略+测试案例等等)
第二部分:Linux( Linux基础+Linux练习题)
第三部分:MySQL(基础知识+查询练习+万年学生表经典面试题汇总+数据库企业真题)
第四部分:Web测试
第五部分:API测试
第六部分:App测试
第七部分:管理工具
第八部分:Python基础(Python基础+编程题+集合+函数+Python特性等等)
第九部分:Selenium相关
第十部分:性能测试
第十一部分:LordRunner相关
第十二部分:计算机网络
第十三部分:组成原理
第十四部分:数据结构与算法
第十五部分:逻辑题
第十六部分:人力资源
软件测试基础 软件测试的步骤是什么?如何录制测试脚本?应该考虑进行如何测试的测试方法怎样估计测试工作量?测试设计的问题当测试过程发生错误时,有哪几种解决办法?测试执行的问题测试评估的目标如何提高测试?C/S模式的优点和缺点B/S模式的优点和缺点… Linux grep和find的区别? grep 都有哪些用法?查看IP地址?创建和删除一个多级目录?在当前用户家目录中查找haha.txt文件?如何查询出tomcat的进程并杀掉这个进程,写出linux命令?动态查看日志文件?查看系統硬盘空间的命令?查看当前机器listen 的所有端口?… Python 统计python源代码文件中代码行数,去除注释,空行,进行输出?python调用cmd并返回结果?冒泡排序1,2,3,4 这4个数字,能组成多少个互不相同的且无重复的三位数,都是多少?请用 python 打印出 10000 以内的对称数(对称数特点:数字左右对称,如:1,2,11,121,1221 等)给定一个整数 N,和一个 0-9 的数 K,要求返回 0-N 中数字 K 出现的次数判断 101-200 之间有多少个素数,并输出所有的素数一个输入三角形的函数,输入后输出是否能组成三角形,三角形类型,请用等价类- 划分法设计测试用例…
关于pytorch中多个backward出现的问题:enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly True. 在执行代码中包含两个方向传播(backward)时,可能会出现这种问题:
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [10, 1]], which is output 0 of AsStridedBackward0, is at version 2; expected version 1 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True). 什么情况下会出现这种问题,我们先构建一个场景:
import torch from torch import nn as nn from torch.
使用Microsoft.AspNet.WebApi.Core可以解决普通接口的跨域,但如果接口功能是下载文件,像我的Webapi添加了下载pdf接口,不管客户端怎么调用,都会有提示跨域,目前在解决方法是在此接口加上
response.AddHeader("Access-Control-Allow-Origin", "*");
就可以解决问题
Hello,大家好,我是小马🚀🚀🚀,最近创建了一个深度学习代码库,欢迎大家来玩呀!代码库地址是https://github.com/xmu-xiaoma666/External-Attention-pytorch,目前实现了将近40个深度学习的常见算法!
For 小白(Like Me):最近在读论文的时候会发现一个问题,有时候论文核心思想非常简单,核心代码可能也就十几行。但是打开作者release的源码时,却发现提出的模块嵌入到分类、检测、分割等任务框架中,导致代码比较冗余,对于特定任务框架不熟悉的我,很难找到核心代码,导致在论文和网络思想的理解上会有一定困难。
For 进阶者(Like You):如果把Conv、FC、RNN这些基本单元看做小的Lego积木,把Transformer、ResNet这些结构看成已经搭好的Lego城堡。那么本项目提供的模块就是一个个具有完整语义信息的Lego组件。让科研工作者们避免反复造轮子,只需思考如何利用这些“Lego组件”,搭建出更多绚烂多彩的作品。
For 大神(May Be Like You):能力有限,不喜轻喷!!!
For All:本项目就是要实现一个既能让深度学习小白也能搞懂,又能服务科研和工业社区的代码库。本项目的宗旨是从代码角度,实现🚀让世界上没有难读的论文🚀。
(同时也非常欢迎各位科研工作者将自己的工作的核心代码整理到本项目中,推动科研社区的发展,会在readme中注明代码的作者~)
Attention Series 1. External Attention Usage 1.1. Paper "Beyond Self-attention: External Attention using Two Linear Layers for Visual Tasks"
1.2. Overview 1.3. Usage Code from model.attention.ExternalAttention import ExternalAttention import torch input=torch.randn( 50, 49, 512) ea = ExternalAttention(d_model= 512,S= 8) output=ea(input) print(output.shape) 2. Self Attention Usage 2.1. Paper "Attention Is All You Need"
1.2. Overview 1.3. Usage Code from model.attention.SelfAttention import ScaledDotProductAttention import torch input=torch.
一、IDEA常用设置
1、IDEA设置自动换行显示
Settings > Editor > General > Soft Wraps
soft wrap files 一行打勾, 并添加上 *.java,分号分隔
2、Ctrl+滚轮控制字体放大缩小
3、忽略大小写智能提示
4、自动删除已导入的无用包,快捷键:Ctrl + Alt + O
虽有快捷键,但有时难免会忘记快捷键是什么,经过下面的设置就idea会帮我们自动去除
①Add unambiguous imports on the fly
快速添加明确的导包
IDEA将在我们书写代码的时候自动帮我们导入需要用到的包。
但是对于那些同名的包,还是需要手动Alt+Enter进行导入的
②Optimize imports on the fly (for current project)
动态优化导入(针对当前项目)
(意味着每个项目都要根据自己需求决定是否点这个选项)
IDEA将在我们书写代码的时候自动帮我们优化导入的包,
比如自动去掉一些没有用到的包
5、解决层叠窗口:打开多个文件时,窗口被隐藏了,不方便查找
6、设置文件编码格式的位置
File->Settings->Editor->File Encodings
7、设置编辑区背景色
8、设置背景图 9、导出、导入常用设置setting.xml
为另一个idea导入该设置文件
10、方法分割线
修改分割线颜色:
效果:
其它:
IDEA中查看方法参数快捷键: Ctrl+P 效果如图所示:
二、插件
file >> settings >> plugins 1、翻译插件Translation
file >> settings >> plugins>>搜索Translation
上篇文章《消息队列入门》里面提到,技术是把双刃剑!使用消息队列是因为他带给我们很多好处:系统间解耦、异步执行、削峰限流,但是使用消息队列可能带来一些问题:消息队列的消息被重复消费、消息的顺序保证、异步执行导致的数据不一致;
本篇就来介绍一下这几个引入消费队列后可能带来的问题,以及常见的解决方案;
1. 消息重复消费问题 消息重复消费是使用消息队列之后,必须考虑的一个问题,也是比较严重和常见的问题;
例如,对于订单场景,订单结果的通知一般都是异步方式,由订单中台接收第三方支付渠道的回执,然后封装成业务订单结果投递给业务方;目前我接触的投递方式有HTTP/DUBBO回调和消息队列MQ;
考虑到下游业务方的消费能力(消费速度),使用消息队列是比较好的选择;例如一个累计消费活动的页面,你下单完成了立刻去看一眼活动页面,有时候累计金额马上就加上去了,有时候却延迟有很久,为啥?这个速度取决于消息队列的消费速度,消费慢堵塞了就迟点看到呗;
一般来说,消息队列的接收模式往往是手动确认的,这意味着如果消费者的处理逻辑中抛出了异常,该消息会被重新投递;
此外,支付结果消息的下游监听服务一般是多个,当某个下游业务方出现短期不可用,当它恢复时可能希望某个时间区间消息重新投递,这时其他系统也会收到这些被消费过的消息,就需要考虑其他系统收到重复消息时,是否会产生脏数据?如同一条支付成功的消息投递了两次,会不会出现发两个奖品的情况;
事实上,消息重发是很常见的,服务的网络抖动,开发人员代码Bug等都可能处理失败,并要求消息重发的;这就需要让我们的接口具备一个特性——幂等;
幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中;
在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同;
幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数;这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变;
——《幂等 百度百科》
如何实现幂等? 一般幂等,需要分场景去考虑,看是强校验还是弱校验;比如跟金钱相关的场景那就很关键,就做强校验,别不是很重要的场景如消息频控(疲劳度控制),就可以做弱校验;
(1)强校验:比如你监听到用户支付成功的消息,然后执行业务订单更新、权益发放、下游消息本地持久化这一系列DB操作,可以将这些操作放在一个事务内;
每次消息过来都要拿着业务订单号这样的唯一标识去订单流水表查,看看有没有已经处理过这条流水,处理过就直接终止流程返回,不用走下面的流程了,没有就执行后面的后置处理逻辑;
(2)弱校验:这个简单,一些不重要的场景,比如短信发放消息的处理,可以把{接收者ID+业务场景ID}作为唯一标识作为Redis的key放到缓存里面,设置失效时间(做疲劳度控制),每次接收到执行短信发放消息时就去Redis判断,看当前是否还需要给用户发短信;
之所以是弱校验,是因为用KV就算Redis内数据清空了也没关系,最多是多消费一次多发一条短信,业务也无关痛痒;
2. 消息顺序消费问题 关于顺序消费,开发过程中这样的场景不多,网上更多的都是介绍binlog的同步,好像更多的场景就没了;正常的业务场景就是按照步骤执行,天然的时序的,很难出现并行投递消息的场景;
举个例子,我们都知道数据量大的时候,数据同步压力还是很大的,有时候数据量大的表需要同步几个亿的数据给下游,这种情况可以将需要同步的数据怼到队列里面去,然后下游慢慢消费的;
这时就可能出现同时对库里的一条数据进行了增、改、删三个操作,但是你消息发过去消费的时候变成了改、删、增,这样数据就不对了;
如何解决消息顺序消费? 几种不同MQ实现顺序消息的方式可以参考这篇《几种MQ顺序消息的实现方式》;这里简单的说一下RocketMQ里面的一个简单实现;
RocketMQ的官方文档里面给出了"消息有序性"的定义——
消息有序指的是一类消息消费时,能按照发送的顺序来消费;
例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成,消费时要按照这个顺序消费才能有意义,但是同时订单之间是可以并行消费的;RocketMQ可以严格的保证消息有序;
顺序消息分为全局顺序消息与分区顺序消息,全局顺序是指某个Topic下的所有消息都要保证顺序;部分顺序消息只要保证每一组消息被顺序消费即可。
全局顺序 对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费;适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景;分区顺序 对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区; 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费;Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念; 适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。 如果想要实现全局顺序消息,那么只能使用一个队列,以及单个生产者,这会严重影响性能;
因此,我们常说的顺序消息通常是只的部分顺序消息,就上面的例子来说,我们不用管不同的订单ID的消息之间的总体消费顺序,只需要保证同样订单ID的消息能按照订单创建、订单付款、订单完成这个顺序消费就可以了;
顺序消费实际上有两个核心点,一个是生产者有序存储,另一个是消费者有序消费;
(1)生产者有序发送
我们知道RocketMQ中生产者生产的消息会放置在某个队列中,基于队列FIFO先进先出的特性天然的可以保证存入队列的消息顺序和拉取的消息顺序是一致的,因此,我们只需要保证一组相同的消息按照给定的顺序存入同一个队列中,就能保证生产者有序存储;
普通发送消息的模式下,一个topic下有多个队列,生产者会采用轮询的方式将消费均匀的分发到不同的队列中,然后被不同的消费者消费;因为一组消息在不同的队列,此时就无法使用队列天然的FIFO特性来保证消息有序性了;
RocketMQ支持生产者在投放消息的时候自定义投放策略,即为当前消息选择投放到的队列;RocketMQ提供MessageQueueSelector队列选择机制,他有三种实现:
我们实现一个MessageQueueSelector接口(使用Hash取模法),来保证同一个订单在同一个队列中就行了,即通过订单ID%队列数量得到该ID的订单所投放的队列在队列列表中的索引,然后该订单的所有消息都会被投放到这个队列中;
另外,对于消息生产方,顺序消息必须使用同步发送的方式才能保证生产者发送的消息有序,这个也很好理解吧;
举个例子,有2个队列,那么订单ID为1,2,3的三组消息中,1、3组消息根据Hash取模结果存放于第一个队列,而2组消息存放于第二个队列,如下图是一种消息可能的消息存放顺序:
注意:实际上,采用队列选择器的方法有时也会存在问题;我们的目的是将消息发送到同一个队列中,试想如果某个broker挂了,那么队列数就会减少一部分,如果采用Hash取余的方式投递,可能导致同一个业务中的不同消息在队列数发生变化前后,分别被发送到不同的队列中,导致短暂的部分消息无序;同样的,如果增加了队列服务器数,那么也会造成短暂的造成部分消息无序;
(2)消费者有序消费
生产者有序存储实现了,那么该如何实现消费者有序消费呢?
RockerMQ的MessageListener回调函数提供了两种消费模式,有序消费模式MessageListenerOrderly和并发消费模式MessageListenerConcurrently;
文章目录 移动Web开发学习笔记视口 viewportmeta视口标签二倍图物理像素 & 物理像素比二倍图背景缩放 background-size 移动端技术解决方案CSS3盒子模型box-sizing移动端特殊样式设置移动端常见布局 流程布局/百分比布局flex布局flex布局小练习需求1: 常见的上下结构需求2:背景渐变色需求3:10个盒子占两行需求4:> 箭头符号 rem适配布局 rem+媒体查询rem单位媒体查询 Media Query引入资源 rem适配方案技术方案1:less+媒体查询+rem技术方案2:flexible.js+rem 响应式布局 bootsrap 移动Web开发学习笔记 视口 viewport 视口是浏览器显示页面内容的屏幕区域,分为布局视口、视觉视口和理想视口。
布局视口:移动设备的浏览器默认设置了布局视口
问题:元素显示是按在布局视口显示的,所以视觉视口元素看上去很小,默认通过手动缩放网页
理想视口: 网页在手机屏幕显示完整,手机屏幕有多宽,布局视口就有多宽
meta视口标签 meta视口标签的主要目的:布局视口的宽度和理想视口宽度一致
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"> 属性解释说明width宽度设置的是viewport视口宽度,可以设置为device-width设备宽度initial-scale初始缩放比,大于0的数字aximum-scale最大缩放比,大于0的数字minimum-scale最小缩放比,大于0的数字user-scalable用户是否可以缩放,yes或no( 1或0) 二倍图 物理像素 & 物理像素比 物理像素: 真实存在的,在厂商出厂时就设置好了,比如苹果6是750*1334
物理像素比: 1px能够显示的物理像素点的个数
PC端: 1px(css像素)=1个物理像素
移动端: 不同的手机物理像素比不同,iPhone8中1px=2个物理像素
二倍图 图片按照物理像素比放大会变模糊
在标准的viewport设置中,使用多倍图来提高图片质量,解决在高清设备中的模糊问题,通常使用二倍图
举例
需要一个5050css像素的图片,直接放入iphone8(物理像素比为2)中会放大2倍,图片会模糊。
可以采用放一个100*100css像素的图片,手动把这个图片缩小成5050像素,放大两倍后图片依然是清晰的,因为图片本身就是100*100css像素的。
<style> img{ width:50px; height:50px; } </style> <body> <img src='100.jpg'> </body> 背景缩放 background-size 语法: background-size: 背景图片宽度 背景图片高度
为了清晰一般缩放大小和盒子大小一致
目录
1.模拟滤波器与数字滤波器
2.冲激响应(Impulse Response)
3.IIR(Infinite impulse response)&FIR(Finite impulse response)
1.模拟滤波器与数字滤波器 利用模拟电路直接对模拟信号进行处理构成了模拟滤波器,因此它是一个连续时间系统,比如中频或者射频通信电路等;
利用离散时间系统对数字信号(时域离散,幅度值量化)进行滤波则构成了数字滤波器。
当然,对于模拟信号进行采样处理后也可以使用数字滤波器处理,而且相比于模拟滤波器,数字滤波器更加易于实现,稳定性、精度、可靠性、性价比也更高,因此数字滤波器的应用不断变得广泛起来。
2.冲激响应(Impulse Response) 当一个系统的输入为冲激函数时,它的输出即为冲激响应。如下图,其中 h(t) 就是冲激响应:
3.IIR(Infinite impulse response)&FIR(Finite impulse response) (1)IIR(无限冲激响应)型数字滤波器
顾名思义,当输入为冲激函数时,输出冲激响应h[n](由于属于数字滤波器,自变量变为n)可以无限延长。
(2)FIR(有限冲激响应)型数字滤波器
当输入为冲激函数时,输出冲激响应 h[n] 可以在有限的时间长内结束。
造成这种现象的主要原因是因为IIR型的滤波器采用了递归的结构,即结构中存在回环形成反馈支路来不断地产生输入以进行无限的输出;与之相比,FIR滤波器则实现的较为简单,它的结构中不存在反馈部分,因此它的冲激响应是有限的。通过下图中的差分方程和结构图可以很轻松地看出二者的区别:
由于IIR滤波器的反馈很难调节,所以很容易引起震荡(比如麦克风中产生啸叫),而FIR滤波器不存在反馈调节的影响,因此FIR滤波器更加稳定。IIR滤波器的非线性相位特性导致它一般只能用在语音通信等一些对于相位不敏感的场合中,FRI滤波器则可以使用在图像处理等一些对相位有要求的传输系统中。
运行panda3d Tut-Music-Box.py示例;
如下图,点击按钮有一个打开关闭盒子的效果,还会播放不同音乐;
Panda将音频系统分为两类:声音效果,音乐;
Panda提供三种音频库:openAL,FMOD,Miles;
self.musicBoxSound = base.loadMusic('music/musicbox.mp3'),载入音频文件;
self.lidSfx = base.loadSfx('music/openclose.mp3'),载入音效;
用pview查看一下模型,如下图;
单独把界面部分的代码看一下;
import direct.directbase.DirectStart from panda3d.core import NodePath,TextNode from panda3d.core import Vec3,Vec4 from direct.gui.OnscreenText import OnscreenText from direct.showbase.DirectObject import DirectObject from direct.interval.SoundInterval import SoundInterval from direct.gui.DirectSlider import DirectSlider from direct.gui.DirectButton import DirectButton from direct.interval.MetaInterval import Sequence,Parallel from direct.interval.LerpInterval import LerpFunc import sys class World(DirectObject): def __init__(self): self.slider = DirectSlider(pos = Vec3(0,0,.7), value = .50, command = None) self.button = DirectButton(pos = Vec3(.
什么是适配器模式?
适配器模式是一种结构型设计模式。适配器模式是:当接口无法和类匹配到一起工作时,通过适配器将接口变换成可以和类匹配到一起的接口。
打个比喻:有一个电器的插头是三脚的,而现有的插座是两孔的,要使插头插上插座,我们需要一个插头转换器,这个转换器即是适配器。
源(Adaptee):需要被适配的对象或类型,相当于插头。
适配器(Adapter):连接目标和源的中间对象,相当于插头转换器。
目标(Target):期待得到的目标,相当于插座。
这是我们原来存在的代码
class Adaptee{ public void method1(){ System.out.println("这是原来的类,里面存在method1"); } } 这是客户需要的目标接口
interface Target{ public void method1(); public void method2(); } 很显然原来的类无法满足客户的需求,这时候就需要一个适配器来让两者相匹配。
(之前我会不懂,为什么不在原来的类上去修改?因为原来的类被用了这么久,肯定是正确的,你在原来的类上修改,当类里面的代码很多,不容易维护。建一个适配器就很容易定位到错误在哪里)
适配器模式分类:
类适配器模式:类适配器使用的是继承的方式,一般来说无法对其子类进行适配
对象适配器模式:对象适配器使用的是组合的方式,子孙类都可以被适配。另外,对象适配器对于增加一些新行为非常方便,而且新增加的行为同时适用于所有的源。
接口适配器模式(又称缺省适配器模式):接口适配器模式(缺省适配模式)基本思想是,为一个接口提供缺省实现,这样子类可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。
举例:
类适配器模式,从名字可以看出来直接和类相关,通过继承类,实现接口来达到需求。由于是继承的方式来得到适配器类,所以无法再对其子类进行适配。
class Adaptee{//源码 public void method1(){ System.out.println("这是原来的类,里面存在method1"); } } interface Target{//目标接口 public void method1(); public void method2(); } class Adapter extends Adaptee implements Target{//适配器类 @Override public void method2() { System.out.println("这是接口中的方法。"); } } 现在我们来测试一下适配器
public class Test { public static void main(String[] args) { Target adapter = new Adapter(); adapter.
中间件使用 在go-zero中,中间件可以分为路由中间件和全局中间件,路由中间件是指某一些特定路由需要实现中间件逻辑,其和jwt类似,没有放在jwt:xxx下的路由不会使用中间件功能, 而全局中间件的服务范围则是整个服务。
路由中间件 1、编辑 api 文件 userlogin/userlogin.api 生命接口需要添加的中间件,多个中间件用逗号分隔
@server( middleware : Tagging,Version ) service userlogin-api { @handler Tags get /api/tags returns (TagResponse) } 2、goctl api 命令重新执行 生成middleware 文件
userlogin/internal/middleware/taggingmiddleware.gouserlogin/internal/middleware/versionmiddleware.go 可以看到路由文件中userlogin/internal/handler/routes.go 新增了一下代码
server.AddRoutes( rest.WithMiddlewares( []rest.Middleware{serverCtx.Tagging, serverCtx.Version}, []rest.Route{ { Method: http.MethodGet, Path: "/api/tags", Handler: TagsHandler(serverCtx), }, }..., ), ) 3、 文件中添加中间件依赖 userlogin/internal/svc/servicecontext.go
type ServiceContext struct { Config config.Config Tagging rest.Middleware Version rest.Middleware UserModel user.UserModel } func NewServiceContext(c config.Config) *ServiceContext { conn := sqlx.
解题思路 反编译 undefined4 main(void) { EVP_PKEY_CTX *in_stack_fffffff0; init(in_stack_fffffff0); puts("Welcome, my friend. What\'s your name?"); vul(); return 0; } void vul(void) { undefined local_2c [40]; memset(local_2c,0,0x20); read(0,local_2c,0x30); printf("Hello, %s\n",local_2c); read(0,local_2c,0x30); printf("Hello, %s\n",local_2c); return; } void hack(void) { system("echo flag"); return; } 从反编译结果来看,漏洞还是很清晰的,vul中的read函数提供了溢出点,hack函数提供了system函数调用。
难点&思路 首先是溢出点,从局部变量大小和读取长度限制来看,可以溢出,但是长度不长,经过测试,溢出点在第44字节处,也就是说,只能设置一个4字节返回地址。
undefined local_2c [40]; read(0,local_2c,0x30); 再就是hack函数,system的参数需要构造,但是从上面一条可以看出,普通的溢出没法构造更多的参数。
所以,难点就是如何扩展溢出长度?
从汇编和反编译代码来看,没有有效途径,但是有一个疑点:返回地址前面是ebp地址,如果溢出只能覆盖到返回地址,那么另外一个能影响的就是ebp,是否可以通过控制ebp来控制下次的执行?
经过反复调试发现,返回地址为leave会将栈址降低,跳到局部变量范围,那就可以通过read函数输入需要的参数信息。
然后,剩下最后一个问题,ebp的地址如何设置?
vul的两次read和printf很值得分析,从前面分析得知,read长度限制只比局部变量多8个字节,这8个字节就是ebp以及函数返回地址,而printf以字符串格式打印,那将局部变量全部填充为非0字节,就能打印出后面8个字节的内容。(如果8个字节中有0x00,那确实也会存在阶段的问题),还好,经过测试,该方法有效。
解题脚本 from pwn import * context(arch = 'amd64', os = 'linux',log_level = 'debug', terminal="/bin/sh") #sh = process('.
目录
前言
Linux基本指令
1.ls指令
1.1 ls
1.2 ls -l
1.3 ls -a
1.4 ls -d
1.5 绝对路径和相对路径
2.pwd指令
3.cd指令
4.touch指令
5.mkdir指令
6.rmdir指令和rm指令
1.rmdir指令
2.rm指令
3.通配符
7.man指令
8.cp指令
9.mv指令
9.1 移动文件(windows系统下的剪切)
9.2 将文件重命名
10、cat,more与less指令
10.1 cat指令
10.2 more指令
10.3 less指令
11、重定向
11.1输入重定向
11.2输出重定向 11.3追加重定向
12、head与tail指令
12.1 head指令:
12.2 tail指令
12.3| 命令符
13.时间相关的指令
13.1date显示
13.2时间戳
14、cal命令 15、find命令与which命令
16、grep指令
17、zip/unzip指令
17.1 zip
17.2 unzip
18、tar指令 19、bc指令
20、uname -r指令
21、重要的几个热键
22、添加用户和删除用户
22.1 adduser ---添加用户
多态性 多态性是一种允许使用一个界面来访问一类动作的特性,特定的动作可以由不同的具体情况而定(传入不同的参数)。多态性是发送消息给某个对象,让该对象自行决定响应何种行为。
通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用
public class Test1 { public static void main(String[] args) { Fa cc=new Fa(); //调用的是一个名称为pp的方法,但是参数不同执行的处理不同 cc.pp();//Fa...pp cc.pp(12);//Fa.pp(int) } } class Fa{ public void pp(){ System.out.println("Fa...pp"); } public void pp(int k){ System.out.println("Fa.pp(int)"); } } 多态性通过允许同一界面指定一类动作减少了程序的复杂度,编译器工作就是选择适用于各个情况的特定动作,而程序员则无须手动进行选择,使用者仅仅是记得以及利用这个统一的界面
多态形成的三个必要条件:
有继承,父类定义方法,子类重写方法父类的引用指向子类的对象可以使用参数传递时多态,也可以直接创建对象时多态 多态可以用三个定义和两个方法来总结。三个定义分别是父类定义子类构建、接口定义实现类构建和抽象类定义实体类构建,而两个方法分别是方法重载和方法重写。
多态分为两种:
编译时多态:方法的重载运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态 对象的多态性 继承表示的是is a的语义
public class 汽车 extends 车库{} 错误的 public class 学生 extends 人{} 正确的,因为任何一个学生都是人 强调的一个点:编程是对现实世界的模拟体现
class 动物{} class 猫 extends 动物{} 猫 x=new 猫(); 动物 x=new 猫(); 正确的,因为所有的猫都是动物,因为定义class 猫 extends 动物{} 猫 x=new 动物(); 错误,不是所有的动物都是猫,因为动物是猫的父类 一个对象x有两种形态,猫这类事物即具有猫的形态,又具有着动物的形态,这就是对象的多态性。简单说就是一个对象对应着不同类型
很多人咨询小编,说他在使用电脑的过程中经常会遇到找不到msvcp140.dll无法继续执行代码,他一脸懵逼不知道如何进行解决,其实这个是我们电脑中的组件运行库丢失所导致的。要解决这个问题也不难,下面我们一起来看看。
【dll文件常见问题】
找不到msvcp140.dll无法继续执行代码
找不到msvcp140.dll就是系统中缺少丢失了这个运行库。
解决方法:
找不到msvcp140.dll的方法一:
1.搜索并下载“vc运行库”,注意有64位和32位区分的,
2.然后安装到电脑上一般就能解决msvcp140.dll丢失的问题!
找不到msvcp140.dll的方法二:
1.下载msvcp140.dll到电脑中
2.32位系统复制到C:\Windows\System32目录下。
64位系统请将文件复制到C:\Windows\SysWOW64目录
3.然后打开"开始-运行-输入regsvr32 msvcp140.dll",回车即可解决。
找不到msvcp140.dll的方法三:
直接去电脑修复精灵下载dll修复工具,用这个小工具来进行相关的修复,dll修复工具操作也比较简单,点击检测,然后再点击修复就可以了,几乎是全程自动的,不需要你自己去怎么操作。
以上就是关于小编给大家分享的找不到msvcp140.dll无法继续执行代码的解决方法,希望本文能帮到大家,如果想了解更多的电脑修复问题,可以继续关注小编哦。
一、运算符 首先我们要知道Sass的数据类型 数字 :1、2、3、10px字符串:有引号的字符串:"foot"、'bar' 没有引号的字符串:baz颜色:blue,#999999,rgba(255,0,0,0.8)布尔类型:true,false空值:null数组(list):用空格或逗号作为分隔符,1.5em 2em 3em ,1.5em,2em,3emmaps:相当于JavaScript的object,(key1:value1,key2:value2) 基本运算符 数学运算符;+ - * / %
关于运算符;< > >= <=
逻辑运算符 and or not
数学运算符 //数学运算符;+ - * / % //关于运算符;< > >= <= //逻辑运算符 and or not p { width: 1+2; width: 1+2px; width: 10+20%; width: 20-10; width: 20-10px; width: 20-10%; // 运算符 /:1.作用数学运算符 2.分隔符 // border-radius: 10px/20px; //当两个单位用/进行分隔,/代表的分隔符 // border-radius: 10/20; // border-radius: 10/20px; //当变量与数字用/链接,此时代表除法运算符 $num: 10px; $num_2: 20px; // border-radius: $num/20; // border-radius: $num/$num_2; // border-radius: (10/5); // border-radius: 10-10/5; //当不想让变量之间进行除法运算,可以用插值表达式#{} // border-radius: #{$num}/#{$num_2}; &::after { content: bb+"
致谢 感谢知乎回答“loss的尺度的影响的本质上取决于优化器”给予我的启发!
1 问题描述 最近我在调参时,想到一个问题:“损失函数loss乘以正数因子a是否等价于学习率lr乘以a呢?”
2 解答 对于梯度优化而言,损失函数loss乘以正数因子a与学习率lr乘以a,与优化器算法optimizer有关。
OptimizerEquivalency (ls & lr)ExperimentSGDunknownAdamunknownAdamW✓Torch_adamw_ls.ipynb 3 证明 3.1 朴素SGD:等价 3.2 Adam:不等价,ls失效 这里选择的Adam算法形式是比较简单的算法描述,来自于Adam论文《A Method for Stochastic Optimization》,其公式为
直观解释:根据以上算法流程,当loss乘以尺度 s s s时,loss梯度 g t g_t gt增大 s s s倍,那么 g t 2 {g_t}^2 gt2则会扩大 s 2 s^2 s2倍;由于 m t m_t mt是 g t g_t gt的累加, v t v_t vt是 g t 2 {g_t}^2 gt2的累加,那么 m t m_t mt会扩大 s s s倍, v t v_t vt会扩大 s 2 s^2 s2倍。由于 m ^ t \hat{m}_t m^t与 m t m_t mt线性相关, v ^ t \hat{v}_t v^t与 v t v_t vt线性相关,那么最后一步的梯度更新相当于
这里写目录标题 绝对装入优点缺点应用场景 静态装入优点缺点应用场景 动态装入优点缺点应用场景 在多道程序环境下,要使程序运行,必须先为之创建进程。而创建进程的第一件事,便是将目标模块(即程序和数据)装入内存。在将目标模块装入内存时,可以有绝对装入、静态地址重定位和动态地址重定位三种方式。 绝对装入 用户程序经过编译之后,将产生绝对地址(物理地址)的目标模块,即按照装入模块中的物理地址,将程序和数据装入内存。
优点 CPU执行目标代码快。
缺点 由于内存大小限制,能装入内存并发执行的进程数大大减少。
应用场景 绝对装入方式一般只适用于单道程序环境,需要知道该程序实际运行的地址。
静态装入 在多道程序环境下,编译汇编所得到的目标模块的起始地址通常是从0开始的,目标模块中的其它地址也都是相对于起始地址计算的,即目标模块采用的是相对地址。
静态地址重定位就是根据内存的当前情况,将装入模块装入到内存的适当位置,并在程序运行之前对指令和数据的各个地址进行重定位,即完成相对地址到物理地址的映射。地址变换通常是在程序真正运行前时一次完成的,以后不再改变。
优点 无需硬件支持。
缺点 程序重定位之后就不能在内存中搬动了。要求程序的存储空间是连续的,不能把程序放在若干个不连续的区域中。 应用场景 针对多道程序环境下,编译程序不可能预知编译后所得的目标模块应该存放在内存的何处。
动态装入 动态地址重定位不是在程序执行之前而是在程序执行过程中进行地址变换。更确切的说,是把这种地址转换推迟到程序真正要执行时才进行,即在每次访问内存单元前才将要访问的程序或数据的相对地址变换成物理地址。
动态重定位可使装配模块不加任何修改而装入内存。为使地址转换不影响指令的执行速度,这种方式需要一个重定位寄存器的支持。
优点 目标模块装入之后再进行搬迁也不会影响其正确执行。
缺点 需要硬件支持。
应用场景 一个进程可能被多次换出,又被多次换入,每次换之后的位置都是不同的,应采用这种装入模式。
Flutter用过的图表库: fl_chart ,缺点是自定义一些东西比较麻烦,而且数据填入的层级问题比较反人类graphic ,缺点是数据不能为空,没有空布局,可以先判断是否有数据然后在加载列表 graphic自定义TooltipGuide的实现: List<Figure> _renderer(Offset anchor, Map<int, Tuple> selectedTuples, Map<String, Color> groupColors) { if (anchor.dy.isNaN) { anchor = Offset(anchor.dx, 50); } final windowPath = Path(); const space = 5; const bgColor = Color(0xFF4C4C4C); List<Figure> figures = []; var width = 0.0; var height = 0.0; List<TextPainter> textPainters = []; List<String> groupNames = []; selectedTuples.removeWhere((key, value) => value[yName].isNaN); selectedTuples.forEach((key, value) { final text = '${value[xName]} ${value[groupName] ?? ''}:${value[yName]}'; final textPaint = TextPainter( text: TextSpan(text: text, style: TextStyle(color: Colors.
前言
在一个网站中,很多数据需要即时更新,比如期货交易类的用户资产。在以前,这种功能的实现一般使用http轮询,即客户端用定时任务每隔一段时间向服务器发送查询请求来获取最新值。这种方式的弊端显而易见:
有可能造成数据更新不及时,如果前端轮询频率为5s,也许数据在这5s内已经更新多次了。
有可能对数据库造成额外压力,例如一个用户资产长时间不变化,但客户端还是要定时去查询,这种无意义查询占比相当高,对服务器造成不必要的压力。
要经过请求和响应两次交互,增加了耗时,而且http请求可能携带大量的header信息,增加网络带宽占用
HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议-WebSocket,很好地解决了http轮询的弊端。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
也就是说,http轮询机制,主动权完全在客户端,而WebSocket机制中,主动权可以交给服务端,数据推送可以更精确,包括何时推送(定时推送还是更新即推送),推送什么数据。
准备工作
JMeter可以非常便利地进行WebSocket接口测试,但需要引入下列依赖:
jetty-http
jetty-io
jetty-util
websocket-api
websocket-client
websweocket-common
相关依赖下载:
https://pan.baidu.com/s/1PTOyTBzmOwLPNhxB-TxR7g ,提取码:uq25
下面内容基于JMeter5.1.1
将相关jar包放入JMeter安装目录的/lib/etc中,重启JMeter。在取样器中,可以看到比之前多了websweocket相关的取样器。
脚本编写
在编写脚本之前,先要搞清楚推送服务的逻辑,它的逻辑是这样的:
首先,客户端向服务端发送请求,建立连接
建立连接后,客户端需要定时向服务端发送ping-pong消息,维持心跳
客户端发送主动断开连接的请求,服务端断开该连接
建立连接,使用【WebSocket request-response Sampler】,顾名思义,这个取样器既能发送请求也能接收响应。
说明一下各项内容:
Connection:有use existing connection和setup new connection两种模式,前者是使用已有连接,即上一个websocket请求所建立的连接通道,选择后Server URL全置灰只读不可操作。后者指新建连接通道。
Server URL:ws协议和wss(加密的websocket)可选,sever name or IP(服务器地址)、Port(端口号)、Path(路径)、Connection timeout(连接超时时间)这些含义也很明了。
Data:发送数据,可以选择Text(文本,包括JSON)和Binary(二进制)形式,也可以通过勾选Read request data from file来从文件中获取data。
这个请求要与连接请求是同一个线程,并且要定时运行,因此设计脚本结构如下:
注意两点:
1.想要建立3000个连接的话,一定是将【线程数】设置为3000,循环次数设置为1,而不是相反,这是许多人容易弄混淆的。
2.【Ramp-up 时间】这个参数是全部线程启动的时间,如果想给服务器较大的瞬时压力,就把时间设置短一些。经过实测,这个时间太短的话,最终成功建立的连接会明显少于设置的【线程数】,所以一般设置长一点。
一般的websocket推送服务,会设计定时心跳检测机制,也就是客户端定时向服务端发送一条特定的消息,这样服务端就会保持这个连接,否则的话,这个客户端就被服务端判定为不活跃而被断掉连接。因此,为了让我们的脚本持续跑下去,就需要加入心跳检测请求。
因为线程循环次数是1次(多次的话,就是一个线程反复建立连接了),因此我们要把【心跳检测】放到一个循环控制器中。
而【固定定时器】的作用,就是控制【心跳检测】发送的频率:
心跳检测:
尤其要注意两点:
1.Connection项一定要选择 use existing connection,表示使用该线程已经建立的连接,否则就重新创建连接了。
2.Request data 根据服务端的实现而定。
一、什么是日志 日志:就是介绍一个过程和经历的详细记录。项目日志:就是项目开发过程的详细记录,一般由项目经理记录。代码里的日志:就是程序员记录某个开发过程的详细情况,这是项目里每个程序员需要做的工作。日志和异常处理结合得当的话,会给项目维护带来非常大的价值。 二、日志的重要性 日志,通常不会在需求阶段作为一个功能单独提出来,也不会在产品方案中看到它的细节。但是,这丝毫不影响它在任何一个系统中的重
要地位。为了保证服务的高可用,发现问题一定要及时,解决问题一定要迅速,所以生产环境一旦出现问题,预警系统就会通过邮件、短信甚至
电话的方式实施多维轰炸模式,确保相关负责人不错过每一个可能的 bug。预警系统判断疑似 bug 大部分源于日志。当该错误日志达到一
定次数出现的时候,就会触发报警。 三、日志在项目中的作用 主要用于记录程序运行的情况,以便于程序在部署之后的排错调试等,也有利于将这些信息进行持久化(如果不将日志信息保存到文件或
数据库,则信息便会丢失)。
查看程序当前运行状态查看程序历史运行轨迹排查系统问题优化系统性能安全审计的基石 四、Java 日志使用的困惑 大多数的程序员都能认识到日志在项目中的重要性,可是对日志记录具体要怎么做、做到什么程度、日志记录用什么工具,会有很多困惑。
工具困惑:作为 Java 程序员,幸运的是,Java 拥有功能和性能都非常强大的日志库;不幸的是,日志库不止一个,JUL(
java.util.logging), JCL( Jakarta Commons Logging,Spring 框架默认使用的),Log4j, Log4j2, Logback、 SLF4j、 jboss-logging
(Hibernate 框架默认使用的) 等,这么多的日志工具到底使用什么感到困惑。使用困惑:有的程序员即使知道写 Java 程序用什么日志工具,可能对日志记录具体应该怎么写,写什么东西,什么情况下要写,这些仁
者见仁智者见智的东西也会产生困惑。 五、Java 日志演化历史 最先出现的是 Apache 开源社区的 Log4j,这个日志确实是应用最广泛的日志工具,成为了 Java 日志的事实上的标准。然而,当时 Java 的开发主体 Sun 公司认为自己才是正统,在 Jdk1.4 中增加了 JUL 日志实现,企图对抗 Log4j,但是却造成了 Java 目
前开发者记录日志局面的混乱,迄今为止仍饱受诟病。想象下你的项目应用使用 Log4j,然后使用了一个第三方库,而第三方库使用了 JUL,那么,你的应用就得同时使用 Log4j 和 JUL 两个
日志工具了,然后又有需要使用另外一个第三方库,但是这个第三方库使用了 Log4j 和 JUL 之外的simplelog。这个时候你的应用里各种log
工具满天飞,这势必会使你的程序员感到崩溃。因为这些日志工具互相没有关联,替换和统一日志工具也就变成了比较 棘手的一件事情。为了搞定这个日常开发中比较棘手的问题,Apache 提供了一个日志框架作为日志的抽象,名字为 JCL。JCL 对各种日志接口进行抽象,
目录
一、如何描述一个BUG?
二、BUG级别的定义
1.崩溃
2.严重
3.一般
4.次要
三、BUG的生命周期
一、如何描述一个BUG? 1.版本号(代码版本号)
2.测试环境/平台
不同的浏览器对同一个页面解析是不一样的:
①Windows、MAC等;
②Firefox、Chrome、Edge、360、搜狗等以及浏览器对应的版本号;
③IOS、Android等;
3.测试步骤和测试数据
4.实际运行结果
5.预期运行结果
6.附件(错误截图、错误日志等)
二、BUG级别的定义 1.崩溃 系统运行阻断,严重的影响了开发人员和测试人员的工作,需要立即修复;
问:线上出现崩溃级别的BUG怎么办?
答:回退到一个稳定的版本。
2.严重 系统还可以运行,但是已经不稳定了,如果再运行下去,可能会产生严重的后果;
3.一般 系统可以稳定的运行,但是一些次要功能没有实现,可能会影响客户的体验;
4.次要 影响用户的视觉体验,界面的文字提示内容,展示,图片排版,要不要改得和产品经理商量;
三、BUG的生命周期 问:
测试人员提了一个BUG,开发人员已经修改,但测试人员测试时,发现BUG依然存在,为什么?
答:
①开发人员可能没修改好;
②开发人员没有把代码更新到测试环境;
③测试人员忘拉取最新的代码到测试环境进行发布。
1、离线安装Jenkins 防火墙开放端口
firewall-cmd --zone=public --add-port=8080/tcp --permanent firewall-cmd --reload firewall-cmd --zone=public --list-ports 一、离线安装jenkins
可以自行到官网下载,链接如下:
https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.324/jenkins.war https://www.oracle.com/java/technologies/downloads/#java8 https://mirrors.huaweicloud.com/java/jdk/ https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.73/bin/apache-tomcat-8.5.73.tar.gz 上传安装包:
1、安装jdk 要安装的项⽬(jenkins)是由java语法开发,需要安装java语⾔的编译器,系统才能识别。
tar -xf jdk-8u311-linux-x64.tar.gz vim ~/.bash_profile export JAVA_HOME=/home/cmq/jdk1.8.0_311 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar source ~/.bash_profile java -version 2、安装Tomcat,启动jenkins tar -xf apache-tomcat-8.5.73.tar.gz cp jenkins.war apache-tomcat-8.5.73/webapps/ cd apache-tomcat-8.5.73/bin/ ./startup.sh 3、配置jenkins .jenkins文件夹中解压插件的意义:
/root/.jenkins:该位置是默认插件放置的位置,如果不自己解压添加插件文件,启动jenkins的时候会提示让手动选择安装哪些插件。这样是为了跳过这一步。
访问jenkins:
http://192.168.104.32:8080/jenkins/ 按提示找到密码,输入密码,继续
选择插件来安装 点击无,不要选择插件安装 创建管理员用户 保存并完成 2、离线安装插件 1. 去官网下载插件
Jenkins Plugins
2. 搜索指定插件名
3. 点击要安装的插件
4. 进行下载
5. 下载后,根据官网给出的说明进行安装,此处选择直接从页面安装
系统管理-》插件管理-》高级-》上传插件
(by 亲持红叶) CATLOG 文章目录 CATLOG一、基础1.1、一元一次方程1.2 、上下标1.3、求和1.4、分数1.5、矩阵1.6、希腊字母1.7、省略号1.8、大括号1.8、大大括号1.9、多行公式 二、数学公式2.1、傅里叶级数2.2、高斯公式2.3、定积分2.4、和的展开式2.5、三角恒等式2.6、欧拉公式2.7、格林公式2.8、伯努利方程2.9 、全微分方程2.10 、非齐次微分方程通解2.11、柯西中值定理2.12、拉格朗日中值定理2.13、曲面面积2.14、重积分2.15、arcsinx 求导2.16、泰勒级数2.17、三角函数积分2.18、二次曲面2.19、二阶微分2.20、方向导数 三、公式3.1、练习一3.2、练习二3.3、练习三3.4、练习四 四、其他的一些例子 基础推荐
https://zhuanlan.zhihu.com/p/261750408
一、基础 1.1、一元一次方程 $$ y = a+bx $$ y = a + b x (1) y = a+bx \tag 1 y=a+bx(1)
1.2 、上下标 $$ y = a + b_{ij}^2 $$ y = a + b i j 2 (2) y = a + b_{ij}^2\tag 2 y=a+bij2(2)
1.3、求和 $$ \sum_{i=0}^n(x_i^2+y_j^3) $$ ∑ i = 0 n ( x i 2 + y j 3 ) (3) \sum_{i=0}^n(x_i^2+y_j^3)\tag 3 i=0∑n(xi2+yj3)(3)