月度归档:2014 年一月

javascript立即调用的函数表达式

jquery中最外围的一个方法即立即调用的函数表达式,代码如下:

(function(e,t){
//jquery code
})(window)

代码一
这个方法开始接触时是一头雾水,这段代码其实等价于:

var fn = function(e,t){
//jquery code
}
fn(window);

代码二
看到第二段代码便恍然大悟,其实代码一是因为第一对圆括的优先级最高关系,导致function(e,t){}先运行,即先声明了一个匿名函数,之后又碰到后面的一对圆括号:(window),使得之前声明的匿名函数得到立即执行。
除此之外,还有很多其他的匿名行数写法,通过使用一元或二元运算符来引导解析器,指明运算符附近是一个表达式。
如:

( function() {}() );
[ function() {}() ];
~ function() {}();
! function() {}();
+ function() {}();
- function() {}();

delete function() {}();
typeof function() {}();
void function() {}();
new function() {}();
new function() {};

var f = function() {}();

1, function() {}();
1 ^ function() {}();
1 > function() {}();
// ...

Web Worker笔记

由于javascript是单线程,为了模拟多线程,通常是利用setTimeOut,setInterval,ajax的XMLHttpRequest。HTML5出现后,我们可以通过Worker实现js的多线程。

代码:
main.html:

<html>
 <head>
  <script type="text/javascript" src='test.js'></script>
  <script type="text/javascript">
	var worker = new Worker('test.js');
	worker.addEventListener('message',function(e){
		console.log('worker return :',e.data);
	},false);
	worker.postMessage('1');
	worker.postMessage('2');
	testFn();
	worker.postMessage('1');
  </script>
 </head>
</html>

test.js:

self.addEventListener('message',function(e){
	switch (e.data)
	{
	case "1":
		self.postMessage(e.data+": var a="+self.a);
		self.a = "worker var a: 1";
	break;
	case "2":
		self.postMessage(e.data+": var a="+self.a);
		self.a = "worker var a: 2";
		break;
	}

},false);
function testFn(){
	console.log("this is worker.js function");
	self.a="worker var a : function";
}

ps:页面不能直接打开运行,需要放在web服务器上,否则报安全错误:Uncaught Error: SECURITY_ERR: DOM Exception 18
运行结果:

this is worker.js function test.js:16
worker return : 1: var a=undefined main.html:8
worker return : 2: var a=worker var a: 1 main.html:8
worker return : 1: var a=worker var a: 2

可以看到:
1,testFn后调用反而先运行了。
2,testFn将a赋值为”worker var a : function”,虽然先运行了,但是后面打印的结果均无此结果,

总结:postMessage是异步调用,worker对象的window与js的window并非共享的

ps:Worker传递的对象是通过复制传递的,并非共享的

参考:
Web Workers 的基本信息

Data URI scheme

这几天都在抢票 ,在研究360抢票插件时发现验证码的src为一串非正常URL的字符“data:image/png;base64,… …”,于是对这串字符感到好奇而进行了学习。
这串字符叫做:Data URI scheme。Data URI scheme是在RFC2397中定义的,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。
字符组成:
data:表示取得数据的协定名称
image/png:表示MIME TYPE数据类型.
base64:编码方式。
逗号后面的是编码后的字符。
目前支持的类型有:

data:,文本数据
data:text/plain,文本数据
data:text/html,HTML代码
data:text/html;base64,base64编码的HTML代码
data:text/css,CSS代码
data:text/css;base64,base64编码的CSS代码
data:text/javascript,Javascript代码
data:text/javascript;base64,base64编码的Javascript代码
data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据

在php中base64用如下编码方法即可:

base64_encode(file_get_contents('test.png'))

在java中用sun.misc.BASE64Encoder进行base64编码文件:

File file = new File("test.png");
FileInputStream fis = new FileInputStream(file);
byte[] buf = new byte[1024];
int len = 0;
int count = 0;
byte[] total = new byte[]{};
while((len=fis.read(buf))!=-1){
	count = total.length+len;
	byte[] tmp = new byte[count];
	System.arraycopy(total, 0, tmp, 0, total.length);
	System.arraycopy(buf, 0, tmp, total.length ,len);
}
fis.close();
BASE64Encoder be = new BASE64Encoder();
String string = be.encode(total);

