php介绍

javaphp比较:

参见文章:

http://blog.csdn.net/jinxfei/archive/2010/08/10/5801280.aspx

http://www.zendstudio.net/archives/some-php-development-tips-from-my-own/

上手复杂度:PHP

我用 Java 做了 2-3 年的 Swing 开发,然后转向WEB,第一个接触的框架是 Struts,当时的感受就是要配置的东西太多了,前后鼓捣了三个多月,才感觉渐入佳境了。

如今PHP从开始了解到现在总共三个月左右的时间(而且只是业余时间),其中有一周的时间在看PHP官网的文档,了解主要的语言特性,后面基本上就是边看边改代码,并照猫画虎的写东西。虽说当年对软件开发的理解不能和今天相提并论,但客观的说,PHP的确简单、易学,而且特别适合做WEB开发。

开发感受:各有胜场

PHP
最让我不爽的地方:

经常是出错后屏幕一片空白(White ScreenOf Death,都有专有名词了,可见这是PHP出错表现的一大特性),什么信息都没有。

这可通过error_reporting (打印在web容器log里)和 display_errors(直接在输出上显示)来设置
开发工具的auto complete能力远不如javaIDE方面还在起步阶段

PHP比较爽的地方:

php中,数组和哈希表等价,而且是使用最广泛的数据结构,变长参数+数组做参数,能大大提高写代码的灵活性。

基本上不用为NPE(null pointer error)担心。Php存在垃圾自动回收机制

访问数据库比JDBC简单多了,不用什么持久化框架也能很快的写出类似DAO的代码。Php也存在ORM框架,但是php的特点不适合搞这些东西,php就是要简单,高性能,针对特定应用。

许多专为WEB设计的特性,使得从页面获取信息,或者向页面输出信息都变得非常轻巧。

谈不上爽或者不爽的特性:

echo 的内容直接到前台页面上了,一开始我以为echojavaSystem.out一样,会写到日志。

由于不像Java那样对classpath以及class的路径有着严格的要求,一时之间还不习惯,原来创建一个Java类放在什么地方基本上没什么可考虑的,但现在经常要决策一个文件该放在哪个目录下。

因为可以OOP,也可以不OOP,所以,增加新功能点的时候,经常很纠结O还是不O

代码风格啊!太习惯了getData这样的命名,是在不适应get_data这样的函数,因此,执着着,没有入乡随俗的改过来,也好,一眼就可以看出,哪些是属于框架的,哪些是属于我的。
平台对比
如果拿PHPJAVA比,我觉得PHP是瑞士军刀,而JAVA则是家庭五金维修工具N件套,N >=100,在解决网站开发这一问题上,PHP的确是小巧、易用,但也有不尽如人意的地方。
比如,我发现J2EE中几乎必不可少的JDBC连接池,在PHP中约等于无,所以,用户请求过来,如果需要访问数据库,都是现连、现取、现关,究其原因,是架构不同造成的。
  实际上,J2EE中有Web Container的概念,用户请求是由Container分配的线程完成的,线程可以使用进程的内存空间交互数据;PHP是依附于Apache的,每 次用户请求,Apache都启动一个新的进程来执行PHP脚本,进程执行完,一切资源都回收了,所以在默认情况下,一个PHP脚本想要留下点全局的东 西并不容易(我一开始就被 global 这个关键词给骗了);当然,也不是说不同的请求之间完全没法交换数据,只是这样需要使用共享内存,或者使用文件做持久化。
不过,Apache用进程处理请求应该比线程模式要更加健壮,因为在J2EE中,因为一个线程的问题导致整个Container挂掉的情况屡见不鲜。
OOP
PHP主流版本已经对OOP的支持很好,但因为历史原因,好多PHP的开源项目的代码都是不那么OOP的。一开始,我是跟着框架的习惯,用不怎么OOP的方式写代码,在写了十几个零散的函数之后,终于忍不住,又全部重构成对象了。
  做了这么多年的JavaOOP的思想已经非常深入,虽然当年从学校出来的时候,也是从结构化程序设计转向面向对象的,但N年之后,再从面向对象转向结 构化,这种不习惯的感觉更加强烈。也许是OOP真的是更加符合自然的思考习惯吧,现在看着一长串的零散的函数,很有一种不安全的感觉,况且还要挖空心思的 为方法起名,以避免冲突,累!
总结
1、应该把PHP纳入自己的开发工具箱
2PHP不够完美,但可圈可点之处甚多。
3、面向对象为PHP增色不少
4、在开源领域,PHP方面比较发达的是最终应用,所以才有那么多人使用wordpress建独立博客,哪怕没有开发经验;JAVA方面比较发达的是开发框架和类库,给程序员们使用的。从这个角度来讲,Java是个小众的语言。 

php联合java

http://hi.baidu.com/lei0827/blog/item/28439a4e923234ced1c86a18.html

直接调用的方式

1、种是用php自身带的模块调用java(经过网友的证明发现这种方法不好)。

2、通过php-java-bridge模块调用java。(经过网上普遍推荐)。[最新的版本实现是基于pjb,感觉倒不如直接用http调用.]


间接调用的方式

3、通过webservice或者直接http方式访问java服务

 

xmpp php

http://code.google.com/p/xmpphp/ 这个稍微强一点

http://www.code.blitzaffe.com/pages/phpclasses/files/jabber_client_52-11

由于php对多线程支持的不好,且对象生命周期短,几个php xmpp库都不理想,不知道怎么实现webchat。

考虑的问题:怎么在1个session里面保持住连接,不至于每次请求都登陆一次吧。

 

php运行环境:

web服务器(apache, nginx)--开源免费

php--开源免费

zendframework--开源免费

经过实际应用证明的高性能,稳定,可用。

http://blog.s135.com/post/314/

http://lin128.blog.51cto.com/407924/277272

http://guogoul.com/2008/07/08/nginx_2/

 

使用php的应用:

www.yahoo.com

www.baidu.com

www.sina.com

www.163.com

www.sohu.com

