php面试
1.大型的分页查询
发现当表中有很多上万条数据时,越后的数据用limit分页显示就越慢(>2秒),可能是mysql的特性所致。所以花了点时间总结实现了更优解决方案,最终实现毫秒级响应。若网友有更优的,请留言,谢谢!
<?
/*
高效分页效果:
特点及优点:
1.不使用limit,当总记录数很大时,limit取后面的数据会很慢
2.保存主键值至数组,再截取最终需要的一段主键值,再放入sql in中,减少了数据库的负担。
步骤:
1.先取出所有记录的主键id值
2.保存id值入数组
3.根据当前页、每页数据量,获取需要返回记录的id串 ;implode(",",array_slice($conndb_arr,($page-1)*$page_size,$page_size));array_slice取出数组中的一段,implode组合数组为字符串
4.构造最终的sql语句 "$sql where id in(".implode(",",array_slice($conndb_arr,($page-1)*$page_size,$page_size)).")"
例子如下:
*/
if(isset($_GET["page"]))$page = intval($_GET["page"]);else $page = 1; //取出当前所在页,默认为1
$page_size =9; // 每页显示记录数
//完整的查询
$sql="select id,title,addtime,visit,content,(select count(*) from blog_news where archive_id=blog_archive.id) as news_c,(select realname from users where id=blog_archive.users_id) as creator from blog_archive";
$sql_c="select id from blog_archive order by id desc";// 取出表所有id值 (强烈建议id为主键或已添加索引)
$result=conndb($sql_c);
if(getresult_right($result)){ //自定义的sql语句执行结果判断语句
$amount=mysql_num_rows($result);//得到总记录数
//$row =mysql_fetch_array($result);
while ($row =mysql_fetch_array($result)){
$conndb_arr[]=$row[0];//将所有id值存入数组
}
// 记算总共有多少页
if( $amount ){
if( $amount < $page_size ){ $page_count = 1; } //如果总数据量小于$PageSize,那么只有一页
if( $amount % $page_size ){ //取总数据量除以每页数的余数
$page_count = (int)($amount / $page_size) + 1; //如果有余数,则页数等于总数据量除以每页数的结果取整再加一
}else{
$page_count = $amount / $page_size ; //如果没有余数,则页数等于总数据量除以每页数的结果
}
} else $page_count = 0;
if($page>$page_count)$page=(int)$page_count;
if( $amount ){
//array_slice($conndb_arr,($page-1)*$page_size,$page_size)表示取出id数组中的一段,从($page-1)*$page_size开始取$page_size个
$result=conndb("$sql where id in(".implode(",",array_slice($conndb_arr,($page-1)*$page_size,$page_size)).")");
while ($row =mysql_fetch_array($result)){ //循环输出分页记录
echo $row[id]."<br>";
}
}else{
echo "没有找到任何记录!";
}
}
?>
2.你知道哪些设计模式,并且他们的使用场景和作用是什么
3.php的优化方法
代码优化是开发程序和网站必不可少的一步,代码优化好了,可以大大增加程序的运行效率。使网站或程序加载反应更快。用户体验也就会更好。下面就为大家总结了50条PHP代码优化技巧。
1、 用单引号代替双引号来包含字符串,这样做会更快一些。因为 PHP 会在双引号包围的 字符串中搜寻变量,单引号则不会,注意:只有 echo 能这么做,它是一种可以把多个字符 串当作参数的“函数”(译注:PHP 手册中说 echo 是语言结构,不是真正的函数,故把函数 加上了双引号)。
2、如果能将类的方法定义成 static,就尽量定义成 static,它的速度会提升将近 4 倍。
3、$row['id'] 的速度是$row[id]的 7 倍。
4、echo 比 print 快,并且使用 echo 的多重参数(译注:指用逗号而不是句点)代替字符串 连接,比如 echo $str1,$str2。
5、在执行 for 循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用 foreach 代替。
6、注销那些不用的变量尤其是大数组,以便释放内存。
7、尽量避免使用__get,__set,__autoload。
8、require_once()代价昂贵。
9、include 文件时尽量使用绝对路径,因为它避免了 PHP 去 include_path 里查找文件的速 度,解析操作系统路径所需的时间会更少。
10、如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用 $_SERVER['REQUEST_TIME'] 要好于 time()
11、函数代替正则表达式完成相同功能。
12、str_replace 函数比 preg_replace 函数快,但 strtr 函数的效率是 str_replace 函数的四倍。
13、如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么 可以考虑额外写一段替换代码, 使得每次传递参数是一个字符, 而不是只写一行代码接受数 组作为查询和替换的参数。
14、使用选择分支语句(译注:即 switch case)好于使用多个 if,else if 语句。
15、用@屏蔽错误消息的做法非常低效,极其低效。
16、打开 apache 的 mod_deflate 模块,可以提高网页的浏览速度。
17、数据库连接当使用完毕时应关掉,不要用长连接。
18、错误消息代价昂贵。
19、在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。
20、递增一个全局变量要比递增一个局部变量慢 2 倍。
21、递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢 3 倍。
22、递增一个未预定义的局部变量要比递增一个预定义的局部变量慢 9 至 10 倍。
23、仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局 部变量)。PHP 大概会检查看是否存在全局变量。
24、方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了 10 个方法,但性能上没有变化。
25、派生类中的方法运行起来要快于在基类中定义的同样的方法。
26、调用带有一个参数的空函数,其花费的时间相当于执行 7 至 8 次的局部变量递增操作。 类似的方法调用所花费的时间接近于 15 次的局部变量递增操作。
27、Apache 解析一个 PHP 脚本的时间要比解析一个静态 HTML 页面慢 2 至 10 倍。尽量 多用静态 HTML 页面,少用脚本。
28、除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套 PHP 缓存机制通常 可以提升 25%至 100%的性能,以免除编译开销。
29、尽量做缓存,可使用 memcached。memcached 是一款高性能的内存对象缓存系统, 可用来加速动态 Web 应用程序,减轻数据库负载。对运算码 (OP code)的缓存很有用,使 得脚本不必为每个请求做重新编译。
30、 当操作字符串并需要检验其长度是否满足某种要求时, 你想当然地会使用 strlen()函数。 此函数执行起来相当快,因为它不做任何计算,只返回在 zval 结构(C 的内置数据结构,用 于存储 PHP 变量)中存储的已知字符串长度。但是,由于 strlen()是函数,多多少少会有些 慢,因为函数调用会经过诸多步骤,如字母小写化(译注:指函数名小写化,PHP 不区分函 数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用 isset() 技巧加速执行你的代码。 (举例如下) if (strlen($foo) < 5) { echo “Foo is too short”
} (与下面的技巧做比较) if (!isset($foo{5})) { echo “Foo is too short”
} 调用 isset()恰巧比 strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它 的执行不需要函数查找和字母小写化。 也就是说, 实际上在检验字符串长度的顶层代码中你 没有花太多开销。
31、当执行变量$i 的递增或递减时,$i++会比++$i 慢一些。这种差异是 PHP 特有的,并不 适用于其他语言, 所以请不要修改你的 C 或 Java 代码并指望它们能立即变快, 没用的。 ++$i 更快是因为它只需要 3 条指令(opcodes),$i++则需要 4 条指令。后置递增实际上会产生一 个临时变量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的 一种,正如 Zend 的 PHP 优化器所作的那样。牢记这个优化处理不失为一个好主意,因为 并不是所有的指令优化器都会做同样的优化处理, 并且存在大量没有装配指令优化器的互联 网服务提供商(ISPs)和服务器。
32、并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很 多内存。
33、并非要用类实现所有的数据结构,数组也很有用。
34、不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?
35、当你需要时,你总能把代码分解成方法。
36、尽量采用大量的 PHP 内置函数。
37、如果在代码中存在大量耗时的函数,你可以考虑用 C 扩展的方式实现它们。
38、 评估检验(profile)你的代码。 检验器会告诉你, 代码的哪些部分消耗了多少时间。 Xdebug 调试器包含了检验程序,评估检验总体上可以显示出代码的瓶颈。
39、mod_zip 可作为 Apache 模块,用来即时压缩你的数据,并可让数据传输量降低 80%。
40、在可以用 file_get_contents 替代 file、fopen、feof、fgets 等系列方法的情况下,尽量 用 file_get_contents,因为他的效率高得多!但是要注意 file_get_contents 在打开一个 URL 文件时候的 PHP 版本问题;
41、尽量的少进行文件操作,虽然 PHP 的文件操作效率也不低的;
42、优化 Select SQL 语句,在可能的情况下尽量少的进行 Insert、Update 操作(在 update 上,我被恶批过);
43、尽可能的使用 PHP 内部函数(但是我却为了找个 PHP 里面不存在的函数,浪费了本可 以写出一个自定义函数的时间,经验问题啊!);
44、 循环内部不要声明变量, 尤其是大变量: 对象(这好像不只是 PHP 里面要注意的问题吧?);
45、多维数组尽量不要循环嵌套赋值;
46、在可以用 PHP 内部字符串操作函数的情况下,不要用正则表达式;
47、foreach 效率更高,尽量用 foreach 代替 while 和 for 循环;
48、用单引号替代双引号引用字符串;
49、“用 i+=1 代替 i=i+1。符合 c/c++的习惯,效率还高”
50、对 global 变量,应该用完就 unset()掉;
4.php中传值与传引用的区别。什么时候传值什么时候传引用
值传递: 函数范围内对值的任何改变在函数外部都会被忽略;
引用传递: 函数范围内对值的任何改变在函数外部也能反映出这些修改;
优缺点:按值传递时,php必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。
按引用传递则不需要复制值,对于性能提高很有好处。
<?php
$name = "aa";
function add_img(&$name)
{
$name = "bb";
}
add_img($name);
echo $name;
//输出bb,不是aa
5.说一下php的(内存)垃圾回收机制
PHP的垃圾回收机制(建议收藏)知乎上一个不错的帖子
6.php如何实现页面跳转
在网页开发中,实现页面跳转是一个常见的需求。对于PHP语言来说,我们可以使用一些方法来实现页面跳转。在本文中,我们将讨论一些PHP方法来实现页面跳转。
一、使用header()函数实现跳转
其中一个最常见的方法就是使用PHP的header()函数来实现跳转。该函数可以设置HTTP响应头,包括Location头用于重定向。
header()函数的基本格式如下:
header("Location: http://www.example.com/");
在上述代码中,我们指定了Location头,该头中包含了要跳转的URL。
需要注意的是,在使用header()函数前不能有任何输出,否则会导致出错。我们经常看到一个报错信息:
Warning: Cannot modify header information - headers already sent by ...
这是因为在header()函数调用之前,PHP已经输出了一些内容。为了避免这个问题,在使用header()函数之前请确保没有输出。
二、使用Location重定向代码实现跳转
除了header()函数,我们还可以使用Location重定向代码来实现跳转。Location重定向代码可以通过HTML元数据来执行重定向。这种方法可以在不使用header()函数的情况下进行跳转。
Location重定向代码的基本格式如下:
<meta http-equiv="refresh" content="0; url=http://www.example.com/">
在上述代码中,我们使用了HTML元数据meta,并设置了http-equiv属性为refresh,content属性中包含了要执行的动作和跳转的URL。其中,content属性的值中0表示在不等待任何时间后开始跳转,url属性中指定了要跳转的URL。
需要注意的是,在使用Location重定向代码进行跳转时,不能有任何输出,否则会导致出错。跳转时尽量不要使用该方法。
三、使用JavaScript实现跳转
除了上述两种方法,我们还可以使用JavaScript来实现跳转。该方法可以在不使用header()函数的情况下执行重定向。同时,我们还可以在跳转之前添加一些JS代码进行处理。
JavaScript实现跳转的基本代码如下:
<script type="text/javascript">
window.location.href="http://www.example.com/";
</script>
在上述代码中,我们使用了window.location.href属性来指定要跳转的URL。需要注意的是,若使用该方法,在跳转时会在新的页面中打开指定的URL。
四、总结
在本文中,我们探讨了三种实现跳转的方法。使用header()函数和Location重定向代码可以实现服务器端跳转,而使用JavaScript可以实现客户端跳转。
总体来说,header()函数和Location重定向代码是较为常用的方法。但是,若需要在跳转时进行处理或在客户端跳转时使用JS操作,使用JavaScript也是一个好的选择。
在使用PHP实现跳转时,务必谨慎处理,避免误用导致程序出错。
7.php遍历文件夹下所有文件(写出代码)
需要php获取文件夹下所有文件名,我们有时候需要读取目录里面的内容,在 PHP 有多个函数可以获取文件系统目录信息,今天就给大家分享 PHP 遍历目录的三种方法。
php获取文件夹下所有文件名实现代码:
1、用 dir() 返回对象
function listDir($dir) {
$mydir = dir($dir);
echo "<ul>";
while ($file = $mydir - >read()) {
if ((is_dir("$dir/$file"))) {
echo "<li>$file</li>";
listDir("$dir/$file");
}
elseif($file !== "." & $file !== "..") echo "<li><a href='$dir/$file' target='_blank'>$file</a></li>";
}
echo "</ul>";
$mydir - >close();
}
listDir(".");
2、使用 readdir() 函数
function listDir2($dir) {
$mydir = opendir($dir);
echo "<ul>";
while (($file = readdir($mydir)) !== false) {
if ($file != '.' && $file != '..') {
if (is_dir($file)) {
echo "<li class='dir'>$file</li>";
listDir2("$dir/$file");
} else {
echo "<li class='file'><a href='$dir/$file' target='_blank'>$file</a></li>";
}
}
}
closedir($mydir);
echo "</ul>";
}
listDir2('.');
3、使用 scandir() 函数
function listDir3($dir) {
$mydir = scandir($dir);
echo "<ul>";
foreach($mydir as $key = >$value) {
if ($value != '.' && $value != '..') {
if (is_dir($value)) {
echo "<li class='dir'>$value</li>";
listDir3("$dir/$value");
} else {
echo "<li class='file'><a href='$dir/$value' target='_blank'>$value</a></li>";
}
}
}
echo "</ul>";
}
listDir3(".");
对于上面提到的3个php函数,对执行速度没有做过测试,你可以按照你的习惯和喜欢选用一个。
$path = './use';
$result = scanFile($path);
function scanFile($path) {
global $result;
$files = scandir($path);
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
if (is_dir($path . '/' . $file)) {
scanFile($path . '/' . $file);
} else {
$result[] = basename($file);
}
}
}
return $result;
}
php使用递归的方法删除目录中的所有文件
function delDir($directory){//自定义函数递归的函数整个目录
if(file_exists($directory)){//判断目录是否存在,如果不存在rmdir()函数会出错
if($dir_handle=@opendir($directory)){//打开目录返回目录资源,并判断是否成功
while($filename=readdir($dir_handle)){//遍历目录,读出目录中的文件或文件夹
if($filename!='.' && $filename!='..'){//一定要排除两个特殊的目录
$subFile=$directory."/".$filename;//将目录下的文件与当前目录相连
if(is_dir($subFile)){//如果是目录条件则成了
delDir($subFile);//递归调用自己删除子目录
}
if(is_file($subFile)){//如果是文件条件则成立
unlink($subFile);//直接删除这个文件
}
}
}
closedir($dir_handle);//关闭目录资源
rmdir($directory);//删除空目录
}
}
}
正因为来之不易,所以才有了后来的倍加珍惜。
8.写出至少2种获取文件后缀的方法或函数
一系列的操作还有判断文件大小等等... 今天就来聊一聊php实现获取文件扩展名的相关话题。
我在这里提供七种方法。 每一种方法都有些写注释让大家都能浅显易懂的理解和运用。
第一种:
$file = '东旭编程社区.x.png';
echo substr(strrchr($file, '.'), 1);
解析:strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符
第二种:
$file = 'zhudongxu.z.png';
echo substr($file, strrpos($file, '.')+1);
解析:strrpos()函数查找 "." 在字符串中最后一次出现的位置,返回位置 substr()从该位置开始截取
第三种:
$file = 'zhudongxu.y.z.png';
$arr=explode('.', $file);
echo $arr[count($arr)-1];
解析:explode()函数用“.”把字符串进行分割成数组 count()获取数组的长度 -1是数组的下标从0开始
第四种:
$file = '东旭编程社区.y.z.png';
$arr=explode('.', $file);
echo end($arr);
解析:和第三种方法一样 不一样的是利用end()函数直接返回数组最后一个元素
第五种:
$file = 'x.zhudongxu.z.png';
echo strrev(explode('.', strrev($file))[0]);
解析:先用strrev()反转字符串然后用explode()函数分割成数组取出第0个也就是gnp 然后把字符串反转一次 [ 第一次反转只是为了保证数组的0下标永远获取的是文件扩展名或后缀 在不知道数组长度的情况下 ]
第六种:
$file = 'x.东旭编程社区.z.png';
echo pathinfo($file)['extension'];
解析:pathinfo()函数以数组的形式返回文件路径的信息。包含[dirname] [basename] [extension] 其中extension就是文件的扩展名
第七种:
$file = 'x.y.东旭编程社区.png';
echo pathinfo($file, PATHINFO_EXTENSION);
解析:和第六种方法一样pathinfo()函数第二个参数 可以传入[PATHINFO_DIRNAME ][PATHINFO_BASENAME][PATHINFO_EXTENSION] PATHINFO_EXTENSION获取的就是就是文件的扩展名
9.写一个函数吗,获取一篇文章内容的全部图片,并下载
function download_images($article_url = '', $image_path = 'tmp'){
// 获取文章类容
$content = file_get_contents($article_url);
// 利用正则表达式得到图片链接
$reg_tag = '/<img.*?\"([^\"]*(jpg|bmp|jpeg|gif|png)).*?>/';
$ret = preg_match_all($reg_tag, $content, $match_result);
$pic_url_array = array_unique($match_result1[1]);
// 创建路径
$dir = getcwd() . DIRECTORY_SEPARATOR .$image_path;
mkdir(iconv("UTF-8", "GBK", $dir), 0777, true);
foreach($pic_url_array as $pic_url){
// 获取文件信息
$ch = curl_init($pic_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$fileInfo = curl_exec($ch);
$httpinfo = curl_getinfo($ch);
curl_close($ch);
// 获取图片文件后缀
$ext = strrchr($pic_url, '.');
$filename = $dir . '/' . uniqid() . $ext;
// 保存图片信息到文件
$local_file = fopen($filename, 'w');
if(false !== $local_file){
if( false !== fwrite($local_file, $filecontent) ){
fclose($local_file);
}
}
}
}
10.php如何实现不用自带的cookie函数为客户端下发cookie。对于分布式系统,如何保存session值
这个题有点绕。考的还是COOKIE和SESSION的基础知识。服务端通过set-cookie命令来通知客户端保存cookie。
只要按照domain path 过期时间等规则 用header函数就可以实现。
分布式系统session,集中处理。按我们公司的架构,为了实现高可用和高容灾,提供一个分布式的验签服务。具体的可以看下redis的分布式服务架构。
11.使用php实现双向队列
12.url中获取文件扩展名
/**
* strrchr - 查找指定字符在字符串中的最后一次出现
* strrpos — 计算指定字符串在目标字符串中最后一次出现的位置
* end — 将数组的内部指针指向最后一个单元
* pathinfo — 返回文件路径的信息
* 可以通过参数 options 指定要返回哪些单元。
* 它们包括:PATHINFO_DIRNAME,PATHINFO_BASENAME 和 PATHINFO_EXTENSION。默认是返回全部的单元
*/
$url = "http://www.baidu.com/aaa/test.php";
echo "第一种方法:\n";
echo strrchr($url, '.'); //.php
echo substr(strrchr($url, '.'), 1); //php
echo "第二种方法:\n";
echo substr($url, strrpos($url, '.')+1);
echo "第三种方法:\n";
echo end(explode('.', $url));
echo "第四种方法:\n";
$info= pathinfo($url);
echo $info['extension'];
echo "第五种方法:\n";
echo pathinfo($url, PATHINFO_EXTENSION);
13.怎么保证促销商品不会超卖,请写出一定方案
避免商品超卖的4种方案(以下是一些核心思路)
原始方案(失败):在每次下订单前我们判断促销商品的数量够不够,不够不允许下订单,更改库存量时加上一个条件,只更改商品库存大于0的商品的库存,当时我们使用ab进行压力测试,当并发超过500,访问量超过2000时,还是会出现超卖现象。
public function buyOne() {
$shop = Shop::find(1);
if ($shop->number > 0) {
DB::update("update shop set number = number - 1 where id = 1");
}
}
第1种方案:使用mysql的事务加排他锁来解决,首先我们选择数据库的存储引擎为innoDB,使用的是排他锁实现的,刚开始的时候我们测试了下共享锁,发现还是会出现超卖的现象。有个问题是,当我们进行高并发测试时,对数据库的性能影响很大,导致数据库的压力很大。
//2.利用数据库的forupdate来加锁(在数量少的情况下并不会出现问题,但是当并发达到(ab -n 1000 -c 200),
//就会出现请求非2XX的响应增多,1000 失败了 60)time per request 65.195
//在高并发的情况下,会导致数据库连接数不够,部分php获取不到连接而报错,或者是超过等待时间而报错
public function indexMysql() {
DB::beginTransaction();
//通过for update 加排它锁
$shop = DB::table('shop')->where('id', '=', 1)->lockForUpdate()->first();
if ($shop->number > 0) {
if (DB::update("update shop set number = number - 1 where id = 1")) {
DB::commit();
} else {
DB::rollBack();//回滚并重试
usleep(100000);
$this->indexMysql();
}
} else {
DB::commit();
}
}
第2种方案:使用文件锁实现。当用户抢到一件促销商品后先触发文件锁,防止其他用户进入,该用户抢到促销品后再解开文件锁,放其他用户进行操作。这样可以解决超卖的问题,但是会导致文件得I/O开销很大。
第3种方案:使用redis的setnx来实现锁机制。但是并发大的情况下,锁的争夺会变多,导致响应越来越慢。(与第四种方案类似)
//在数量少的情况下并不会出现问题,但是当并发达到(ab -n 1000 -c 200 就会出现请求非2XX的响应增多,1000 失败了 54) time per request 127.575
public function index() {
//测试并发超卖现象
if (Redis::setnx(self::KEY, 1)) {//拿到了锁
$this->buy();
} else {
usleep(100000);//等会再去拿锁
//Log::info("未争夺到锁,睡眠100ms");
$this->index();
}
}
private function buy() {
$shop = Shop::find(1);
if ($shop->number > 0) {
$shop->number --;
$shop->save();
}
Redis::del(self::KEY);
}
第4种方案:redis的队列来实现。将要促销的商品数量以队列的方式存入redis中,每当用户抢到一件促销商品则从队列中删除一个数据,确保商品不会超卖。这个操作起来很方便,而且效率极高
//4.使用redis队列来,用户过来直接入队列,然后再将操作更新到数据库
//最佳体验(redis pconnect 9.481s, 无丢失, 无框架)
public function push() {
//入队列
Redis::lpush(self::QUEUE, 1);
}
//脚本调用pop方法 * * * * * php xxx.php
public function pop() {
while (($key = Redis::rpop(self::QUEUE))) {
$shop = Shop::find(1);
if ($shop->number > 0) {
DB::update("update shop set number = number - 1 where id = 1")
}
}
}
14.接口数据安全如何保证
15.session和cookie的区别
1、对象不同
cookie:是针对每个网站的信息,每个网站只能对应一个,其他网站无法访问,这个文件保存在客户端,每次您拨打相应网站,浏览器都会查找该网站的 cookies,如果有,则会将该文件发送出去。cookies文件的内容大致上包括了诸如用户名、密码、设置等信息。
session:是针对每个用户的,只有客户端才能访问,程序为该客户添加一个 session。session中主要保存用户的登录信息、操作信息等等。此 session将在用户访问结束后自动消失(如果也是超时)。
2、存储数据大小不同
cookie:一个 cookie存储的数据不超过3K。
session:session存储在服务器上可以任意存储数据。当 session存储数据太多时,服务器可选择进行清理。
3、生命周期不同
cookie:cookie的生命周期当浏览器关闭的时候就消亡了,cookie的生命周期是累计的,从创建时就开始计时,30min后cookie生命周期结束。
session:session的生命周期是间隔的,从创建时开始计时如在30min内没有访问session,那么session生命周期就被销毁。
4、存储位置不同
cookie:cookie数据保存在客户端。
session:session数据保存在服务器端。
5、数据类型不同
两者都是key-value结构,但针对value的类型是有差异的。
cookie:value只能是字符串类型。
session:value是object类型。
6、安全性不同
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session。
16.冒泡排序和快速排序
17.oop思想和mvc的理解
一个思想 一个模式 (模式是凌驾于面向对象之上的一种存在)
OOP是面向对象编程 MVC是实现系统所选择的一种系统架构。
不使用MVC也一样可以实现系统的。 不使用OOP也一样可以编程。
与MVC相比,面向对象是微观的,而设计模式是更加宏观的一种概念。两者并不是一种类型的东西。
OOP
面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。OOP 主要有以下的概念和组件:
组件 - 数据和功能一起在运行着的计算机程序中形成的单元,组件在 OOP 计算机程序中是模块和结构化的基础。
抽象性 - 程序有能力忽略正在处理中信息的某些方面,即对信息主要方面关注的能力。
封装 - 也叫做信息封装:确保组件不会以不可预期的方式改变其它组件的内部状态;只有在那些提供了内部状态改变方法的组件中,才可以访问其内部状态。每类组件都提供了一个与其它组件联系的接口,并规定了其它组件进行调用的方法。
多态性 - 组件的引用和类集会涉及到其它许多不同类型的组件,而且引用组件所产生的结果得依据实际调用的类型。
继承性 - 允许在现存的组件基础上创建子类组件,这统一并增强了多态性和封装性。典型地来说就是用类来对组件进行分组,而且还可以定义新类为现存的类的扩展,这样就可以将类组织成树形或网状结构,这体现了动作的通用性。
由于抽象性、封装性、重用性以及便于使用等方面的原因,以组件为基础的编程在脚本语言中已经变得特别流行。
MVC
MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型(M)、视图(V)、控制器(C),它们各自处理自己的任务。
视图 :视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Adobe Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services。如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
模型 :模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
控制器 :控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后确定用哪个视图来显示模型处理返回的数据。
现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。