首先,最新的Debian9阿里云源如下(底下这个源是正确的,在阿里云评论区里找到的,阿里云官网上面的是旧的,是不行的):
deb http://mirrors.aliyun.com/debian-archive/debian stretch main contrib non-free deb http://mirrors.aliyun.com/debian-archive/debian stretch-backports main deb http://mirrors.aliyun.com/debian-archive/debian-security stretch/updates main deb-src http://mirrors.aliyun.com/debian-archive/debian stretch main deb-src http://mirrors.aliyun.com/debian-archive/debian stretch-backports main deb-src http://mirrors.aliyun.com/debian-archive/debian-security stretch/updates main 但是运行:apt update 时第二条会出现 NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D 需要公钥的问题
解决方法: 安装最新版本的 debian-archive-keyring 即可 》apt-get install debian-archive-keyring 然后,再运行 apt update 就正常了 》apt update ---------------- 其它参考 ----------------
阿里云所有镜向源地址(debian,centos,ubuntu等):阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区
1、什么是Nacos Nacos是阿里的一个开源产品,是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案,用来实现配置中心和服务注册中心。
Nacos 快速开始
2、安装运行nacos nacos下载地址
下载地址: https://github.com/alibaba/nacos/releases
zip为Windows压缩包 tar.gz为linux压缩包
个人百度网盘分享链接:https://pan.baidu.com/s/1RTNA0Gx5chpyb-HXCOuJuw?pwd=8848 提取码:8848 下载解压后运行nacos 进入bin目录 执行下面命令即可 -m为启动模式,设置为单机模式运行
startup.cmd -m standalone
如果不想每次输入-m standalone可以右键startup.cmd使用文本打开修改配置即可
这样我们只需要双击startup.bat文件即可自动在单机模式下运行nacos
默认端口8848 浏览器访问localhost:8848/nacos即可进入nacos控制台 账号密码默认都是nacos
3、Nacos注册中心的使用 将微服务注册到nacos
准备了两个微服务分别是订单微服务和商品微服务
需要引入的依赖为
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.5.RELEASE</version> </dependency> 3.1在application.yml文件中需要配置服务名称和nacos连接地址 注意:服务名称不能重复 服务名称不能没有 重复则nacos视为一个服务 没有nacos扫描不到则服务列表不显示
spring: application: name: product-service cloud: nacos: discovery: server-addr: localhost:8848 3.2在启动类是加上注解@EnableDiscoveryClient(不加也可以) @SpringBootApplication @EnableDiscoveryClient public class OrderServer { public static void main(String[] args) { SpringApplication.run(OrderServer.class,args); } } 启动两个微服务
观察nacos控制台在服务列表可以看到刚刚启动的两个微服务
4、Nacos注册中心的原理 Nacos将服务可以分为服务消费者和服务提供者 在我的项目中现在有订单和商品微服务,在订单服务中需要调用商品服务查询商品信息
概述 业务中经常会遇到一些延迟执行的需求;通常想到的都是rabbitmq或者rocketmq的延迟消息;
但是系统中不一定集成了mq,但为了控制分布式下的并发,一般redis都是有集成的;
redis的key过期监听那个时间不准确,在集群环境下节点挂了也容易丢失;
那么用redisson的延迟队列,正好可以用来解决轻量级的延时消息;
简单的来说就是消费者生产了一个消息任务,塞到ZSet里(用当前时间戳+延迟时间作为分数),等时间到了,就会放到任务List中,然后消费者真正去执行任务都是从任务List中获取任务;
redisson中的消费者并不是一直轮询获取任务;而是有具体时间的延迟任务,时间到了去任务队列中获取任务;
注意点,在消费者监听处如果使用thread相关操作因为redisson的默认线程name为redisson-netty会抛异常,我的处理方式是把相关操作都放到自己的线程池中操作.
官方解释是在netty线程中调用同步方法可能会导致超时;
issue:https://github.com/redisson/redisson/issues/3549
异常见源码
org.redisson.command.CommandAsyncService.get(org.redisson.api.RFuture<V>) 版本
redisson:redisson-spring-boot-starter-3.17.6.jar
redis:6.2.7
redisson延时任务机制简述 生产者先将任务push到delay_queue_timeout等待队列中,延迟时间到了,消费者会把任务从timeout队列挪到SANYOU任务队列中(消费者实际获取任务的队列),然后消费者就能拿到最终要执行的任务了;
这里具体要说的就是客户端通知和获取机制;
消费者在启动时通常都会去get一下队列,达到订阅队列的目的;
RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("SANYOU"); RDelayedQueue<String> delayQueue = redissonClient.getDelayedQueue(blockingQueue); 这样做的目的:
消费者订阅队列,从delay_queue_timeout等待延迟队列中将已经到达时间的任务挪到真正的任务List队列中,然后再将delay_queue_timeout队列中第一个(也就是第一个要执行的)的任务的时间拿到,用这个时间开启一个延迟任务,时间到了之后,会发布一个消息到时间通知channel中;然后客户端监听到这个channel中的消息后,会再次重复上述步骤,让delay_queue_timeout中的任务,可以都放到真正的任务List队列中;
这样有一个好处就是不用一直while扫描等待,客户端的延迟任务时间和delay_queue_timeout中的延迟时间是一样的,可以精准利用cpu,理论上是没有延迟的,但是实际消息数量大量增加,消费者消费比较慢,还是会造成延迟任务消费延迟;
另外由于客户端都是用lua脚本去redis的同一个List队列中获取任务,lua脚本在redis中都是原子任务,而且redis真正的操作是单线程的,所以不会存在任务广播情况(并发获取时,一个任务不会被多个消费者同时拿到);
捞一张图片
代码Demo import cn.hutool.extra.spring.SpringUtil; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RBlockingDeque; import org.redisson.api.RBlockingQueue; import org.redisson.api.RDelayedQueue; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Slf4j @Component public class RedissonDelayQueueConfig implements InitializingBean { @Resource private RedissonClient redissonClient; //延时队列map private final Map<String, RDelayedQueue<DelayMessageDTO>> delayQueueMap = new ConcurrentHashMap<>(16); /** * 消费者初始化所有队列,订阅对应的队列,并开启第一个过期任务的过期时间对应的延迟任务 */ @PostConstruct public void reScheduleDelayedTasks() { DelayQueueEnum[] queueEnums = DelayQueueEnum.
☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░ 一、引言 在2021年6月22日发布《《数字图像处理》第三章学习总结感悟1:灰度变换与空间滤波概念及常用灰度变换方法介绍》之后,老猿就暂停了数字图像处理的学习,而是开始重新学习(本来应该是复习,可是以前的高数知识完全忘光了)高数中的导数、微分、不定积分和定积分相关知识,主要是因为在学习直方图处理中碰到了定积分相关的知识,而这些知识老猿一点概念都没有了。不过总算是过来了,今天我们继续开始图像处理的学习。如果对定积分知识不记得或不知道的,请通过老猿的专栏《人工智能数学基础》进行学习。
二、直方图处理 2.1、直方图(histogram)处理概述 灰度级(intensity levels)范围为[0,L-1]的数字图像的直方图可以用一个离散函数(discrete function)h(rk)=nk表示(此两处中的k原文是下标k,为了书写简便,没有用下标形式,特此说明,下同),其中rk是第k级灰度值,nk是图像中灰度为rk的像素个数。
假设M和N是图像的行数和列数,乘积MN表示的图像像素的总数,在实践中,常用每个灰度级的像素个数除以MN来归一化直方图(normalized histogram)。因此,归一化后的直方图由p(rk)=nk/MN给出,其中k=0、1、…、L-1,归一化直方图的所有分量之和应等于1。简单地说,p(rk)是灰度级在图像中出现的概率的一个估计。
直方图是多种空间域(spatial domain)处理技术的基础。直方图操作(Histogram manipulation)可用于提供有用的图像统计(image statistics)信息、图像增强(image enhancement)、图像压缩与分割。
直方图在软件中计算简单,而且有助于商用硬件实现,因已成为实时图像处理的一种流行工具。
作为灰度变换的直方图处理的介绍,我们考虑下面的图3.16:
图3.16是《《数字图像处理》第三章学习总结感悟1:灰度变换与空间滤波概念及常用灰度变换方法介绍》3.5.2节( 分段线性变换应用1–对比度拉伸)中的花粉图像(pollen image)。
图3.16所示的以4个基本灰度级为特征的花粉图像:暗图像(dark image)、亮图像(light image)、低对比度图像(low contrast image)和高对比度图像(high contrast image)。图的右侧显示了与这些图像对应的直方图,每个直方图的水平轴对应于灰度值rk,垂直轴对应于值h(rk)=nk,或归一化后的值p(rk)=nk/MN。
因此直方图就可以简单地被看成是对应于rk的h(rk)=nk或p(rk)=nk/MN的图形。
从图3.16可以看出:
在暗图像中,直方图的分量集中在灰度级的低(暗)端亮图像直方图的分量则倾向于灰度级的高端低对比度图像具有较窄的直方图,且集中于灰度级的中部。对于单色图像,这意味着暗淡,好像灰度被冲淡了一样高对比度图像中直方图的分量覆盖了很宽的灰度级范围,而且像素的分布没有太不均匀,只有少量垂线比其他的高许多 直观上,可以得出这样的结论:若一幅图像的像素倾向于占据整个可能的灰度级并且分布均匀,则该图像会有高对比度的外观,并展示灰色调的较大变化。最终效果将是一幅灰度细节丰富且动态范围较大的图像。
实际上,仅仅依靠输入图像直方图中的可用信息就可开发出一个变换函数来自动地实现这种效果,在下面的直方图均衡中将介绍与此相关的内容。
直方图处理涉及直方图均衡、直方图匹配、局部直方图处理、图像增强中使用直方图统计等内容,而且涉及相关的数学知识,这部分将分为多篇博文进行介绍,相关内容随着后续的介绍逐渐补充。
2.2、直方图处理博文目录 本文涉及一系列博文,将逐渐更新(其中带星号的为付费专栏文章):
人工智能数学基础:两个存在映射关系的随机变量的概率密度函数关系研究数字图像直方图处理涉及的数学知识介绍数字图像处理:图像直方图基础知识介绍 《数字图像处理》第三章学习总结感悟2-1:直方图均衡处理*《数字图像处理》直方图均衡学习总结+感悟*数字图像处理:直方图匹配或规定化Histogram Matching (Specification)原理及感悟数字图像直方图匹配或规定化Histogram Matching (Specification)处理数字图像处理:局部直方图处理(Local Histogram Processing)温故而知新:直方图均衡、直方图匹配的再次理解数字图像处理:使用直方图统计进行图像增强OpenCV-Python图像直方图计算详解、示例及图形呈现数字图像处理:OpenCV-Python中的直方图均衡知识介绍及函数equalizeHist详解*数字图像处理:OpenCV直方图均衡算法研究及模拟实现OpenCV-Python自适应直方图均衡类CLAHE及方法详解OpenCV-Python对比度受限的自适应直方图均衡CLAHE知识介绍OpenCV自适应直方图均衡CLAHE图像和分块大小不能整除的处理OpenCV自适应直方图均衡CLAHE C++源代码分享OpenCV自适应直方图均衡CLAHE的clipLimit的含义及理解OpenCV自适应直方图均衡CLAHE的裁剪处理过程*计算机视觉算法探究:OpenCV CLAHE 插值算法详解 三、小结 本文及其子系列文章介绍了数字图像处理有关的概念、数学知识以及直方图均衡、直方图匹配、局部直方图处理、图像增强中使用直方图统计等内容,方便详细学习数字图像处理的直方图处理。
更多图像处理请参考专栏《OpenCV-Python图形图像处理》及《图像处理基础知识》的介绍。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《 专栏:Python基础教程目录》从零开始学习Python。
如对文章内容存在疑问或需要相关资料,可在博客评论区留言,或关注:老猿Python 微信公号发消息咨询,可通过扫二维码加微信公众号。
写博不易,敬请支持: 如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
关于老猿的付费专栏 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.
门锁控制电路 二、设计思路
电路设计
1.电源部分:使用BATTERY为整个电路提供电源,可以在电路中加入一个电 源开关,以便控制电源的开启和关闭。
2.处理器部分:使用AT89C51芯片作为主处理器,通过编写程序实现门锁的 控制。AT89C51芯片具有丰富的I/O端口,可以方便地与外部器件进行通信。
3.按键输入部分:使用KEYPAD-SMALL实现按键输入。设计一个简单的矩阵 键盘,包括数字0-9、确认键、取消键和解锁键等。当用户按下相应的按键 时,处理器将接收按键输入并执行相应的操作。
4.显示部分:使用LM016L液晶显示屏显示当前门锁的状态和操作提示等信 息。处理器通过液晶驱动器与LM016L连接,控制显示的内容和方式。
5.电机驱动部分:使用L293D电机驱动芯片驱动MOTOR,实现门锁的开关操 作。处理器通过输出口连接L293D的输入引脚,控制电机的转动方向和速度。
#include<reg51.h> typedef unsigned char u8; typedef unsigned int u16; sbit RS = P3^0; sbit EN = P3^1; sbit IN1 = P3^2; sbit IN2 = P3^3; #define KEY P1 #define DIS P2 void delay_10us(u8 ten_us) { while(ten_us--); } u8 get_key() { u8 key_value = 16; KEY = 0xF7; if(KEY!=0xF7) { delay_10us(1000); switch(KEY) { case 0x77: key_value = '+';break; case 0xB7: key_value = '=';break; case 0xD7: key_value = '0';break; case 0xE7: key_value = 'c';break; } } while(KEY!
一款用GO语言编写的JS爬取工具~ 分享一个自己在实战过程中用的比较顺手的JS爬取工具
@Author: pingc0y https://github.com/pingc0y/URLFinder URLFinder URLFinder是一款用于快速提取检测页面中JS与URL的工具
通常用于快速查找隐藏在页面或js中的敏感或未授权api接口
功能类似于JSFinder,开发由来就是使用它的时候经常返回空或链接不全,作者还不更新修bug,那就自己来咯
URLFinder更专注于提取页面中的JS与URL链接,提取的数据更完善且可查看状态码、内容大小、标题等
基于golang的多线程特性,几千个链接也能几秒内出状态检测结果
有什么需求或bug欢迎各位师傅提交lssues
功能说明 1.提取页面与JS中的JS及URL链接(页面URL最多深入一层,防止抓偏) 2.提取到的链接会显示状态码、响应大小、标题等(带cookie操作时请使用-m 3 安全模式,防止误操作) 3.支持配置Headers请求头 4.支持提取批量URL 5.支持结果导出到csv文件 6.支持指定抓取域名 7.记录抓取来源,便于手动分析
结果会优先显示输入的url顶级域名,其他域名不做区分显示在 other 结果会优先显示200,按从小到大排序(输入的域名最优先,就算是404也会排序在其他子域名的200前面)
使用截图 单url截图(旧版截图)
批量url截图 (旧版截图)
使用教程 单url时使用
URLFinder.exe -u http://www.baidu.com -s all -m 2 URLFinder.exe -u http://www.baidu.com -s 200,403 -m 2 复制
批量url时使用
URLFinder.exe -s all -m 2 -f url.txt -o d:/ 复制
参数:
-h 帮助信息 (可以看到当前版本更新日期) -u 目标URL -d 指定获取的域名 -a 自定义user-agent请求头 -s 显示指定状态码,all为显示全部 -m 抓取模式: 1 正常抓取(默认) 2 深入抓取 (url只深入一层,防止抓偏) 3 安全深入抓取(过滤delete,remove等敏感路由) -c 添加cookie -i 加载yaml配置文件(不存在时,会在当前目录创建一个默认yaml配置文件) -f 批量url抓取,需指定url文本路径 -o 结果导出到csv文件,需指定导出文件目录(.
配置完log,启动项目的时候报错,查了下,记录
我的logging.json是这样 { "version": 1, # 配置文件版本号 "formatters": { "default": { "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s" # 默认的日志格式,包含时间、日志级别、模块和消息 } }, "handlers": { "console": { "class": "logging.StreamHandler", # 日志处理器的类,将日志输出到控制台 "level": "DEBUG", # 控制台处理器的日志级别为 DEBUG "formatter": "default", # 使用上面定义的 "default" 格式化器 "stream": "ext://sys.stdout" # 输出流为标准输出流 }, "file": { "class": "logging.handlers.RotatingFileHandler", # 日志处理器的类,将日志输出到文件 "level": "INFO", # 文件处理器的日志级别为 INFO "formatter": "default", # 使用上面定义的 "default" 格式化器 "filename": "logs/log", # 日志文件的名称(logs 目录下的 log 文件) "
弹窗页面展示信息
<uv-popup ref="leave" mode="top" round="20"> <view class="leave uni-flex uni-column space-around"> <view class="title uni-flex align-items">设备/网络信息权限使用说明</view> <view class="tabs"> 为保证您正常、安全地使用,需要获取设备信息及网络信息 </view> </view> </uv-popup> js代码
注释:
每个权限有唯一的缓存
不同的权限又不同的android.permission.
android.permission.ACCESS_NETWORK_STATE
// #ifdef APP if (!uni.getStorageSync('limitForWifiInfo') && plus.os.name === 'Android') { this.$nextTick(() => { this.$refs.leave.open(); }) } let _permissionID; _permissionID = 'android.permission.ACCESS_NETWORK_STATE' plus.android.requestPermissions([_permissionID], (e) => { if (e.granted.length > 0) { //当前查询权限已授权,此时可以通知页面执行接下来的操作 console.log('同意') this.$nextTick(() => { this.$refs.leave.close(); }) uni.setStorageSync('limitForWifiInfo', true) } else { //还未授权当前查询的权限,打开权限申请目的自定义弹框 console.log('禁止') this.
发现用print在console里面打不出来,所以查了一下关于pytest的log配置,记录
首先需要在根目录新建 pytest.ini
如果你只需要使用print打印日志的话,就只需要这样写
[pytest] addopts = -s #addopts 是一个配置项,用于指定传递给 pytest 的额外命令行选项。 #-s 是 pytest 的一个命令行选项,表示禁用输出捕获,允许测试中的 print 语句将输出直接打印到控制台。 #因此,这个配置告诉 pytest 在运行时使用 -s 选项,使得测试中的输出能够直接显示在终端上,而不是被 #pytest 捕获并隐藏。这在调试和查看详细信息时很有用。 就可以在pytest中在console中看到print打印的东西呢。
但是如果需要log配置的话。
[pytest] log_cli = true log_cli_level = INFO log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s) log_cli_date_format = %Y-%m-%d %H:%M:%S 然后在test中这样就可以使用了 import pytest import logging log=logging.getLogger(__name__) @pytest.fixture def xxxx(): ... yield xxxx def test_xxx(xxxx): log.error("Log Something") ... 如果要和flask的log全局配置结合使用,请参考我的另一篇blog:
Flask 3.x log全域配置(包含pytest)-CSDN博客
文章目录 参考描述动态组件子组件举个栗子切换组件 keep-alive子组件组件的再生成keep-aliveincludeexclude 生命周期钩子 参考 项目描述搜索引擎Bing哔哩哔哩黑马程序员VueJS 官方文档动态组件 & 异步组件 描述 项目描述Edge109.0.1518.70 (正式版本) (64 位)操作系统Windows 10 专业版@vue/cli5.0.8npm8.19.3VueJS2.6.14 动态组件 动态组件即动态切换组件,实现组件的动态切换可以使用 VueJS 提供的 component 元素,该元素拥有一个 is 属性。
你可以向 component 元素提供一个组件的名称来作为 is 属性的参数,接下来对应的组件将替代 components 元素。
子组件 在该部分内容中需要用到两个子组件,即 First.vue 及 Last.vue。接下来的内容中,如果没有特殊提示,First.vue 及 Last.vue 中的内容均如下所示。
First.vue
<template> <div class="container"></div> </template> <script> export default { } </script> <style scoped> .container{ width: 400px; height: 180px; background-color: dodgerblue; } </style> Last.vue
<template> <div class="container"></div> </template> <script> export default { } </script> <style scoped> .
电磁脉冲(Electromagnetic Pulse,简称 EMP)是一种突发性的电磁辐射,通常由高能量的电流脉冲产生。制作电磁脉冲需要特定的设备和技术,并且需要小心处理,因为它可能对电子设备和系统造成损坏。以下是一种常见的电磁脉冲制作方法:
高能量脉冲发生器:首先,需要一台高能量脉冲发生器来产生电流脉冲。这种发生器通常使用电容器和脉冲电源来存储和释放大量能量。它们可以产生高达数千伏的电压,并在极短的时间内释放电流脉冲。
辐射天线:接下来,需要一个合适的辐射天线来将电流脉冲转化为电磁辐射。辐射天线可以是天线阵列、螺旋天线或其他类型的天线,其设计和尺寸取决于所需的电磁脉冲特性。
激发装置:最后,需要一个激发装置来将电流脉冲传输到辐射天线。这通常涉及到设计适配器和传输线路,以确保电流能够有效地传输到天线。
当涉及到制作电磁脉冲时,需要具备以下一些基础知识:
电磁学基础:了解电磁场理论、电磁波传播以及天线设计等基本概念。
电子学基础:理解电路和电子器件的工作原理,包括电容器、电感器和开关等。
高压电源:了解高压电源的构造和原理,以及如何产生和控制高电压。
辐射天线设计:熟悉不同类型的天线,包括天线阵列、螺旋天线等,以及它们与电磁波的相互作用。
电磁兼容性(EMC):了解电磁脉冲对电子设备和系统的影响,以及如何减轻电磁干扰和保护设备。
安全措施:在进行任何电磁脉冲实验或操作时,必须遵循安全规范,包括防护设备、防止损坏设备、防止电磁辐射对人体的伤害等。
常见的高能量脉冲发生器设计方案包括:
储能型脉冲发生器(Capacitor Discharge Pulse Generator,简称CDPG):这种方案使用电容器储存能量,并通过放电来产生高能量脉冲。典型的设计包括充电电路、开关和放电电路等。
级联脉冲发生器(Cascade Pulse Generator):这种方案使用多个级联的电容器和开关来逐级放电,以达到更高能量的脉冲。每个级别的电容器充电至不同的电压,逐级放电产生级联效应。
脉冲形成网络(Pulse Forming Network,简称PFN):这种方案使用电容器和电感器等元件构成特定形状的脉冲波形。电容器充电后,通过开关放电,电感器和电容器之间的相互作用形成所需的脉冲形状。
这些仅是常见的高能量脉冲发生器设计方案的一部分,具体的设计方案和技术取决于所需的脉冲参数和应用场景。
文章目录 cookiecookie 的定义cookie如何产生与存储cookie 的使用限制cookie构成JavaScript脚本处理cookiecookie使用注意事项 web StoragesessionStorage特点语法 localStorage代码示例 localStorage与 sessionStorage 异同点 小结 cookie cookie 的定义 HtTTP cookie 也称为 cookie,中文翻译过来就是曲奇、小甜饼的意思。最初用于在客户端存储会话信息。cookie 在浏览器中,通常以键值对的形式存储。
cookie如何产生与存储 cookie 既然是用来存储会话信息的,就是说,他是和服务器之间建立的会话。
在浏览器某一个网站应用发起一个请求的时候,服务器会在响应的HTTP 请求时,通过创建一个set-cookie 的头部信息,告诉客户端,需要将set-cookie 包含的键值对存储起来,这个就是cookie的由来。
其中 HTTP 响应头格式如下所示,cookie 的键值对为name=value
HTTP/1.1200 OK Content-type: text/html Set-Cookie: name=value Other-header: other-header-value 当下一次这个网站请求服务器接口的时候,浏览器就是将cookie 对应的值添加到请求中,这样服务器通过cookie ,就知道是哪一个客户端发起的请求,cookie用于标识客户端
cookie 的使用限制 cookie 受同源策略限制,其与特定的域名绑定的,不能跨源使用。cookie 在浏览器创建的时候,就和客户端所对应的URL (协议、端口,域名)绑定,其他的域名不能使用这个cookie、
除了同源策略的限制外,cookie本身能存储的信息也受限制,还有以下规则
每个cookie 不能超过4096字节,也就是4kb每个域不能超过20个cookie 如果某些域超过了这些限制的上限,浏览器会删除之前的cookie。有些浏览器随机删除,有些会将最少使用的删除。
cookie构成 cookie 整体有以下的部分构成
名称:名称不区分大小写
值:以字符串形式存储值
域
cookie有效的域,表明cookie只能作用与这个域,发送到这个域的所有请求都包含对应的cookie。可以设置成包含子域,默认是不包含。
路径
请求URL地址包含这个路径才会把cookie发送到服务器,例如指定cookie 只能有http://www.a/book/ 访问,因此访问http://www.a/ 不会发送cookie,即使是一个域。
过期时间
表示将在什么时候,这个cookie 将会失效,被删除。超过这个时间戳,就不会发送浏览器。默认情况下,浏览器结束回话后,会删除所有cookie,不过,可以设置cookie 的有效时间,这个值为GMT格式(Wdy,DD-MM-YYYY HH:SS GMT),即使关闭回话,没有超过这个时间,cookie 都是存在客户端的。
文章目录 概要XSS(Cross-site scripting:跨站脚本攻击)存储型 XSS反射型XSS代码例子容易发生XSS攻击的情形基于DOM的XSS 跨站请求伪造(CSRF)防御措施对XSS 攻击的防御方案对用户输入过滤和转义使用HTTP Only Cookie使用Content Security Policy(CSP)对用户权限进行严格控制 对CSRF(跨站伪造请求)防御方案验证 HTTP Referer字段 使用Token验证使用验证码 小结 概要 关于前端的网络攻击,有以下两种是最为常见的
Cross-site scripting:跨站脚本攻击
跨站请求伪造(CSRF)
下面分别介绍两种攻击方式
XSS(Cross-site scripting:跨站脚本攻击) 跨站脚本攻击是一种安全漏洞,攻击者可以利用漏洞,向网站注入恶意的客户端代码。
如果受害者在没有察觉中运行这些恶意代码,攻击者就可以突破网站的访问限制,以受害者身份,去操作网站上任何可执行的操作,或者读取受害者在目标网站上的个人信息、cookie、session tokens 等网站验证信息。
XSS 攻击有三种类型,分别如下:
存储型 XSS 存储型XSS,攻击者提交了带有恶意脚本的内容到服务器,这个内容保存到数据库。当其他用户访问这个网站后,内容被这些用户获取,恶意代码便可以在这些用户客户端运行,发起攻击。
反射型 反射型也称为“非持久型XSS” ,它需要靠被攻击者服务器,将用户输入的数据反射回来给浏览器。
攻击者会构造一个包含恶意脚本的URL,并将此URL 发送给用户。当用户点击打开这个URL 时,服务器会将有恶意代码的内容返回到浏览器并运行,达到攻击目标。
这种方式不将恶意脚本存储在被攻击的服务器,而是拼接在URL中,并最后随着操作结果返回到受害者浏览器。通过欺骗浏览器信任此恶意脚本,执行窃取个人身份信息如cookie 等发送到攻击者的服务器。
举例来说,如果一个用户在登录某个Web应用程序后获得了一个cookie,攻击者可以将含有恶意代码的URL发送给用户。
当用户打开这个URL时,Web服务器会执行该URL中的请求,并将恶意代码以请求结果返回给用户浏览器,浏览器执行URL中包含的JavaScript代码。这样,攻击者就可以利用这段恶意代码将用户的cookie信息发送到他们控制的服务器上,进而实现非法登录等恶意行为。
XSS代码例子 下面的地址中,欢迎XXX 是根据URL 的参数name 的值来确定的,是一个动态内容。当我们改变name的值的时候,HTML 显示的值也会变成name对的值。
<!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <script> window.alert = function() //这里是显示一条指定消息和一个确认按钮的警告框 { confirm("完成的不错!");//指定消息完成得不错! window.location.href="level2.php?keyword=test"; //刷新当前页面,并且重定向到level2 } </script> <title>欢迎来到level1</title> </head> <body> <h1 align=center>欢迎来到level1</h1> <h2 align=center>欢迎用户test</h2><center><img src=level1.
这些是一些常见的命令和功能,用于在命令行界面中进行文件和目录的创建、删除、复制、移动和搜索。
cd ..:这个命令用于切换到当前目录的父目录。它可以帮助在目录层次结构中向上导航。例如,如果当前目录是 /home/user/documents,使用 cd .. 命令将切换到 /home/user 目录。
cd + 目录:这个命令用于切换到指定的目录。您需要提供目录的路径作为参数,可以是相对路径(相对于当前目录)或绝对路径(完整的目录路径)。例如,cd documents 将切换到当前目录下的 documents 目录。
dir:这个命令用于查看当前目录下的文件和文件夹列表。在 Windows 上,相当于 ls 命令。它会列出当前目录下的所有文件和子目录的名称。
cls:这个命令用于清空命令行窗口中的内容,实现清屏效果。在 Windows 上,相当于 clear 命令。
上键/下键:这个功能用于在命令行中浏览之前输入的命令。按上键可以查看之前输入的命令历史记录,按下键可以浏览较新的命令。
Tab 键:在命令行中按下 Tab 键可以自动补齐命令或文件名。它可以帮助您快速输入长命令或者确保正确输入文件名。
常见的命令和功能:
mkdir:这个命令用于创建新的目录。您需要提供目录的名称作为参数,例如 mkdir new_directory 将在当前目录下创建一个名为 “new_directory” 的新目录。
rm:这个命令用于删除文件或目录。要删除文件,您可以使用 rm 文件名 命令,例如 rm file.txt 将删除名为 “file.txt” 的文件。要删除目录及其内容,您可以使用 rm -r 目录名 命令,例如 rm -r directory 将删除名为 “directory” 的目录及其所有内容。
cp:这个命令用于复制文件或目录。要复制文件,您可以使用 cp 源文件 目标文件 命令,例如 cp file.txt new_file.txt 将复制名为 “file.txt” 的文件并将其命名为 “new_file.txt”。要复制目录及其内容,您可以使用 cp -r 源目录 目标目录 命令,例如 cp -r directory new_directory 将复制名为 “directory” 的目录及其所有内容并将其命名为 “new_directory”。
解决办法:
yarn config set ignore-engines true 具体参考文章:解决yarn install报错:error @achrinza/node-ipc@9.2.2: The engine “node“ is incompatible _ 潘子夜个人博客
原生的 Cesium中提供了绘制圆柱的方法,看似没有提供绘制圆锥的方法,其实在配置项里面可以直接设置参数生成圆锥,在cylinder对象里面有两个参数,topRadius:上底面的半径(如果为0则是圆锥啦);bottomRadius:下底面的半径 ;
import * as Cesium from "cesium"; let cylinderNum = 0; /** * 圆柱/圆锥实体 */ class CylinderGraphics { /** * 加载方法 * @param {Object} parameter -实体默认配置项 * @param {Number} i -判断是否为圆锥,i等于true则上底面半径为0,i等于false则上底面半径等于下底面半径 * @param {Array} parameter.clickPointH -底面圆点的坐标经纬度高程数组 * @param {Number} [parameter.radius] -下底面圆的半径(单位:米) * @param {Cesium.Viewer} parameter.viewer -地图主窗口 * @param {Number}[parameter.numberOfVerticalLines] -沿轮廓的周长绘制的垂直线的数量,数量越多越圆滑,默认20条 * @return {Cesium.Entity} -返回圆柱/圆锥实体 */ draw(parameter, i) { let xy = parameter.clickPointH; let l = parameter.radius; let v = parameter.
1.根据entity对象直接删除;
viewer.entities.removeAll();
2.根据entity的id删除对象;
viewer.entities.removeById(id);
3.直接全部删除所有的entity对象;
viewer.entities.remove(obj);
/** * entity实体删除类 */ class removeEntity { /** * 据entity(实体)对象删除方法 * @param {Cesium.Viewer} viewer -地图主窗口 * @param {Object} obj -entity实体对象 */ removeByObj(viewer, obj) { viewer.entities.remove(obj); } /** * 据entity(实体)对象id删除方法 * @param {Cesium.Viewer} viewer -地图主窗口 * @param {Object} id -entity实体对象id */ removeById(viewer, id) { viewer.entities.removeById(id); } /** * 删除全部entity实体方法 * @param {Cesium.Viewer} viewer -地图主窗口 */ removeAllEntity(viewer) { // 删除全部entity实体 viewer.entities.removeAll(); } } export default removeEntity;
1.数据准备:
包括要绘制的围栏坐标以及围栏高度,以及纹理材质中要提供的图片,图片在将在文章顶部展示👆
let positions = [ [ 106.54093483238756, 37.73128859082618, 1287.2467035732923 ], [ 106.54096882123775, 37.73120923938572, 1285.23045636352 ], [ 106.54080469913156, 37.73116536856507, 1285.2307197571026 ], [ 106.54077328413864, 37.731250730122945, 1287.2464886557223 ], [ 106.54077950460314, 37.731249823726316, 1289.2465544884512 ] ]; // 围栏坐标,高度 this.addWalls(positions, 10); 2.调用初始化动态墙的方法,主要是运用了Primitive的材质渲染(GLSL语言) addWalls(positionLonLat, height) { let tempArr = []; let tempHeights = []; positionLonLat.forEach((e) => { tempArr.push(e[0], e[1]); tempHeights.push(e[2]); }); tempArr.push(positionLonLat[0][0], positionLonLat[0][1]); let source = // 着色器代码 "czm_material czm_getMaterial(czm_materialInput materialInput)\n\ {\n\ czm_material material = czm_getDefaultMaterial(materialInput);\n\ vec2 st = materialInput.
<a href="链接" >下载</a> 一个文件链接(一般是服务器上的某个文件),这个链接一般地址栏输入是预览,不是附件下载
如果想改成附件下载
1、后端处理,后端加上一个响应头 res.setHeader('Content-Dispostion', 'attachment', 'name.pdf') 然后当你访问这个链接,浏览器发现有这个相应头,会自动触发下载行为
2、a标签 加上 download属性 <a href="链接" download="文件名" >下载</a> 这种也可以,但是局限性太大,
如果这个文件的下载要求的是携带token,那a标签这种就不生效了(a标签没法携带token)。会成为预览
方案:a标签可以携带cookie,所以可以有另一种解决方法,在下载文件前,发送一个请求获取一个临时token通过cookie进行携带,
a标签下载是流式下载,会把服务器的文件像流水一样存储到本地磁盘,所以下载直接能看到下载,不会将文件缓存到浏览器,
3、写一个方法进行下载 (本质还是利用a标签进行下载) 这个方法可以是一个ajax请求,这个请求就可以携带token,然后将请求到的服务器文件转成blob,在创建一个a标签进行下载,
但是**这种是有问题的,**如果文件小还行,文件大了就会出现点击了下载,但是没有反应,过了几分钟后才出现了下载,
这种等待时间就是将服务器端的那个文件转成了blob,才进行a标签的流式下载,
//获取blob export function handleGetBlob(url) { // console.log(url) return new Promise((resolve) => { const xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.responseType = 'blob' xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.response) } } xhr.setRequestHeader('Cache-Control', 'no-cache') xhr.send() }) } /** * 下载入口 */ export function downloadFile(url, name) { return new Promise((resolve, reject) => { handleGetBlob(url) .
STL之vector容器的介绍与模拟实现 1. vector简介2. vector容器使用2.1vectord 定义2.2 vector iterator 的使用2.3 vector 空间增长问题2.4 注意事项 3. vector功能模拟实现3.1 架构搭建3.2 空间控制板块3.3 迭代器3.4 增加/删除数据3.5 运算符重载3.6构造/析构 4. 整体代码 所属专栏:C“嘎嘎" 系统学习❤️
🚀 >博主首页:初阳785❤️
🚀 >代码托管:chuyang785❤️
🚀 >感谢大家的支持,您的点赞和关注是对我最大的支持!!!❤️
🚀 >博主也会更加的努力,创作出更优质的博文!!❤️
1. vector简介 vector的文档介绍
vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素
进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自
动处理。本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小
为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是
一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大
小。vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存
储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是
对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增
长。与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末
尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list
统一的迭代器和引用更好。 2. vector容器使用 一下垒列出的都是一些比较重要的接口。
2.1vectord 定义 (constructor)构造函数声明接口说明vector()(重点)无参构造vector(size_type n, const value_type& val = value_type())构造并初始化n个valvector (const vector& x);(重点) 拷贝构造vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造 2.2 vector iterator 的使用 iterator的使用接口说明begin +end(重点)获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iteratorrbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator 2.