这些就足够了

Continue reading php介绍

php基础

先花一分钟看看常见符号和函数: http://www.chinaz.com/program/2010/0331/110317.shtml

 

echo和print的区别

PHP 和 HTML 最简单的交互是通过 print 和 echo 语句来实现的,在实际使用中, print 和 echo 两者的功能几乎是完全一样。可以这么说,凡是有一个可以使用的地方,另一个也可以使用。但是,两者之间也还是一个非常重要的区别:在 echo 函数中,可以同时输出多个字符串,而在 print 函数中则只可以同时输出一个字符串。同时,echo函数并不需要圆括号,所以echo函数更像是语句而不像是函数。

echo 和 print 都不是函数,而是语言结构,所以圆括号都不是必需的。他们的区别在于:
(1) echo可以输出多个字符串,像下面这样:
echo 'a','b','c';
如果你非要加上圆括号,注意写成echo ('a','b','c');是错误的,应该写成:
echo ('a'),('b'),('c');
它没有像函数的行为,所以不能用于函数的上下文
(2) print只能输出一个字符串,它可以表现得像一个函数,比如你可以如下使用:
$ret = print 'Hello World';
所有它能用在更复杂的表达式中。
另外,echo的效率相对比较快~

如下代码:

<?php
$a='hello ';$b='php world!';echo $a,$b.'<br />';//echo 可以用逗号分隔字符串变量来显示print $a.$b.'<br />';//而print不能使用逗号,只能用点号分隔,print $a,$b.'<br />';//使用逗号时报错。
?>

echo    命令和    print    命令    相同,没有区别  
echo    函数    和    print    函数    有区别。  
echo()    无返回值,与echo    命令相同  
print()    有返回值,成功,返1,false,返0.    
printf()    和    sprintf()    类似,均为格式化输出,不同的是前者输出到标准输出,后者输出到变量  
形如  
echo    <<<    EOT  
EOT;  
print    <<<    EOT  
EOT;  
的书写格式,其含义如下:  
<<<    运算符,将由自定义分界符间的内容视为字符串,可对其间的变量做处理  
EOT    自定义分界符,结束时必须位于行首

传址与传值:

>$a = 1; function go(&$b) { $b = $b + 1; } go($a); echo $a; ========系统输出2,因为函数直接修改了$a的数值

Continue reading php基础

html5 demo赏析

http://html5demos.com/观赏html5 demo

 

Storageevents

可监听本地存储localStorage里面某一项的改变事件

 

dataset (data-*attributes)

<div id="test" data-name="viael.dataset" data-height="short">This element hasdata</div>

el.dataset.name = "via el.dataset"

el.dataset.height = "short"

注意属性是以data-开头的

 

History API usingpushState

使用pushState函数修改浏览器历史记录。

 

Browserbased file readingNot part of HTML5

通过FileReader 获得文件控件的路径

 

Drag files directlyinto your browserNot directly part of HTML5

原理同上,浏览器可就收外部拖拽的文件。

 

Simple chatclient

利用websocket

 

Two videosplaying in sync

Vedio标签 currentTime控制播放进度

 

Interactive canvas gradients

Canvas & Video
Video

Canvas 

Canvasvideo特性

 

ContentEditable

标签的contenteditable 属性使得标签及其子标签都可编辑

 

GeolocationWorkson Safari Mobile too

使用navigator.geolocation

 

postMessagesame domain

postMessagecross domain

 

使用postmessage跨域请求,接收页面需要代码(window.onmessage)监听消息

 

drag and drop

drag anything

新增了可监听的事件,使用dataTransfer 

offline detectionWorks on Safari Mobile too

如下代码:

addEvent(window, 'online', online);

addEvent(window, 'offline', online);

 

navigator.onLine testsDoesn't use events, only polls

使用navigator.onLine属性判断

 

on/offlineevent tests

window , body都提供online/offline事件

offlineapplication using the manifestFF 3.6 isstill buggy - doesn't request manifest after initial load

使用window.applicationCache存储。

 

Storage

Window的两个属性sessionStorage,localStorage

 

Web SQL DatabaseStorage

Web SQLDatabase - rollback test

openDatabase ,transaction,executeSql Web Workerswatch out - uses a lot of CPU!

使用Worker对象,多线程

使用postmessage传递参数(调用方和worker线程之间),使用onmessage事件监听。

 

IndexedDB

是一种轻量级NOSQL数据库

window.indexedDB = window.mozIndexedDB || window.webkitIndexedDB;

var request = indexedDB.open("MyTestDatabase"); 

http://rainsilence.iteye.com/blog/984569

Continue reading html5 demo赏析

push pull poll 长连接 websocket pushlet cometd

IBM总结文章:

http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

 

里面推荐的pushlet之前使用过的,这次再看一下,看源码和试验ajax push实质仍然是pull技术。?

它的脚本库没有考虑到其他脚本库,使用window.onEvent来作为回调,不是很好。

示例不是很好,只写了pull方式的。

不建议用,看到用的人没多少,网上的帖子都是粘来粘去,没有实际的例子,日期很早,最近的没有。

看他的文档也写的不清楚,看了一天没看明白,还是不知道怎么用。确定不是自己理解力问题。

 

webqq通过观察应该是长轮询,再看到这边篇帖子的大讨论:

http://www.iteye.com/topic/785931?page=7

主要以下几点:

认为是长轮询实现

认为长轮询较好:

长轮询的优势是,如果没有消息,客户端N秒才会有一次请求。
如果有消息,也会立即发送到客户端。(如果刚好回应完一个请求时有新消息... 还是有一定延时)
与iframe + script方式的长连接相比,它实现更简单,也不会在浏览器下显示“正在加载”信息。

按个人理解,使用带部分缓冲的长轮询能减少服务器开锁
即有新消息并不立即返回,而是等待一定时间,以免消息频繁时过多轮询。[这又存在延迟的问题]

长连接存在进度条一直加载的问题。

 

服务端要配合使用nio(tomcat6.jetty支持)较好,否则压力较大。