使用data URI scheme与普通的http URI scheme区别如下:
1,浏览器对编码的数据不会进行缓存,并且随html同时加载,不另起请求;
2,便于传输,不会被拦截,只要页面能加载,便能获取到编码后的数据,这样360抢票插件就能将验证码图片进行编码后传输,在服务器后台进行识别,而不必去关心session问题;
3,保存数据的大小上受限制(Firefox 1.5支持高达100KB的数据);
4,编码后会增加图片大小;
3,但如果使用过多会增加html的大小,可用css解决,即在css的background-image中使用data URI scheme,如:

background-image: url("data:image/png;base64/9j/4AA....+b0//2Q==");

但是IE8以下版本不兼容。ie以下只得用http URI scheme.

参考:http URI scheme与data URI scheme

什么是data URI scheme及如何使用data URI scheme

360抢票插件突破五秒限制

机票太贵,只能跻身火车票抢票队列。悲催的是现在买了两趟车票都是站票,为了能抢趟稍微舒服点的票,在电脑前多少个日夜刷票,用了n个抢票软件都不好使。好不容易昨天晚上360帮我刷了张坐票但是但是我并不知情,而错过付款时间,多么悲催的命运。

于是本人决定研究一下抢票插件,对其进行改进,献给无数跟我一样悲催的朋友。

首先,拿360开刀,360抢票插件是我知道的相对最好的抢票插件了,因为它可以自动识别验证码,虽然准确率有待提高,但是运气好的话,还是能一次成功的,比起手动输入还是要快。注意:是运气好的话,中奖了要记得回帖哈。

经研究发现,12306的5秒限制好像是在前端限制的,服务端貌似没有做限制,可以用下面的地址去请求一下(这是“深圳到株洲”的查询请求):https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2014-01-27&leftTicketDTO.from_station=SZQ&leftTicketDTO.to_station=ZZQ&purpose_codes=ADULT,多次刷新貌似也没有什么问题,不知道为什么那么多抢票软件都还要做这个限制,百思不得其解啊,还望高人指点,难道是担心‘查水表’吗,应该是我想太多了,呵呵。

一,下载360抢票专版,或者’360抢票王’插件–>点击插件栏‘票’字的插件–>点击360抢票二代;或者直接地址栏输入:http://pc.huochepiao.360.cn进入抢票界面。我的抢票王插件版本是:5.2.0.20。有可能版本不一样,做法也不一样了。

二,进入界面后登录自己的账户,先不要急着刷票,按F12打开调试界面(或者点浏览器‘工具’–>开发人员工具 打开调试界面),按图1操作,打开页面文件列表:

sp1
图1

三,打开文件列表后,找到index.js文件,在文件中搜索“5100”(如果找不到,则继续找其他文件,版本不同可能文件也不一样),找到这一行后,在此行设置断点(即单击左边对应的行号,出现蓝色的标记),如图2:

刷票步骤2
图2

四,此时基本完成一半了,接下来就是刷新本页面,但调试界面不要关掉。刷新后可以看到浏览器被刚才设置的断点断下来了。这时我们找到我们刚才找到的5100的地方,懂点web知识的朋友们应该都知道怎么做了,我们把5100改成你想要刷新的间隔时间(单位:毫秒),我这这里改成500,即半秒钟刷一次(太小了可能数据还没接收完就再次刷新了),然后按CTRL+S保存。保存后点继续,就那个类似播放按钮的那个三角形的键(或者按F8),一直点到变成两束的形状(类似暂停的键);或者直接把调试界面关闭。如图3:

ps:”5100″的数字改了后一定要记得按“Ctrl+S”保存,而且保存后要让程序继续走(如图3中的第二步)直到走完(或者直接关闭调试窗口)。此后千万不能再刷新页面,否则那数字白改了,得重新修改

刷票步骤3
图3

五,我们现在要做的就是,选好刷票时间地点人员等等信息,然后点击‘开始刷票’,看到了吧,刷新频率还满意吗?不满意修改刚才的数字后重来一次。至此,万事俱备,只欠东风了,等待着放票或者捡漏吧。

刷票步骤4
图4

最后,祝君好运。。。

ps:此教程仅仅适用于360抢票王插件。其他插件没去研究。经测试抢票王5.2.0.20版本的可用,其他版本未做测试。

附:12306刷票成功后自动邮件通知JAVA源代码(github)

需导入12306证书:keytool -import -alias cacerts -keystore %JAVA_HOME%\jre\lib\security\cacerts -file (12306证书目录)\srca.cer -trustcacerts

JDK默认导入证书口令:changit

wordpress笔记

