静态页的DOM结构(格式必须这样写,引入mui的css)
<div id="pullrefresh" class="mui-content mui-scroll-wrapper" class="maincon"> <div class="mui-scroll"> <div class="mui-table-view mui-table-view-chevron"> </div> </div> </div> 下面是js(一定要引入jquery.js以及mui的js)
$(function(){ //上拉加载下拉刷新 mui.init({ pullRefresh : { container:"#ouye",//待刷新区域标识,querySelector能定位的css选择器均可,比如:id、.class等 up : { height:50,//可选.默认50.触发上拉加载拖动距离 auto:false,//可选,默认false.自动上拉加载一次 contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容 contentnomore:'没有更多数据了',//可选,请求完毕若没有更多数据时显示的提醒内容; callback :pullupRefresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据; } } }); //加载更多 var counter = 1;//计数器 var Flag=true; data(); function data() { //业务 var result = ""; var byName = decodeURI($.getUrlVar('id'));// $.ajax({ type: 'post', url: "/commenc", async: false, dataType: "json", data: { gid:byName, page: counter }, success: function (data) { Flag=data.
$(document).on("mousewheel DOMMouseScroll", function (e) { var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) || // chrome & ie (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1)); // firefox s = $(window).scrollTop(); if(s != 0){ $('.nav_top').addClass('nav_box');//滚动条样式 } if (delta > 0) { // 向上滚 $('.nav_top').fadeIn(400);//导航条显示 $('.nav_top').addClass('nav_box'); if(s == 0){ $('.nav_top').removeClass('nav_box'); } } else if (delta < 0) { // 向下滚 $('.nav_top').fadeOut(400);//导航条隐藏 } });
作者:苏江同学 链接:https://www.jianshu.com/p/5fea30b25f0a 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
拜占庭将军问题很多人可能听过,但不知道是什么意思,本文从非专业的角度来讲讲,拜占庭将军问题到底是说什么的。
拜占庭将军问题(Byzantine Generals Problem),首先由Leslie Lamport与另外两人在1982年提出,很简单的故事模型,却困扰了计算机科学家们数十年。
故事大概是这么说的:
拜占庭帝国即中世纪的土耳其,拥有巨大的财富,周围10个邻邦垂诞已久,但拜占庭高墙耸立,固若金汤,没有一个单独的邻邦能够成功入侵。任何单个邻邦入侵的都会失败,同时也有可能自身被其他9个邻邦入侵。拜占庭帝国防御能力如此之强,至少要有十个邻邦中的一半以上同时进攻,才有可能攻破。
然而,如果其中的一个或者几个邻邦本身答应好一起进攻,但实际过程出现背叛,那么入侵者可能都会被歼灭。
于是每一方都小心行事,不敢轻易相信邻国。这就是拜占庭将军问题
在拜占庭问题里,各邻国最重要的事情是:所有将军如何能过达成共识去攻打拜占庭帝国。
达成共识并非坐下来开个会那么简单,有的将军心机深不可测,口是心非,如果有叛徒,可能会出现各种问题:
叛徒可能欺骗某些将军自己将采取进攻行动。 叛徒可能怂恿其他将军行动。 叛徒可能迷惑其他将军,使他们接受不一致的信息,从而感到迷惑。
针对拜占庭问题的深入研究,科学家们得出一个结论:如果叛徒的数量大于或等于1/3,拜占庭问题不可解。
解释过程可以用一个副官模型来解释:
假设只有3个人,A、B、C,三人中如果其中一个是叛徒。当A发出进攻命令时,B如果是叛徒,他可能告诉C,他收到的是“撤退”的命令。这时C收到一个“进攻”,一个“撤退“,于是C被信息迷惑,而无所适从。
如果A是叛徒。他告诉B“进攻”,告诉C“撤退”。当C告诉B,他收到“撤退”命令时,B由于收到了司令“进攻”的命令,而无法与C保持一致。
正由于上述原因,在只有三个角色的系统中,只要有一个是叛徒,即叛徒数等于1/3,拜占庭问题便不可解。
当然,只要叛徒数小于1/3,问题还是可解的。
科学家们提出了口头信息方案和书面协议两个方案。
解决方案一:用口头信息 口头信息即使将军们派人用口信传达消息,口头传达消息的实际含义指的是:
每个被发送的消息都能够被正确投递 信息接受者知道消息是谁发的 沉默(不发消息)可以被检测 口头协议的算法很简单,如果其中一个节点,比如1发布消息出去,210都接受到1的消息,然后210也分别转告给其他的节点,每个节点都是信息的转达者,一轮下来,每个节点手上都会有10个信息(进攻或者撤退),有叛徒的话,那信息可能有进攻或者不进攻的不一致消息。每个人相当于手里有一本消息的账本,该怎么决策呢?如果有一半以上的人说进攻,那么采取进攻行动就是能成功的,所以这时即便有叛徒,只要听大部分人的,少数服从多数来行动即是有利的。
这种口头协议的算法也存在明显的缺点:口头协议并不会告知消息的上一个来源是谁,也就是消息不可追根溯源,出现信息不一致也很难找到叛徒在哪。
解决方案二:用书面协议 可以假设10个国家,每个国家都可以派人向各个国家派信,比如一起约定 “某天早上六点,大家一起进攻拜占庭,同意就签个字”。收到信的国家如果同意的话,就可以在原信上签名盖章。
书面协议相比口头协议,实际说的是在这个多人的将军模型中加了了个隐含条件:
将军们能够使用签名技术,签名不可伪造,一旦篡改即可发现。 同时任何人都可以验证签名的可靠性。 书面协议相比口头协议,所有的消息都是有记录的,解决了追根溯源的问题。
但在现实中仍然可能面临各种问题:
中世纪的邻邦之间沟通只能靠信使骑马,将军们互不信任,也不可能亲自聚在一起开会,物理距离导致信息传输延迟。
真正可信的签名体系难以实现。签名造假的问题也没法避免。
签名消息记录的保存难以摆脱中心化的机构。
另外,倘若每个国家都各自向其他9个国家派出信使,在这个网络即需要90次的传输才能完成一轮信息交流,但是每个国家可能回馈不同的进攻时间,在这种异步通信的条件下,要能协商一致是个大问题。
也就是如果能够依赖中心化可信的机构,也许能通过多方的签名记录整合在一起,更容易地实现9个国家的意见统一,但这是个伪假设,因为前提是这个网络就是互不信任的。
这就是一个由互不信任的各个邻邦国家所构成的分布式网络,要获得最大的利益,又必须一起努力才能完成,如何达成一致的共识,变成了一个难题。
莱斯利·兰伯特提出了“拜占庭将军问题”,但真正解决这以难题的是——中本聪。
终极解决方案:区块链技术 互联网的存在,首先降低了信息的流通成本。每个将军配一台电脑,就解决了”书面协议“中骑马通讯造成时间延迟的问题。
如果10个将军中的几个同时发起消息,势必会造成系统的混乱,造成各说各的攻击时间方案,行动难以一致。
谁都可以发起进攻的信息,但由谁来发出呢?中本聪巧妙地在个系统加入了发送信息的成本,即:一段时间内只有一个节点可以传播信息。
它加入的成本就是”工作量“——节点必须完成一个计算工作才能向各城邦传播消息,当然,谁第一个完成工作,谁才能传播消息。
当某个节点发出统一进攻的消息后,各个节点收到发起者的消息必须签名盖章,确认各自的身份。中本聪在这里引用现代加密技术为这个信息签名。
这种加密技术——非对称加密完全可以解决古代难以解决的签名问题:
消息传送的私密性 能够确认身份 签名不可伪造、篡改 非对称加密算法的加密和解密使用不同的两个密钥.这两个密钥就是我们经常听到的”公开密钥”(公钥)和”私有密钥”(私钥).
公钥和私钥一般成对出现, 如果消息使用公钥加密,那么需要该公钥对应的私钥才能解密; 同样,如果消息使用私钥加密,那么需要该私钥对应的公钥才能解密.
非对称加密的作用是:保护消息内容, 并且让消息接收方确定发送方的身份.
比如,将军A想给将军B发送消息,为防止消息泄露,将军A只需要使用B的公钥对信息加密,而B的公钥是公开的,B只需要用只有他自己只的私钥解密即可。
将军B想要在信件上声明自己的身份,他可以自己写一段”签名文本“,并用私钥签名,并广播出去,所有人可以根据B的公钥来验证该签名,确定的B的身份。
由此,一个不可信的分布式网络变成了一个可信的网络,所有的参与者可以在某件事在达成一致。
写到这里,同时终于明白了工作量证明(Proof Of Work)的意义。有人说挖矿浪费了巨大的社会资源,但建立信任的成本可不是0,挖矿是维护比特币网络可靠性的最好办法。
I was also facing the same issue
remote: Repository not found fatal: repository 'https://github.com/MyRepo/project.git/' not found remote: Repository not found. fatal: repository 'https://github.com/MyRepo/project.git/' not found
I uninstalled the git credentials manager and reinstalled it and then I could easily pull and push to the repository. Here are the commands
$ git credential-manager uninstall $ git credential-manager install
前两天突然发现自己一直以来对相对路径绝对路径的理解都是错的,于是赶紧查了相关资料。
1.绝对路径 绝对路径是指文件在硬盘上真正存在的路径。例如“bg.jpg”这个图片是存放在硬盘的“E:\book\网页布局\代码\第2章”目录下,那么 “bg.jpg”这个图片的绝对路径就是“E:\book\网页布局\代码\第2章\bg.jpg"。那么如果要使用绝对路径指定网页的背景图片就应该使用 以下语句: <body background="E:\book\网页布局\代码\第2章\bg.jpg" > 2.使用绝对路径的缺点 事实上,在网页编程时,很少会使用绝对路径,如果使用“E:\book\网页布局\代码\第2章\bg.jpg”来指定背景图片的位置,在自己的计算机上 浏览可能会一切正常,但是上传到Web服务器上浏览就很有可能不会显示图片了。因为上传到Web服务器上时,可能整个网站并没有放在Web服务器的E盘, 有可能是D盘或H盘。即使放在Web服务器的E盘里,Web服务器的E盘里也不一定会存在“E:\book\网页布局\代码\第2章”这个目录,因此在浏 览网页时是不会显示图片的。 3.相对路径 为了避免这种隋况发生,通常在网页里指定文件时,都会选择使用相对路径。所谓相对路径,就是相对于自己的目标文件位置。 举个例子,假设“s1.html”文件所在目录为“E:\book\网页布局\代码\第2章”,而“bg.jpg”图片所在目录为“E:\book\网页 布局\代码\第2章\img”,那么“bg.jpg”图片相对于“s1.html”文件来说,是在其所在目录的“img”子目录里,则引用图片的语句应该 为: <body background="img/bg.jpg"> 注意:相对路径使用“/”字符作为目录的分隔字符,而绝对路径可以使用“\”或“/”字符作为目录的分隔字符。由于“img”目录是“第2章”目录下的子目录,因此在“img”前不用再加上“/”字符。 在 相对路径里常使用“../”来表示上一级目录。如果有多个上一级目录,可以使用多个“../”,例如“http://www.cnblogs.com/”代表上上级目录。假设 “s1.html”文件所在目录为“E:\book\网页布局\代码\第2章”,而“bg.jpg”图片所在目录为“E:\book\网页布局\代码”,那 么“bg.jpg”图片相对于“s1.html”文件来说,是在其所在目录的上级目录里,则引用图片的语句应该为: <body background="../bg.jpg"> 再举一个例子,假设“s1.htm”文件所在目录为“E:\book\网页布局\代码\第2章”,而“bg.jpg”图片所在目录为“E:\book\网页布局\代码\img”,那么“bg.jpg”图片相对于“s1.htm”文件来说,是在其所在目录的上级目录里的“img”子目录里,则引用图片的语句 应该为: <body background="../img/bg.jpg"> 总结
同一个目录的文件引用
如果源文件和引用文件在同一个目录里,直接写引用文件名即可。 我们现在建一个源文件info.html,在info.html里要引用index.html文件作为超链接。
假设info.html路径是:c:/Inetpub/wwwroot/sites/blabla/info.html
假设index.html路径是:c:/Inetpub/wwwroot/sites/blabla/index.html
在info.html加入index.html超链接的代码应该这样写:
<a href = "index.html">index.html</a>
如何表示上级目录
../表示源文件所在目录的上一级目录,../../表示源文件所在目录的上上级目录,以此类推。
假设info.html路径是:c:/Inetpub/wwwroot/sites/blabla/info.html
假设index.html路径是:c:/Inetpub/wwwroot/sites/index.html
在info.html加入index.html超链接的代码应该这样写:
<a href = "../index.html">index.html</a>
假设info.html路径是:c:/Inetpub/wwwroot/sites/blabla/info.html
假设index.html路径是:c:/Inetpub/wwwroot/index.html
在info.html加入index.html超链接的代码应该这样写:
<a href = "../../index.html">index.html</a>
假设info.html路径是:c:/Inetpub/wwwroot/sites/blabla/info.html
假设index.html路径是:c:/Inetpub/wwwroot/sites/wowstory/index.html
在info.html加入index.html超链接的代码应该这样写:
<a href = "../wowstory/index.html">index.html</a>
如何表示下级目录
引用下级目录的文件,直接写下级目录文件的路径即可。
假设info.html路径是:c:/Inetpub/wwwroot/sites/blabla/info.html
假设index.html路径是:c:/Inetpub/wwwroot/sites/blabla/html/index.html
设备需求 1、一台具有流量的手机A 2、一台安装测试App的手机B 3、一台MAC
一、共享wifi 手机A关闭wifi,打开个人热点,开启热点,点击仅蓝牙和USB 二、MAC连接共享wifi 用USB将手机A与MAC连接,查看一下显示iPhone USB是否已经连接上(偏好设置->网络),若没有,可尝试关闭MAC的wifi,将自动连接共享wifi。 三、MAC创建IPV6共享 MAC打开共享(偏好设置->共享),长按option键,点击互联网共享,界面下边会出现创建NAT64网络,然后按照下图所示,共享以下来源的连接选择iPhone USB,用以下端口共享给电脑选择Wi-Fi。 点击Wi-Fi选项,可设置共享wifi密码,以便手机B连接 然后点击互联网共享,开始共享wifi 四、连接共享IPV6网络 手机B连接MAC共享的wifi,显示如下代表ipv6创建成功
在学习STM32 IAP 时,遇到了关于数组存储空间绝对定位的问题,例如:
u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X20001000))); 首先我们先搞懂这里的两个关键字.
__attribute__ 是用来指定变量或结构位域的特殊属性,该关键字后的双括弧中的内容是属性说明.at 关键字可以用来设置变量的绝对地址,也就是通过这个关键字,指定某个变量处于内存里面的某个给定的地址. 那么上面的那条语句的意思就是,将 USART_RX_BUF 数组的首地址设定为 0X20001000 (SRAM内存地址区域).
疑惑: 在学习STM32 IAP 编程时,IAP程序将串口接收到的APP bin文件数据存储在设定的区域上(0X20001000)SRAM中,更新APP程序时,将SRAM中接收到的数据写入到Flash中,完成APP固件的更新.那是否可以将串口数组直接定位到Flash中呢?(Flash写操作前,必须先进行擦除)
找了中文意思,没有找到!
fan-out: refers to the number of pointers per node that the tree is having.
即,树中每个结点的孩子结点的个数,或者是每个结点的指针的个数。
一、概述 xmlproperty是Ant内置任务,用于从格式良好的XML文件中加载属性。例如:
<root> <properties> <foo>bar</foo> </properties> </root> 等价于java属性文件的root.properties.foo = bar,默认情况下此任务不对输入做处理,不会解析属性引用如${foo}。 可以通过semanticAttributes属性启动输入处理,如果设置为true,当XML加载时会进行以下处理: 1.解析属性引用。 2.以下属性将做不同的处理: id:属性与给定的id值关联。 location:属性被视为文件位置。 refid:属性设置为引用属性的值。 value:属性值设置为指定的值。 3.路径结构可以通过以下属性定义: pathid:给定的id用于标识路径。 二、属性 file:要解析的XML文件,可以通过嵌套资源或单元素资源集合指定。
prefix:预置到每个属性的前缀。
keepRoot:是否保留XML根标签做为属性名的第一个值,默认为true。
validate:是否验证输入文件,否则XML必须是格式良好的,默认为false。
collapseAttributes:是否将属性视为嵌套元素,默认为false。
semanticAttributes:是否启用属性名称的特殊处理,默认为false。
includeSemanticAttribute:是否将语义属性名做为属性名的一部分,如果semanticAttributes设置为false,忽略此属性,默认为false。
rootDirectory:解析文件引用的目录,如果semanticAttributes设置为false,忽略此属性,默认为${basedir}。
delimiter:ant1.7.1起,用于分隔多个值的分隔符。默认为“,”。
支持的嵌套元素:
xmlcatalog:用于执行实体解析。
三、简单示例 property.xml
<root attr1="attrvalue1"> <property> <p1 attr2="attrvalue2">value1</p1> <p2>value2</p2> </property> </root> build.xml <project> <xmlproperty file="property.xml" prefix="test1"/> <xmlproperty file="property.xml" collapseAttributes="true" prefix="test2"/> <xmlproperty file="property.xml" keepRoot="false" prefix="test3"/> <echo>${test1.root.property.p1}</echo> <echo>${test1.root.property.p2}</echo> <echo>${test3.property.p1}</echo> <echo>${test3.property.p1(attr2)}</echo> <echo>${test1.root(attr1)}</echo> <echo>${test1.root.property.p1(attr2)}</echo> <echo>${test2.root.attr1}</echo> <echo>${test2.root.property.p1.attr2}</echo> </project>
1,点击Window下的Show View 如图
2,在下方的控制台中右击 MyEclipse Derbv 打开 New
3,以oracle为例
4,打开之后就可以看到数据库中的表了
移远M26 GSM实时获取网络时间 1.启用同步网络时间, 开启同步网络时间功能 AT+QNITZ=1,响应OK 2.获取最近一次的网络同步时间 AT+QLTS,响应+QLTS: <time>,<ds> 例: +QLTS: "18/03/14,08:08:35+32,0"
time格式: yy/MM/dd,hh:mm:ss±zz,各指年,月,日,小时,分钟,秒和时区(用当地时间和 GMT 时间之间的差别来表示,以四分之一小时格式来表示;范围(-47~+48) 将获取的时间存于结构体ST_Time local_time中 local_time.year = atoi(pHead +8); //其中*pHead指向+QLTS: "18/03/14,08:08:35+32,0"
local_time.month = atoi(pHead+11);
local_time.day = atoi(pHead+14);
local_time.hour = atoi(pHead+17);
local_time.minute= atoi(pHead+20);
local_time.second = atoi(pHead+23);
local_time.timezone = atoi(pHead+26);
typedef struct {
s32 year; s32 month;
s32 day;
s32 hour;
s32 minute;
s32 second;
s32 timezone; }ST_Time;
3.用获取的同步时间配置实时时钟 AT+CCLK=<time>, 响应OK, 例:AT+CCLK="18/03/14,08:08:35+32"
4.获取实时时钟AT+CCLK? 响应+CCLK: <time> 例 +CCLK: "18/03/14,08:09:06+32"
备注:每次重新上电获取一次网络时间,并将其设置为RTC时间,之后就可以通过实时查询实时时钟得到准确时间
关于这个问题是在 《 基于MySQL Yum存储库在Linux-7.2上安装MySQL-5.7.21数据库服务(实战篇) 》 时遇到的问题,这是 mysql 初始化时,使用临时密码,修改自定义密码时,由于自定义密码比较简单,就出现了不符合密码策略的问题。
密码策略问题异常信息:
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
如下图:
解决办法:
1、查看 mysql 初始的密码策略,
输入语句 “ SHOW VARIABLES LIKE 'validate_password%'; ” 进行查看,
如下图:
2、首先需要设置密码的验证强度等级,设置 validate_password_policy 的全局参数为 LOW 即可,
输入设值语句 “ set global validate_password_policy=LOW; ” 进行设值,
如下图:
3、当前密码长度为 8 ,如果不介意的话就不用修改了,按照通用的来讲,设置为 6 位的密码,设置 validate_password_length 的全局参数为 6 即可,
输入设值语句 “ set global validate_password_length=6; ” 进行设值,
如下图:
4、现在可以为 mysql 设置简单密码了,只要满足六位的长度即可,
输入修改语句 “ ALTER USER 'root'@'localhost' IDENTIFIED BY '123456'; ” 可以看到修改成功,表示密码策略修改成功了!!!
Graphlib 1、概念 Graphlib是一个用于直接或间接地制作或修改图画的javascript库
参考: https://github.com/cpettitt/graphlib https://github.com/cpettitt/graphlib/wiki
1、二叉搜索树
二叉搜索树需满足以下四个条件:
若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;任意节点的左、右子树也分别为二叉查找树;没有键值相等的节点。 2、什么是伸展树(Splay Tree) 假设想要对一个二叉查找树执行一系列的查找操作。为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。splay tree应运而生。splay tree是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。
3、AVL树
AVL树是一种最古老的平衡树,它的平衡条件是:每个节点的左子树和右子树的高度最多相差1。对于插入、删除等改变树高度的操作,会通过旋转使树满足平衡条件。假设删除采用的是懒惰删除(即不移除节点,只将节点标识为已删除),那么对于插入则会出现下面四种情况。假设M表示从叶子上溯到根的过程中出现的第一个不平衡点。 1,对M的左儿子的左子树进行一次插入,简记左-左。 2,对M的右儿子的右子树进行一次插入,简记右-右。 3,对M的左儿子的右子树进行一次插入,简记左-右。 4,对M的右儿子的左子树进行一次插入,简记右-左。 上述四种情况,前两种可以使用单旋转进行解决,后两种要使用双旋转(即进行两次单旋转)。 对于左-左:将M与M左儿子L进行旋转——将M变为L的右儿子,而L的右儿子变为M的左儿子。对于右-右也类似。 对于左-右,将M与M的左儿子L与L的右儿子G进行旋转——先将G与L进行右-右旋转,再将G与M进行左-左旋转。 4、节点自平衡树(Size Balanced Tree,简称SBT)
Size Balanced Tree(简称SBT)是一种平衡二叉搜索树,它通过子树的大小s[t]来维持平衡性质。它支持很多动态操作,并且都能够在O(log n)的时间内完成。 为了下面方便讨论, 我们设 left [T] : 结点 T 的左儿子
right [T] : 结点 T 的右儿子
s [T] : 以T为根的子树的结点个数(大小)) SBT为什么能保持平衡? 因为 对于SBT的每一个结点 t,有如下性质: 性质(a) s[ right[t] ]≥s[ left [ left[ t ] ] ], s[ right [ left[t] ] ]
性质(b) s[ left[t] ]≥s[right[ right[t] ] ], s[ left[ right[t] ] ]
主要方法有两种:
第一种:
这种也是最简单的。
示例代码:
<a href="tel:+18790853577">点击拨打</a> 第二种:
<a href="wtai://wp/mc;18790853577">Call ME</a> 第二种比较标准的写法。但是不要希望支持所有的机型。
有些设备还允许发送DMTF音通话后,目标已回答。访问音控制的服务,帮助台系统或语音信箱,这是非常有用的,你可以说的链接,拨打这个电话号码,当电话被接听,请按2,等待2秒,然后按913#“。你这样做使用postd的参数后的数字:语法; postd=<numbers>。您可以使用数字,*,#(使用URL编码的23%价值),以及一秒钟的暂停和w等待音暂停。
<a href="tel:+1800229933;postd=4">Call us free!</a> DEN网络(如Nextel公司)使用广播数据包,使内部网络的内部呼叫。如果你正在这样的网络,例如与客户,企业内部网,你可以允许用户启动内部调用其他成员的团队(或外部调用)使用直接连接的URL计划
<a href="dc:5040*0077">呼叫</a> 有些机型用户呈现一个子菜单,一个电话,当他们点击链接,使他们可以选择是否将纯语音或视频通话(可在3G系统中)。日本的一些手机还允许你指定一个链接应该发起视频通话,使用的协议TEL-AV:<手机号>。
下面介绍下拨打400电话的方法:
拨打400电话的时候,可以直接<a href="tel:40065242,2356">点击拨打</a>
逗号前面是主机号码,后面是分机号
此文来自: 马开东博客 转载请注明出处 网址: http://www.makaidong.com
码。不过这种方法只对部分手机机型有效,至今没有找到对所有机型有效的方法。哪位大侠有好的方法希望在留言里给予提醒。在此谢过
转载于:https://www.cnblogs.com/feiyu159/p/8550124.html
概述 本文会从一下几点介绍压缩也解压 1. 什么是压缩、解压? 2. hadoop中的压缩 、解压格式有哪些? 3. 有什么优缺点? 4. 应用场景有哪些? 5. 如何使用? 6. LzoCodec和LzopCodec区别 7. Hive中的使用 大家可以带着上述几个问题来进行学习、思考。
1 什么是压缩、解压 用一句最直白的话概述,压缩就是通过某种技术(算法)把原始文件变下,相应的解压就是把压缩后的文件变成原始文件。嘿嘿是不是又可以变大又可以变小。
想要对hadoop中压缩,解压进行深刻的认识,可以从该路线进行思考:hdfs ==> map ==> shuffle ==> reduce 2 hadoop中的压缩格式 压缩格式UNIX工具算 法文件扩展名可分割DEFLATE无DEFLATE.deflateNogzipgzipDEFLATE.gzNoLZ4无LZ4.LZ4NObzipbzipbzip.bz2YESLZOlzopLZO.lzoYES if indexedSnappy无Snappy.snappyNO 一个简单的案例对于集中压缩方式之间的压缩比和压缩速度进行一个感观性的认识
测试环境: 8 core i7 cpu 8GB memory 64 bit CentOS 1.4GB Wikipedia Corpus 2-gram text input 压缩比 压缩时间 可以看出压缩比越高,压缩时间越长,压缩比:Snappy < LZ4 < LZO < GZIP < BZIP2
gzip: 优点:压缩比在四种压缩方式中较高;hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;有hadoop native库;大部分linux系统都自带gzip命令,使用方便。 缺点:不支持split。
lzo压缩 优点:压缩/解压速度也比较快,合理的压缩率;支持split,是hadoop中最流行的压缩格式;支持hadoop native库;需要在linux系统下自行安装lzop命令,使用方便。 缺点:压缩率比gzip要低;hadoop本身不支持,需要安装;lzo虽然支持split,但需要对lzo文件建索引,否则hadoop也是会把lzo文件看成一个普通文件(为了支持split需要建索引,需要指定inputformat为lzo格式)。
今天在复习Java Web时,因为初次使用 IntelliJ IDEA 中,
当使用javax.servlet包下的类时(例:javax.servlet.http.HttpServletRequest), 你会发现在IntelliJ IDEA里无法成功编译这个程序。
问题解决: 办法1:使用Project Structure
在弹出的窗口中选择tomcat所在的目录,进入里面的lib目录,寻找servlet-api.jar这个jar包(如果JSP页面也有相关的JavaWeb对象,则还要寻找jsp-api.jar;如果只有Servlet,则只选择servlet-api.jar)
选择项目
OK!
方法二:使用Maven
在pom.xml文件中添加如下
OK!
使用 tabular*, \hzise 或 \textwidth, 然后加上一些奇怪的符号。
举例:
\begin{table}[!ht] \caption{Parameter values}\label{tab:parametervalues} \begin{tabular*}{\hsize}{@{}@{\extracolsep{\fill}}lllllllllllll@{}} \toprule $p_{t}$ &21 &22 &20 &15 &10 &8 &5 &10 &18 &10 &14 &18\\ \midrule $c_{t}$ &5 &13 &10 &10 &10 &10 &10 &10 &10 &10 &10 &10\\ $h_{t}$ &10 &5 &5 &5 &5 &5 &5 &5 &5 &5 &5 &5 \\ $s_{t}$ &100 &100 &100 &100 &100 &100 &100 &100 &100 &100 &100 &100\\ $d_{t}$ &30 &45 &50 &55 &45 &55 &90 &80 &90 &65 &80 &70 \\ \bottomrule \end{tabular*} \end{table} 该例子中的 llllll 表示左对齐,可以改为 c 居中,r 右对齐。显示效果:
http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php
先看下源码,发现这个,emmm注入无疑了。
咋整。。。没遇到过这种情况啊,想着如何构造' or 1='1之类的,什么情况下md5加密后会形成这玩意呢。。。搞来搞去搞不出。。回过头来看题。。。觉得url里面ffifdyop有点奇怪,这个是啥意思?直接拿去交一发,结果。。。。
一时无语。。。还是经验太少。。
ACM刷着累,不如刷道web玩一玩,这题是一个改密码的场景,随便填点东西提交,发现返回了一段话:
emmm...那就去step2.php看看....发现进去后会秒回step1.php,那就直接看源码吧
看到这个:
那就去submit.php瞧一瞧,发现只有一句话。。。
admin....难不成是找到管理员账号就可以登录了?那咋办,回去step1.php和step2.php找找看,step1没啥信息。。。但是step2里面暴露了玄机:
嘿嘿嘿 邮箱找到了但是还缺点啥
token.....这玩意写爬虫的时候遇到过,还挺麻烦的。。
想半天,发现了这个
似曾相识,之前做过一道类似的啊。。。Vim编辑的东西会留下备份文件,百度了一波,发现只需构造这样的url就可以访问:
http://ctf5.shiyanbar.com/10/upload/.submit.php.swp
感觉快成功了~~~看下代码可知token要十位的长度且为0,emmm那就写十个0吧,因为这里是弱类型,于是
ctf5.shiyanbar.com/10/upload/submit.php?emailAddress=admin@simplexue.com&token=0000000000
好吧。。。回去继续撸网络流。。。
今天在处理Spring JDBC 批处理过程中,出现了以下出错
三月 08, 2018 10:14:49 下午 org.springframework.jdbc.support.SQLErrorCodesFactory <init> 信息: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana] Exception in thread "main" org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [update Student set age = ? where id = ?]; Could not retrieve transaction read-only status from server; nested exception is java.sql.SQLException: Could not retrieve transaction read-only status from server at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:108) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.
前言: 为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。
转载自看完这篇“史密斯圆图”告别懵逼射频!
文章出处: http://www.mweda.com/hfss-cst-29038-1.html
这是什么东东?
今天解答三个问题:
1.是什么?
2.为什么?
3.干什么?
1.是什么? 该图表是由菲利普·史密斯(Phillip Smith)于1939年发明的,当时他在美国的RCA公司工作。史密斯曾说过,“在我能够使用计算尺的时候,我对以图表方式来表达数学上的关联很有兴趣”。
史密斯图表的基本在于以下的算式。
当中的Γ代表其线路的反射系数(reflection coefficient)
即S参数(S-parameter)里的S11,ZL是归一负载值,即ZL / Z0。当中,ZL是线路本身的负载值,Z0是传输线的特征阻抗(本征阻抗)值,通常会使用50Ω。
简单的说:就是类似于数学用表一样,通过查找,知道反射系数的数值。
2.为什么? 我们现在也不知道,史密斯先生是怎么想到“史密斯圆图”表示方法的灵感,是怎么来的。
很多同学看史密斯原图,屎记硬背,不得要领,其实没有揣摩,史密斯老先生的创作意图。
我个人揣测:是不是受到黎曼几何的启发,把一个平面的坐标系,给“掰弯”了。
世界地图,其实是一个用平面表示球体的过程,这个过程是一个“掰直”。
史密斯原图,巧妙之处,在于用一个圆形表示一个无穷大的平面。
2.1 首先,我们先理解“无穷大”的平面 首先的首先,我们复习一下理想的电阻、电容、电感的阻抗。
在具有电阻、电感和电容的电路里,对电路中的电流所起的阻碍作用叫做阻抗。阻抗常用Z表示,是一个复数,实部称为电阻,虚部称为电抗,其中电容在电路中对交流电所起的阻碍作用称为容抗 ,电感在电路中对交流电所起的阻碍作用称为感抗,电容和电感在电路中对交流电引起的阻碍作用总称为电抗。 阻抗的单位是欧姆。
R,电阻:在同一电路中,通过某一导体的电流跟这段导体两端的电压成正比,跟这段导体的电阻成反比,这就是欧姆定律。
(理想的电阻就是 实数,不涉及复数的概念)。
如果引入数学中复数的概念,就可以将电阻、电感、电容用相同的形式复阻抗来表示。既:电阻仍然是实数R(复阻抗的实部),电容、电感用虚数表示,分别为:
说明:负载是电阻、电感的感抗、电容的容抗三种类型的复物,复合后统称“阻抗”,写成数学公式即是:阻抗Z= R+i(ωL–1/(ωC))。其中R为电阻,ωL为感抗,1/(ωC)为容抗。
(1)如果(ωL–1/ωC) > 0,称为“感性负载”;
(2)反之,如果(ωL–1/ωC)<0,称为“容性负载”;
我们仔细看阻抗公式,它不再是一个实数。它因为电容、电感的存在,它变成了一个复数。
电路中如果只有电阻,只影响幅度变化。
我们通过上图,我们知道,正弦波的幅度发生了变化,同时,相位也发生了变化,同时频率特性也会变化。所以我们在计算的过程中,即需要考虑实部,也需要考虑虚部。
我们可以在一个复平面里面,以实部为x轴、以虚部为y轴,表示任意一个复数。我们的阻抗,不管多少电阻、电容、电感串联、并联,之后,都可以表示在一个复平面里面。
在 RLC 串联电路中,交流电源电压 U = 220 V,频率 f = 50 Hz,R = 30 Ω,L =445 mH,C =32 mF。
在上图中,我们看到通过几个矢量的叠加,最终阻抗在复平面中,落在了蓝色的圆点位置。
所以,任意一个阻抗的计算结果,我们都可以放在这个复平面的对应位置。
各种阻抗的情况,组成了这个无穷大的平面。
2.2.反射公式 信号沿传输线向前传播时,每时每刻都会感受到一个瞬态阻抗,这个阻抗可能是传输线本身的,也可能是中途或末端其他元件的。对于信号来说,它不会区分到底是什么,信号所感受到的只有阻抗。如果信号感受到的阻抗是恒定的,那么他就会正常向前传播,只要感受到的阻抗发生变化,不论是什么引起的(可能是中途遇到的电阻,电容,电感,过孔,PCB转角,接插件),信号都会发生反射。
前言:记录自己在工作中遇到的小问题,积少成多!因为是新手,有什么写的不好的地方还希望大吉指出来。有什么更好的办法也希望大家能够提出来,一起交流分享!(小弟在这里先谢谢大家)
正文: J2EE、J2SE、J2ME是Java平台的三个版本:
1、J2EE企业版 用于企业应用,支持分布式部署;
2、J2SE标准版 用于桌面应用,是J2EE的基础;
3、J2ME移动版(微信版) 用于小型设备,是J2SE的一个子集;
从上到下功能依次变小
简单地说:
J2SE是基础
扩充一点,再加一点EJB等企业方面的特性就是J2EE;
压缩一点,再加一点CLD等方面的特性就是J2ME;
补充: 参考链接1:http://blog.csdn.net/litong09282039/article/details/46011781
java.io.IOException: invalid constant type: 15 at javassist.bytecode.ConstPool.readOne(ConstPool.java:1027) at javassist.bytecode.ConstPool.read(ConstPool.java:970) at javassist.bytecode.ConstPool.<init>(ConstPool.java:127) at javassist.bytecode.ClassFile.read(ClassFile.java:716) at javassist.bytecode.ClassFile.<init>(ClassFile.java:103) at org.scannotation.AnnotationDB.scanClass(AnnotationDB.java:311) at org.scannotation.AnnotationDB.scanArchives(AnnotationDB.java:294) javassist版本与jdk版本不兼容,建议jdk1.7对应javassist版本3.9.0 jdk1.8对应3.15.0
关键是看这个方法的是否是静态方法,
1.非静态方法之间,锁住的是本类的对象,所以,当一个方法在执行的时候,就会握住这个锁,其他方法就不能进行。
2.当方法时静态方法时,进程拿到的锁和非静态的不是一个,所以在静态方法之间,必须同步,而非静态方法中可以进行,也就是说,A如果是静态同步方法,B是非静态同步方法,那么A和B是可以并发执行的。
本人是第一次发博客,有错误的地方,请谅解。(最好是指出) 本人刚刚开始做这道题时,代码写了100多行,后来才简化。 这道题主要是坐标点的算法。横坐标和纵坐标都要分别求出 看一下下面的矩阵,就是a[x][y]是‘*’的上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子的方位图 a[x-1][y-1] a[x-1][y] a[x-1][y+1] a[x] [y-1] a[x][y](初始点) a[x][y+1] a[x+1][y-1] a[x+1][y] a[x+1][y+1] 所以,为了更方便的去计算坐标点的横坐标和纵坐标,我们开两个数组。 int dx[]={1,0,-1,0,-1,1,1,-1}; int dy[]={0,1,0,-1,-1,-1,1,1}; 【C++代码】 #include<stdio.h> #include<iostream> //头文件 using namespace std; char a[101][101]; //开数组 char b[101][101]; int n,m; //行,列 int dx[]={1,0,-1,0,-1,1,1,-1}; //横坐标的加减点 int dy[]={0,1,0,-1,-1,-1,1,1}; //纵坐标的加减点 void lt(int x,int y) //开一个算周围方块++的函数 { int nx,ny; for (int k=0;k<8;k++) { nx=x+dx[k]; //每个坐标点算出并存储 ny=y+dy[k]; if (nx>=1&&nx<=n&&ny>=1&&ny<=m) //判断边界 { b[nx][ny]++; //周围方块++ } } } int main() { scanf("%d%d",&n,&m); //输入行,列 for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { cin>>a[i][j]; //输入每个点 } } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { if(a[i][j]=='?
这里说一下我自己犯的一个错误。我有三个项目eureka-server,provide-service,consumer-service,以下我统称为ABC三个项目。现在的步骤是这样的,先访问C项目的一个接口,接口里面用restTemplate发送的一个请求,具体看下面
@RestController public class TestController { @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/test") public void test() { //template.getForEntity("http://localhost:8000/test",String.class); restTemplate.getForEntity("http://provide-serivce/test",String.class); } } 然后B的test这个接口代码如下
@RequestMapping(value = "/test") public String test(HttpServletResponse resp) { System.out.println("provide-service is provides services"); return "redirect:/page"; } 这里ABC的配置是正常的,并且BC项目都注册到A上了,当我们访问C的test接口时显示如下错误
java.net.UnknownHostException: provide-serivce at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[na:1.8.0_144] at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_144] at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_144] at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_144] at java.net.Socket.connect(Socket.java:538) ~[na:1.8.0_144] 这里显示的错误很明显,就是不知道的域名。然后我就一直纳闷了,按我自己的逻辑,我的消费者已经拥有的从注册中心拉取服务名实例的权限,已经拥有服务名列表(服务名就是包含元元素,其中包含ip,port),为什么显示不知道的域名呢?当然了这就是我想当然的问题了。是的C项目确实有从注册中心拿的服务实例列表,但是我错的点resttemplate只是类似于httpclient的一个发送rest风格的请求,它这里是没有办法去识别所谓的服务名的,不识别服务名当然就会报那个错误咯。在《spring Cloud 微服务实战》这本书上写的,一定要@loadBalance注解修饰的restTemplate才能实现服务名的调用,没有修饰的restTemplate是没有该功能的。@loadBalance是Netflix的ribbon中的一个负载均衡的注解,当我项目加了loadbalacnce的时候,就可以了。
至于为什么一定要该注解修饰,这里我大概讲一下。loadBalance这个注解加上之后,这个注解有3件事情要处理。
第一件就是从负载均衡器中选一个对应的服务实例,那有的人就会问为什么从负载均衡器中挑选,原因很明显就是,所有的服务名实例都放在负载均衡器中的serverlist。
第二件事情就是从第一件事情挑选的实例中去请求内容。
第三件事情就是由服务名转为真正使用的ip地址
讲到这里大概应该清楚了吧。哎,之前也是百思不得其解,现在终于明白了
JS Cookie丢失问题 前些天有人问我vue中使用proxy发送请求,为什么请求时cookie丢失,首先说一下我对cookie的理解:
1、cookie在正常情况下是会在每次请求时自动携带,
2、cookie虽然是由一个网页所创建,但并不只是创建cookie的网页才能读取该cookie。
在默认情况下,与创建cookie的网页在同一目录或子目录下的所有网页都可以读取该cookie。即:
(1)如果在这个目录下还有子目录,要使在子目录中也可以访问,则需要使用path参数设置cookie,语法如下:
document.cookie="name=value; path=cookiePath";
(2)如果要使cookie在整个网站下可用,可以将cookieDir指定为根目录,示例如下:
document.cookie="userId=320; path=/"; 上面所说都指的是在同一个目录中的访问,可是要想在不同虚拟目录中访问则要另外想办法来解决这个问题。
设置路径代码如下:
var now=new Date()
new Date().setDate(now.getDate()+1);
var cookies="setCookies="+escape("我的cookies")+";expires="+now.toString()+";path=/";
注意:path不能解决在不同域中访问cookie的问题。
(3) 在默认情况下,只有和设置cookie的网页在同一个Web服务器的网页才能访问该网页创建的cookie。
但可以通过domain参数来实现对其 的控制,其语法格式如下:
document.cookie="name=value; domain=cookieDomain";
设置域代码如下:
var now=new Date()
new Date().setDate(now.getDate()+1); var cookies="userName="+escape("哈哈")+";expires="+now.toString()+";path=/; domain=.baidu.com"; 看完上面的叙述我们回到上面的疑问,不难理解vue中使用proxy时cookie丢失的原因就是path和domain,
如果后台返回cookie的path是'/b'而本地前端本地开发地址为localhost:8080/#/home 页面,我们需要再后端返回cookie时手动修改path路径,代码如下: proxyTable: { '/api':{ target: '后台接口地址', changeOrigin: true, pathRewrite: { '^/api': '/b',//注意这里只是接口关键字的替换,与cookie的path无关 }, onProxyRes(proxyRes, req, res) { var oldCookie = proxyRes.headers['set-cookie'] if(oldCookie== null || oldCookie.length==0){ delete proxyRes.headers['set-cookie'] return } var oldCookieItems = oldCookie[0].
原型和原型链是js中的难点也是重点,明白了原型和原型链会让我们在后面不管是学习还是工作都会更加高效,并且原型和原型链会是面试中必不可少的话题。看完此篇文章一定会让你对原型,原型链有深刻全面的了解。
深入系列:深入javascript之作用域
深入系列:深入javascript之执行上下文
一,函数对象 所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
所有函数拥有prototype属性(显式原型)(仅限函数)
原型对象:拥有prototype属性的对象,在定义函数时就被创建
二,构造函数 先复习下构造函数
//创建构造函数 function Word(words){ this.words = words; } Word.prototype = { alert(){ alert(this.words); } } //创建实例 var w = new Word("hello world"); w.print = function(){ console.log(this.words); console.log(this); //Person对象 } w.print(); //hello world w.alert(); //hello world print()方法是w实例本身具有的方法,所以w.print()打印hello world;alert()不属于w实例的方法,属于构造函数的方法,w.alert()也会打印hello world,因为实例继承构造函数的方法。
实例w的隐式原型指向它构造函数的显式原型,指向的意思是恒等于
w.__proto__ === Word.prototype 当调用某种方法或查找某种属性时,首先会在自身调用和查找,如果自身并没有该属性或方法,则会去它的__proto__属性中调用查找,也就是它构造函数的prototype中调用查找。所以很好理解实例继承构造函数的方法和属性:
w本身没有alert()方法,所以会去Word()的显式原型中调用alert(),即实例继承构造函数的方法。 三,原型和原型链 Function.prototype.a = "a"; Object.prototype.b = "b"; function Person(){} console.log(Person); //function Person() let p = new Person(); console.
实现高性能负载均衡的Tomcat集群:
工具:nginx-1.13.9和多个apache-tomcat-9.0.0.M9(解压版)nginx下载地址:https://nginx.org/en/download.html
一.多个tomcat的配置 先看安装版的界面:
从这可以看出需要免安装版的tomcat里面需要设置的主要是server shutdown port(8005) 和 http/1.1 Connector Port (8080)和AJP/1.3 Connector Port(8009)等三个参数及windows Service Name tomcat服务器名称(对应免安装版的D:\nginx\tomcat\apache-tomcat-9.0.0.M91目录里的名字apache-tomcat-9.0.0.M91),主要是这四个参数。上面截图参数是默认参数。
故看看下面免安装版的注意点:
解压多个tomcat名字命名不一样。tomcat里面的设置点:
A.修改Tomcat的conf目录下的server.xml,修改这多个Tomcat的启动端口,分别为18080和28080等。
需要修改的是下面三处:蓝色的端口号(关闭,启动,?)
<Server port="28005" shutdown="SHUTDOWN">
<Connector port="28080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="28009" protocol="AJP/1.3" redirectPort="8443" />
B.在startup.bat里面开头部分设置JAVA_HOME和CATALINA_HOME
SET JAVA_HOME=D:\software\jdk1.8
SET CATALINA_HOME=D:\nginx\tomcat\apache-tomcat-9.0.0.M91
@echo off
然后启动并访问tomcat首页,看是不是能正常启动,
三个tomcat启动后截图:
这样三个tomcat能正常启动了。
注意点:tomcat启动报错:1.端口号问题2.配置环境问题
The JRE_HOME environment variable is not defined correctly(报错了)原因:Set JAVA_HOME or JRE_HOME if not already set and ensure any provided(设置了多个JAVA_HOME)
二,nginx的简单配置 nginxconf的原始代码:
#user nobody;
写本篇文章的目的主要是因为在进行单片机开发的过程中,基本上都是使用的keil作为开发工具,因此这里主要针对我个人在进行单片机开发过程中遇到的问题和疑惑做一个总结,方便其他学习者参考。
1、keil工具介绍
keil软件主要是在进行单片机开发的时候使用,主要有针对于c51(AT89C51、STC89C51等51单片机)、arm单片机(LPC、STM32等系列arm单片机),该工具主要集编辑、编译、硬件芯片基本头文件和启动代码支持、调试等于一体。
keil是公司名称
uVision是IDE名称,用于源代码编辑等,包含了编译、调试、下载等工具。
MDK是微控制器开发集合,包含了不同芯片内核所需的库和文件,支持ARM等。
MDKCM是兼容开发集合,如MDKCM518是在uVision5上兼容uVision4的包。
2、在keil4上ulink下载调试不支持
在使用ULINK进行单片机程序下载和调试的时候,如果在keil软件中显示不出来ULINK设备,这时候,可能原因是ULINK的驱动没安装上,这就需要去手动安装ULINK(网上自己搜索下载),要么就更新keil4版本,最好到4.7以后,因为4.7版本以后自带了ULINK的驱动
3、keil4使用方法
(1)首先你需要下载安装keil4的安装包:mdk4.exe(网上下载就好了)
安装过程中,关于存放安装路径一定不要有中文
(2)对安装的keil4进行破解
使用网上的keil破解软件,先在keil4的license management中将CID拷贝到破解软件,然后选择target目标:C51或者arm,最后将生成的许可证在keil4中输入注册就可以了。
如果不破解,也能正常使用,只是编写的程序体积不能超过32KB
(3)新建工程
注意选择自己芯片对应的型号,并且添加start.s启动代码
4、keil4和keil5的区别
keil4是基本将所有的单片机芯片厂商生产的各种型号单片机的头文件、汇编启动代码、初始化代码这些硬件相关代码都囊括了,在新建工程的时候直接去选择就好了,缺点就是不能支持更多的库文件
keil5则是将所有关于硬件芯片的东西全部剥离了,软件是软件、固件库是固件库,二者分开了,也就是说你除了安装keil软件(mdk5.exe)以外还要安装对应芯片的固件库。
5、keil5安装
除了安装mdk5.exe程序和破解之外,还需要安装开发芯片的固件库:http://www.keil.com/boards2/
找到自己的芯片型号,下载安装就可以了。
6、keil4和keil5共存
keil4和keil5共存主要分为以下两部分:
(1)keil5支持打开并编译下载keil4的工程
需要安装支持包:MDKCM
(2)在Windows上同时安装keil4和keil5,并且二者支架互不干扰
同时安装keil4,keil5都可以,但是会出现每次打开工程默认是以keil5打开,要想修改,就需要按下Windows窗口键+R,在运行中输入regedit回车,然后在注册表中找到HKEY_CLASSES_ROOT\UVPROJFILE\Shell\open\command,然后修改数值数据为keil4的安装路径就可以了:
#include <iostream>
#include <vector> #include <boost/config.hpp> #include <boost/graph/graph_traits.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/dijkstra_shortest_paths.hpp> #include <boost/property_map/property_map.hpp> #include <boost/graph/graph_utility.hpp> // Create a struct to hold properties for each vertex typedef struct vertex_properties { std::string label; int p1; } vertex_properties_t; // Create a struct to hold properties for each edge typedef struct edge_properties { std::string label; //int p1; double weight; } edge_properties_t; // Define the type of the graph typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, vertex_properties_t, edge_properties_t> graph_t; typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_descriptor_t; typedef graph_t::edge_descriptor edge_descriptor_t; typedef boost::property_map<graph_t, boost::vertex_index_t>::type index_map_t; typedef boost::iterator_property_map<vertex_descriptor_t*, index_map_t*, vertex_descriptor_t, vertex_descriptor_t&> predecessor_map_t; // The graph, with edge weights labeled.
之前看过阿里巴巴 陶辉写的《深入理解Nginx:模块开发与架构解析》,里面也提到了这一点,今天突然想到了,就回顾记录一下,有可能说的不全。
nginx反向代理为什么能降低上游服务器的负载。 一般来说公网延迟高,客户端与nginx之间的请求连接走公网,nginx先把这些请求缓存住,等这些请求数据全部完成之后nginx再向内网服务器请求,降低公网网络延迟成本,同时也降低一个连接占用服务端程序的时间。
原因:因为tcp不一定一次就能把全部数据传输完毕,所以一个连接可能需要等待很久才能把所有需要的数据都传输完毕,而这样的空闲连接如果都直接连接到服务器上的话,会加重服务器负担,而nginx在这方面做了很大的优化,可以承载更多的连接,空闲连接也不会占据太多内存,所以nginx作为反向代理能降低上游服务器的负载。
相信大家在工作中会接触到合代码的情况,特别像使用SVN这种类似的版本管理的工具,我们开发过程中不可能就拉一个主干,然后所有的需求都在主干上开发。这肯定是不合理的。一般我们会拉一个主干,然后拉一个分支,然后再分支上开发,开发完上线后再将分支代码合到主干。当然我们可能会拉多个分支来开发不同的需求。那么我们就可以用BCompare工具来合代码,操作起来也十分方便。
第一步:我们将两个不同的分支代码(文件夹)直接拉到BCompare中,它会自动打开。
第二步:我们将无关的内容排除,如本例中的.svn(h)。按住ctrl选中两边的.svn(h)文件夹,右键选择排除 第三步:排除无关文件夹后,随便选中一个文件夹,然后ctrl+A全选,点击工具栏中的全部展开。展开后,再随便选中一个文件夹,ctrl+A全选,然后点击操作选择比较内容。如图 第四步:我们可以看到有CRC比较、二进制比较、基于规则的比较。我们可以选中CRC比较,点击开始
第五步:第一项比较开始后我们再重复第四步的操作,点击操作选择比较内容,然后选择二进制比较,接下来重复同样的步骤直到三个比较都完成。 第六步:比较完后,剩下的就是两边有差别的内容了,我们看到左边主要有红色文件和蓝色文件名 弟七步:对于红色的文件,说明我们修改了里面的内容(这里是代码)。我们点击红色文件,就可以看到里面的差异内容了,假设我是要将左边的代码合到右边,那么只要点击旁边的小箭头就可以了,然后点击下右边保存。而对于蓝色的文件,说明是新增的内容(比如实体类),我们只需要右键选择复制到右边就OK 了。 以上都完成后,我们就可以提交到SVN了。 当然这只是此工具的一小部分操作,既可以比较文件也可以比较文件夹。
_analyze是Elasticsearch一个非常有用的API,它可以帮助你分析每一个field或者某个analyzer/tokenizer是如何分析和索引一段文字。 返回结果字段含义: token是一个实际被存储在索引中的词 position指明词在原文本中是第几个出现的 start_offset和end_offset表示词在原文本中占据的位置。 1、默认analyzer GET /_analyze? {"analyzer" : "standard", "text" : "床前明月光"} { "tokens": [ { "token": "床", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "前", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "明", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2 }, { "token": "月", "start_offset": 3, "end_offset": 4, "type": "<IDEOGRAPHIC>", "position": 3 }, { "token": "光", "start_offset": 4, "
方法一:较为简单,创建一个公共的js,将下列代码放入并引用
$.extend({ getUrlVars: function(){ var vars = [], hash; var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for(var i = 0; i < hashes.length; i++){ hash = hashes[i].split('='); vars.push(hash[0]); vars[hash[0]] = hash[1]; } return vars; }, getUrlVar: function(name){ return $.getUrlVars()[name]; } }); 在需要的页面中声明变量,获取想要得到的url参数
Var 变量名 = decodeURI($.getUrlVar('参数名')); 方法二:适用于全局
function GetQueryString(参数名) { var reg = new RegExp("(^|&)" + 参数名 + "=([^&]*)(&|$)"); var r = decodeURI(window.location.search.substr(1)).match(reg); if (r != null)return unescape(r[2]); return null; } var sid = GetQueryString("
应公司需求实现云空间多文件上传功能,后台接口为JAVA开发。
先开始采用直接调用后台给的接口实现多文件上传功能,发现jqery封装的上传进度监测并不准确,而且文件上传文件速度过慢,用过很多方法都没有实现想要的效果。
后来改用阿里云oss对象存储来实现多文件上传功能并监测上传进度的功能:
首先,引入js文件,这是必不可少的
<script src="https://www.promisejs.org/polyfills/promise-6.1.0.js"></script> <script type="text/javascript" src="http://gosspublic.alicdn.com/aliyun-oss-sdk.min.js"></script> 接下来是js功能实现 var urllib = OSS.urllib; var Buffer = OSS.Buffer; var OSS = OSS.Wrapper; var STS = OSS.STS; var j=0; $("#fileMutiply").change(function eventStart(){ var ss =this.files; //获取当前选择的文件对象 var cd = ss.length; $('.zwj').html(cd); for(var m=0;m<ss.length;m++){ //循环添加进度条 efileName = ss[m].name ; if (ss[m].size> 1024 * 1024){ sfileSize = (Math.round(ss[m].size /(1024 * 1024))).toString() + 'MB'; } else{ sfileSize = (Math.round(ss[m].size/1024)).toString() + 'KB'; } } var appServer = ' '; //获取所需参数accessKeyId、accessKeySecret、stsToken接口地址 var bucket = ' ';//通过控制台创建的bucket的名称 var region = ' '; //bucket 所在的区域, 默认 oss-cn-hangzhou aj(); function aj(){ if(j>=ss.
一.前期准备 docker安装 (我使用的是1.13.1)
docker-compose安装 (我使用1.19.0)
go语言 (我使用的是go1.8.3)
开发环境: ubuntu16.10
1.docker 安装
sudo apt install docker.io 安装成功后,可以通过以下指令来查看版本:
docker -v 2.docker-compose安装
sudo curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose 安装成功后,通过以下指令查看版本:
docker-compose -v GO 语言环境安装
下载地址: https://golang.org/dl/ 选择合适的版本 我的版本是go1.8.3.linux-amd64.tar.gz
tar -zxvf go1.8.3.linux-amd64.tar.gz -C /usr/local 之后就可以在/usr/local下看到go文件夹了
接着配置环境变量,我的workspace是$HOME/go
sudo vi ~/.profile 在末尾加上
export PATH=$PATH:/usr/local/go/bin export GOROOT=/usr/local/go export GOPATH=$HOME/go export PATH=$PATH:$HOME/go/bin 配置完毕后执行:
source ~/.profile 查看go的版本:
go version 二.Fabric网络搭建 进入工作目录$HOME/go
创建以下一系列文件夹:
$HOME/go/src/github.com/hyperledger
问题:js报Uncaught SyntaxError: Unexpected token ILLEGAL
引起原因有如下:
1,button中的onclick();方法的参数没有获取到,从而导致参数为空而报错
2,检查参数引号是否为正确,是否忘了闭合。
3,如果参数中的数是从数据库中获取的,请检查数据库中的数据是否存在空格或者空行,就像我今天添加数据时是直接从网页上复制进去的,从而导致有空行存在,那么参数中的数据就存在有空行了,这样就会报这个错误。
Tween.js 是一个小型的 JavaScript 库,可以从 https://github.com/sole/tween.js 下载。这个库可以用来定义某个属性在两个值之间的过渡,自动计算起始值和结束值之间的所有中间值。这个过程叫 tweening(补间)。例如,你可以用这个库将一个网格 x 轴上的位置在 10 秒钟内从 10 递减到 3,如下代码片段所示:
var tween = new TWEEN.Tween({x: 10}) .to({x: 3}, 10 000) .easing(TWEEN.Easing.Elastic.InOut) .onUpdate(function() { // 更新你的 Mesh }) .onComplete(function(){ // 如果需要,在此进行后处理动作 }); 在这段简短的示例代码中,我们创建了一个 TWEEN.Tween 对象,这个对象可以保证 x 属性在 10 秒钟内从 10 变化到 3。通过 Tween.js 你还可以指定在指定时间内属性如何变化,是线性的、指数性的,还是其他任何可能的方式(具体看可参考官方指南https://github.com/sole/tween.js/blob/master/docs/user_guide.md)。
属性值在指定时间内的变化成为 easing(缓动),在 Tween.js 中,你可以通过 .easing() 函数来配置缓动效果。在 three.js 中使用这个库非常简单。下面我们给出一个完整的示例,代码如下所示:
<!DOCTYPE html> <html> <head> <title>示例 09.03 - 补间动画</title> <script src="../build/three.js"></script> <script src="../build/js/controls/OrbitControls.js"></script> <script src="../build/js/libs/stats.min.js"></script> <script src="
在运用element-ui的表格展开行组件时,默认的是点击左边的小箭头才能展开,但是实际的需求却是点击一整行展开,实现方法如下:
<el-table :data="entdatas" style="width: 100%" row-key="id" :expand-row-keys="entexpands" @row-click="rowExpand"> <el-table-column type="expand"> <template scope="props"> <el-form label-position="left" inline class="demo-table-expand"> <el-form-item label="名称:"> <span style="cursor:pointer;color:#4AA6FF;" @click="_goEntDetail(props.row.ENTNAME)">{{props.row.ENTNAME}}</span> </el-form-item> <el-form-item label="类型:"> <span>{{props.row.ENTTYPE}}</span> </el-form-item> <el-form-item label="状态:"> <span>{{props.row.ENTSTATUS}}</span> </el-form-item> <el-form-item label="日期:"> <span>{{props.row.ESDATE}}</span> </el-form-item> </el-form> </template> </el-table-column> <el-table-column label="名称" prop="ENTNAME"> </el-table-column> <el-table-column label="状态" prop="ENTSTATUS"> </el-table-column> <el-table-column label="日期" prop="ESDATE"> </el-table-column> </el-table> export default { data() { return { entdatas:[], entexpands: [] } }, rowExpand(row, event, column) { Array.prototype.remove = function (val) { let index = this.
定义 如果在子类中对从父类继承来的成员变量进行重新定义,即出现了子类变量对父类变量的隐藏
隐藏的问题 设定A为父类,B为子类,当B的对象调用父类里面的方法(就是子类里面没有进行重写的方法),且方法里面用到了出现隐藏的变量,则该方法只会调用父类里面的参数变量,不会调子类里面重定义的变量。
和重写比较 重写是针对方法而言的,隐藏是针对变量而言。
在子类中,如果子类重写了父类的方法,那么子类在调用时会用重写的方法,即使子类调用父类的方法f方法(这个父类方法里面调用了有被子类重写的方法f1方法),f方法在调用f1时,会用重写后f1。当f调用被子类隐藏的变量(即被子类重定义的参数),会调用父类里面的变量,f1会调用子类重定义的变量。
所以:子类继承的方法,只能操作子类继承和隐藏的成员变量。(今天看到的一道面试题)
下面段网上的代码帮助理解:
publicclass Main {
publicstaticvoid main(String[] args) {
A a = new A();
a.printOut();
System.out.println("------------------------------");
B b = new B();
b.printOut();
System.out.println("------------------------------");
b.show();
System.out.println("------------------------------");
a = b;
a.printOut();
}
}
class A{
inti = 0;
publicvoid doAdd(){
i++;
System.out.println("A.i相加");
}
publicvoid printOut(){
this.doAdd();
System.out.println("A:"+i);
}
}
class B extends A{
publicinti = 0;
publicvoid doAdd(){
i+=2;
//super.i+=2;
System.out.println("B.i相加");
}
publicvoid show(){
我们在讨论相机和动画之前,先来看看对象的选择实现,尽管这个跟动画没有直接的关系,但了解这个实现之后将会是一个很有益的补充。
在给出示例代码之前,我们先来看一下核心代码:
function onDocumentMouseDown(event) { event.preventDefault(); mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObjects([scene.getObjectByName('cube'), scene.getObjectByName('sphere'), scene.getObjectByName('cylinder')], false); if (intersects.length < 1) { highlightBox.visible = false; return; } var intersected = intersects[0].object; ...... } 在这段代码里,我们使用了 THREE.Raycaster 类,来检测我们是否点在了一个对象上。当我们在屏幕上点击时,会发生以下事情:
首先,基于我们在屏幕上点击的位置,创建出一个二维向量;接着,我们通过 raycaster.setFromCamera 函数,从屏幕上的点击位置向场景中发射一束光线;最后,我们用 raycaster.intersectObjects 函数,来判断指定的对象中有没有被这束光线击中的; 上述步骤的最后一步中,结果包含了所有被光线击中的对象信息,这些信息包括:
distance: 123.456789face: THREE.Face4faceIndex: 4object: THREE.Meshpoint: THREE.Vector3 其中 object 属性就是我们点击后选中的网格对象。face 和 faceIndex 指的是网格中被选中的面。distance 属性是从相机到被点物体间的距离。而 point 则是被选中物体网格对象上的一个点。
将.csv格式数据导入数据库: 方式一、 在 MySQL 或者是 SQL Server 中直接编写代码,建立表格,然后导入数据。
注意:导入数据的格式要与创建数据库时的格式相同,不然会乱码。
Windows 一般都是GBK或者UTF-8
如:
CREATE TABLE `采购网` (
`采购项目名称` TEXT NULL,
`品目` TEXT NULL,
`采购单位` TEXT NULL,
`行政区域` TEXT NULL,
`公告时间` TEXT NULL,
`获取招标文件时间` TEXT NULL,
`获取招标文件的地点` TEXT NULL,
`开标时间` TEXT NULL,
`开标地点` TEXT NULL,
`预算金额` TEXT NULL,
`采购单位地址` TEXT NULL,
`采购单位联系方式` TEXT NULL,
`代理机构名称` TEXT NULL,
`代理机构地址` TEXT NULL,
`代理机构联系方式` TEXT NULL
)
COLLATE='gbk_chinese_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT
;
方式二、 直接用R来导入数据库。
注意:导入数据的格式要与创建数据库时的格式相同,不然会乱码。
kea安装之前,首先安装了mysql,在安装kea时执行
./configure \--with-dhcp-mysql 时却显示configure: error: --with-dhcp-mysql should point to a mysql_config program,导致kea一直安装不下去,找了半天,最后指定一个路径显示
checking for MySQL headers and library... no configure: error: Needs MySQL library 可以定位到问题时mysql安装问题,使用yum install -y mysql-devel解决问题,重新执行
./configure \--with-dhcp-mysql接下来再执行make,make install安装kea
as()函数比as.data.frame()、as.array()等函数广泛,更具有强制性。 一、
as()函数:强制给对象到定类。如关联规则(arules)类型、智能推荐("binaryRatingMatrix""recommenderlab")类型,as.data.frame()、as.array()等函数就做不到转换。
使用: as ( object , class ,strict= true , ext ) as ( object , class ) < - value 解释: x:任何r对象。 class:要强制对象的类的名称。 Strict:逻辑标志。如果为true,返回的对象必须严格从目标类(除非该类是虚拟类,在这种情况下,对象将来自最近的实际类,特别是原始对象,如果该类直接扩展虚拟类)。如果为false,将返回目标类的任何简单扩展,而不需要进一步更改。大致来说,一个简单的扩展只是将片段添加到现有类。 Value:用于修改对象的值。 二、
as.data.frame()、as.array()等函数,可以对已有的常用的类型转换。
类型:检查对象是否是数据帧,或者是否可以强制执行。 使用: as.data.frame(x, row.names = NULL, optional = FALSE, ...) 解释: X:任何r对象。 row.names:为数据帧提供行名称的空或字符向量。不允许丢失的值。 optional :逻辑的。如果为true ,则设置行名称和转换列名。请注意,所有r的基本包as.data.frame ( )方法只用于列名处理,基本上是data.frame ( * , check.names = !)的含义。 ... Stringsasfactors:逻辑:字符向量是否应该转换为一个因素。
当前项目使用Perforce控制版本。
我们可以使用 p4 change changelist# 打开一个 changelist 的相关描述,可以通过修改 Description 字段来进行修改。可是在自动化中,该方法并不合适,好在 P4 提供了 p4 change -o 以及 p4 change -i 两个指令。
p4 change
The -o flag writes the changelist specification to the standard output.
The -i flag reads a changelist specification from the standard intput.
具体用法如下:
p4 change -o changelist#(如果不加,默认为default) > xxx脚本修改xxxp4 change -i < xxx 如何使用脚本修改文件呢?这里以 python 为例。我们使用 open 函数来读写文件。open 函数常用模式:
模式含义r读模式r+读写模式,在原文件的基础上编辑w写模式,如果文件存在,则先清除文件内容a追加模式 我们需要将 “Description:” 下一行的描述修改为新描述(这里假设Description没有换行符):
data = "" flag = False with open('xxx', 'r') as f: for line in f.
假期无聊第二季,用C语言实现简单经典小游戏——贪吃蛇。特别适合新手熟悉C语言。(完整程序在文章最后!!!) 主要涉及C语言知识点如下: 结构体,函数的定义及调用,指针变量,指针和数组,逻辑表达式,基本的选择和循环语句,头文件的编写等。 可以说是麻雀虽小,五脏俱全,是新手练习C语言的绝佳小项目! 游戏界面如下: 基本思路: 蛇每吃一个食物蛇身子就增加一格,用WASD控制蛇头的运动,而蛇身子跟着蛇头走,每后一格蛇身子下一步走到上一格蛇身子的位置,以此类推。
程序主要变量如下:
#define M 20//整个图形界面的长和宽 #define N 60 struct snake a[(M - 2)*(N - 2)];//蛇身数组 int snake_x =4;//蛇身的XY坐标 int snake_y =4; int X = 1;//控制蛇头的方向量 int Y = 0; int food_x , food_y ;//食物的XY坐标 int score = 0;//分数 食物的随机位置产生是通过两个随机数分别代表X,Y坐标实现的。
void food(int *x, int *y,int *fx,int *fy,int *s, struct snake *snake) { int ffx, ffy;//上一次食物的XY坐标 ffx = *fx; ffy = *fy; if (*x == *fx && *y == *fy)//如果吃到了食物,产生下一个食物 { do { *fx = 1 + rand() % (N - 3); *fy = 1 + rand() % (M - 3); } while (ffx == *fx && ffy == *fy);//保证与上次食物位置不同 for (int i= (*s); i >= 0; i--) { if ((snake + *s)->snake_x == *fx && (snake + *s)->snake_y == *fy) { *fx = 1 + rand() % (N - 3); *fy = 1 + rand() % (M - 3); } }//大概率保证食物与蛇身子的位置不同(不能完全保证) (*s)++ ; //分数加一!
在前面的Android中getSystemService流程中,我们知道在系统启动的时候,会启动一些系统的必要服务,SystemUI也是在SystemServer#startOtherServices这里启动的
SystemUI启动时机 static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); } 上面启动了SystemUIService服务,下面看看那SystemUIService服务具体做了什么
public class SystemUIService extends Service { @Override public void onCreate() { super.onCreate(); ((SystemUIApplication) getApplication()).startServicesIfNeeded(); } } SystemUIApplication#startServicesIfNeeded
public void startServicesIfNeeded() { startServicesIfNeeded(SERVICES); } private void startServicesIfNeeded(Class<?>[] services) { .... final int N = services.length; for (int i = 0; i < N; i++) { Class<?
分布式事务10_最大努力通知形势 更多干货 分布式事务处理一分布式事务二分布式事务处理三分布式事务四_基于可靠消息的最终一致性分布式事务五_基于可靠消息的最终一致性_异常流程分布式事务六_常规MQ队列分布式事务七_幂等性设计分布式事务八_可靠消息最终一致性方案分布式事务九_基于可靠消息的最终一致性代码分布式事务10_最大努力通知形势柔性事务解决方案:TCC(两阶段型、补偿型)支付宝 分布式事务服务 DTS 一分布式事务服务 DTS二分布式事务服务 DTS三支付宝 分布式事务服务 DTS四 实现 业务活动的主动发,在完成业务处理后,向业务活动的被动方发送消息允许消息丢失业务活动的被动方根据定时策略,向业务活动的主动发查询,恢复丢失的业务消息 约束 被动方的处理结果不影响主动方的处理结果 成本 业务查询与校对系统的建设成本 适用范围 对业务最终一致性的时间敏感度低跨企业的业务活动 用到的服务模式 可查询操作 方案特点 业务活动的主动发在完成业务处理后,向业务活动被动方发送通知消息(允许消息丢失)主动发可以设置时间梯度通知规则,在通知失败后按照规则重复通知,直到通知N次后不再通知主动发提供校对查询接口给被动方按需校对查询,用于恢复丢失的业务消息 行业应用案例 银行通知、商户通知等(各大交易业务平台的商户通知:多次通知、查询校对、对账文件) 设计 数据库 rp_notify_record DROP TABLE IF EXISTS `rp_notify_record`; CREATE TABLE `rp_notify_record` ( `id` varchar(50) NOT NULL DEFAULT '' COMMENT '主键ID', `version` int(11) NOT NULL DEFAULT '0' COMMENT '版本事情', `create_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间', `edit_time` datetime DEFAULT NULL COMMENT '最后修改时间', `notify_rule` varchar(255) DEFAULT NULL COMMENT '通知规则(单位:分钟)', `notify_times` int(11) NOT NULL DEFAULT '0' COMMENT '已通知次数', `limit_notify_times` int(11) NOT NULL DEFAULT '0' COMMENT '最大通知次数限制', `url` varchar(2000) NOT NULL DEFAULT '' COMMENT '通知请求链接(包含通知内容)', `merchant_order_no` varchar(50) NOT NULL DEFAULT '' COMMENT '商户订单号', `merchant_no` varchar(50) NOT NULL DEFAULT '' COMMENT '商户编号', `status` varchar(50) NOT NULL DEFAULT '' COMMENT '通知状态(对应枚举值)', `notify_type` varchar(30) DEFAULT NULL COMMENT '通知类型', PRIMARY KEY (`id`), KEY `AK_KEY_2` (`merchant_order_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='通知记录表 RP_NOTIFY_RECORD'; rp_notify_record_log DROP TABLE IF EXISTS `rp_notify_record_log`; CREATE TABLE `rp_notify_record_log` ( `id` varchar(50) NOT NULL DEFAULT '' COMMENT 'ID', `version` int(11) NOT NULL DEFAULT '0' COMMENT '版本号', `edit_time` datetime DEFAULT NULL COMMENT '最后修改时间', `create_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间', `notify_id` varchar(50) NOT NULL DEFAULT '' COMMENT '通知记录ID', `request` varchar(2000) NOT NULL DEFAULT '' COMMENT '请求内容', `response` varchar(2000) NOT NULL DEFAULT '' COMMENT '响应内容', `merchant_no` varchar(50) NOT NULL DEFAULT '' COMMENT '商户编号', `merchant_order_no` varchar(50) NOT NULL COMMENT '商户订单号', `http_status` varchar(50) NOT NULL COMMENT 'HTTP状态', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='通知记录日志表 RP_NOTIFY_RECORD_LOG'; 接口 RpNotifyService public interface RpNotifyService { /** * 创建消息通知 * @param rpNotifyRecord */ public long createNotifyRecord(RpNotifyRecord rpNotifyRecord) throws NotifyBizException; /** * 修改消息通知 * @param rpNotifyRecord */ public void updateNotifyRecord(RpNotifyRecord rpNotifyRecord) throws NotifyBizException; /** * 创建消息通知记录 * @param rpNotifyRecordLog * @return */ public long createNotifyRecordLog(RpNotifyRecordLog rpNotifyRecordLog) throws NotifyBizException; /** * 发送消息通知 * @param notifyUrl 通知地址 * @param merchantOrderNo 商户订单号 * @param merchantNo 商户编号 */ public void notifySend(String notifyUrl,String merchantOrderNo,String merchantNo) throws NotifyBizException; /** * 通过ID获取通知记录 * @param id * @return */ public RpNotifyRecord getNotifyRecordById(String id) throws NotifyBizException; /** * 根据商户编号,商户订单号,通知类型获取通知记录 * @param merchantNo 商户编号 * @param merchantOrderNo 商户订单号 * @param notifyType 消息类型 * @return */ public RpNotifyRecord getNotifyByMerchantNoAndMerchantOrderNoAndNotifyType(String merchantNo , String merchantOrderNo , String notifyType) throws NotifyBizException; /** * 按条件分页查询通知记录.