别的实现有使用cometD的。

 

之前自己做过长连接,主要问题是浏览器一直在转,让人很不舒服,而且容易崩溃。

flash主要是防火墙的问题。

 

长轮询比较好实现,注意客户端要延长超时时间。

一般的长poll是不需要comet就可以实现的,只不过Tomcat6之后支持Bayeux协议可以使用nio/异步servlet来提高性能。

Ext.Ajax.request({
                    url : 'LongPoll',
                    timeout:360000,//延长超时
                    success : function(response, opts) {
                        console.log('finish');
                        dorq();
                    },
                    failure : function(response, opts) {
                        console.log('server-side failure with status code '
                                + response.status);
                    }
                });

 

这里有一些列很好的文章:

反向Ajax:

第1部分:Comet介绍 http://kb.cnblogs.com/page/112185/

Forever Iframe

Forever Iframe(永存的Iframe)技术涉及了一个置于页面中的隐藏Iframe标签,该标签的src属性指向返回服务器端事件的servlet路径。每次在事件到达时,servlet写入并刷新一个新的script标签,该标签内部带有JavaScript代码,iframe的内容被附加上这一script标签,标签中的内容就会得到执行。

1. 优点:实现简单,在所有支持iframe的浏览器上都可用。

2. 缺点: 没有方法可用来实现可靠的错误处理或是跟踪连接的状态,因为所有的连接和数据都是由浏览器通过HTML标签来处理的,因此你没有办法知道连接何时在哪一端已被断开了。

Multi-part XMLHttpRequest

1. 优点:只打开了一个持久连接,这就是节省了大部分带宽使用率的Comet技术。

2. 缺点:并非所有的浏览器都支持multi-part标志。某些被广泛使用的库,比如说用Java实现的CometD,被报告在缓冲方面有问题。例如,一些数据块(多个部分)可能被缓冲,然后只有在连接完成或是缓冲区已满时才被发送,而这有可能会带来比预期要高的延迟。

流方式,服务端要知道客户端是否关闭也是个问题,否则客户端已经断开,服务端仍在运行,可能的解决办法是心跳,那不跟poll差不多了。

第2部分: WebSocket http://kb.cnblogs.com/page/112616/

第3部分:Web服务器和Socket.IO http://kb.cnblogs.com/page/114594/

第4部分:Atmosphere和CometD http://kb.cnblogs.com/page/116653/

Atmosphere和CometD都是稳定的、开源的反向Ajax解决方案,我们在Ovea选用的是CometD,因为我们在一个集群环境内部为移动设备开发可伸缩的事件驱动应用,我们完全掌控基础设施(我们使用Jetty)。不过,在没有额外开发的情况下,如果你正在出售web应用且希望你的反向Ajax功能在尽可能多的服务器上都可运作的话,CometD可能不是最好的选择。但现在随着越来越多的Web应用开始支持Servlet 3.0规范,CometD的局限性呈下降趋势。说到传输层,余下的主要差异则取决于对WebSocket的支持。

关于servlet 3.0 参见 http://kazge.com/archives/635.html ,在此文中主要指异步servlet处理。Ovea是php网站,但是使用java的CometD来做comet服务?

作者还是倾向于cometD,但是cometD要求jetty6以上以及任何支持Servlet 3.0规范的服务器中

第5部分:事件驱动的Web开发 http://kb.cnblogs.com/page/117099/

comet有多种实现,long poll,长连接,上面的文章仍然推荐long poll。

cometD可以使用websocket作为传输协议。

WebSockets与Bayeux/CometD http://www.infoq.com/cn/news/2010/05/websockets-bayeux

文中提到的Greg Wilkins是jetty作者

http://www.htmlgoodies.com/html5/tutorials/making-html5-websockets-work.html#fbid=x32iZkQSYda

此文中写道支持websocket的浏览器有:

IEFirefoxChromeSafariOpera
10~6.014.05.0 (partial support*)11.0 (partial support*)

支持webscoket的服务容器有

Java的Jetty(原文竟然写作Betty)  Oracle的Glassfish

php 的Wamp and XAMPP, lighttpd的mod_websocket

python的Tornado

nodejs + http://socket.io/  (socket.io是javascript库,包括服务端和客户端,所以要在nodejs上跑了)

微软的那就不说了

 

再来总结一下:

Well,本来是想找到关于websocket的有利消息,但是让我失望了。原因是:

1:目前主流的php服务器支持不行:apache,ngix不支持, java中的tomcat7,jboss7,webshpere8都还没支持。

2:浏览器支持也不给力:目前只FF6,Chrome14支持,况且websocket还只是个html5草案。

3:假使花个大力气做出来了,然后你发现其实long poll也能同样做的更好,不知你会怎么想。

再来看看CometD这个东西:

引用http://kb.cnblogs.com/page/116653/ 中的话:

1. 优点

从客户端到服务器端,以及从一个独立的Java客户端到服务器端,CometD提供了一个完整的解决方案。框架有详尽的文档说明,有一个很好的API,且非常容易使用。最重要的是,它拥有一种事件驱动的方法。CometD和Bayeux是许多事件驱动应用的构成部分,其他的反向Ajax框架并未提供任何的事件驱动机制,使得最终用户不得不开发自己的定制解决方案。

javascript有dojo和jquery的支持。

CometD支持许多必需的功能,比如说重连接、可靠的超时检测、回退、批处理、消息确认,以及更多你不会在其他反向Ajax框架中找得到的功能。CometD可让你实现最可靠的、低延时的通信。

2. 缺点
除了Jetty for Comet(Tomcat)之外,CometD目前并未支持任何的Servlet 2.5容器,其也不支持Glassfish/Grizzly WebSocket。

我的观点:

java实现,所以,关php什么事?关那么多的php 应用什么事?这不过是java众多框架中的又一个。

不支持Servlet 2.5容器,我自己实现long poll还不是一样?啊,对,它在上面封装了一层,不过这个转换服务器的情况真的很可能发生吗?即使会,转换的工作会很难吗?它的封装对性能有影响吗?

