新概念三学习1~8课

(一个有要求自己写3,4篇以上的东东,来凑数的。-.-~)

大概说一些现在整理的学习方式,不保证适合所有人,因为自己时间有限,所以尽量利用自学的资源看,目标是先会看会写,零碎时间利用率高:

资源集合,不一定保证有效。如果失效了可以单独m我。百度网盘可以直接收藏,连接失效了,资源还是可以看的,最爽还是能在线看。

http://bbs.zhan.com/thread-51490-1-1.html?sid=2001&utm_source=baidu&utm_medium=CPC1&utm_campaign=ysyh-xingainianyingyu

自学导读文件是pdf版本的。最好是下载:adobe acrobat 里面有文档扫描功能,当然,错误不少。不过整理笔记时,复制出来再做修改还是比较方便。

哥的学习方式还是和原来一样,看中文,翻译成英文再去看课文。

http://st.hujiang.com/topic/15699641296/#post_list_15589149

简单防恶意提交处理+session保存机制细节

最近一个活动被人搞,主要频繁提交,把这边的一个表塞了很多恶心数据。

场景为:

手机访问,输入身份证相关信息,接口1~3秒,其它活动相关信息。再提交。

处理方式:

主要加了些验证,如图形和session限制。

因为是手机访问,所以同ip是很有可能的情况,只能做一个大阀值处理,但是阀值不好控制,多了没效果,少了,真实手机用户有问题。所以异常ip需要先确认是不是一些运营商的服务器这些要查查。不是就可以直接封了。再加个简单的session校验,说实在,没啥用。不过一般人是通过电脑才来黑,如果通过运营商(就是手机热点)。同时用代理也有一定几率伪造终端ip,暂时都没有啥太好的方式感觉。

贴代码(yii版本):

<?php
/**
 * 特别注意:
 * 服务器上和本地的类是不同的。本地服务器因为链接问题,所以直接进行reture处理。
 * @author caihaibin
 *
 */
class SubmitTools {
	static function model() {
		return new SubmitTools ();
	}
	/**
	 * 防重复提交校验
	 *
	 * @param string $key
	 *        	特殊项目,自己提供当前用户唯一标志。如:活动id+用户手机号码 (必要时,活动链接也可以)
	 * @param boolean $debug_write_log
	 *        	当为true时,所有通过和不通过都写入到日志
	 * @return boolean 指定时间内的第一次提交,为true,重复提交会抛出异常
	 */
	static function record($key = '', $debug_write_log = false) {
		if (empty ( $key )) {
			$key = 'submit_' . Yii::app ()->session->getSessionID ();
		}
		$result = Yii::app ()->tmpcache->get ( $key );
		if ($result) {
			if ($debug_write_log)
				write_log ( 'mult_submit_error', $key );
			throw new Exception ( '当前用户,10秒内只能提交一次' );
		}
		Yii::app ()->tmpcache->add ( $key, '1', 10 );
		if ($debug_write_log)
			write_log ( 'mult_submit', $key );
		return true;
	}
}

上面这个版本是结合php-redis的版本

因为场景里有个情况叫身份校验延迟,这种情况下,验证码校验后更新了数据,但是在会话结束前是不会写到session的数据源里的。所以用redis,记录提交的标志。不提供的情况下就是session_id,还可以自己拼标志,比如身份证号。

多提供个yii的:

Yii::app ()->tmpcache->add ( $key, '1', 10 );

源码说明:

	/**
	 * Stores a value identified by a key into cache if the cache does not contain this key.
	 * This is the implementation of the method declared in the parent class.
	 *
	 * @param string $key the key identifying the value to be cached
	 * @param string $value the value to be cached
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
	 * @return boolean true if the value is successfully stored into cache, false otherwise
	 */
	protected function addValue($key,$value,$expire)
	{
		if ($expire == 0)
			return (bool)$this->executeCommand('SETNX',array($key,$value));

		if($this->executeCommand('SETNX',array($key,$value)))
		{
			$this->executeCommand('EXPIRE',array($key,$expire));
			return true;
		}
		else
			return false;
	}

储存标记是原来有的,则不进行覆盖。同时yii其它cache方式如file也有相应处理。

 

 

PHP-Redis

官方原文档地址:

http://redisdoc.com/

php-redis文档

http://www.cnblogs.com/weafer/archive/2011/09/21/2184059.html