方法说明:
get_settings(‘home’); 获取首页地址
bloginfo(‘name’); 获取站点名称
the_permalink(); 当前文章页面地址
the_title(); 当前文章标题
the_content(); 当前文章内容
comments_template(); 评论输入模版
get_sidebar(); 工具栏

文件说明:
wp-content/plugins/ :插件存放目录
wp-content/themes/ :主题存放目录
wp-content/uploads :上传文件存放目录
wp-includes/default-widgets.php :小工具php文件
wp-includes/general-template.php :模版生成,(包括小工具HTML生成方法)

libvirt创建kvm虚拟机配置说明

一、通过xml创建虚拟机,virsh define vm.xml.

vm.xml配置如下:

<domain type='kvm'>
	<name>testvm</name><!--虚拟机名称-->
	<memory>1024000</memory><!--在不修改配置不reboot的情况下,虚拟机的最大内存-->
	<currentMemory>1024000</currentMemory>
	<!--虚拟机当前内存,一般小于等于memory的值,可以用virsh setmen 调整虚拟机内存,但不能大于memory设置的值。-->
	<vcpu>1</vcpu><!--cpu核数目-->
	<os>
		<type arch='x86_64' machine='pc'>hvm</type>
		<boot dev='hd' /><!--启动方式可以是 cdrom、hd-->
	</os>
	<features>
		<acpi />
	</features>
	<clock offset='utc' />
	<on_poweroff>destroy</on_poweroff>
	<on_reboot>restart</on_reboot>
	<on_crash>destroy</on_crash>
	<devices>
		<emulator>/usr/bin/kvm</emulator>
		<disk type='file' device='disk'>
			<driver name='qemu' type='qcow2' /><!--镜像文件类型:qcow2、raw 。。。-->
			<source file='/mnt/testlz/ubuntu1204.img' /><!--镜像地址-->
			<target dev='vda' bus='virtio' /><!--指定硬盘号,virtio优化虚拟机IO-->
			<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' />
		</disk>
		<interface type='bridge'><!--网络连接方式:birdge,network-->
			<source bridge='br0' /><!--网桥名称,如果连接方式为network 则把birdge改为network,br0改为对应的网络-->
			<model type='virtio' />
			<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0' />
		</interface>
		<input type='tablet' bus='usb' />
		<input type='mouse' bus='ps2' />
		<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
			<!--vnc端口,autoport为yes时,端口号会自动分配(如果被占用则自动向后+1)-->
			<listen type='address' address='0.0.0.0' />
		</graphics>
		<video>
			<model type='cirrus' vram='9216' heads='1' />
			<address type='pci' domain='0x0000' bus='0x00' slot='0x02'function='0x0' />
		</video>
		<memballoon model='virtio'>
			<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' />
		</memballoon>
	</devices>
</domain>

如果要从cdrom启动则增加如下代码:

<disk type='file' device='cdrom'>
	<driver name='qemu' type='raw' />
	<source file='/opt/lizhao/ubuntu-12.04-server-amd64.iso' />
	<!-- 光盘iso文件地址 -->
	<target dev='hdc' bus='ide' />
	<readonly />
	<alias name='ide0-1-0' />
	<address type='drive' controller='0' bus='1' target='0' unit='0' />
</disk>

二、通过命令行创建虚拟机,命令如下:

virt-install --name=testVM\    #虚机名称
--ram=1024 \  #内存大小
--vcpus=1 \    #cpu核数
--boot=cdrom \   #启动方式
--os-type linux \   #系统类型
--os-variant ubuntuprecise \   #系统版本标识,可用 virsh --os-variant list 查看所有系统版本列表
--disk path=/opt/lizhao/lizhao.qcow2,device=disk,cache=writeback,format=qcow2,bus=virtio \  #镜像文件地址,如果是qcow2的格式,必须指定cache=writeback,format=qcow2,否则会出现读取大小错误,virtio,io加速
--cdrom=/opt/lizhao/ubuntu-12.04-server-amd64.iso  \  #光驱文件地址
--bridge=br0,model=virtio \   #网络连接类型,桥接、nat
--vnc --vncport=5900 --vnclisten=0.0.0.0 \ #vnc
--accelerate \   #kvm加速
--hvm \
--noautoconsole

wordpress小工具修改

wordpress小工具管理在:外观–>小工具中,通过拖拽可以定制使用的小工具。

默认的‘功能’小工具的链接为登录、文章Rss,评论Rss,WordPress.org。这些链接在管理面板是不能进行管理的,只能通过修改源代码的方式进行管理。对应的文件为/wp-includs/default-widgets.php,我们只需搜索WordPress.org即可以找到相应的代码位置,修改对应的<li>节点即可,如我要去掉WordPress.org的链接,把对应的<li>注释即可:


<ul>
 <?php wp_register(); ?>
 <li><?php wp_loginout(); ?></li>
 <li><a href="<?php bloginfo('rss2_url'); ?>" title="<?php echo esc_attr(__('Syndicate this site using RSS 2.0')); ?>"><?php _e('Entries <abbr title="Really Simple Syndication">RSS</abbr>'); ?></a></li>
 <li><a href="<?php bloginfo('comments_rss2_url'); ?>" title="<?php echo esc_attr(__('The latest comments to all posts in RSS')); ?>"><?php _e('Comments <abbr title="Really Simple Syndication">RSS</abbr>'); ?></a></li>
 <!--<li><a href="<?php esc_attr_e( 'http://wordpress.org/' ); ?>" title="<?php echo esc_attr(__('Powered by WordPress, state-of-the-art semantic personal publishing platform.')); ?>"><?php
 /* translators: meta widget link text */
 _e( 'WordPress.org' );
 ?></a></li>-->
 <?php wp_meta(); ?>
 </ul>

参考:wordpress默认“功能”小工具修改

struts2上传大小为0的文件问题解决

当struts上传大小为0kb的文件的时候,struts默认当文件不存在,后台接收的文件file.exist()的值为false;

我使用的struts版本为:2.1.8.1;其他版本可能会没有这个问题,未做测试;

参考:Struts 2.3.1 GA 版发布

  • [WW-3562] – FileUploadInterceptor: File not uploaded when file is empty (0 bytes)

struts 配置有个属性struts.multipart.parser,该属性指定处理multipart/form-data的MIME类型(文件上传)请求的框架,该属性支持cos、pell和jakarta等属性值,即分别对应使用cos的文件上传框架、pell上传及common-fileupload文件上传框架。该属性的默认值为jakarta。

为jakarta时候,如果上传的文件大小为0kb,则struts读取文件则是不存在的:

When not selecting any file to upload in a file input, Struts does not ignore the 0 byte file
returned by jakarta FileUpload.
This means that a file is injected in the action even if nothing was uploaded.

In webwork the check was done in the constructor of  com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest:

else if (item.getSize() == 0) {
log.warn("Item is a file upload of 0 size, ignoring");
}

In struts the parsing of the request moved from the constructor to a parse method but the
above check disappeared.

Additionally this behaviour is inconsistant with the "pell" implementation that ignores 0
byte files.

--
This message is automatically generated by JIRA.

这里是STRUTS_MULTIPART_PARSER的官方文档说明:

STRUTS_MULTIPART_PARSER

public static final String STRUTS_MULTIPART_PARSER

The org.apache.struts2.dispatcher.multipart.MultiPartRequest parser implementation for a multipart request (file upload)

See Also:
Constant Field Values

注意  如果需要使用cos或者pell的文件上传方式,则应该将对应的JAR文件复制到Web应用中。
例如,使用cos上传方式,则需要自己下载cos框架的JAR文件,并将该文件放在WEB-INF/lib路径下。但是我测试仍然为通过,原因未知。

解决办法2:

if (!srcFile.exists()) {
 try {
   destFile.createNewFile();//创建空文件
 } catch (IOException e) {
   LogUtil.error(e);
   return;
 }
} else {
//文件操作
}

参考:

struts2 的struts.properties配置详解

http://www.iteye.com/problems/19141

myeclipse8.6安装github插件

安装egit:

1,下载egit,地址:http://pan.baidu.com/s/1bnrHZXH

2,下载后解压到Genuitec\MyEclipse-8.6\dropins目录下,文件包括features、plugins,artifacts.jar、content.jar。

也可以通过link方式安装(未测试)

3,解压后重启myeclipse,打开window -> preferences ,在team下面出现了git表示安装成功。

4,配置git:打开window -> preferences -> general -> network Connections -> ssh2,选择key management选项卡,点击generate RSA key,在下面的文本框中会生成一串key,复制这一串key。

打开github页面,登录后进入设置界面(account settings),点击ssh keys菜单,进入页面后,点击add ssh key按钮,打开添加页面后,title可以任意填写,key的输入框输入刚才复制的那一串key,点击Add key添加完毕,权限配置完毕。

5,在github页面进入项目页面,找到:You can clone with HTTPS, SSH, or Subversion ,点击ssh,复制旁边的文本框中的地址。这个就是项目的checkout地址了

参考:Eclipse下搭建GitHub开发环境