我难道有点势力吗,用了java鄙视.net,用了php轻视java?

Continue reading push pull poll 长连接 websocket pushlet cometd

将目录或指定文件使用img2py进行处理

img2py 可以将图片文件存成文本文件,但它不支持多个文件处理,这特别在我的目录下有许多的文件,如果一个个处理的话,会非常麻烦。于是为了解决目录及支持多个文件的问题,我编写了下面的小程序,希望对你有用。

import wx.tools.img2py as img2py
import getopt
import sys
import os
import os.path

def usage():
    print """
%s [-d directory][-h] -o outputfile files
""" % sys.argv[0]

def main():
    if len(sys.argv) == 1:
        usage()
        sys.exit(1)
    try:
        opts, fileArgs = getopt.getopt(sys.argv[1:], "d:o:h")
    except getopt.GetoptError:
        usage()
        sys.exit(1)

    imagedir = ''
    outputfile = ''
    for opt, val in opts:
        if opt == "-h":
            usage()
            sys.exit(1)
        elif opt == "-d":
            imagedir = val
        elif opt == "-o":
            outputfile = val

    convert(outputfile, imagedir, fileArgs)

def isImageFile(filename):
    f, ext = os.path.splitext(filename)
    if os.path.isfile(filename) and ext.lower() in ('.gif', '.png', '.bmp', '.jpg', '.ico'):
        return True
    else:
        return False
           
def convert(outputfile, dir='', imagefiles=[]):
    files = []
    files.extend(imagefiles)
    if dir:
        f = [os.path.join(dir, x) for x in os.listdir(dir) if os.path.isfile(os.path.join(dir, x))]
        files.extend(f)
    files = list(set([x for x in files if isImageFile(x)]))
    for i, x in enumerate(files):
        name = os.path.splitext(os.path.basename(x))[0].lower()
        cmd =[]
        if i != 0:
            cmd.append('-a')
        cmd.append('-n')
        cmd.append(name.capitalize())
        cmd.append(x)
        cmd.append(outputfile)
        os.system("img2py %s" % " ".join(cmd))
   
if __name__ == '__main__':
    main()

我们在写gui程序的时候,经常会用到一些图标图片资 源,对此有几种解决办法,有人喜欢用zip模块将其打包,用的时候取出来,因为python读取zip文件也是很方便的,有人则干脆不打包,直接放在一个 子目录中,用的时候直接读取。而我则喜欢将其转换为.py文件,作为模块调用。

我在看wxPython程序的例程的时候,[encode_bitmaps.py]发现它的图片是从一个模块(.py文件)中调入的,于是很好奇,顺藤摸瓜,于是发现:

wxPython安装好之后,会在 wx\tools 目录下安装一些工具,其中名为img2py.py的工具。
这个工具可以很方便的将我们程序中所用到的图片或者图标资源转换成py文件,这样我们在需要使用这些图片资源的时候,只需要
import 这些扩展名为.py的模块文件即可

在命令行下输入img2py.py并回车,可以查看详细的帮助信息。而一般情况下,我们所要做的,只是将图片转换为.py文件

例如,我有一个ico文件,想用其作为我程序的托盘图标

那么我可以这样做

首先,将其转换为 .py 文件

img2py.py myicon.ico myicon.py 

 

然后,在程序中导入这个模块

import myicon 

最后,当我需要用它的时候,只需要:

icon = myicon.geticonIcon() 

注意,如果你的myicon.py中没有geticonIcon()方法,只需要加入如下一行语句即可:

geticonIcon = icon.GetIcon 

怎么样,是不是很方便?

在 wx\tools 目录下还有一些其他的工具,具体用法还有待大家发掘

--------------------------------------------------

目的:
        即为img2py的用处,img2py是将图像转为以py文件存储的程序,简化了程序过程中读文件的处理。

开发环境:eclipse+pydev插件

步骤:
1,在 eclipse工程中增加个含有main函数的模块,用来处理图片到py,代码如下:
'''
Created on 2009-6-16
@author: fengxuanshuo

This is a way to save the startup time when running img2py on lots of
files...

'''
import sys
from wx.tools import img2py

command_lines = [
                 "-a -F -n book   pictures/right_menu/222.png   ../main/images.py",
                 "-a -F -n boo   pictures/right_menu/111.png   ../main/images.py",
                 "-a -F -n ook_red   pictures/right_menu/000.png   ../main/images.py",
                 ]

if __name__ == '__main__':
    for line in command_lines:
        args = line.split()
        img2py.main(args)

其中command_lines为命令行执行内容,程序需要的图片都可以处理,而且目标文件可以有多个,名字自己取。

2,执行新增加的模块,就会发现 main目录多了个images.py文件。

3,更新eclipse pydev工程:pydev插件并没有常用的那个add file to project选项,不过有pydev->source format python files.

4,然后再原工程里面就可以用图片py文件了(可能有些版本,在生成py文件的时候不会加import相关库的语句,需要手动添加)

5,images.py 在wxpython demo 中的用法
定义全局变量 images: images =None
在app里面声明全局的images : globel images
import imgaes as i
images = i

其他py文件类似,这么做的好处在demo的注释里面说了,不罗嗦了,over

Continue reading 将目录或指定文件使用img2py进行处理

jsp 缓存, html 缓存, ajax缓存,解决方法

 

有关页面缓存问题.这个问题上网找了 好多.但发觉各种解决方法,都彼此分离,没有一篇统一的解决方法,本人近日,也遇到了页面缓存的问题,根据网上各页面缓存的解答,做了一个总结。

1.服务器端缓存的问题, 防止JSP页面缓存:

  1. <% 
  2. // 将过期日期设置为一个过去时间 
  3. response.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT"); 
  4. // 设置 HTTP/1.1 no-cache 头 
  5. response.setHeader("Cache-Control", "no-store,no-cache,must-revalidate"); 
  6. // 设置 IE 扩展 HTTP/1.1 no- cache headers, 用户自己添加 
  7. response.addHeader("Cache-Control", "post-check=0, pre-check=0"); 
  8. // 设置标准 HTTP/1.0 no-cache header. 
  9. response.setHeader("Pragma", "no-cache"); 
  10. %> 