瞬时并发量上来,服务器集群后。剩下的瓶颈就是数据库,不过这边真心以目前的条件看无解中。需求修改太频繁。很多东西都是刚定就说什么什么时候要。频繁变化的东西,何来的优化呢~

新概念2复习到 86

终于快完了。然后就看三。

不过对于三还没有什么好的学习方向,估计是按要求做题了,哈哈~!

前段时间买了两本英语书,一本是《新概念英语3》(吐槽:光盘和其它东西都是单独卖的,坑)

一本是老外写的,名字给忘了。元旦回家看看再补上。

主要讲一个外国人在中国做老师,并从外国人的角度分析和理解各种中国习惯。感动啊~英语看这本无压力。。。。专业名词少。。都比较生活化。。。

解决phonegap 2.9 多次上传导致的 线程占用异常.

虽然是个很老的版本,但是优势是支持 清理缓存。同时没有什么太高的要求。

最近实现一个对话功能,需要能实现类似微信的上传录音功能。

录音好说,但是多次上传时,会报错,最终发现是线程被占用,释放做得不好啊。。

两个解决方案,修改原代码。用filereader代替。

简单解决。用filereader 读取录取后的文件,然后传到服务器。

代码如下:

获取文件内容

function getData(filepath, datacall, failcall) {
	var path = filepath;
	var level = "window.requestFileSystem";
	if (typeof failcall != 'undefined') {
		fail = failcall;
	} else {
		function fail(error) {
			// console.log(evt);
			// evt.target.
			console
					.log("gddebug file getData " + level + " fail "
							+ error.code);
		}
	}
	if (typeof datacall == 'undefined') {
		datacall = function(data) {
		};
	}
	window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
			function(fileSystem) {
				level = "fileSystem.root.getFile";
				console.log('gddebug fileSystem.root.getFile ' + path);
				fileSystem.root.getFile(path, null, function(fileEntry) {
					level = "fileEntry.file";
					fileEntry.file(function(file) {
						console.log("gddebug readAsDataURL");
						var reader = new FileReader();
						reader.onloadend = function(evt) {
							console.log("gddebug" + "Read as data URL");
							console.log("gddebug" + evt.target.result);
							datacall(evt.target.result);
						};
						reader.readAsDataURL(file);
					}, fail);
				}, fail);
			}, fail);
}

上传文件:

function uploadFile(url, filepath, wincall, failcall, calltype) {
	if (typeof calltype == 'undefined') {
		calltype = 'html';
	}
	filepath = filepath.replace(/^file:///, '');
	getData(filepath, function(data) {
		$.post(url, {
			file : data,
			filename : basename(filepath)
		}, wincall, calltype);
	}, failcall)
}

服务器解析代码:

if(isset($_POST['file'])){
	if(empty($_POST['file'])){
		sjson(false,$title,'');
	}
	$filepath='record/'.$_POST['filename'];
	$_POST['file']=preg_replace('/^data:[^;]+?;base64,/','',$_POST['file']);
	$_POST['file']=base64_decode($_POST['file']);
	file_put_contents($filepath,$_POST['file']);
}

补充amr 转 mp3版本

if(isset($_POST['file'])){
	if(empty($_POST['file'])){
		sjson(false,$title,'');
	}
	$filepath='record/'.$_POST['filename'];
	$_POST['file']=preg_replace('/^data:[^;]+?;base64,/','',$_POST['file']);
	$_POST['file']=base64_decode($_POST['file']);
	file_put_contents($filepath,$_POST['file']);
	if(preg_match('/.amr/i',$filepath)){
		$target_mp3=preg_replace('/.amr$/i','.mp3',$filepath);
		//将amr转换成mp3
		exec("java -jar amr.jar {$filepath} {$target_mp3}");
		$filepath=$target_mp3;
	}
	$urlpath='http://192.168.0.144/test/phonegap/www/upload/'.$filepath;
	sjson(true,$title,'',array('path'=>$urlpath,'html'=>$html));
}

 

编写可直接命令运行的jar文件

准备一个完整的项目.

各种类需要放在里面进行正常引用。外部引用类需要放进来。

打包工具:eclipse 需要支持导出 runnable jar file.老版本只能导出jar

操作:eclipse 右键 export -> java->runnable jar file.

然后就可以直接命令运行。也可以通过php进行调用了。

对于需要传入的参数。就是 public static void main(String[] args) 这个args 东东了。

第一个参数就是args[0]

比如写了一个amr转mp3的jar。执行代码

java -jar amrtomp3.jar “amr filepath”  “mp3 filepath”

 

 

Yii soap 一个奇怪的异常 + 一个不是方法的方法

最近对接第三方通知接口时,出现一个奇怪的问题。

soap的请求,有进入soap service 的 init 事件,确没有进入最终的动作。

暂时查不出原因,因为服务器只有上传的权限,没有拦截报文和相关其它的权限。同时只有目标发起时才发生,都是要钱的,不土豪。。测试不起。。也只能做猜想,尝试各种方法先解决了。

猜想:

1.报文有出现特殊字符,在复制的过程中会被处理,但是本身程序正常处理时,碰到会异常

2.请求不完整,可能第三方通知机制,接通后不等响应就把请求停了。这块不好验证。

3.框架或服务器bug。

经过各种尝试之后,确认了些问题,问题并不出在报文和请求头,因为将报文和请求头保存之后,在本地和在服务端模拟请求。都有正常响应。(不确认是否在各种复制的过程中,特殊字符丢失)

时间紧迫,所以按最快的方式处理。因为init能正常进行访问,所以将通知请求的解析在init中进行处理,解析出目标数据再调用原来的动作。

//获取soap报文,普通的 soap?wsdl是响应报文,不要搞混
$reqxml = file_get_contents ( 'php://input' );
//判断请求报文是否有对应的动作
if ($reqxml && preg_match ( '/xxxxxRequest/', $reqxml ))
//解析xml,得到对应数据
$reqxml = @simplexml_load_string ( $reqxml, NULL, LIBXML_NOCDATA );
//注意有些特殊标签在属性里,需要进行特殊关联。因为只有一个,这边进行了简单处理。
$request = json_decode ( json_encode ( $reqxml ), true );
//自己调用原来的函数。触发对应的通知处理
.....
//函数返回后,和原来的情况一样。没有经过目标函数,所以需要手动输出响应报文
echo '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:xxxxxxControllerwsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:xxxxxxResponse>xxxxxx</ns1:xxxxxResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>';'
//记得关闭,
exit ();

先留位置,因为只是特殊出现。暂时只保留特殊处理。先记录,后面有时间再深入研究解决,好吧。是测试太频繁。。。。钱钱钱的问题。。。。

解决 navicat 导入大sql文件 ,单行过长问题。

前段时间维护一个项目,搞错需求。导致以为是翻新。。。把整个库拷贝了份。。(文件来源貌似是用mysql自带导出的,具体不清楚)

1g多,不算太多,主要一个问题出在sql是以:

insert into table (row…) values (value…), (value…), (value…)….

单行。。没错。。就是单行。很多sql程序,处理该机制是一直循环识别到换行符号。。导致一个问题。内存不够。在内存比较足的机器足足运行了超过半天还不到一半,没耐性的哥想原因。顺便写了写脚本解决。

$file_source = 'c:/xxxx.sql';
$file_target = 'c:/xxxx2.sql';
$rh = fopen ( $file_source, 'rb' );
$wh = fopen ( $file_target, 'wb' );
if ($rh === false || $wh === false) {
	// error reading or opening file
	return true;
}
$count = 0;
$begin = 0;
$span = 300;
$lasttable = '';
while ( ! feof ( $rh ) ) {
	$line = fgets ( $rh );
	if (preg_match ( '/INSERT INTO `(w+)`/ims', $line, $match )) {

		// if ($lasttable == $match [1])
		// continue;
		// // $line=preg_replace('/', $replacement, $subject)
		$lasttable = $match [1];
		// gddebug ( $line );
		// fputs ( $wh, $line );
		$line = preg_replace ( '/),(/ism', ");n INSERT INTO `{$lasttable}` VALUES (", $line );
		// gddebug ( $line );
		// exit ();
	}
	if (preg_match ( '/^--/ims', $line ))
		continue;
	if (preg_match ( '/^/*/ims', $line ))
		continue;
	if (preg_match ( '/LOCK TABLES/ims', $line ))
		continue;
	if (preg_match ( '/UNLOCK TABLES/ims', $line ))
		continue;
	fputs ( $wh, $line );
	// if ($count > $line) {
	// gddebug ( $line );
	// }
	$count ++;
	// if ($count > $begin + $span)
	// exit ();
	// exit;
}
fclose ( $rh );
echo ($count);

1g文件。40分钟导入~