<% // 将过期日期设置为一个过去时间 response.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT"); // 设置 HTTP/1.1 no-cache 头 response.setHeader("Cache-Control", "no-store,no-cache,must-revalidate"); // 设置 IE 扩展 HTTP/1.1 no-cache headers, 用户自己添加 response.addHeader("Cache-Control", "post-check=0, pre-check=0"); // 设置标准 HTTP/1.0 no-cache header. response.setHeader("Pragma", "no-cache"); %>

当然,每一个页面都包含这些代码会很繁琐,可以通过自定义过滤器 (Filter)的方法来处理相关的页面

2.防止html页面缓存

  1. <meta http-equiv="pragma" content="no-cache"> 
  2. <meta http-equiv="cache-control" content="no-cache"> 
  3. <meta http-equiv="expires" content="0">    

<meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0">

3.防止Ajax缓存

如果,你的页面,已经设置了防止JSP,HTML的页面缓存,但发觉页面缓存, 始终存在,就要考虑是否Ajax造成的页面缓存了。

1)设置了,如上1,2之后

Ajax缓存,产生的原因是:request, url的地址上:
IE中如果XMLHttpRequest提交的URL与历史一样则使用缓存,根本不向服务器端提交。因此无法取到刚提交的数据。

针对ajax,需要如下设置:

方法一:加时间戳 var url = BaseURL + "&timeStamp=" + new Date().getTime();
方法二:加随机数 var url = BaseURL + "&r=" + Math.random();

总结:原引(http://www.javaeye.com/topic/150162)

在jsp页面中,光是使用html的<meta> tag是无法禁止缓存的。一定要加上

response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);

有人肯定会说,这个跟html的tag设置没有不同啊。的确,我也觉得,但实践证明,没有这几句,光靠html tag不行。

所以当action会返回页面时,有以下这两种情况:

a,返回的页面没有写上上面的禁止cache的语句(或者只写了html tag)。IE存储的是URL link + page result(cache eabled)。这也就是导致了之前为什么还会有cache的原因

b,返回的页面写上了禁止cache语句 。IE存储的是URL link + page result(cache disabled)。这样才能够实现到我们想要的目的。每次都会真正的发出request。

Continue reading jsp 缓存, html 缓存, ajax缓存,解决方法

编码与控制台

public void testReadPackageResourceToString()
{

try
{

String s1 = FileUtils.readPackageResourceToString("co/common/util/iso8859.html",null,"iso-8859-1");

String s2 = FileUtils.readPackageResourceToString("co/common/util/utf8.html",null,"utf-8");
String s3 = FileUtils.readPackageResourceToString("co/common/util/gbk.html",null,"gbk");
// you should change the console's encoding to utf-8
// System.out.println(new String(s1.getBytes("utf-8")));
// System.out.println(new String(s2.getBytes("utf-8")));
// System.out.println(new String(s3.getBytes("utf-8")));
//
byte[] cs = s2.getBytes();//错的
byte[] cs1 = new String(s2.getBytes("utf-8")).getBytes();//对的
byte[] cs2 = new String(s2.getBytes("utf-8"),"utf-8").getBytes();//错的
byte[] cs3 = s2.getBytes("utf-8");//对的
byte[] cs4 = new String(s2.getBytes("utf-8"),"cp1252").getBytes(); //对的,与二相同
System.out.println("====s2.getBytes()=======");
for (int i = 0 ; i < cs.length ; i++)
{
System.out.println(cs[i]);
}
System.out.println("====new String(s2.getBytes(\"utf-8\"),\"utf-8\").getBytes();=======");
for (int i = 0 ; i < cs1.length ; i++)
{
System.out.println(cs1[i]);
}
System.out.println("====new String(s2.getBytes(\"utf-8\"),\"utf-8\").getBytes()=======");
for (int i = 0 ; i < cs2.length ; i++)
{
System.out.println(cs2[i]);
}
System.out.println("====s2.getBytes(\"utf-8\");=======");
for (int i = 0 ; i < cs3.length ; i++)
{
System.out.println(cs3[i]);
}
System.out.println("====new String(s2.getBytes(\"utf-8\"),\"cp1252\").getBytes()=======");
for (int i = 0 ; i < cs4.length ; i++)
{
System.out.println(cs4[i]);
}
// System.out.println(s2);
// System.out.println(new String(s2.getBytes("utf-8"),"utf-8"));
// System.out.println(new String(s2.getBytes()));
// System.out.println(new String(s2.getBytes(),"utf-8"));
}
catch (IOException e)
{
e.printStackTrace();
fail();
}

}

String.getBytes(encoding) 是将字符串编码到指定格式

new String

                    Charset 和 Encoding 的区别是什么?

在绝大多数情况下,包括某些专业文章中,字符集和编码都统称为编码,这是因为一个字符集往往对应一种编码。但是在程序中,我们来不得半点马虎,我们 应该清楚地知道字符集和编码有什么区别。以 ASP.NET 为例,Response.Charset 和 Response.Output.Encoding(只读)中的 Charset 和 Encoding 有什么区别呢?

Charset 是字符集,Encoding 是编码。

  • 字符集即字符的集合,规定了在这些集合里面有哪些字符,每一个字符都有一个编号(一个整数),但这只是编号 不是编码。
  • 编码就规定了一个编号如何与二进制交互。

我们大多数人最先接触到的字符集是 1963 年的 ASCII,其中的每一个字符只需要用一个字节来表示就可以了。但世界上有许多种语言,像亚洲文字,比如中文,常用汉字就几千个,仅用一个字节来表示显然 是不够的,假如我们使用两个字节。

那么问题就来了,为什么我们要把两个字节看成是一个汉字的编号呢?为什么我们不把两个字节看成 ASCII 字符集的两个编号呢?为了解决此问题,就得使用编码来标识了。

还有一个问题,编号(整数)1234 在字符集 A 中代表“千”,1234 在字符集 B 中代表“一”,那么 1234 究竟代表什么字呢?这就得明确字符集了。

浏览器可以自动识别使用哪个字符集,一般说来它们使用 HTTP 头部的 Content-Type 标明的字符集,如果没有向 HTTP 头部发送该信息,一般参考使用 HTML 的 head 标签中的 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />,为什么是参考使用呢?因为现在浏览器都比较聪明,如果发现这里用错了,一般会给予纠正。

我们做网页时,如果指定的 Charset 是 GB2312,那么就不应该在网页中出现繁体字,因为 GB2312 标准只有几千个简体的中文字。如果我们的网页编码是 UTF-8,我们就不要指定字符集是 GB2312,因为虽然 UTF-8 编码对应的 UTF-8 字符集包含了 GB2312 的字符,但同一个字符在两个字符集中的编号不一样。

对于我们中文简体网页,一般来说有两种搭配:

  • 一种是字符集是 GB2312,编码使用 ANSI。占用磁盘空间最少,网络传输效率最高。
  • 一种是字符集是 UTF-8,编码使用 UTF-8。虽然占用磁盘空间大,传输效率略低,但因为兼容面广,在应用 Ajax 以及包含多种语言文字时使用方便。鉴于此原因,现在许多网页开发工具都默认使用 UTF-8 来保存网页,比如 Visual Web Developer
在web中
response.setContentType("text/javascript; charset=utf-8");
response.setCharacterEncoding("utf-8");
Writer out = response.getWriter();//要注意这一句不要放在设置编码的语句之前,否则不起作用。

Continue reading 编码与控制台

javascript call和apply最基本的作用

<html>
<head>
<script language="javascript"> 

function Animal(){ 
   this.name = "a"; 
   this.showName = function(){ 
       alert(this.name); 
   } 
function Cat(){
this.name = "c";
Animal.call(this);
Cat.prototype = new Animal();
var cat = new Cat(); 
cat.showName();    //但是alert的是a而不是c,还不是完全的对象继承
alert(cat instanceof Animal);   //True

 
</script>
</head>
<body></body>
</html>

<html>
<head>
<script language="javascript"> 

function Animal(){ 
   this.name = "a"; 
   this.showName = function(){ 
       alert(this.name); 
   } 
function Cat(){
Animal.call(this);//这一句应该在开头,因为这个操作会执行将Animal的属性赋值给Cat的操作,它会覆盖这一句之前的属性
this.name = "c";
Cat.prototype = new Animal();
var cat = new Cat(); 
cat.showName();//alert的是c
alert(cat instanceof Animal);//True

 
</script>
</head>
<body></body>
</html>

apply and call
    它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别:
     apply(thisArg,argArray);
     call(thisArg[,arg1,arg2…] ]);

知道这些也就差不多了
========================================================================

详解 http://www.javaeye.com/topic/155109

领悟 JavaScript 中的面向对象

 

注:读完本文后请务必接着看完所有回复!

JavaScript 是面向对象的。但是不少人对这一点理解得并不全面。

在 JavaScript 中,对象分为两种。一种可以称为“普通对象”,就是我们所普遍理解的那些:数字、日期、用户自定义的对象(如:{})等等。

还有一种,称 为“方法对象”,就是我们通常定义的 function。你可能觉得奇怪:方法就是方法,怎么成了对象了?但是在 JavaScript 中,方法的确是被当成对象来处理的。下面是一个简单的例子:

Js代码
  1. function func() {alert('Hello!');} 
  2. alert(func.toString()); 

function func() {alert('Hello!');} alert(func.toString());
在这个例子中,func 虽然是作为一个方法定义的,但它自身却包含一个 toString 方法,说明 func 在这里是被当成一个对象来处理的。更准确的说,func 是一个“方法对象”。下面是例子的继续:

Js代码
  1. func.name = “I am func.”; 
  2. alert(func.name); 

func.name = “I am func.”; alert(func.name);
我们可以任意的为 func 设置属性,这更加证明了 func 就是一个对象。那么方法对象和普通对象的区别在哪里呢?首先方法对象当然是可以执行的,在它后面加上一对括号,就是执行这个方法对象了。

Js代码
  1. func(); 

func();
所以,方法对象具有二重性。一方面它可以被执行,另一方面它完全可以被当成一个普通对象来使用。这意味着什么呢?这意味着方法对象是可以完全独 立于其他对象存在的。这一点我们可以同 Java 比较一下。在 Java 中,方法必须在某一个类中定义,而不能单独存在。而 JavaScript 中就不需要。

方法对象独立于其他方法,就意味着它能够被任意的引用和传递。下面是一个例子:

Js代码
  1. function invoke(f) { 
  2.     f(); 
  3. invoke(func); 

function invoke(f) { f(); } invoke(func);
将一个方法对象 func 传递给另一个方法对象 invoke,让后者在适当的时候执行 func。这就是所谓的“回调”了。另外,方法对象的这种特殊性,也使得 this 关键字不容易把握。这方面相关文章不少,这里不赘述了。

除 了可以被执行以外,方法对象还有一个特殊的功用,就是它可以通过 new 关键字来创建普通对象。

话说每一个方法对象被创建时,都会自动 的拥有一个叫 prototype 的属性。这个属性并无什么特别之处,它和其他的属性一样可以访问,可以赋值。不过当我们用 new 关键字来创建一个对象的时候,prototype 就起作用了:它的值(也是一个对象)所包含的所有属性,都会被复制到新创建的那个对象上去。下面是一个例子:

Js代码
  1. func.prototype.name=”prototype of func”; 
  2. var f = new func(); 
  3. alert(f.name); 

func.prototype.name=”prototype of func”; var f = new func(); alert(f.name);
执行的过程中会弹出两个对话框,后一个对话框表示 f 这个新建的对象从 func.prototype 那里拷贝了 name 属性。而前一个对话框则表示 func 被作为方法执行了一遍。你可能会问了,为什么这个时候要还把 func 执行一遍呢?其实这个时候执行 func,就是起“构造函数”的作用。为了形象的说明,我们重新来一遍:

Js代码
  1. function func() { 
  2.     this.name=”name has been changed.” 
  3. func.prototype.name=”prototype of func”; 
  4. var f = new func(); 
  5. alert(f.name); 

function func() { this.name=”name has been changed.” } func.prototype.name=”prototype of func”; var f = new func(); alert(f.name);
你就会发现 f 的 name 属性不再是"prototype of func",而是被替换成了"name has been changed"。这就是 func 这个对象方法所起到的“构造函数”的作用。所以,在 JavaScript 中,用 new 关键字创建对象是执行了下面三个步骤的:

  1. 创建一个新的普通对象;
  2. 将方 法对象的 prototype 属性的所有属性复制到新的普通对象中去。
  3. 以新的普通对象作为上下文来执行方法对象。

对 于“new func()”这样的语句,可以描述为“从 func 创建一个新对象”。总之,prototype 这个属性的唯一特殊之处,就是在创建新对象的时候了。

那么我们就可以利用这一点。比如有两个方法对象 A 和 B,既然从 A 创建的新对象包含了所有 A.prototype 的属性,那么我将它赋给 B.prototype,那么从 B 创建的新对象不也有同样的属性了?写成代码就是这样:

 

Js代码
  1. A.prototype.hello = function(){alert('Hello!');} 
  2. B.prototype = new A(); 
  3. new B().hello(); 

A.prototype.hello = function(){alert('Hello!');} B.prototype = new A(); new B().hello();
这就是 JavaScript 的所谓“继承”了,其实质就是属性的拷贝,这里利用了 prototype 来实现。如果不用 prototype,那就用循环了,效果是一样的。所谓“多重继承”,自然就是到处拷贝了。

JavaScript 中面向对象的原理,就是上面这些了。自始至终我都没提到“类”的概念,因为 JavaScript 本来就没有“类”这个东西。面向对象可以没有类吗?当然可以。先有类,然后再有对象,这本来就不合理,因为类本来是从对象中归纳出来的,先有对象再有类, 这才合理。像下面这样的:

Js代码
  1. var o = {}; // 我 发现了一个东西。 
  2. o.eat = function(){return "I am eating."// 我发现它会吃; 
  3. o.sleep = function(){return "ZZZzzz..."// 我 发现它会睡; 
  4. o.talk = function(){return "Hi!"} // 我发现它 会说话; 
  5. o.think = function(){return "Hmmm..."} // 我 发现它还会思考。 
  6.  
  7. var Human = new Function(); // 我决定给它起名叫“人”。 
  8. Human.prototype = o; // 这个东西就代表了所有“人”的概念。 
  9.  
  10. var h = new Human(); // 当我发现其他同它一样的东西, 
  11. alert(h.talk()) // 我就知道它也是“人”了! 

var o = {}; // 我发现了一个东西。 o.eat = function(){return "I am eating."} // 我发现它会吃; o.sleep = function(){return "ZZZzzz..."} // 我发现它会睡; o.talk = function(){return "Hi!"} // 我发现它会说话; o.think = function(){return "Hmmm..."} // 我发现它还会思考。 var Human = new Function(); // 我决定给它起名叫“人”。 Human.prototype = o; // 这个东西就代表了所有“人”的概念。 var h = new Human(); // 当我发现其他同它一样的东西, alert(h.talk()) // 我就知道它也是“人”了!

 

=================================================================================

/**
作者认为第三种理解较正确,见最后
**/
prototype属性,只有function对象中才具有的显式属性;

网上三种理解:
            1:通过构造函数创建的普通对象,通过其constructor属性引用它的构造函数对象,从而间接引用(拥有)了构造对象中的prototype对象;

如图:

此观点的文章:   参看 jimichan的文章:详解 javascript类继承机制的原理 中的: “(说成间接的是因为每个object 都有一个 constructor 属性指向它的构造函数)。”
非常感谢在此问题上,作者对我的回信;如有冒犯,敬请原谅;

            2:构造函数创建对象时,copy prototype中的属性和代码给所创建的对象。从而使创建的对象拥有了prototype中的所有功能和属性;

如图:

此观点的文章:   参看 yiding_he的文章:领悟 JavaScript 中的面向对象 中的:  “ 在 JavaScript 中,用 new 关键字创建对象是执行了下面三个步骤的:

   1. 创建一个新的普通对象;
   2. 将方法对象的 prototype 属性的所有属性复制到新的普通对象中去。
   3. 以新的普通对象作为上下文来执行方法对象。”

此观点在回贴中被 xieye反对

            3:构造函数在创建对象时,把构造函数中的prototype引用赋给创建的普通对象;也就是说由构造函数创建的对象,都有一个指针指向 prototype对象;

如图:

此观点的文章:   参看 李站的文章:悟透javascript中的" 我们已经知道,用 var anObject = new aFunction() 形式创建对象的过程实际上可以分为三步:第一步是建立一个新对象;第二步将该对象内置的原型对象设置为构造函数prototype引用的那个原型对象;第 三步就是将该对象作为this参数调用构造函数,完成成员设置等初始化工作。对象建立之后,对象上的任何访问和操作都只与对象自身及其原型链上的那串对象 有关,与构造函数再扯不上关系了"   以及  “语法甘露 中的:上面代码的最后一句证明,新创建的对象的constructor属性返回的是Object函数。其实新建的对象自己及其原型里没有 constructor属性,那返回的只是最顶层原型对象的构造函数,即Object。”

综上所述:根据贴子:领悟 JavaScript 中的面向对象 中作者 afcn0的回贴 “其实还有补充,就是如果构造函数返回object类型,那new对象无效,prototype问题是楼主还不 太了解prototype继承方式,__proto__属性,以及isPrototypeOf方法所至 ” 的提示,查阅了文章:javascript 中的继承

Html 代码
  1. 此文中提 到:jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau"); 
  2.  
  3. 调用这句时,都发生了什么: 
  4.  
  5. 1 当js看见 new操作符,它创建一个新的普通对象,并且设置它的__proto__ 属性为Engineer.prototype。 
  6.  
  7. 2 new 操作符传递这个新的对象作为Engineer 构造器的this的值。 
  8.  
  9. 其实最主要做的事就是上面的两件,剩下的都是很简单的函数调用. 

根据上文的提示作了简单测试:

Javascript 代码
  1. function person(name,b){ 
  2.     this.name=name; 
  3.  
  4. person.prototype.sayHello=function(a){ 
  5.     //alert("hello,i am "+this.name); 
  6.     alert(this==a); 
  7.     } 
  8.  
  9.  
  10. function employee(name, salary) 
  11.     person.call(this, name);    //调用上层构造函数 
  12.     this.salary = salary;       //扩展的成员 
  13. }; 
  14.  
  15. var p=new person("yangsp",p); 
  16. //p.sayHello(p); 
  17. //alert(p.constructor); 
  18.  
  19. //下面两句验证了普通对象中确有_proto_属性,且引用的是prototype对象;(在ff下调试,ie下不 可); 
  20. alert(p.__proto__==person); 
  21. alert(p.__proto__==person.prototype)) 
  22.  
  23. //alert("p有prototype属性吗? "+p.prototype);    //表明普通对象中没有 prototype属性;                              

总结:

Html 代码
  1. 比较赞同 第三种理解; 
  2.       即:prototype是function对象中专有的属 性。 
  3.           _proto_是普通对象的隐式属性,在new的时候,会指向 prototype所指的对象; 
  4.           普通对象中的constructor属性指向构造 函数,因此一个用构造函数创建的对象可能有两种方式关联到prototype.但继承应该是根据_proto_关联到prototype属性; 

另外:ecma-262中提到:every object created by that constructor has an implicit reference to the prototype (called the object's prototype) associated with its constructor 以及其图示;不敢肯定它的implicit reference间接还是隐式链接;

Continue reading javascript call和apply最基本的作用

样式表hack-区别IE和非IE浏览器

只看第一个就差不多了:


1.区别IE和非IE浏览器

#tip {
background:blue; /*非IE 背景藍色*/
background:red \9; /*IE6、IE7、IE8背景紅色*/
}


2.区别IE6,IE7,IE8,FF

【区别符号】:「\9」、「*」、「_」
【示例】:
#tip {
background:blue; /*Firefox 背景变蓝色*/
background:red \9; /*IE8 背景变红色*/
*background:black; /*IE7 背景变黑色*/
_background:orange; /*IE6 背景变橘色*/
}

【说明】:因为IE系列浏览器可读「\9」,而IE6和IE7可读「*」(米字号),另外IE6可辨识「_」(底线),因此可以依照顺序写下来,就会让浏 览器正确的读取到自己看得懂得CSS语法,所以就可以有效区分IE各版本和非IE浏览器(像是Firefox、Opera、Google Chrome、Safari等)。


3.区别IE6、IE7、Firefox (方法 1)

【区别符号】:「*」、「_」
【示例】:
#tip {
background:blue; /*Firefox背景变蓝色*/
*background:black; /*IE7 背景变黑色*/
_background:orange; /*IE6 背景变橘色*/
}

【说明】:IE7和IE6可读「*」(米字号),IE6又可以读「_」(底线),但是IE7却无法读取「_」,至于Firefox(非IE浏览器)则完全 无法辨识「*」和「_」,因此就可以透过这样的差异性来区分IE6、IE7、Firefox


4.区别IE6、IE7、Firefox (方法 2)

【区别符号】:「*」、「!important」
【示例】:
#tip {
background:blue; /*Firefox 背景变蓝色*/
*background:green !important; /*IE7 背景变绿色*/
*background:orange; /*IE6 背景变橘色*/
}

【说明】:IE7可以辨识「*」和「!important」,但是IE6只可以辨识「*」,却无法辨识「!important」,至于Firefox可以 读取「!important」但不能辨识「*」因此可以透过这样的差异来有效区隔IE6、IE7、Firefox。


5.区别IE7、Firefox

【区别符号】:「*」、「!important」
【示例】:
#tip {
background:blue; /*Firefox 背景变蓝色*/
*background:green !important; /*IE7 背景变绿色*/
}

【说明】:因为Firefox可以辨识「!important」但却无法辨识「*」,而IE7则可以同时看懂「*」、「!important」,因此可以 两个辨识符号来区隔IE7和Firefox。


6.区别IE6、IE7 (方法 1)

【区别符号】:「*」、「_」
【示例】:
#tip {
*background:black; /*IE7 背景变黑色*/
_background:orange; /*IE6 背景变橘色*/
}

【说明】:IE7和IE6都可以辨识「*」(米字号),但IE6可以辨识「_」(底线),IE7却无法辨识,透过IE7无法读取「_」的特性就能轻鬆区隔 IE6和IE7之间的差异。


7.区别IE6、IE7 (方法 2)

【区别符号】:「!important」
【示例】:
#tip {
background:black !important; /*IE7 背景变黑色*/
background:orange; /*IE6 背景变橘色*/
}

【说明】:因为IE7可读取「!important;」但IE6却不行,而CSS的读取步骤是从上到下,因此IE6读取时因无法辨识 「!important」而直接跳到下一行读取CSS,所以背景色会呈现橘色。


8.区别IE6、Firefox

【区别符号】:「_」
【示例】:
#tip {
background:black; /*Firefox 背景变黑色*/
_background:orange; /*IE6 背景变橘色*/
}

【说明】:因为IE6可以辨识「_」(底线),但是Firefox却不行,因此可以透过这样的差异来区隔Firefox和IE6,有效达成CSS hack。

Continue reading 样式表hack-区别IE和非IE浏览器

Pagination


Total views.

© 2013 - 2019. All rights reserved.

Powered by Hydejack v6.6.1