憨厚生

----Java's Slave----
***Java's Host***

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  165 随笔 :: 17 文章 :: 90 评论 :: 0 Trackbacks

2009年10月22日 #

【转】http://www.cnblogs.com/myssh/archive/2009/12/18/1627368.html

在《Pragmatic AJAX中文问题 A Web 2.0 Primer 》中偶然看到对readyStae状态的介绍,感觉这个介绍很实在,摘译如下:

 0: (Uninitialized) the send( ) method has not yet been invoked. 
 1: (Loading) the send( ) method has been invoked, request in progress. 
 2: (Loaded) the send( ) method has completed, entire response received.
 3: (Interactive) the response is being parsed. 
 4: (Completed) the response has been parsed, is ready for harvesting. 

 0 - (未初始化)还没有调用send()方法
 1 - (载入)已调用send()方法,正在发送请求
 2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
 3 - (交互)正在解析响应内容
 4 - (完成)响应内容解析完成,可以在客户端调用了

对于readyState的这五种状态,其他书中大都语焉不详。像《Foundations of AJAX中文问题》中,只在书中的表2-2简单地列举了状态的“名称”--The state of the request. The five possible values are 0 = uninitialized, 1 = loading, 2 = loaded, 3 = interactive, and 4 = complete。而《Ajax in Action》中好像根本就没有提到这5种状态的细节。《Professional AJAX中文问题》中虽不尽人意,但还是有可取之处:

There are five possible values for readyState: 
0 (Uninitialized): The object has been created but the open() method hasn’t been called. 
1 (Loading): The open() method has been called but the request hasn’t been sent. 
2 (Loaded): The request has been sent. 
3 (Interactive). A partial response has been received. 
4 (Complete): All data has been received and the connection has been closed. 

readyState有五种可能的值:
0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法。
1 (载入):已经调用open() 方法,但尚未发送请求。
2 (载入完成): 请求已经发送完成。
3 (交互):可以接收到部分响应数据。
4 (完成):已经接收到了全部数据,并且连接已经关闭。

在《Understanding AJAX中文问题: Using JavaScript to Create Rich Internet Applications》中,则用下表进行了说明:

readyState Status Code

Status of the XMLHttpRequest Object
(0) UNINITIALIZED
未初始化
The object has been created but not initialized. (The open method has not been called.)
(XMLHttpRequest)对象已经创建,但尚未初始化(还没有调用open方法)。
(1) LOADING
载入
The object has been created, but the send method has not been called.
(XMLHttpRequest)对象已经创建,但尚未调用send方法。
(2) LOADED
载入完成
The send method has been called, but the status and headers are not yet available.
已经调用send方法,(HTTP响应)状态及头部还不可用。
(3) INTERACTIVE
交互
Some data has been received. Calling the responseBody and responseText properties at this state to obtain partial results will return an error, because status and response headers are not fully available.
已经接收部分数据。但若在此时调用responseBody和responseText属性获取部分结果将会产生错误,因为状态和响应头部还不完全可用。
(4) COMPLETED
完成
All the data has been received, and the complete data is available in the responseBody and responseText properties.
已经接收到了全部数据,并且在responseBody和responseText属性中可以提取到完整的数据。

根据以上几本书中的关于readyState五种状态的介绍,我认为还是《Pragmatic AJAX中文问题 A Web 2.0 Primer 》比较到位,因为它提到了对接收到的数据的解析问题,其他书中都没有提到这一点,而这一点正是“(3)交互”阶段作为一个必要的转换过程存在于“(2)载入完成”到“(4)完成”之间的理由,也就是其任务是什么。归结起来,我觉得比较理想的解释方法应该以“状态:任务(目标)+过程+表现(或特征)”表达模式来对这几个状态进行定义比较准确,而且让人容易理解。现试总结如下:

readyState 状态

状态说明

(0)未初始化

此阶段确认XMLHttpRequest对象是否创建,并为调用open()方法进行未初始化作好准备。值为0表示对象已经存在,否则浏览器会报错--对象不存在。

(1)载入

此阶段对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true)完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。

(2)载入完成

此阶段接收服务器端的响应数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示已经接收完全部响应数据。并为下一阶段对数据解析作好准备。

(3)交互

此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。状态3表示正在解析数据。

(4)完成

此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。

概而括之,整个XMLHttpRequest对象的生命周期应该包含如下阶段:
创建-初始化请求-发送请求-接收数据-解析数据-完成

在具体应用中,明确了readyState的五个状态(XMLHttpRequest对象的生命周期各个阶段)的含义,就可以消除对Ajax核心的神秘感(语焉不详的背后要么是故弄玄虚,制造神秘感;要么就是“以其昏昏,使人昭昭”),迅速把握其实质,对减少学习中的挫折感和增强自信心都极其有益。

比如,通过如下示例:

//声明数组 var states = [“正在初始化……”, “正在初始化请求……成功! 正在发送请求……”, “成功! 正在接收数据……”, “完成! 正在解析数据……”, “完成! ”]; //回调函数内部代码片段 if (xmlHttp.readyState==4) { var span = document.createElement(“span”); span.innerHTML = states[xmlHttp.readyState]; document.body.appendChild(span); if (xmlHttp.status == 200) { var xmldoc = xmlHttp.responseXML; //其他代码 } //别忘记销毁,防止内存泄漏 xmlHttp = null; }else{ var span = document.createElement(“span”); span.innerHTML = states[xmlHttp.readyState]; document.body.appendChild(span); }

结果如下:

正在初始化请求……成功!
正在发送请求……成功!
正在接收数据……完成!
正在解析数据……完成!

我们很容易明白XMLHttpRequest对象在各个阶段都在做什么。因此,也就很容易对Ajax的核心部分有一个真正简单明了的理解。

本博PS:readyState一般用在异步请求时程序响应的判断,Iframe, javaScript脚本同样适用,参考另一篇文章:http://d-tune.javaeye.com/blog/506074

文章出处:http://www.cn-cuckoo.com/2007/07/16/the-details-for-five-states-of-readystate-9.html

posted @ 2010-06-07 09:19 二胡 阅读(617) | 评论 (2)编辑 收藏

历史 
    CVS 诞生于 1986 年,当时作为一组 shell 脚本而出现;1989年3月,Brian Berlinor用C语言重新设计并编写了CVS的代码;1993年前后,Jim Kingdon最终将CVS设计成基于网络的平台,开发者们能从Internet任何地方获得程序源代码。截至目前最新版本是2004年12月13日发布的1.12.11。 

功能介绍 
一、 代码统一管理,保存所有代码文件更改的历史记录。对代码进行集中统一管理,可以方便查看新增或删除的文件,能够跟踪所有代码改动痕迹。可以随意恢复到以前任意一个历史版本。并避免了因为版本不同引入的深层BUG。 
二、 完善的冲突解决方案,可以方便的解决文件冲突问题,而不需要借助其它的文件比较工具和手工的粘贴复制。 
三、 代码权限的管理。可以为不同的用户设置不同的权限。可以设置访问用户的密码、只读、修改等权限,而且通过CVS ROOT目录下的脚本,提供了相应功能扩充的接口,不但可以完成精细的权限控制,还能完成更加个性化的功能。 
四、 支持方便的版本发布和分支功能。

基本概念 
资源库(Repository)
 
CVS的资源库存储全部的版本控制下的文件copy,通常不容许直接访问,只能通过cvs命令,获得一份本地copy,改动后再check in(commit)回资源库。而资源库通常为与工作目录分离的。CVS通过多种方式访问资源库。每种方法有不同目录表示形式。 
版本(Revision) 
每一个文件的各个版本都不相同,形如1.1, 1.2.1,一般1.1是该文件的第一个revision,后面的一个将自动增加最右面的一个整数,比如1.2, 1.3, 1.4...有时候会出现1.3.2.2,原因见后。revision总是偶数个数字。一般情况下将revision看作时CVS自己内部的一个编号,而tag则可以标志用户的特定信息。 
标签(Tag) 
用符号化的表示方法标志文件特定revision的信息。通常不需要对某一个孤立的文件作tag,而是对所有文件同时作一个tag,以后用户可以仅向特定tag的文件提交或者checkout。另外一个作用是在发布软件的时候表示哪些文件及其哪个版本是可用的;各文件不同revision可以包括在一个tag中。如果命名一个已存在的tag默认将不会覆盖原来的; 
分支(Branch) 
当用户修改一个branch时不会对另外的branch产生任何影响。可以在适当的时候通过合并的方法将两个版本合起来;branch总是在当前revision后面加上一个偶数整数(从2开始,到0结束),所以branch总是奇数个数字,比如1.2后面branch为1.2.2,该分支下revision可能为1.2.2.1,1.2.2.2,... 
冲突(Conflct) 
完全是纯文本的冲突,不包含逻辑上的矛盾。一般是一份文件,A做了改动,B在A提交之前也做了改动,这样最后谁commit就会出现冲突,需要手工解决冲突再提交。 

CVS与eclipse集成开发 
  前面对CVS的历史、功能、概论等理论知识做了介绍。下面我们将使用最流行的Java IDE Eclipse中内置的CVS工具,以一个完整开发流程,介绍实际环境中CVS的正确使用。关于CVS系统的安装,不是本文的内容,您可以从附录的链接中获取安装的介绍资料。 

常用的CVS控制命令 
Check Out(检出) 
把源文件从cvs源代码仓库中取出,缺省的版本是最新的版本,你也可以选择指定的版本。在每次更改源代码之前,需要Check Out最新的版本,再起基础之上对源代码进行修改。将代码目录checkout到指定目录下,所有文件都是read-write。 
Check In(检入) 
把源代码加入到cvs源代码仓库中,每一个添加进代码库中的文件的版本是 1.1。以后每次修改文件重新ci以后,此文件的版本递增为1.2 ,1.3.……。在每次对源代码修改之后,需要Check In,提交最新版本的源代码。 
Synchronize with Repository(与资源库同步,简称同步) 
使本地更改与资源库同步,它会列出本地和资源库之间不同的所有文件。 
Add to Version Control 
将新的文件加入到版本控制之中。 
Add to .cvsIgnore 
将文件设置到版本控制之外,这样该文件或目录中的文件的更改在CVS中不可见,即使同步也无法发现。

CVS正确使用步骤 
一、 同步(Synchronize)
 
就是将本地更改与服务器同步,同步之后可以清晰的看到上一捡出(Check Out)版本之后本地、服务器上的最新改动。这是非常有用的,特别是敏捷开发,强调集体拥有代码。有了同步功能,你可以全局把握项目的代码,可以很方便的跟踪公共模块代码的任何改动。 
具体操作:在Eclipse的资源视图(Resource Perspective)或者Java视图(Java Perspective)中,选中要同步的目录,点击右键选择"Synchronize with Repository",之后它将显示同步的视图。如下图: 

(图一、CVS同步视图) 
同步之后,它有四种Mode可以选择,见上图绿色框框里按钮。从做到右分别为: 
Incoming Mode:表示修改是来自服务器,对应于更新(update)操作。 
Outgoing Mode:表示修改是来自本地,对应提交(commit)操作。 
Incoming/ Outgoing Mode:本地和服务器修改都在该模式(Mode)中显示。 
Conflicts Mode:显示本地和服务器修改的冲突文件。 
二、 更新(update) 
比较简单,选择Incoming Mode,再选中要更新的文件,右键选择update操作。 
三、 解决冲突并合并(solve conflct and merge) 
如果有冲突文件,冲突文件不能更新。你必须先解决冲突再操作。选中冲突的文件,再点右键选择"Open in Compare Editor",用比较工具打开该文件。如下图: 

(图二、CVS比较器视图)

比较器(Compare)视图,左边版本底的是本地文件(Local File),右边是远程服务器文件(Remote File)。使用"Select Next Change"按钮(绿框中的第一箭头向下按钮),逐一查看不同点。如果不同点标识为黑色框框,则不用管它。如果是蓝色框框,则需要手工调整。如上图,不同点是蓝色框框,将鼠标放到两个不同点的中间小方框中,则凸出一个向右的按钮,并显示提示信息"Copy Current Change from Right to Left",意思是将右边服务器的不同点覆盖到左边的本地文件。点中此按钮。重复这样的操作,将所有服务器上的更改拷贝到本地。 
如果有一行代码,本地和服务器都同时做了修改。这时,修改点则显示红色框框。这时,你就必须手工做正确的修改。全部修改完成,保存本地文件。 
此时,如果修改点没有了蓝色的框框,就可以开始做合并(merge)操作了。操作也很简单,选择该文件,点击右键,选择"Mark as merged"。 
注意:必须确保没有蓝色框框,即完全拷贝了服务器的修改才可以做合并(merge)操作,否则会覆盖服务器上的代码。 
四、 提交(commit) 
更新服务器代码,解决冲突之后,首先要查看本地文件修改之后是否有错误。如果有,当然首先解决错误,再提交。 

posted @ 2010-03-30 09:48 二胡 阅读(511) | 评论 (0)编辑 收藏

转  http://blog.cnw.com.cn/index.php/20937/viewspace-3418

HTTP头字段包括4类:
       general-header ;
     request-header ;
       response-header ;
     entity-header .
 
*******************************************************************************
 General Header Fields
=============================
   general header是request、response都可用的, 但是不能用于entity.
 
 
       -- Cache-Control
       -- Connection
       -- Date
       -- Pragma
       -- Trailer
       -- Transfer-Encoding
       -- Upgrade
       -- Via
       -- Warning
 
*******************************************************************************
 Request Header Fields
======================
 
   request-header fields 允许客户端传递关于request和客户端的附加信息到服务端,
 
       -- Accept
       -- Accept-Charset
       -- Accept-Encoding
       -- Accept-Language
       -- Authorization
       -- Expect
       -- From
       -- Host
       -- If-Match
       -- If-Modified-Since
       -- If-None-Match
       -- If-Range
       -- If-Unmodified-Since
       -- Max-Forwards
       -- Proxy-Authorization
       -- Range
       -- Referer
       -- TE
       -- User-Agent
 
*******************************************************************************
  Response Header Fields
===============================
 
   response-header fields 允许服务端传递关于response的、不能放到Status-Line的附加信息。
   这些头给出关于服务端的信息。 
 
      -- Accept-Ranges
      -- Age
      -- ETag
      -- Location
      -- Proxy-Authenticate
      -- Retry-After
      -- Server
      -- Vary
      -- WWW-Authenticate
 
*******************************************************************************
 Entity Header Fields
========================
 
   Entity-header fields 定义关于entity-body的metainformation(标题字段数据),
   如果当前没有body, 则定义被request确定的资源信息.
   一些metainformation是可选的; 一些是必须的。
 
       -- Allow
       -- Content-Encoding
       -- Content-Language
       -- Content-Length
       -- Content-Location
       -- Content-MD5
       -- Content-Range
       -- Content-Type
       -- Expires
       -- Last-Modified
       -- extension-header


【转自】http://www.x5dj.com/userforum/00100239/00305167.shtml


一、基础篇
HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP协议的详细内容请参考RFC2616。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求,请求头包含请求的方法、URI、协议版本、以及包含请求修饰符、客户信息和内容的类似于MIME的消息结构。服务器以一个状态行作为响应,相应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。
通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和可选的消息体组成。HTTP的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。
1、通用头域
通用头域包含请求和响应消息都支持的头域,通用头域包含Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via。对通用头域的扩展要求通讯双方都支持此扩展,如果存在不支持的通用头域,一般将会作为实体头域处理。下面简单介绍几个在UPnP消息中使用的通用头域。
Cache-Control头域
Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no- store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、 private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、 max-age。各个消息中的指令含义如下:
Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
Date头域
Date头域表示消息发送的时间,时间的描述格式由rfc822定义。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的时间表示世界标准时,换算成本地时间,需要知道用户所在的时区。
Pragma头域
Pragma头域用来包含实现特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。
2、请求消息
请求消息的第一行为下面的格式:
Method SP Request-URI SP HTTP-Version CRLF 
Method表示对于Request-URI完成的方法,这个字段是大小写敏感的,包括OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE。方法GET和HEAD应该被所有的通用WEB服务器支持,其他所有方法的实现是可选的。GET方法取回由Request-URI标识的信息。HEAD方法也是取回由Request-URI标识的信息,只是可以在响应时,不返回消息体。POST方法可以请求服务器接收包含在请求中的实体信息,可以用于提交表单,向新闻组、BBS、邮件群组和数据库发送消息。
SP表示空格。
Request-URI遵循URI格式,在此字段为星号(*)时,说明请求并不用于某个特定的资源地址,而是用于服务器本身。
HTTP-Version表示支持的HTTP版本,例如为HTTP/1.1。
CRLF表示换行回车符。
请求头域允许客户端向服务器传递关于请求或者关于客户机的附加信息。请求头域可能包含下列字段Accept、Accept-Charset、Accept- Encoding、Accept-Language、Authorization、From、Host、If-Modified-Since、If- Match、If-None-Match、If-Range、If-Range、If-Unmodified-Since、Max-Forwards、 Proxy-Authorization、Range、Referer、User-Agent。对请求头域的扩展要求通讯双方都支持,如果存在不支持的请求头域,一般将会作为实体头域处理。
典型的请求消息:
GEThttp://class/download.microtool.de:80/somedata.exe
Host:download.microtool.de
Accept:*/*
Pragma:no-cache
Cache-Control:no-cache
Referer:http://class/download.microtool.de/
User-Agent:Mozilla/4.04[en](Win95;I;Nav)
Range:bytes=554554-
上例第一行表示HTTP客户端(可能是浏览器、下载程序)通过GET方法获得指定URL下的文件。棕色的部分表示请求头域的信息,绿色的部分表示通用头部分。
Host头域
Host头域指定请求资源的Intenet主机和端口号,必须表示请求url的原始服务器或网关的位置。HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回。
Referer头域
Referer头域允许客户端指定请求uri的源资源地址,这可以允许服务器生成回退链表,可用来登陆、优化cache等。他也允许废除的或错误的连接由于维护的目的被追踪。如果请求的uri没有自己的uri地址,Referer不能被发送。如果指定的是部分uri地址,则此地址应该是一个相对地址。
Range头域
Range头域可以请求实体的一个或者多个子范围。例如,
表示头500个字节:bytes=0-499
表示第二个500字节:bytes=500-999
表示最后500个字节:bytes=-500
表示500字节以后的范围:bytes=500-
第一个和最后一个字节:bytes=0-0,-1
同时指定几个范围:bytes=500-600,601-999
但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200(OK)。
User-Agent头域
User-Agent头域的内容包含发出请求的用户信息。

3、响应消息
响应消息的第一行为下面的格式:
HTTP-Version SP Status-Code SP Reason-Phrase CRLF
HTTP-Version表示支持的HTTP版本,例如为HTTP/1.1。
Status-Code是一个三个数字的结果代码。
Reason-Phrase给Status-Code提供一个简单的文本描述。Status-Code主要用于机器自动识别,Reason-Phrase主要用于帮助用户理解。Status-Code的第一个数字定义响应的类别,后两个数字没有分类的作用。第一个数字可能取5个不同的值:
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求
响应头域允许服务器传递不能放在状态行的附加信息,这些域主要描述服务器的信息和Request-URI进一步的信息。响应头域包含Age、 Location、Proxy-Authenticate、Public、Retry-After、Server、Vary、Warning、WWW- Authenticate。对响应头域的扩展要求通讯双方都支持,如果存在不支持的响应头域,一般将会作为实体头域处理。
典型的响应消息:
HTTP/1.0200OK
Date:Mon,31Dec200104:25:57GMT
Server:Apache/1.3.14(Unix)
Content-type:text/html
Last-modified:Tue,17Apr200106:46:28GMT
Etag:"a030f020ac7c01:1e9f"
Content-length:39725426
Content-range:bytes554554-40279979/40279980
上例第一行表示HTTP服务端响应一个GET方法。棕色的部分表示响应头域的信息,绿色的部分表示通用头部分,红色的部分表示实体头域的信息。
Location响应头
Location响应头用于重定向接收者到一个新URI地址。
Server响应头
Server响应头包含处理请求的原始服务器的软件信息。此域能包含多个产品标识和注释,产品标识一般按照重要性排序。
4、实体信息
请求消息和响应消息都可以包含实体信息,实体信息一般由实体头域和实体组成。实体头域包含关于实体的原信息,实体头包括Allow、Content-Base、Content-Encoding、Content-Language、 Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、 Etag、Expires、Last-Modified、extension-header。extension-header允许客户端定义新的实体头,但是这些域可能无法未接受方识别。实体可以是一个经过编码的字节流,它的编码方式由Content-Encoding或Content-Type定义,它的长度由Content-Length或Content-Range定义。
Content-Type实体头
Content-Type实体头用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,或GET方法发送的请求介质类型Content-Range实体头
Content-Range实体头
用于指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:
Content-Range:bytes-unit SP first-byte-pos - last-byte-pos/entity-legth
例如,传送头500个字节次字段的形式:Content-Range:bytes0-499/1234如果一个http消息包含此节(例如,对范围请求的响应或对一系列范围的重叠请求),Content-Range表示传送的范围,Content-Length表示实际传送的字节数。
Last-modified实体头
Last-modified实体头指定服务器上保存内容的最后修订时间。
5、 HTTP 头参考(microsoft)
HTTP 请求和 HTTP 响应都使用头发送有关 HTTP 消息的信息。头由一系列行组成,每行都包含名称,然后依次是冒号、空格、值。字段可按任何顺序排列。某些头字段既能用于请求头也能用于响应头,而另一些头字段只能用于其中之一。
许多请求头字段都允许客户端在值部分指定多个可接受的选项,有时甚至可以对这些选项的首选项进行排名。多个项以逗号分隔。例如,客户端可以发送包含 “Content-Encoding: gzip, compress,”的请求头,表示可以接受各种压缩类型。如果服务器的响应正文使用 gzip 编码,其响应头中将包含“Content-Encoding: gzip”。
有些字段可以在单个头中出现多次。例如,头可以有多个“Warning”字段。
下表列出了 HTTP 1.1 头字段。注意:有些头字段是 MIME 字段。MIME 字段在 Internet Engineering Task Force (IETF) 文档 RFC 2045 中进行了定义,但也可用于 HTTP 1.1 协议。有关 MIME 和 HTTP 1.1 规范的详细信息,请参阅 IEIF 页。
一般头字段
一般头字段可用于请求消息和响应消息。
 名称          示例值
Cache-Control  "max-age=10"
Connection    "close"
Date          "Tue, 11 Jul 2000 18:23:51 GMT"
Pragma        "no-cache"
Trailer         "Date"
Transfer-Encoding"chunked"
Upgrade       "SHTTP/1.3"
Via            "HTTP/1.1 Proxy1, HTTP/1.1 Proxy2"
Warning       "112 Disconnected Operation"
请求头字段
请求头字段仅用于请求消息。
   名称             示例值
Accept           "text/html, image/*"
Accept-Charset   "iso8859-5"
Accept-Encoding "gzip, compress"
Accept-Language "en, fr"
Authorization     [credentials]
Content-Encoding "gzip"
Expect           "100-continue"
From            "user@microsoft.com"
Host            "www.microsoft.com"
If-Match         "entity_tag001"
If-Modified-Since"Tue, 11 Jul 2000 18:23:51 GMT"
If-None-Match    "entity_tag001"
If-Range         "entity_tag001" or "Tue, 11 Jul 2000 18:23:51 GMT"
If-Unmodified-Since"Tue, 11 Jul 2000 18:23:51 GMT"
Max-Forwards    "3"
Proxy-Authorization[credentials]
Range       "bytes=100-599"
Referer      "http://www.microsoft.com/resources.asp"
TE          "trailers"
User-Agent   "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"
 
>>请求头字段的具体含义
Accept:浏览器可接受的MIME类型。
Accept-Charset:浏览器可接受的字符集。
Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。
Connection:表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点, Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小。
Content-Length:表示请求消息正文的长度。
Cookie:设置cookie,这是最重要的请求头信息之一
From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。
Host:初始URL中的主机和端口。
If-Modified-Since:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答。
Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝。
Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。
User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。
UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型。
响应头字段
响应头字段仅用于响应消息。
  名称          示例值
Accept-Ranges  "none"
Age            "2147483648(2^31)"
ETag           "b38b9-17dd-367c5dcd"
Last-Modified    "Tue, 11 Jul 2000 18:23:51 GMT"
Location        "http://localhost/redirecttarget.asp"
Proxy-Authenticate[challenge]
Retry-After      "Tue, 11 Jul 2000 18:23:51 GMT" or "60"
Server         "Microsoft-IIS/5.0"
Vary            "Date"
WWW-Authenticate[challenge]
实体头字段
实体头字段可以用于请求消息或响应消息。实体头字段中包含消息实体正文的有关信息,如使用的编码格式。
   名称            示例值
Allow              "GET, HEAD"
Content-Encoding   "gzip"
Content-Language  "en"
Content-Length     "8445"
Content-Location   "http://localhost/page.asp"
Content-MD5       [md5-digest]
Content-Range     "bytes 2543-4532/7898"
Content-Type      "text/html"
Expires           "Tue, 11 Jul 2000 18:23:51 GMT"
Last-Modified      "Tue, 11 Jul 2000 18:23:51 GMT"
>>实体头字段的具体含义
Allow服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。
Content-Length表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。
Content-Type表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。
Date当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。
Location表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。
注意这种功能通常是通过设置HTML页面HEAD区的<META. HTTP-EQUIV="Refresh" C>实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置 Refresh头更加方便。
注意Refresh的意义是“N秒之后刷新本页面或访问指定页面”,而不是“每隔N秒刷新本页面或访问指定页面 ”。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META. HTTP-EQUIV="Refresh" ...>。
注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
请求头示例
以下是 HTTP 请求的简单示例。
GET /articles/news/today.asp HTTP/1.1
Accept: */*
Accept-Language: en-us
Connection: Keep-Alive
Host: localhost
Referer:http://localhost/links.asp
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
Accept-Encoding: gzip, deflate
该请求具有请求行,其中包括方法 (GET)、资源路径 (/articles/news/today.asp) 和 HTTP 版本 (HTTP/1.1)。由于该请求没有正文,故所有请求行后面的内容都是头的一部分。紧接着头之后是一个空行,表示头已结束。
响应头示例
Web 服务器可以通过多种方式响应前一个请求。假设文件是可以访问的,并且用户具有查看该文件的权限,则响应类似于:
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Thu, 13 Jul 2000 05:46:53 GMT
Content-Length: 2291
Content-Type: text/html
Set-Cookie: ASPSESSIONIDQQGGGNCG=LKLDFFKCINFLDMFHCBCBMFLJ; path=/
Cache-control: private
...
响应的第一行称为状态行。它包含响应所用的 HTTP 版本、状态编码 (200) 和原因短语。示例中包含一个头,其中具有五个字段,接着是一个空行(回车和换行符),然后是响应正文的头两行。
有关HTTP头完整、详细的说明,请参见http://www.w3.org/Protocols/的HTTP规范。
 
附录:HTTP协议状态码的含义
  状态代码 状态信息 含义
100 Continue初始的请求已经接受,客户应当继续发送请求的其余部分。(HTTP 1.1新)
101 Switching Protocols服务器将遵从客户的请求转换到另外一种协议(HTTP 1.1新
200 OK一切正常,对GET和POST请求的应答文档跟在后面。
201 Created服务器已经创建了文档,Location头给出了它的URL。
202 Accepted已经接受请求,但处理尚未完成。
203 Non-Authoritative Information文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝(HTTP 1.1新)。
204 No Content没有新文档,浏览器应该继续显示原来的文档。
205 Reset Content没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容(HTTP 1.1新)。
206 Partial Content客户发送了一个带有Range头的GET请求,服务器完成了它(HTTP 1.1新)。
300 Multiple Choices客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明。
301 Moved Permanently客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
302 Found类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。注意,在HTTP1.0中对应的状态信息是“Moved Temporatily”,出现该状态代码时,浏览器能够自动访问新的URL,因此它是一个很有用的状态代码。注意这个状态代码有时候可以和301替换使用。例如,如果浏览器错误地请求http://host/~user(缺少了后面的斜杠),有的服务器返回301,有的则返回302。严格地说,我们只能假定只有当原来的请求是GET时浏览器才会自动重定向。请参见307。
303 See Other类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取(HTTP 1.1新)。
304 Not Modified客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy客户请求的文档应该通过Location头所指明的代理服务器提取(HTTP 1.1新)。
307 Temporary Redirect和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是POST,即使它实际上只能在POST请求的应答是303时才能重定向。由于这个原因,HTTP 1.1新增了307,以便更加清除地区分几个状态代码:当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只能跟随对GET请求的重定向。(HTTP 1.1新)
400 Bad Request请求出现语法错误。
401 Unauthorized客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。
403 Forbidden资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。
404 Not Found无法找到指定位置的资源。这也是一个常用的应答,
405 Method Not Allowed请求方法(GET、POST、HEAD、DELETE、PUT、TRACE等)对指定的资源不适用。(HTTP 1.1新)
406 Not Acceptable指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容(HTTP 1.1新)。
407 Proxy Authentication Required类似于401,表示客户必须先经过代理服务器的授权。(HTTP 1.1新)
408 Request Timeout在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。(HTTP 1.1新)
409 Conflict通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。(HTTP 1.1新)
410 Gone所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址。它和404的不同在于,返回407表示文档永久地离开了指定的位置,而404表示由于未知的原因文档不可用。(HTTP 1.1新)
411 Length Required服务器不能处理请求,除非客户发送一个Content-Length头。(HTTP 1.1新)
412 Precondition Failed请求头中指定的一些前提条件失败(HTTP 1.1新)。
413 Request Entity Too Large目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头(HTTP 1.1新)。
414 Request URI Too LongURI太长(HTTP 1.1新)。
416 Requested Range Not Satisfiable服务器不能满足客户在请求中指定的Range头。(HTTP 1.1新)
500 Internal Server Error服务器遇到了意料不到的情况,不能完成客户的请求。
501 Not Implemented服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求。
502 Bad Gateway服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。
503 Service Unavailable服务器由于维护或者负载过重未能应答。
504 Gateway Timeout由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答。(HTTP 1.1新)
505 HTTP Version Not Supported服务器不支持请求中所指明的HTTP版本

posted @ 2010-01-08 09:15 二胡 阅读(268) | 评论 (0)编辑 收藏

JQuery作者John Resig的讲座
http://v.youku.com/v_show/id_XMjQzMDY4NDQ=.html

posted @ 2009-12-23 15:04 二胡 阅读(153) | 评论 (0)编辑 收藏

转 http://blog.youmila.com/?p=513

关于跨域名问题还是问题么,这方面的解决实践非常多,今天我就旧话重提把我所知道的通过几个应用场景来分别总结一下

先说明一点:我说的某某域名在您的控制下的意思是这个域名下的网页由您来负责开发内部的JavaScript
场景一:将bbs.xxx.com的页面用iframe嵌入到www.xxx.com的中,如何在iframe内外使用js通信
一级域名都是xxx.com 这个域名一定是在您的控制下,所以你只要在两个页面中同时升级域名即可
在父窗口和iframe内部分别加上js语句:document.domain=”xxx.com”;
之后2个页面就等于在同一域名下,通过window.parent oIframe.contentDocument就可以相互访问,进行无障碍的JS通信
在新浪、淘宝等很多页面都能找到这样的语句。不过document.domain不可以随便指定,只能向上升级,从bbs.xxx.com升级到yyy.com肯定会出错

场景二:将www.yyy.com的页面用iframe嵌入到www.xxx.com的中,两个域名都在您的控制下,如何在iframe内外进行一定的数据交流
你可以通过相互改变hash值的方式来进行一些数据的通信

这里的实现基于如下技术要点:
1、父窗口通过改变子窗口的src中的hash值把一部分信息传入,如果src只有hash部分改变,那么子窗口是不会重新载入的。
2、子窗口可以重写父窗口的location.href,但是注意这里子窗口无法读取而只能重写location.href所以要求前提是您控制两个域名,知道当前父窗口的location.href是什么并写在子窗口内,这样通过parent.location.href = “已知的父窗口的href”+”#”+hash。这样父窗口只有hash改变也不会重载。
3、上面两步分别做到了两个窗口之间的无刷新数据通知,那么下面的来说如何感知数据变化。标准中没有相关规定,所以当前的任意浏览器遇到location.hash变化都不会触发任何javaScript事件,也就是说您要自己写监听函数来监视loaction.hash的值的变化。做法是通过setTimeout或者setInterval来写一个监听函数每20-100ms查看一下hash是否变化,如果变化了驱动js根据新的数据做想做的事情。

这种实现的一些分析:
1、信息通道是双向的,当然会兼容单向,如果只是父窗口向子窗口通知数据,只需要子窗口写hash监听,反之亦然。
2、局限性也是颇大,因为这种通信的前提是双方知道对方的location.href。如果父窗口带有动态的location.search也就是查询参数,那么子窗口的处理上就比较困难,需要把父窗口的location.search作为传递信息的一部分告知子窗口。
3、另外的困扰会有浏览器带给你,IE之外的浏览器遇到hash的改变会记录历史,这样你在处理前进后退的时候会非常头疼

场景三:将www.yyy.com的页面用iframe嵌入到www.xxx.com的中,只有被嵌入的yyy.com在您的控制下,如何在iframe内外进行一定的交流
真实场景:google adsence的一个需求,你希望google发现您的页面不能匹配出相关性非常好的按点击付费广告时,你希望google的广告iframe能够隐藏。
google的广告iframe在google域下显然不能把自己隐藏掉,那么怎么办呢?
1、google会提供给你一个html页面
2、您将这个页面放置在您的域名下,并告诉google它的位置
3、当google发现没有很好的广告时,会将子窗口的loaction重定向到您的那个页面下,这样您的页面因为同域名就可以访问父页面来隐藏自己了
是不是很巧的方法?

场景四:您是内容发布商,如何改造接口,让其他域名下的页面可以从浏览器端出发获得您的数据
我们知道ajax的xmlHttpRequest()说到底是一个无刷新请求服务器数据的辅助工具,但是xmlHttpRequest并不能跨域名请求数据,在某些情况下成了极大的限制。
但是我们如果通过其他方式完成无刷新请求数据不也可以么,我们用Dom方法操作动态JS脚本请求来做这件事。
    //创建一个脚本节点
    var oScript = document.createElement(’script’);
    //指定脚本src src可以指向任意域名
    //注意src不再指向静态js,而是带着查询参数指向一个动态脚本广播服务。
    oScript.src = “http://yyy.com/query.php?”+yourQueryString;   
    //如果指定了charset 同时还可以解决xmlHttpRequest另一大困扰 乱码问题                                                                                                                           
    //oScript.charset = “utf-8″;
    //通过Dom操作把这个新的节点加入到文档当中                                 
    document.getElementsByTagName(”head”)[0].appendChild(oScript);

这样只要query.php的输出是可执行的javaScript脚本,比如:djsCallBack({jsondata});
当他从服务器返回后就会自动执行,你可以方便的用json方式来做数据传递了。
要注意,您的脚本请求最好带上时间戳,避免浏览器缓存造成取回数据实时性下降。

如果您是数据提供者,您可以要求数据索取者在查询参数中提供回调函数名,比如query.php?callback=myDataHandler&key=…?
这样您就可以根据参数来提供给他myDataHandler({jsondata}),这样不同的数据索取者都会得到自定义的正确的异步回调。

场景五:通过后端程序语言,为了跨域名而做各自的后台数据抓取转化服务,比如php curl,YAHOO  CHINA NCP就是用这种方案。

场景六:通过flash proxy,因为flash的跨域调用可以通过crossdomain.xml和security.allowdomain(’*')文件实现,而js又可以和flash进行通信,所以js完全可以借用flash

               实现js跨域通信。

 
总结总结
第一种场景,相应的处理办法有这非常好的效果,可以说完全解决了问题。
第二种场景,相应的处理办法具有一定的跨域数据交流功效,具有相当大的局限,并不适合在复杂业务流程中应用,实际上我也确实也没看到过基于此的大规模应用。
第三种场景,相应的处理办法比较巧妙,虽然redirect之后就不干你什么事了,但如果你是google一样面向众多域名的内容提供商,也是个不错的解决思路。
第四种场景,相应的处理办法非常强大,对比Ajax可以看到,跨域名没问题,无刷新没问题,本身又是异步的,JSON比xml快的多,同时解决乱码问题,只是请求都是Get方式的,不能做Post方式的请求。多一种武器自然可以从容选择了。

第五种场景,处理很方便,也很实用。

第六种场景,需要一定的flash基础哈,作用当然非常强大。

posted @ 2009-12-16 17:51 二胡 阅读(1086) | 评论 (0)编辑 收藏


The Java Community Process(SM) Program

转 http://blog.csdn.net/sergeycao/archive/2009/02/04/3861560.aspx

J2ME 配置规范
=========
JSR 30 --- Connected Limited Device Configuration 1.0
http://jcp.org/en/jsr/detail?id=30

JSR 139 --- Connected Limited Device Configuration 1.1
http://jcp.org/en/jsr/detail?id=139

JSR 36 --- Connected Device Configuration 1.0
http://jcp.org/en/jsr/detail?id=36

JSR 218 --- Connected Device Configuration 1.1
http://jcp.org/en/jsr/detail?id=218

========================================
1、JSR 30、JSR139 简介 及它们之间的关系
CLDC全称为Connected Limited Device Configuration(有限连接设备配置),
分别对应了JSR 30和JSR 139两个JSR。

CLDC专门针对移动电话、阅读器和主流的PDA(个人数字助理)定义了一组基础的应用程序编程接口和虚拟机标准,
和简表文件一起配合,就构成了一套实用的Java平台,可以为内存不多、处理器性能有限、图形能力一般的设备开发应用程序。

JSR 30 CLDC 1.0 提供了基本的语言类库,主要是定义了JAVA编程语言的一套子集,包括虚拟机的功能上,网络支持,安全安装以及其他核心API上都是子集和全集的关系,主要目标是某类嵌入式的消费类产品。由于不支持浮点运算,可以用CLDC1.1替代CLDC1.0;

JSR 139 CLDC 1.1是CLDC 1.0技术标准的修订版本,包含了一些新的特性比如浮点运算和弱引用等方面的支持,和CLDC-1.0是完全向后兼容的;

2、JSR 36、JSR218 简介 及 它们之间的关系
JSR 36 CDC (Connected Device Configuration,连接设备配置)。CDC的目标设备较CLDC具有更大的内存、更快速的处理器、更稳定的电源,以及更出色的网络连接能力。
CDC主要应用在工业控制器、高端PDA、电视机顶盒及车载娱乐与导航系统上。

JSR 218 是在JSR 36基础上进行补充,并兼容JSR 36.

J2ME 简表规范
=========
CDC 简表规范
------------------
JSR 46 --- Foundation Profile
http://jcp.org/en/jsr/detail?id=46

JSR 129 --- Personal Basis Profile Specification
http://jcp.org/en/jsr/detail?id=129

JSR 62 --- Personal Profile Specification
http://jcp.org/en/jsr/detail?id=62

JSR 219 --- Foundation Profile 1.1
http://jcp.org/en/jsr/detail?id=219

JSR 217 --- Personal Basis Profile 1.1
http://jcp.org/en/jsr/detail?id=217

JSR 216 --- Personal Profile 1.1
http://jcp.org/en/jsr/detail?id=216

CLDC 简表规范
--------------------
JSR 37 --- Mobile Information Device Profile 1.0
http://jcp.org/en/jsr/detail?id=37

JSR 118 --- Mobile Information Device Profile 2.0
http://jcp.org/en/jsr/detail?id=118

JSR 195 --- Information Module Profile
http://jcp.org/en/jsr/detail?id=195

JSR 228 --- Information Module Profile 2.0)
http://jcp.org/en/jsr/detail?id=228


厂商可选包(Optional Packages)
-----------------------------------------

CDC设备厂商可选包
...........................
JSR 66 --- RMI Optional Package Specification Version 1.0
http://jcp.org/en/jsr/detail?id=66

JSR 80 --- Java USB API
http://jcp.org/en/jsr/detail?id=80

JSR 113 --- Java Speech API 2.0
http://jcp.org/en/jsr/detail?id=113

JSR 169 --- JDBC Optional Package for CDC/Foundation Profile
http://jcp.org/en/jsr/detail?id=169

JSR 209 --- Advanced Graphics and User Interface Optional Package for the J2ME Platform
http://jcp.org/en/jsr/detail?id=209

CLDC设备厂商可选包
...........................
JSR 75 --- PDA Optional Packages for the J2ME Platform
http://jcp.org/en/jsr/detail?id=75

JSR 82 --- Java APIs for Bluetooth
http://jcp.org/en/jsr/detail?id=82

JSR 120 --- Wireless Messaging API
http://jcp.org/en/jsr/detail?id=120

JSR 135 --- Mobile Media API
http://jcp.org/en/jsr/detail?id=135

JSR 172 --- J2ME Web Services Specification
http://jcp.org/en/jsr/detail?id=172

JSR 177 --- Security and Trust Services API for J2ME
http://jcp.org/en/jsr/detail?id=177

JSR 179 --- Location API for J2ME
http://jcp.org/en/jsr/detail?id=179

JSR 180 --- SIP API for J2ME
http://jcp.org/en/jsr/detail?id=180

JSR 184 --- Mobile 3D Graphics API for J2ME
http://jcp.org/en/jsr/detail?id=184

JSR 190 --- Event Tracking API for J2ME
http://jcp.org/en/jsr/detail?id=190

JSR 205 --- Wireless Messaging API 2.0
http://jcp.org/en/jsr/detail?id=205

JSR 211 --- Content Handler API
http://jcp.org/en/jsr/detail?id=211

JSR 226 --- Scalable 2D Vector Graphics API for J2ME
http://jcp.org/en/jsr/detail?id=226

JSR 229 --- Payment API
http://jcp.org/en/jsr/detail?id=229

JSR 230 --- Data Sync API
http://jcp.org/en/jsr/detail?id=230

运行环境规范
..................
JSR 185 --- JavaTM Technology for the Wireless Industry
http://jcp.org/en/jsr/detail?id=185

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sergeycao/archive/2009/02/04/3861560.aspx

posted @ 2009-12-15 09:32 二胡 阅读(1210) | 评论 (0)编辑 收藏

     摘要: 我google一下,已有人翻译了此文.比我翻译的要好!是译言站翻译的 见url: http://www.yeeyan.com/articles/view/92135/47626/dz 原文见:http://code.google.com/intl/zh-CN/speed/articles/optimizing-javascript.html 不合适的地方,请大家指出来!希望对你有用! ...  阅读全文
posted @ 2009-12-14 21:43 二胡 阅读(1919) | 评论 (0)编辑 收藏

转 http://war.news.163.com/09/1211/18/5Q98H5TU00011232.html

国家战略是一个范军事话题,并非只有军事家才能成为战略精英。在这一点上,美国培养未来的国家决策人才的经验就值得中国反思。

前美国国防部长拉姆斯菲尔德

原文作者:于铁军(北京大学国际关系学院副教授)

美国的精英比较有活力,给人一种生机勃勃的感觉,因为他们更注重全面发展,更注重训练。反观国内精英,大多比较文弱,缺乏朝气,口号、程式,大话、空话很多,行动力、执行力却比较差。各种原因当然很多,其中重要之一是国内的精英培养机制有问题。在这方面,我们应该好好地研究一下美国培养精英的做法。如果我们对精英培养机制和培养内容不重视,中国要实现真正的崛起,难度是很大的。

什么是精英

精英,或者称战略性人才,是个很值得讨论的题目。这里首先需要回答一个问题,什么是精英?精英,一定是有所担当的人,有社会责任感的人,而绝不能是蝇营狗苟之辈。真正的精英,他身上一定带有一些利他的东西,不是完全为了自己。这是精英的一个必备条件。

以美国外交和国家安全领域的情况为例来做具体的说明,哈尔伯斯坦的《出类拔萃之辈》、艾萨克森和托马斯的《美国智囊六人传》,以及詹姆斯·曼的《布什战争内阁史》等传记作品。这些书中对艾奇逊、哈里曼、凯南、麦克罗伊、洛维特、邦迪兄弟、麦克纳马拉、罗斯托、拉姆斯菲尔德、鲍威尔、赖斯、沃尔福威茨、阿米蒂奇等美国外交和国家安全界精英的成长及活动,有惟妙惟肖的描写,有助于增加我们对美国精英养成方式的感性认识。掩卷之余,你可以对书中人物做出或褒或贬的评价,但你一般不会否认,这是一批有理想、有追求、有能力并且关心公共事务的精英,美国这个国家的大政方针为他们所引领。

叱咤风云的美国前国务卿赖斯

美国培养精英的一个重要理念:尚武精神与体育运动

具体到精英的培养,大学里面的培养机制还是比较关键的。当然我们不否认有草根出身的英雄,而且国人还经常说,英雄莫问来路。但社会发展到现在这个阶段,应该说大部分人才还是经过大学的正规教育训练出来的。美国的高等教育制度十分复杂,不像我们那样有一个统一的体制。从精英大学到普通大学,从研究性大学到小型的文理学院,从州立大学到私立大学,各种类型,应有尽有。不管是什么样的大学,从学生录取方面来看,美国比我们更重视学生的综合素质和发展潜力。除了SAT、GRE和GMAT这样的标准化考试之外,推荐信、研究计划、习作、课外活动等也都是很重要的指标,这无疑有助于引导和鼓励学生全面发展。

骑自行车的小布什,体育运动爱好在美国高官中相当普及

中国从小学就开始教育要德、智、体全面发展,但遗憾的是没有落到实处。就拿体育来说,正如中国留美学者薛涌所观察到的,美国精英层中运动员出身或者喜爱体育运动的人高得不成比例。他们在大学时代往往喜欢参加各种体育项目,如橄榄球、棒球、篮球、皮划艇等。参加体育运动,在激烈的竞争中使你的体力达到极限,这有助于一系列优秀品质的培养,如全力以赴、坚忍不拔、公平竞争、团队精神、尊重规则、强身健体,等等,而且还能找到一些志同道合者,为未来的事业编制人脉。在美国大学里,学生的领导能力常常是通过参加某某运动队和某某社团的活动来体现的。光是闷头学习,即使成绩再好,可能也不为人看重。

小布什的身体强壮,当总统时公务再繁忙,也要挤时间骑山地车和跑3英里。还有拉姆斯菲尔德,上大学时是普林斯顿摔跤队的,要不是因为肩伤,本来可以入选美国的奥运代表队。前总统福特,原来是密歇根大学橄榄球队的,水平之高几乎可以当职业运动员,但后来他选择去了耶鲁,毕业后开始从政。赖斯年轻的时候练花样滑冰,据说具备专业水准。其他例子还有许多,美国精英对体育的重视由此可见一斑。

传说中赖斯年轻时学习花样滑冰的照片

体育运动、强健的体魄与尚武精神是密切联系的。西方自古希腊以来便有一种尚武的传统,当代美国也继承了这一传统,并成为其培养精英的一个重要理念。尚武精神在当代的一个重要表现就是重视体育。而在中国方面,长期以来则是尚文轻武的传统占上风。历史学家雷海宗先生早就提出过一种观点,认为中国是“无兵的文化”。春秋战国的时候,还是贵族在打仗。从那以后,兵的文化就日渐弱化,好男不当兵的观念流传甚广,这与西方的情况大相径庭。

美国战略精英的培养机制

1.耶鲁大学的大战略研究:阅读经典、海外游历与现实关怀

耶鲁大学的大战略研究以历史路径为主。冷战史名家约翰·加迪斯教授和曾撰写过《大国的兴衰》的名教授保罗·肯尼迪,都非常重视通过研究历史来探究战略。他们在耶鲁大学设立的大战略研究项目,大致分为阅读经典、海外旅行和当代重大问题讨论三个板块。学生进入到这个项目后,春季学期被用来大量阅读经典著作,读修昔底德,读孙子,读马基雅维利、伊丽莎白二世、美国的开国元勋、康德、梅特涅、克劳塞维茨、林肯、俾斯麦、威尔逊、丘吉尔、两个罗斯福(西奥多·罗斯福和富兰克林·罗斯福)、列宁、斯大林、毛泽东、凯南、基辛格等人的著作。培养战略精英,不了解过去伟大的思想怎么行?不研究战略思想发展史怎么行?

耶鲁大战略研究班的一次集体讨论,未来的国家决策者们通过辩论与他人交流知识

夏季小学期学生们被安排到海外旅行。耶鲁特别鼓励学生到世界各地去游历,主要不是看那些名胜古迹,而是到那些普通观光者不怎么去的地方,比如说,你可以沿着古代的丝绸之路去看看今日的输油管道;你可以先到圣彼得堡学一个月俄语,然后花两个月时间途经西伯利亚回国;你可以到叙利亚、埃及去学阿拉伯语;你可以去中国那些外国人平常不怎么去的地方,了解一下中国的风土人情。这有点像田野调查。他们希望通过这种海外经历,一方面使学生增加对不同文化、不同国家的了解,另一方面把他们置于一种自己不熟悉的、带有挑战性的环境中去磨练他们的意志,增加他们的自信心。

回来之后,在秋季学期开始时讨论美国所面临的当代重大问题。这时候学生要读亨廷顿、福山、扎卡里亚这些人的著作,然后让他们分组进行辩论,假定自己担任国家公职,肩负着重要的职责,你要指出现在美国所面临的主要问题是什么?美国的国家利益是什么?美国到底要维护什么?美国的最大威胁是什么?然后尽自己最大的努力去说服同学、说服教师来接受你的观点。可以想见,这一年的读万卷书、行万里路的训练,对培育学生的战略素养将是很有帮助的。

2.斯坦福大学国际安全与合作中心:走科学技术与跨学科研究之路

 

美国海军预备役军官团的一次课程,相当于中国的国防生制度,但是历史更悠久,制度更健全

斯坦福大学集中搞战略研究的地方,是国际安全与合作中心。该中心的突出特点是重视科技与战略研究的关系,开展真正的跨学科研究。中心的研究人员分成两大拨儿,一拨儿人是科学家和工程师,包括核物理学家、化学家、生物学家、研究导弹的等等;另一拨儿人则是搞人文社会科学的,包括政治学家、历史学家、法学家、经济学家、社会学家等。这两拨儿人整天在一个屋檐下搞研究。在国家安全问题上,如果要提出一项政策,那么该政策在技术上的可行性如何,将是非常重要的一个问题。而对科学家和工程师们来说,他们在人文社科方面的知识、在政策的敏感性等方面可能就稍微欠缺一些。一项政策的历史变迁、在法律上如何操作、如何将技术上的可能性转化成政策,这些问题,他们不太擅长,因此也就需要由一些搞人文社科的来帮助,来协调。两边一搭伙儿就形成了一个良性循环。

中心的跨学科研究取向也体现在中心的教育功能上。中心为斯坦福大学的本科生开设的课程有“军事技术与国家安全”、“核武器国际史”,以及通过模拟来解决国际危机的课程,走的都是技术与战略研究的结合之路。中心还设立了一个本科生国际安全辅修项目,从斯坦福不同专业但都对国际安全问题感兴趣的本科生中选拔优秀者参加,集中学习一年课程,包括实习和撰写有政策意义的研究论文。另外,中心还设立奖学金,将全美名校中从事国际安全问题研究的有前途的年轻人吸收到中心的博士后和博士前项目中,让他们与中心的研究人员密切互动,从而将研究和教学很好地结合起来。

斯坦福的这套做法,对国内的战略研究来说很有借鉴意义。北大在国内也算是顶尖大学,但在国际问题研究领域几乎看不到类似斯坦福那样真正的跨自然和人文社会科学的研究机构。不同领域的专家很少有机会能坐下来一块儿交流、讨论、合作攻关。北大国际关系学院两年多前成立了一个国际战略研究中心,打算在这个方面做一点努力,但未来的路很长。无论是在观念意识方面还是组织架构方面,中国的跨学科战略研究与美国相比,都还有很大差距。

3.哈佛的战略研究:重决策过程与案例研究

哈佛大学的国际事务研究中心

哈佛的战略研究分好几个单位,一个单位是哈佛国际事务研究中心,“文明冲突论”的提出者亨廷顿曾长期担任这个中心的主任;基辛格出道之前也在这儿。后来在该中心下又成立一个奥林战略研究所。在过去近20年中,奥林国家安全项目通过为美国国家安全领域优秀的年轻学者(包括博士待位人、博士后和高等院校的年轻教员,每年10人左右)提供奖学金的方式,为美国的国际战略研究界培养了很多人才。这些人实际上形成了一个圈子。

哈佛的肯尼迪学院在战略研究领域是后起之秀

目前来看,在哈佛的战略研究中,更为活跃的是设立较晚的肯尼迪政府学院。从1960年代起,在政治学家诺伊斯塔特,外交史学家欧内斯特·梅,以及他们的学生、现任肯尼迪政府学院名誉院长格雷厄姆·艾利森的持续努力下,发展了一条从案例和决策过程入手来研究国际战略的路径。艾利森以古巴导弹危机为例所归纳出的三种决策模式,便是其中最为突出的一个范例。在长期关注决策和案例的基础上,肯尼迪学院开设了各种高级别的战略培训班,与政府部门合作,培养各类战略研究人才。

4.麻省理工学院的安全研究项目:与军方密切合作

麻省理工学院(MIT)的安全研究项目(Security Studies Program,简称SSP项目)在美国大学的安全研究领域中是名列前茅的。该项目的前身是麻省理工学院国际问题研究所,在冷战时期主要做宣传战、心理战和第三世界的政治和经济发展研究,后来研究重点转向军控和苏联军事等领域。MIT是一个以工科为主的学校。给人印象特别深刻的是它跟军方的关系特别密切,好多大实验室的研发依靠的都是军工项目。MIT安全项目的规模在美国大学中大概是数一数二的,为美国培养了不少高水平的战略研究人才。在这里只简单介绍一下它独特的“军事研究员”(military fellow)制度。

所谓军事研究员制度,就是MIT跟美国军方签订协议,接受来自美国陆军、空军、海军和海军陆战队的现役校级军官到SSP项目做一年访问学者。他们可以参加SSP项目的所有课程与活动,一年访问结束后,从其所在军种的院校取得学分。我们知道,军事人员有自己的专业知识,他们到MIT来,可以给这里从事战略问题研究的师生传授很多军事知识,弥补他们知识结构上的欠缺。另一方面,军事研究员们也可以充分利用大学的智力资源,在开阔自己视野的同时,把那些他们在实际工作中遇到的难题提供给专家学者们研究讨论,寻找答案。这对双方都大有好处。搞战略研究的,军事是很重要的一个方面。如果对战役、战术这类东西完全不了解,上来就谈战略,其实是相当困难的。

5.哥伦比亚大学的军事行动与战略分析研讨班

哥伦比亚大学的战略研究与教学也非常重视军事。哥伦比亚大学有个战争与和平研究所,它主办的一个名为“军事行动与战略分析”的暑期研讨班(Summer Workshopon Analysis of Military Operations and Strategy,简称SWAMOS)每年夏季开班,主要讲授和讨论军事及战略问题。暑期班的学员,一部分是研究安全问题的博士生,另一部分是在大学中从事国际安全教学与研究的年轻教员,每期学员大约有20人,时间大概是三个星期左右。研讨班的讲师基本上是全美这个领域中最好的专家,有大学教授,有智库中的研究人员,还有政府部门中的相关人士。讲授的内容包括战略思想、陆海空军的基本知识、军事预算、常规战争、反叛乱战争、核战略等。每天上午上三个小时的课,中间休息15分钟,下午分组讨论两小时,然后是师生自由交流和体育活动,晚上再安排看战争片,看完之后还要讨论各种战略战术和战争伦理问题。去参加研究班之前,已经被要求先完成1000页左右的阅读量,材料寄到家。研讨班开班后,每天要看个七八十页材料。这样三个星期下来,等于上了一门本科生、一门研究生的课程。

哥伦比亚大学的“军事行动与战略分析”暑期研讨班课堂

通过考察上述这几所大学的战略精英培养机制,可以使我们认识到美国在培养自己的战略精英方面是多么地不遗余力而又行之有道。相比之下,中国的精英培养机制却存在着种种不足。许多口号都飘在空中,落不到实处,形不成真正的生产力。最重要的是,人的精气神,无论是在精英层次还是民众层次,都做得远远不如欧美。 (本文来源:网易军事 )

posted @ 2009-12-13 11:10 二胡 阅读(253) | 评论 (0)编辑 收藏

说起Google,可谓无人不知无人不晓。作为世界第一的搜索引擎,其强大的搜索功能,可以让你在瞬间找到你想要的一切。不过对于普通的计算机用户而言,Google是一个强大的搜索引擎;而对于黑客而言,则可能是一款绝佳的黑客工具。正因为google的检索能力强大,黑客可以构造特殊的关键字,使用Google搜索互联网上的相关隐私信息。通过Google,黑客甚至可以在几秒种内黑掉一个网站。这种利用Google搜索相关信息并进行入侵的过程就叫做Google Hack。

搜索也是一门艺术

         在我们平时使用搜索引擎的过程中,通常是将需要搜索的关键字输入搜索引擎,然后就开始了漫长的信息提取过程。其实Google对于搜索的关键字提供了多种语法,合理使用这些语法,将使我们得到的搜索结果更加精确。当然,Google允许用户使用这些语法的目的是为了获得更加精确的结果,但是黑客却可以利用这些语法构造出特殊的关键字,使搜索的结果中绝大部分都是存在漏洞的网站。
下面我们先来看看Google的部分语法:
         intitle:搜索网页标题中包含有特定字符的网页。例如输入“intitle: cbi”,这样网页标题中带有cbi的网页都会被搜索出来。
         inurl:搜索包含有特定字符的URL。例如输入“inurl:cbi”,则可以找到带有cbi字符的URL。
         intext:搜索网页正文内容中的指定字符,例如输入“intext:cbi”。这个语法类似我们平时在某些网站中使用的“文章内容搜索”功能。
         Filetype:搜索指定类型的文件。例如输入“filetype:cbi”,将返回所有以cbi结尾的文件URL。
         Site:找到与指定网站有联系的URL。例如输入“Site:family.chinaok.com”。所有和这个网站有联系的URL都会被显示。
         这些就是Google的常用语法,也是Google Hack的必用语法。虽然这只是Google语法中很小的部分,但是合理使用这些语法将产生意想不到的效果。

语法在Google Hack中的作用

         了解了Google的基本语法后,我们来看一下黑客是如何使用这些语法进行Google Hack的,这些语法在入侵的过程中又会起到怎样的作用呢?
         intitle
         intitle语法通常被用来搜索网站的后台、特殊页面和文件,通过在Google中搜索“intitle:登录”、“intitle:管理”就可以找到很多网站的后台登录页面。此外,intitle语法还可以被用在搜索文件上,例如搜索“intitle:"indexof"etc/shadow”就可以找到Linux中因为配置不合理而泄露出来的用户密码文件。
         inurl
         Google Hack中,inurl发挥的作用的最大,主要可以分为以下两个方面:寻找网站后台登录地址,搜索特殊URL。
         寻找网站后台登录地址:和intitle不同的是,inurl可以指定URL中的关键字,我们都知道网站的后台URL都是类似login.asp、admin.asp为结尾的,那么我们只要以“inurl:login.asp”、“inurl:admin.asp”为关键字进行搜索,同样可以找到很多网站的后台。此外,我们还可以搜索一下网站的数据库地址,以“inurl:data”、“inurl:db”为关键字进行搜索即可。


1.寻找网站的后台登录页面
         搜索特殊URL:通过inurl语法搜索特殊URL,我们可以找到很多网站程序的漏洞,例如最早IIS中的Uncode目录遍历漏洞,我们可以构造“inurl:/winnt/system32/cmd exe?/c+dir”这样的关键字进行搜索,不过目前要搜索到存在这种古董漏洞的网站是比较困难的。再比如前段日子很火的上传漏洞,我们使用““inurl:upload.asp”或“inurl:upload_soft.asp”即可找到很多上传页面,此时再用工具进行木马上传就可以完成入侵。


         intext
         intext的作用是搜索网页中的指定字符,这貌似在Google Hack中没有什么作用,不过在以“intext:to parent directory”为关键字进行搜索后,我们会很惊奇的发现,无数网站的目录暴露在我们眼前。我们可以在其中随意切换目录,浏览文件,就像拥有了一个简单的Webshell。形成这种现象的原因是由于IIS的配置疏忽。同样,中文IIS配置疏忽也可能出现类似的漏洞,我们用“intext:转到父目录”就可以找到很多有漏洞的中文网站。


2.随意浏览网站中的文件
         Filetype
         Filetype的作用是搜索指定文件。假如我们要搜索网站的数据库文件,那么可以以“filetype:mdb”为关键字进行搜索,很快就可以下载到不少网站的数据库文件。当然,Filetype语法的作用不仅于此,在和其他语法配合使用的时候更能显示出其强大作用。
         Site
         黑客使用Site,通常都是做入侵前的信息刺探。Site语法可以显示所有和目标网站有联系的页面,从中或多或少存在一些关于目标网站的资料,这对于黑客而言就是入侵的突破口,是关于目标网站的一份详尽的报告。

语法组合,威力加倍

         虽然上文中介绍的这几个语法能各自完成入侵中的一些步骤,但是只使用一个语法进行入侵,其效率是很低下的。Google Hack的威力在于能将多个语法组合起来,这样就可以快速地找到我们需要的东西。下面我们来模拟黑客是如何使用Google语法组合来入侵一个网站的。


    信息刺探
         黑客想入侵一个网站,通常第一步都是对目标网站进行信息刺探。这时可以使用“Site:目标网站”来获取相关网页,从中提取有用的资料。


3.搜索相关页面
         下载网站的数据库
         搜索“Site:目标网站 Filetype:mdb”就可以寻找目标网站的数据库,其中的Site语法限定搜索范围,Filetype决定搜索目标。用这种方法有一个缺点,就是下载到数据库的成功率较低。在这里我们还可以采用另一种语法组合,前提是目标网站存在IIS配置缺陷,即可以随意浏览站点文件夹,我们搜索“Site:目标网站 intext:to parent directory”来确定其是否存在此漏洞。在确定漏洞存在后,可以使用“Site:目标网站 intext:to parent directory+intext.mdb”进行数据库的搜索。


4.找到网站数据库


    登录后台管理
         下载到数据库后,我们就可以从中找到网站的管理员帐户和密码,并登录网站的后台。对于网站后台的查找,可以使用语法组合“Site:目标网站 intitle:管理”或者“Site:目标网站 inurl:login.asp”进行搜索,当然我们可以在这里进行联想,以不同的字符进行搜索,这样就有很大的概率可以找到网站的后台管理地址。接下去黑客就可以在后台上传Webshll,进一步提升权限,在此不再阐述。


    利用其他漏洞
         如果下载数据库不成功,我们还可以尝试其他的入侵方法。例如寻找上传漏洞,搜索“Site:目标网站 inurl:upload.asp”。此外,我们还可以根据一些程序漏洞的特征,定制出Google Hack的语句。
         Google Hack可以灵活地组合法语,合理的语法组合将使入侵显得易如反掌,再加入自己的搜索字符,Google完全可以成为你独一无二的黑客工具。

合理设置,防范Google Hack
   
5. 合理设置网站
         Google Hack貌似无孔不入,实则无非是利用了我们配置网站时的疏忽。例如上文中搜索“intext:to parent directory”即可找到很多可以浏览目录文件的网站,这都是由于没有设置好网站权限所造成的。在IIS中,设置用户访问网站权限时有一个选项,叫做“目录浏览”,如果你不小心选中了该项,那么其结果就如上文所述,可以让黑客肆意浏览你网站中的文件。
         这种漏洞的防范方法十分简单,在设置用户权限时不要选中“目录浏览”选项即可。


6.不要选中该项
         编写robots.txt文件
         robot.txt是专门针对搜索引擎机器人robot编写的一个纯文本文件。我们可以在这个文件中说明网站中不想被robot访问的部分,这样,我们网站的部分或全部内容就可以不被搜索引擎收录了,或者让搜索引擎只收录指定的内容。因此我们可以利用robots.txt让Google的机器人访问不了我们网站上的重要文件,Google Hack的威胁也就不存在了。


         编写的robots.txt文件内容如下:
User-agent: *
Disallow: /data/
Disallow: /db/


         其中“Disallow”参数后面的是禁止robot收录部分的路径,例如我们要让robot禁止收录网站目录下的“data”文件夹,只需要在Disallow参数后面加上“/data/”即可。如果想增加其他目录,只需按此格式继续添加。文件编写完成后将其上传到网站的根目录,就可以让网站远离Google Hack了

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chaosa/archive/2007/10/16/1828301.aspx

posted @ 2009-12-11 09:41 二胡 阅读(1124) | 评论 (6)编辑 收藏

  这样的错误以前我也犯过,也见过不少人这样的写法!下面我也举个例子:
  

 public void writeFile(File f) {
  String content 
= null;
  
try {
   
byte[] b = new byte[1024];
   FileInputStream in 
= new FileInputStream(f);
   in.read(b);
   content 
= new String(b);
  }
 catch (Exception e) {
   System.out.println(e.getMessage());
  }


  
if (content.indexOf("hello"> -1{
   System.out.println(
"yes");
  }
 else {
   System.out.println(
"no");
  }

 }


 上面是个简单的方法,代码中有个隐藏的bug。我在维护一个系统的时候就遇到类似的代码,实际中类似的BUG隐藏
的更深!在对系统业务和代码不是很很熟悉的情况下,我推荐如下写法:

 1 public void writeFile(File f) {
 2  String content = null;
 3  try {
 4   byte[] b = new byte[1024];
 5   FileInputStream in = new FileInputStream(f);
 6   in.read(b);
 7   content = new String(b);
 8  }
 catch (Exception e) {
 9   content="";
10   //如果异常发生的话,content可能为空
11   //下面对content的操作就有可能发生NullPointerException异常
12   System.out.println(e.getMessage());
13  }

14  //下面操作有可能发生NullPointerException异常
15  if (content.indexOf("hello"> -1{
16   System.out.println("yes");
17  }
 else {
18   System.out.println("no");
19  }

20 }


 一般来说异常处理不推荐直接system.out.println打印出来!
 几条建议:
 如果无法处理某个异常,那就不要捕获它。
  ☆ 如果捕获了一个异常,请不要胡乱处理它。
  ☆ 尽量在靠近异常被抛出的地方捕获异常。
  ☆ 在捕获异常的地方将它记录到日志中,除非您打算将它重新抛出。
  ☆ 按照您的异常处理必须多精细来构造您的方法。
  ☆ 需要用几种类型的异常就用几种,尤其是对于应用程序异常。
  ☆ 把低层次的异常封装成层次较高程序员较容易理解的异常。
  ☆ 尽量输出造成异常的完整数据
  ☆ 尽量捕获具有特定含义的异常:比如SqlException,而不是简单地捕获一个Exception


  希望对大家有帮助!

参考:
http://www.blogjava.net/usherlight/archive/2006/10/23/76782.html

posted @ 2009-12-09 16:59 二胡 阅读(390) | 评论 (0)编辑 收藏

        cookie在web开发中应用的比较多!浏览器默认的接受cookie的,但是如果浏览器禁止了cookie,会出现什么情况了?
        在此我测试了如下系统:gmail,163邮箱,126邮箱,tom邮箱
        我在浏览器禁用cookie的情况下,登陆上述4邮箱!
        Gmail:
        正确输入用户名密码后,系统给出如下提示:
        

    163邮箱:

 正确输入用户名密码后,系统给出如下提示:让我搞不清楚是用户名密码错误还是其它错误!



    126邮箱
    
    正确输入用户名密码后,系统给出如下提示:让我搞不清楚是用户名密码错误还是其它错误!

    
    tom邮箱

    正确输入用户名密码后,系统给出如下提示:居然提示我是"非法请求"

 

        从上面测试中感受到不同的用户体验.对大多数做web开发的人来说,判断浏览器是否支持Cookie并不是什么难事!难的是对细节的处理!
        也许我们与优秀的产品差距最大的是对细节的处理!
        
        附: 我测试用的是IE6.0

posted @ 2009-12-08 15:03 二胡 阅读(1752) | 评论 (4)编辑 收藏

 关于沟通,大家都知道其重要性!但是,在实际工作中有不少人做的不够好,也包括我自己!
 客户提出的问题,原因大概有一下几种!
 一、客户对软件系统不熟悉,把属正常情况的现象误以为是问题
     这时候就需要我们听清楚客户的描述,然后根据客户的描述一步步的确认其操作等!
     确保用户的操作的正确性。
 二、系统的bug
   一般要了解如下情况!
   2.1 who:谁操作系统的时候出问题了!一般记录系统的登陆名
   2.2 when:在什么时候操作出问题了!
   2.3 how:怎么操作的!这个比较重要,一般记录的是操作步骤!
   2.4 contact:客户的联系方式,邮件还是电话等。
   2.4 feedback:给客户的反馈,答复什么时候解决此问题!
   2.5 follow:既跟踪,确保客户已经解决此问题!而不能简单告诉用户怎么做,在此之后最后跟用户确认一下此问题是否解决!
   
   我的感受:听客户的意见,然后确认!反复之!
   
posted @ 2009-12-08 11:01 二胡 阅读(156) | 评论 (0)编辑 收藏

        在Web开发中常用到Cookie,所以有时需要判断客户端浏览器是否禁用Cookie!我看了一个gmail的页面原码!它是这样写的,如下:

var c="jscookietest=valid";
document.cookie=c;
if(document.cookie.indexOf(c)==-1)
location="html/zh-CN/nocookies.html";
//不支持Cookie

原理是:先对Cookie赋值,然后再读取
希望对大家有用!
posted @ 2009-12-07 09:17 二胡 阅读(2246) | 评论 (1)编辑 收藏

     JavaScript中的null和undefined,感觉有点易混淆!把Ecma-262下载下来看了看!摘要如下:

     Undefined Value
The undefined value is a primitive value used when a variable has not been assigned a value.
4.3.10 Undefined Type
The type Undefined has exactly one value, called undefined.
4.3.11 Null Value
The null value is a primitive value that represents the null, empty, or non-existent reference.
4.3.12 Null Type
The type Null has exactly one value, called null.

感兴趣的可以看看如下文章:
http://www.blogjava.net/hulizhong/archive/2009/10/22/299430.html
posted @ 2009-12-05 13:45 二胡 阅读(224) | 评论 (0)编辑 收藏

使用聚集索引  
  聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。  
   
  聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节省成本。  
   
  当索引值唯一时,使用聚集索引查找特定的行也很有效率。例如,使用唯一雇员   ID   列   emp_id   查找特定雇员的最快速的方法,是在   emp_id   列上创建聚集索引或   PRIMARY   KEY   约束  
   
   
  使用非聚集索引  
  非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺序。  
   
  与使用书中索引的方式相似,Microsoft®   SQL   Server™   2000   在搜索数据值时,先对非聚集索引进行搜索,找到数据值在表中的位置,然后从该位置直接检索数据。这使非聚集索引成为精确匹配查询的最佳方法,因为索引包含描述查询所搜索的数据值在表中的精确位置的条目。如果基础表使用聚集索引排序,则该位置为聚集键值;否则,该位置为包含行的文件号、页号和槽号的行   ID   (RID)。例如,对于在   emp_id   列上有非聚集索引的表,如要搜索其雇员   ID   (emp_id),SQL   Server   会在索引中查找这样一个条目,该条目精确列出匹配的   emp_id   列在表中的页和行,然后直接转到该页该行。  

-------------------------------------------------------分割线-------------------------------------------------------
        在工作中遇见了SQL性能问题,最后在同事的帮助下解决了此问题:就是通过建聚集索引的方式解决的!
         原来的SQL中有如下的where语句:
         and  datediff(day, date1,'2009-1-01')<=

     and  datediff(day, date1,'2009-2-03')>=

        在date1建了聚集索引,SQL修改如下:
          and   date1>='2009-1-01'

     and  date1<='2009-2-03' 

         去掉了datediff函数,因为用函数的话就不会用到date1的聚集索引! 在此记录一下,以备后查!
    
posted @ 2009-12-04 15:19 二胡 阅读(158) | 评论 (0)编辑 收藏

     在一些框架中看到了类似这样的写法:+new Date();感觉有些怪,查阅了相关资料和一些网友的帮助.对此用法解释如下,希望对大家有所帮助,不合适的地方请大家指正!
一,对于引用类型对象(我指的是String,Date,Object,Array,Function,Boolean)的+运算符运算过程如下!
    1,首先调用此对象的valueOf方法,得到返回数值A
    2,然后把此数值A转换成数字,得到的是最终数值 

    我的测试如下:
   
function w(s){
      document.writeln("<br/>");
      document.writeln(s);
      document.writeln("<br/>-----------------------------");
      }
   String.prototype.valueOf=function(){return 1;};
   w(+new String("sss"));//输出1
   String.prototype.valueOf=function(){return "a";};
    w(+new String("sss"));//输出NaN
  
  
   Date.prototype.valueOf=function(){return 1;};
   w(+new Date());//输出1
   Date.prototype.valueOf=function(){return "a";};
    w(+new Date());//输出NaN
  
   Object.prototype.valueOf=function(){return 1;};
   w(+{});//输出1
   Object.prototype.valueOf=function(){return "a";};
    w(+{});//输出NaN
  
   Array.prototype.valueOf=function(){return 1;};
   w(+[]);//输出1
   Array.prototype.valueOf=function(){return "a";};
    w(+[]);//输出NaN
  
   var s=function(){};
   Function.prototype.valueOf=function(){return 1;};
   w(+s);//输出1
   Function.prototype.valueOf=function(){return "a";};
    w(+s);//输出NaN
  
   Boolean.prototype.valueOf=function(){return 1;};
   w(+new Boolean());//输出1
   Boolean.prototype.valueOf=function(){return "a";};
   w(+new Boolean());//输出NaN
二,对于基本数据数据类型,其值转换成数字
    w(+5);//输出5
    w(+true);//输出1
    w(+false);//输出0
    w(+"ss");//输出NaN
    w(+"111");//输出111

posted @ 2009-12-04 10:00 二胡 阅读(1138) | 评论 (0)编辑 收藏

    在看gmail页面原码的时候,有类似(new Date).getTime()/(new Image).src的写法.这样的写法与new Date().getTime()有什么不同?这样写有什么好处呢?
不明白,那位知道给说一下!
posted @ 2009-12-03 13:34 二胡 阅读(1136) | 评论 (1)编辑 收藏

      最近领导安排我做手机软件开发(j2me),领一手机专做测试!今天不经意见看了手机的短信收件箱,
短信主要有如下:
  1.1     周立波的"我为财狂"手机视频免费看(可惜俺听不懂上海话)
  1.2     移动的短信回执服务推荐
  1.3     基金推荐(既然你提醒投资有风险了,还买它干啥)
  1.4     航班、机票推荐(哥们一直坐火车)
  1.5     某星级酒店招聘(哥们不是帅哥,不符条件)
  1.6     放高利贷的(听说是驴打滚利)
  1.7     <风声>经典镜头免费看
  1.8     给个卡号让汇钱的(你呀谁啊,我不认识,而且发了2条)

      呵呵,列举一下!博你一笑!
posted @ 2009-12-03 10:56 二胡 阅读(167) | 评论 (0)编辑 收藏

SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT。
对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们
并没有注意,其实这两种方式还是有很多差别的。

SQL Server推荐使用 SET 而不是 SELECT 对变量进行赋值。
当表达式返回一个值并对一个变量进行赋值时,推荐使用 SET 方法。

下表列出 SET 与 SELECT 的区别。请特别注意红色部分。

set select
同时对多个变量同时赋值 不支持 支持
表达式返回多个值时 出错 将返回的最后一个值赋给变量
表达式未返回值 变量被赋null值 变量保持原值

下面以具体示例来说明问题:

create table chinadba1(
userid int ,
addr varchar(128)
)
go
insert into chinadba1(userid,addr) values(1,'addr1')
insert into chinadba1(userid,addr) values(2,'addr2')
insert into chinadba1(userid,addr) values(3,'addr3')
go

表达式返回多个值时,使用 SET 赋值


declare @addr varchar(128)
set @addr = (select addr from chinadba1)
/*
--出错信息为
服务器: 消息 512,级别 16,状态 1,行 2
子查询返回的值多于一个。当子查询跟随在 =、!=、<、<=、>、>= 之后,或子查询用作表达式时,这种情况是不允许的。
*/
go

表达式返回多个值时,使用 SELECT 赋值

declare @addr varchar(128)
select @addr = addr from chinadba1
print @addr --结果集中最后一个 addr 列的值
--结果: addr3
go

表达式未返回值时,使用 SET 赋值

declare @addr varchar(128)
set @addr = '初始值'
set @addr = (select addr from chinadba1 where userid = 4 )
print @addr --null值
go

表达式未返回值时,使用 SELECT 赋值

declare @addr varchar(128)
set @addr = '初始值'
select @addr = addr from chinadba1 where userid = 4
print @addr --保持原值
go

需要注意的是,SELECT 也可以将标量子查询的值赋给变量,如果标量子查询不返回值,则变量被置为 null 值。
此时与 使用 SET 赋值是完全相同的
对标量子查询的概念大家应该都觉得陌生,举个例子就能说明

declare @addr varchar(128)
set @addr = '初始值'
--select addr from chinadba1 where userid = 4 为标量子查询语句
select @addr = (select addr from chinadba1 where userid = 4)
print @addr --null值
go

转自:http://blog.csdn.net/shouyenet1/archive/2008/12/13/3511818.aspx

posted @ 2009-12-02 17:10 二胡 阅读(202) | 评论 (0)编辑 收藏

     十字路口过多了,发现一个小现象!就是在黄灯亮起后,绿灯亮起之前!不少人蜂拥而过,大家都想着快一点到马路对面!就是过马路的过程中,有不少插曲:被自行车碰到了,因马路不平而崴脚了,等等!在人生的道路上也有类似的现象!为了更好的奔向目标,请大家毋忘脚下!
posted @ 2009-12-02 08:54 二胡 阅读(168) | 评论 (0)编辑 收藏

转 http://blog.csdn.net/rjchen/archive/2009/11/19/4835865.aspx

管理下属方面有三个人对我影响比较大。

第一个人是金山前任CEO的雷军先生,他说过一句话我印象很深,他说”什么是执行力,执行力就是Double Check!”

第二个人是阿里巴巴的前COO李琪先生,他有个著名的‘16字真言’,一直被我奉为与下属共同成长的宝典。

 

第三个人是台湾的星云大师,他说过“最高明的管理,就是不管理”,他在《包容的智慧》一书中讲过这样一个故事。

“有一年,台湾陷入经济恐慌,大家为了年终奖金、加薪,游行示威,社会动荡不安。我们佛光山也有退伍老兵在这里服务,我跟他们开玩笑说,你们也拿个小旗子,到我们的门口摇旗,要求加薪。一位老兵说,我们不要。我问为什么?他说:比金钱更宝贵的东西,就是尊重。我们在这里服务,法师们每天见到我们,合掌、点头,跟我们讲老伯早、老伯好,我们在精神上就很富有了。我们不要加薪,我们要人尊重。”

最后,星云大师说这个世界上人与人相处,最好的管理就是尊重他,爱护他,善用他。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/rjchen/archive/2009/11/19/4835865.aspx

posted @ 2009-12-01 17:39 二胡 阅读(169) | 评论 (0)编辑 收藏

     在工作中,有如下需求.通过case的嵌套解决了此问题!特此记录一下!(我用的是sql server 2005)
    
    

在查询的时候,有这样的一个需求
数据库内容如下:
iD  description

1     TableClassA.getName()
2     TableClassB.getName(),exception
3     TableClassC,getName()
4     TableClassD,getName().null

我想查询输入以下结果:
iD  description

1     TableClassA
2     TableClassB
3     TableClassC
4     TableClassD
及查询的结果是.号或,前的内容
SQL如下

select id,
     case
    when (CHARINDEX(',',description)>0) and (CHARINDEX('.',description)>0)
     then --在这个做了判断,如同时包含.和,则判断.和,那个在前
      case 
       when CHARINDEX(',',description)>CHARINDEX('.',description) then left(description,CHARINDEX('.',description)-1)
       when CHARINDEX(',',description)<CHARINDEX('.',description) then left(description,CHARINDEX(',',description)-1)
      end
    when (CHARINDEX(',',description)>0) then left(description,CHARINDEX(',',description)-1)
    when (CHARINDEX('.',description)>0) then left(description,CHARINDEX('.',description)-1)
    else description
   end
   as description
  from  tablename

posted @ 2009-12-01 16:28 二胡 阅读(891) | 评论 (0)编辑 收藏

转 http://blog.csdn.net/g9yuayon/archive/2007/02/23/1512851.aspx

从Jao的Programming Musing 看到的:Babar Kazar 整理了一堆经典论文。Jao强烈建议每个严肃的程序员读每篇论文,说它们都或多或少有意思。粗粗扫了一下,很多论文都没读过。挑了些俺多少知道一点的介绍。


· An axiomatic basis for computer programming C. A. R. Hoare
Tony Hoare名下的公理化语义(Axiomatic Semantics)。著名的Hoare Triples, P{C}Q, 就是从这里来的。论文不长,双列6页。前辈们就是这样的,6页纸就能开宗立派。不像俺,6页纸连介绍部分都写不周全。哪位老大想知道怎么证明程序正确。前置条件,不变条件,后置条件的妙用,可以用这篇论文开牙。
· Communicating Sequential Processes (CSP) C. A. R. Hoare
Hoare, 又见Hoare。其实也正常。牛人之牛,就在于成就深广。链接的文档应该不算论文,而算专著。260页。从1985年推出到现在20多年过去,这本书的引用率在CS历史上排名第三,可见其影响之深。对并发编程有强烈兴趣的老大可以去钻研一把。我没读过。
· Call-by-name, call-by-value, and the lambda calculus Gordon Plotkin
没读过。只见LtU介绍过。Gordon老大这篇论文的要点之一是要想顺利地对程序进行推导,就需要有合适的lambda理论。想深入理解call-by-name,call-by-value,和lambda算子的老大们可以上了。
· Towards a theory of type structure John C. Reynolds
号称经典中的经典。不过也没读过。类型系统一直是编程语言研发的热点,也是非常有趣的方向――类型系统的编程好比让机器证明一系列定理。Reynolds在论文里讨论了什么才是正确的类型结构,和句法正确必须独立于任何具体的类型表达形式,并且给出了带类型的lambda算子的一种扩展,允许他描述用户自定义类型和多态函数。满篇公式,有勇气去读的老大要有心理准备。
· Structured Programming with go to Statements Donald E. Knuth
这篇论文详细结构化编程时讨论了什么时候用goto,什么时候不用goto。高爷爷精细务实的态度非常值得学习。高老太爷用了一辈子goto(MIX和MMIX程序里没了Goto怎么玩儿得转嗫?),岂能轻易被Dijkstra对goto的批评吓退?他仔细探讨了几种不同的程序,考察goto用在那些程序里的利弊。最后得出结论,goto在某些程序里仍然高效实用。虽然论文是30年前的,但里面的分析手法和利用goto的优化技术至今可用。
· Definitional interpreters for higher-order programming languages John C. Reynolds
这篇文章俺喜欢。”Metacircular”这个性感的概念就是在这篇论文里首次提出的。想深入了解用一门语言写出的解释器定义这门语言自身的神奇理念,这篇论文是必读材料。有兴趣的老大可以先读SICP的第四章。
· An APL Machine 1970 Philip S. Abrams
只知道APL是门有历史意义的语言。顺便说一句,APL这个名字太土了。A Programming Language ==APL。象什么话嘛。


· The Anatomy of a Large-Scale Hypertextual Web Search Engine Sergey Brin and Lawrence Page
网络是个大的矩阵(transition probability matrix of Markov Chain)。网页的声誉(page rank)就是这个巨大矩阵的principle eigenvector的某个元素。嗯,反正我只有佩服的份儿。
· No Silver Bullet: Essence and Accidents of Software Engineering Frederic P. Brooks, Jr.
地球银都知道。不用俺多嘴了。
· A Mathematical Theory of Communication Claude Shannon
Bell实验室当年辉煌一时。出了名的叫人做A,结果发明了B。香农老大就是其中杰出代表。香农进了Bell实验室后,居然没人吩咐他干嘛。香农老大转念一想,自己喜欢数学,Bell的生意尽在通讯,干嘛不看看把数学应用到通讯上有什么结果呢?于是1948年这篇论文问世乐。搞通讯的人崩溃乐。现代信息理论就诞生乐。
· Bayesian Networks without Tears
贝叶斯理论热了好几年了。估计还会继续热下去。现在信息越来越多,我们已经审美疲劳。大家渴望的不是信息,而是知识。靠个人的力量把信息提炼成知识太慢,我们需要机器的帮忙。机器学习不热都难,而贝叶斯理论在机器学习里有很好的应用。这篇文章行为浅显,可以轻松读完。对了,那个人人喝骂的微软回形针的智能引擎就是用贝叶斯网络实现的。
· A Universal Algorithm for Sequential Data Compression
没读过。无耻地找个借口:我们系开信息理论课的时候,俺刚好毕业。
· A Relational Model of Data for Large Shared Data Banks 1970 Edgar F. Codd
没有关系代数,人类将会怎样?Codd划时代的论文奠定了现代数据库的基础。嘿嘿,其实俺也没有读过这篇论文。顺便说一句,现在的ORM试图把data schema和对象系统映射起来。问题是,data schema只是对关系的一种表达方式而已,还和具体的系统实现有关。也许把对象间的结构和关系映射起来才是正道。
· Let's Build a Compiler 1988-1995
教你一步一步写出一坨编译器。不算论文吧。一篇相当不错的指南。
· Gauging Similarity via N-Grams: Language-Independent Sorting... Marc Damashek
第一次听说
· Worse Is Better Richard P. Gabriel
网上脍炙人口的文章。很有教育意义。简单说,worse is better包括下面几点:
-- 简单:设计要简单。但如果接口和实现不能两全,追求实现的简单。文章里给出的Unix vs Multics的例子非常有意思。
-- 正确:程序必须在所有可见的方面正确。其它地方,如果简单和正确不能两全,追求简单。
-- 一致性:程序不能太不一致。但为了简单,可以在少数地方不一致。
-- 完备性:程序应该尽可能照顾到重要的地方,但是不能牺牲简洁。
强烈推荐。
· Hints on Programming Language Design C.A.R. Hoare
Hoare对设计语言的经验总结。这些经验至今有效。文章很容易读,读后绝对增长程序设计的功力。
· Why Functional Programming Matters John Hughes
为普通程序员准备的大餐,所以写得通俗。没有公式,也没有拗口的术语。着重展示了Fold和Map的强大抽象能力。不由想到我在大学里修的一门课,编程语言。课是好课,老师是一流老师。课上我们学习了浅显的程序语言理论,重点学习了函数编程(用Common Lisp)和逻辑编程(用Prolog)。这门课彻底改变我对编程的理解,明白了imperative programming和OO programming外还有精彩世界。至今想来都觉得幸运。那门课的作业也很有意思,实现一个驻留内存的数据库,支持关系代数里的常见操作。
· On the Expressive Power of Programming Languages Matthias Felleisen
没读过。待读。
· The Early History Of Smalltalk Alan Kay
还有什么好说的呢?Alan Kay这个名字说明一切。30年前Alan Kay就做出来Smalltalk,现在想来仍然让人惊叹。引一段文章Alan Kay评述Smalltalk的话:In computer terms, Smalltalk is a recursion on the notion of computer itself. Instead of dividing "computer stuff" into things each less strong than the whole--like data structures, procedures, and functions which are the usual paraphernalia of programming languages--each Smalltalk object is a recursion on the entire possibilities of the computer. Thus its semantics are a bit like having thousands and thousands of computer all hooked together by a very fast network. Questions of concrete representation can thus be postponed almost indefinitely because we are mainly concerned that the computers behave appropriately, and are interested in particular strategies only if the results are off or come back too slowly.
· Computer Programming as an Art Donald E. Knuth
高老太爷在1974年图灵奖仪式上的致词。真是顶尖geek的风范啊。高太爷在文章里解释了问什么他的书取名为《编程的艺术》。明显他对人们谈到编程时把科学置于艺术之上很不了然。高爷爷追溯“艺术”的词源,说艺术的本意就是技能,也是技术和技巧两次的起源。从这里开始,他开始讨论艺术和科学的关联,讨论艺术在编程里的表现形式和意义。用他的话说,他作为教育者和作者的毕生目标就是叫人写美妙的程序。读起来让人心潮彭湃的说。
· The next 700 programming languages Peter J. Landin
42年前的论文,影响深远。Peter在论文里描述的函数语言ISWIM(If You See What I Mean)现在没有几个人知道了。但他对lambda算子的推崇和对函数语言的论述影响了后来的函数语言设计。
· Recursive Functions of Symbolic Expressions and their Computation by Machine (Part I) 1960 John McCarthy
47年前提出LISP的那篇著名论文。没读过。动态类型检查,Garbage Collection, 递归函数,S-expression, 程序及数据。。。可谓贡献辉煌。


· FORTH - A Language for Interactive Computing Charles H.Moore
只知道Forth是一门stack oriented的编程语言,影响了后来的一些语言,比如CAT。其它的就不知道了。
· Teach Yourself Programming in Ten Years 2001 Peter Norvig
大牛之所以为大牛,原因之一就是目光深远。这篇文章批评那些《24秒学会C++》之类教材的无稽,讨论了学习编程,从菜鸟变成鲲鹏的方法。中文版已经传得满世界都是,赶快找来看吧。Peter Norvig的网站上还有很多高质量的文章。强烈推荐一读。
· The Definition and Implementation of a Computer Language based on constraints Guy Lewis Steele Jr.
好像是Guy Steels的硕士论文。没读过。
· Growing a Language Guy Lewis Steele Jr.
好文!G老大在OOPSLA 98上的主题演讲。G老大主张应该采取渐进的方式设计一门可以被自由扩展的语言(LISP圈子里的牛人们多半都持这种观点吧?)。这篇演讲稿针对该观点做了精练地论述。说起进化的观点,可以参看另外一篇好文章,SICP作者之一,Jay Sussman的近作。
· Epigrams on Programming Alan J. Perlis
A老大发表的一系列关于编程的格言。幽默而深刻。每读必笑。笑后必哭。嗯嗯嗯,夸张一下。不要当真。
· The Complexity of Theorem Proving Procedures Stephen A. Cook
仙风道骨的库克爷爷的成名作。这篇文章一出,好比有人在加州荒漠里发现第一块狗头金,立刻掀起开发加州的狂潮。计算复杂性理论迅速遍地开花。相比这篇论文开创性的贡献,库克因此得到图灵奖不过小小点缀。NP-Complete在这篇论文里被严格定义。更重要的是,库克证明了第一个NP-Complete的问题,SAT(Boolean Satisfiability Problem)。有了SAT,再加上折磨了无数学生的Polynomial Reducibility,无数的NPC问题就出现乐。。。别看俺在这里唾沫横飞,当年做有关计算理论的证明题还是相当吃力的,没有少熬夜。奇怪的是,某一天我给同学讲解我的解法,NPC的相关定义突然变得清晰起来。当初让我绞尽脑汁的证明竟然变得相当机械。后来知道,给人讲解(包括写作)是非常有效地学习方法。怀着备课的目标读文章,假设自己给别人讲解正在读的文章,有助快速理解所读内容。SAT的证明相当复杂,我反正没有耐心读完。
· Steps Toward Artificial Intelligence Marvin Minsky
AI的奠基论文。不过我没读过。
· The Original 'Lambda Papers' Guy Steele and Gerald Sussman
一系列讲解lambda算子和scheme设计的经典论文。学scheme时读过,对理解scheme的设计理念很有帮助。


· The UNIX Time-Sharing System Dennis Ritchie and Ken Thompson
作者不用介绍了吧?这篇文章里介绍的Unix特性早为人熟知。不过第八部分(VIII Perspective)讨论了作者的设计理念,仍然值得一读。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/g9yuayon/archive/2007/02/23/1512851.aspx

posted @ 2009-11-25 14:53 二胡 阅读(269) | 评论 (0)编辑 收藏

转 http://xiaofengtoo.javaeye.com/blog/149129
利用Eclipse进行重构

重构和单元测试是程序员的两大法宝,他们的作用就像空气和水对于人一样,平凡,不起眼,但是意义深重。预善事,必先利器,本文就介绍怎样在Eclipse中进行重构。

本文介绍了Eclipse支持的重构种类,它们的含义,以及怎样重构。本文同时也可以作为学习重构知识的快速手册。

什么是重构
重构是指在保持程序的全部功能的基础上改变程序结构的过程。重构的类型有很多,如更改类名,改变方法名,或者提取代码到方法中。每一次重构,都要执行一系列的步骤,这些步骤要保证代码和原代码相一致。

为什么重构很重要   
         手工重构时,很容易在代码中引入错误,例如拼写错误或者漏掉了重构的某一步。为了防止引入错误,在每次重构前后,都要执行充分的测试。你可能会好奇重构是否是值得的。
重构的理由很多。你可能想要更新一段代码很烂的程序。或者最初的设计队伍都不在了,现在队伍中每人了解这些程序。为了更新,你必须要重新设计构建程序来满足你的需求。另一个原因是原来的设计无法使你将新的特性添加进去。为了添加进去,你要重构这些代码。第三个原因是一个自动重构的工具可以为你自动生成代码,例如Eclipse中的重构功能。使用重构,你可以在重写尽量少的代码和仍保持软件功能的同时,使代码的逻辑性更好。


测试
在重构时,测试是十分重要的。应为重构改变了代码的结构,你要保证重构后代码的功能没有被改变。手工重构时,一个好的测试套是必须的。使用自动重构工具是,测试也是必要的,但不需要很频繁,应为自动重构工具不会产生手工重构时的那些错误,如拼写错误。
Eclipse中可以使用JUnit方便的为程序创建测试代码,具体方法不在本文描述。


Eclipse中的重构
JDT,Eclipse中的Java插件,能够对Java项目,类,或成员进行多种类型的自动重构。可以采取多种方法快速的为Java项目中的某个元素进行重构。
为某些元素进行重构的前提是你必须选中他们。你可以在多个视图中选择这些元素,像大纲视图或包浏览视图。可以按住Ctrl或Shift键,在视图中选择多个元素。另外一种选择的方法是使该元素的编辑区高亮显示,或者把鼠标定位到源程序文件。在选中希望重构的元素后,可以从重构菜单的下拉项选择重构,也可以从右键单击后弹出菜单中选择重构子菜单。同时,Eclipse还提供了重构的快捷键操作。
某些重构可以应用在任意元素上,有些则只能用在特定类型的元素上,如类或方法。在本文的最后的表格中,列出了重构能够应用的元素类型,以及重构的快捷键。
Eclipse中,所有的重构都能够在正式执行之前预览一下。在重构对话框中点击“预览”按钮,可以查看所有将要被改变的地方。唯一没有预览按钮的的重构是Pull Up,在它的重构向导中,到最后,预览面板总会出现。可以将其中的个别变化反选掉,这样这些改变就不会生效。


撤销和重做
       在重构菜单中有撤销和重做项。他们和编辑菜单中的撤销重做不同。即使重构改变了很多文件,编辑菜单中的撤销重做只会更改当前文件。重构菜单中的撤销和重做则会对一次重构的所有文件进行撤销和重做操作。但是在使用时,它们有一定的限制。
重构后,无论重构改变了文件与否,如果任一个文件被另外改变而且保存了,你就无法撤销或重做这个重构。假如一个文件在重构中被修改了,然后又被编辑了,但是还没有保存,这时就会有错误信息提示,如果你想要撤销或重做该重构,必须撤销未保存的文件。
只要注意到以上的限制条件,你就可以随心所欲的对重构进行撤销或重做。你甚至能够编译,运行你的程序测试一下,然后再撤销该重构,只要你没有改变并保存任何文件。

Eclipse中的重构类型
       如果你看一下Eclipse的重构菜单,可以看到四部分。第一部分是撤销和重做。其他的三部分包含Eclipse提供的三种类型的重构。

       第一种类型的重构改变代码的物理结构,像Rename和Move。第二种是在类层次上改变代码结构,例如Pull Up和Push Down。第三种是改变类内部的代码,像Extract Method和Encapsulate Field。这三部分的重构列表如下。

类型1 物理结构
l         Rename
l         Move
l         Change Method signature
l         Convert Anonymous Class to Nested
l         Convert Member Type to New File

类型2 类层次结构
l         Push Down
l         Push Up
l         Extract Interface
l         Generalize Type (Eclipse 3)
l         User Supertype Where Possible
类型3 类内部结构
l         Inline
l         Extract Method
l         Extract Local Variable
l         Extract Constant
l         Introduce Parameter
l         Introduce Factory
l         Encapsulate Field



Rename:
       Rename用来改变一个Java元素的名字。虽然你可以手工改变Java文件Java元素的名字,但是这样不能自动更新所有引用它们的文件或Java元素。你必须在项目中搜索文件然后手工替换这些引用。很可能你就会漏掉一个或者改错一个。Rename重构会智能的更新所有有此引用的地方。
       有时候,Java元素的名字不是很明了,或者它的功能已经改变了。为了保持代码的可读性,该元素的名字也要更新。使用Rename重构,能够十分快捷的更新元素的名字和所有引用它的地方。
       要为一个Java元素改名,在包浏览视图或大纲视图选中该元素,从重构菜单中选择Rename项,或者使用快捷键Alt+Shift+R。Rename对话框会出现。在这里添入新的名字,选择是否更新该元素的引用。点击预览按钮,会打开预览窗口,在这里,你可以看到那些内容会被改变。点击OK按钮,重构结束。

Move
       Move和Rename很相似。它用来把元素从一个位置移动到另一个位置。它主要用来将类从一个包移动到另一个包。选中要移动的元素,从重构菜单中选择Move,或者使用快捷键,Alt+Shift+V,在弹出窗口中选择要移动的目的地。你仍然可以用预览功能检查一下有什么改变,也可以按OK按钮直接让其生效。


Change Method Signature
       更改方法签名能够改变参数名,参数类型,参数顺序,返回类型,以及方法的可见性。也可以添加,删除参数。
       要执行此重构,选择要重构的方法,选中重构菜单的更改方法签名项,会出现更改方法签名对话框。

在此对话框中选择方法的修饰词,返回类型,参数。参数的添加,修改,移动,删除可以通过右边的按钮控制。当添加新的参数时,会自动赋予默认值。凡是调用此方法的地方都会用此默认值作为参数输入。
       改变方法签名可能在方法中导致问题,如果有问题,当你点击预览或OK时,会被标记出来。
      

Move Members Type to New File
       此重构将嵌套类转为一个单独类。将会创建一个新的Java文件包含此嵌套类。选中要重构的类,在重构菜单上选择Move Member Type to New File项,在弹出的对话框中添入要创建的实例的名字。

      

Push Down
       此重构将算中的方法和成员从父类中移动到它的直接子类中,所有下推的方法都可选作为一个抽象方法留在父类中。下推重构对于重新构建项目设计十分有用。
         选择若干方法或成员,从重构菜单中选择下推项,弹出下推对话框。
        
       在此对话框中,可以分别选择方法或成员,所有选中元素都会移动到当前类的子类中。当点击Add Required按钮时,所有已选择元素所必需的元素也会自动选上,此行为并不能保证所有必须的元素都能自动选中,还是需要人工确认。当有方法被选中时,编辑按钮就会可用,点击编辑按钮,弹出编辑对话框。在其中可以选择为选中方法在当前类中遗留抽象方法,还是在当前类中删除这些方法。双击一天选中的方法,也可以打开编辑对话框。在方法的Action列点击,会出现一个下拉列表,可以在其中选择遗留抽象方法还是在当前类中删除方法。按回车键确认编辑结果。


Pull Up
       上移与下推类似,也是在类之间移动方法和成员。上移将方法或成员从一个类移动到它的一个父类中。选中若干个方法或成员,在重构菜单中选择上移项,上移向导马上会出现。
       在选择目标类多选框中,列出了当前类继承的所有父类。你只能将方法或成员移动到它们其中的一个里面。
       如果在选中方法的Action列,被设置成在目标类中声明抽象方法,那么在目标类的非抽象子类中创建必须的方法选项变为可选。当它选中时,目标类的所有子类,如果它们中没有选中的方法,则会为它们创建选中的方法。
       和在下推中一样,选择多个方法,点击编辑按钮,或者双击一个方法,都会打开编辑成员对话框。其中有两个选项,上移和在目标类中声明抽象方法。上移只是简单的复制方法到到父类中,并提供选择是否在当前类中删除该方法。在目标类中声明抽象方法会在父类中创建一个选中方法的抽象方法,如果父类不是抽象类则置为抽象类,最后选中方法留在当前类中。和在下推中一样,也可以点击Action列,可以在出现的下拉列表中选择。
       如果方法的Action列选为上移,在下一步的向导中,将会要求你选择是否在当前类中删除这些方法,选中的方法会在当前类中被删除。
       在向导的任意一步都可以按完成按钮,结束重构操作,此时按照默认规则进行重构。


Extract Interface
       提炼接口可以从一个存在的类中创建一个接口。你可以选择在接口中包含着个类的那些方法。选中一个类,从重构菜单选择提炼接口项,就可以打开提炼接口对话框。
       这此对话框中添入接口的名字,选择希望包含的方法,在这个列表里面只列出了公共方法。选中改变对类[当前类名]的应用为对接口的引用选择框,将把所有对当前类的引用更新为对此接口的引用。


Generalize Type
       泛化类型重构可以将一个声明对象的类型改变为它的超类,选择变量,参数,对象成员,方法返回类型,然后选择重构菜单的泛化类型项。在打开的泛化类型对话框,选择希望的新类型,然后点击完成按钮,结束重构。


Use Supertype Where Possible
       使用超类会将对一个特定类型的引用改变为对它的超类的引用。选择一个类,选中重构菜单的使用超类项,会打开使用超类对话框。选中希望的超类类型,点击完成按钮完成重构。重构后,instanceof 表达式也会做相应的替换。



Inline
       内联是用代码或值来取代调用方法的地方,静态final对象成员,或局部变量。比如说,如果你内联一个方法调用,这个调用的地方就会被替换为该方法体。要内联一个方法,静态final对象成员,局部变量,选中这些元素,在重构菜单中选择内联项,或者使用快捷键Alt + Ctrl + I。在随后打开的内联对话框,你可以选择是否要内联所有的调用,或者是选择的调用。如果选择所有调用,你还可以选择是否删除声明本身。

Extract Method
       如果方法中含有过多特定的操作,方法太长,或者其中的某段代码被多次使用,这时,可以用提炼方法重构将这部分代码提取到单独的方法中。在Eclipse中应用此重构方便快捷。
       选中要提炼的代码段,从重构菜单中选择提炼方法项,或者使用快捷键Alt + Shift + M。
       在提炼方法对话框中,输入新方法的名字,选择修饰词,选择是否让新方法抛出运行时异常。在底部提供了新方法的预览。


Extract Local Variable
       使用一个变量来代替一个表达式有很多好处。如果表达式在多处被使用,这样能够提高性能,而且也提高了代码的可读性。要把一个表达式提炼为局部变量,选择要提炼的表达式,从重构菜单中选择提炼局部变量项,或者使用快捷键Alt + Shift + L。
       在提炼局部变量对话框中输入新变量的名字,选择是否要替换所有的表达式,是否使此变量为final。在对话框的底部提供变量的预览。
      
Extract Constant
       提炼常量与提炼局部变量很相似,唯一的区别是提炼常量重构可以选择提炼出的常量的修饰词,而且此常量将作为类的成员变量。

Introduce Parameter
       介绍参数重构在方法中创建新的参数,然后用此新参数取代局部变量或者成员变量的实例。要是用此重构,选中方法中一个成员变量或局部变量的引用,然后从重构菜单中选择介绍参数项。


Introduce Factory
       工厂是用来创建新对象,返回新创建对象的方法。你可以选择一个类的构造方法,从重构菜单中选择介绍工厂项,应用此重构,为此类创建工厂方法。
      
在介绍工厂对话框,输入工厂方法的名字和需要工厂方法创建的对象的名字。选择构造方法的修饰词是否为私有。
       点击OK按钮后,在指定的类中会出现此指定工厂方法。此方法创建一个当前类的实例,然后返回此实例。

Convert Local Variable to Field
       转换局部变量为成员变量重构,将方法内的变量声明移动到方法所在类中,使该变量对整个类可见。选择一个局部变量,从重构菜单中选择转换局部变量为成员变量项,随后打开配置的对话框。
      
       在此对话框中,添入成员变量的名字,选择修饰词,选择在哪里实例化此成员变量。随后的声明为静态,声明为final 选择项是否可以使用,取决于实例化位置的选择情况。

Encapsulate Field
       要正确的实践面向对象编程,应该将成员变量的修饰词置为私有,提供相应的访问器来访问这些成员变量。但是这些操作很烦琐。如果使用了封装成员变量重构,则十分方便。选择一个成员变量,从重构菜单中选择封装成员变量项。

       在封装局部变量对话框中,添入Getter, Setter方法的名字,选择新方法在哪个方法后出现。选择合适的修饰词。应用了此重构会创建两个新方法,将此成员变量的修饰词置为私有,将对此成员变量的引用改变为对新方法的引用。

重构项列表:
       下表从Eclipse帮助中提取,列出了各种重构支持的Java资源类型,对应的快捷键。

名字 可应用的Java元素 快捷键
Undo 在一次重构后可执行 Alt + Shift + Z
Redo 在一次撤销重构后可执行 Alt + Shift + Y
Rename 对方法,成员变量,局部变量,方法参数,对象,类,包,源代码目录,工程可用。 Alt + Shift + R
Move 对方法,成员变量,局部变量,方法参数,对象,类,包,源代码目录,工程可用。 Alt + Shift + V
Change Method Signature 对方法可用。 Alt + Shift + C
Convert Anonymous Class to Nested 对匿名内部类可用。  
Move Member Type to New File 对嵌套类可用。  
Push Down 对同一个类中成员变量和方法可用。  
Pull Up 对同一个类中成员变量和方法,嵌套类可用。  
Extract Interface 对类可用。  
Generalize Type 对对象的声明可用。  
Use Supertype Where Possible 对类可用。  
Inline 对方法,静态final类,局部变量可用。 Alt + Shift + I
 
Extract Method 对方法中的一段代码可用。 Alt + Shift + M
 
Extract Local Variable 对选中的与局部变量相关的代码可用。 Alt + Shift + L
 
Extract Constant 对静态final类变量,选中的与静态final类变量相关的代码可用。  
Introduce Parameter 对方法中对成员变量和局部变量的引用可用。  
Introduce Factory 对构造方法可用。  
Convert Local Variable to Field 对局部变量可用。 Alt + Shift + F
Encapsulate Field 对成员变量可用。  


       本文介绍了Eclipse提供的各种重构。这些重构易于使用,可以确保代码重构更加方便安全。而且可以自动生成代码以提高生产率。
       某些重构改变了某些类的结构,但没有改变项目中其他类的结构,如下推,上移重构。这时,就要确保项目中所有对改变元素的引用都要被更新。这也是为什么要有一个好的测试套。同时,你也要更新测试套中的对改变元素的引用。所以说,重构和单元测试的有机结合对于软件开发是多么的重要。
posted @ 2009-11-25 10:49 二胡 阅读(985) | 评论 (0)编辑 收藏

 在jquery-1.3.1.js中发现了如下写法:
 var
 // Will speed up references to window, and allows munging its name.
 window = this,
 // Will speed up references to undefined, and allows munging its name.
 undefined
 
 从上面的注释可以得知:这些写是为了提高性能
 
 查了一下资料,得知这些写为什么能提高性能。
 首先,jquery-1.3.1.js的代码都写在一个匿名函数中,上面的代码就定义2个局部变量:window和undefined;
 window变量被赋值为this(既window对象,感觉有点迷惑人,只不过2个变量名一样而已);局部变量undefined没有
 赋值,但是在js代码预编译的时候会被赋值为window.undefined;这样在匿名函数内部引用window,undefined时候
 直接引用局部变量window,undefined就可以了!不用再向上引用全局变量的window,undefined;

 从本质上说,这里利用了函数的作用域效果;当在函数内部调用window,undefined对象时候,系统会先在本地作用域
 查找,找到就调用;找不到,就到上一级的作用域查找;如此类推;
 
 不合适的地方,请大家指出!
posted @ 2009-11-05 18:19 二胡 阅读(1641) | 评论 (1)编辑 收藏

转 http://www.cnblogs.com/yslow/archive/2009/04/29/1446236.html

耦合异步脚本

英文原文地址

 

最近我的工作都是围绕异步加载外部脚本(loading external scripts asynchronously) 展开。当外部脚本以普通方式加载时(<script src="...">) 会阻塞页面内所有其它资源的下载和脚本下方元素的渲染.你可以查看将脚本放在底部(Put Scripts at the Bottom)的样例的效果. 异步加载脚本会避免阻塞行为进而更快的加载页面.

异步加载脚本产生的问题是内嵌脚本使用外部脚本中定义的符号的问题. 如果内嵌脚本使用了异步加载的外部脚本符号,竞争条件下可能会导致未定义的符号错误。因此有必要保证异步脚本和内嵌脚本以下面方式进行耦合:在异步脚本下载完毕之前内嵌脚本不能被执行。

下面有几种方式耦合异步脚本.

  • window’s onload - 内嵌脚本可以尝试使用窗口的onload事件. 实现起来非常简单,但是内嵌脚本不会尽可能早的执行.
  • script’s onreadystatechange - 内嵌脚本可以尝试使用脚本的onreadystatechangeonload 事件(在所有流行的浏览器里面均需要你自己来实现) 代码比较长而复杂,但是可以确保在脚本下载完毕之后马上执行内嵌脚本.
  • hardcoded callback - 外部脚本可以修改为通过一个回调函数(callback function)来明确的调用内嵌脚本,如果外部脚本和内嵌脚本是一个团队开发的话,这样是没有问题的,但如果使用第3方的脚本,这就提供不了必要的灵活性。

在这个博客帖子里我讨论两个问题: 如何使用异步脚本加快页面,如何通过Degrading Script Tags模式耦合外部脚本和内嵌脚本. 我通过我最近刚刚完成的一个项目UA Profiler results sortable图表来演示. 我还使用了Stuart Langridge的 sorttable排序脚本. 把他的脚本增加到我的页面并排序结果耗费了我大约5分钟.通过增加一点使用异步脚本和耦合脚本的工作量我可以使这个页面提高30%的加载速度

普通Script标记

最初我使用普通的方法(<script src="...">)将Stuart Langridge的sorttable排序脚本加入到UA Profiler, 例子见Normal Script Tag. HTTP瀑布图见图1.

普通Script标记
图1: 普通Script标记的瀑布图

表格排序工作正常,但由于它使页面慢了许多,我并不满意. 图1中我们可以看到脚本(sorttable-async.js)阻塞了页面内唯一的后继HTTP请求(arrow-right- 20X9.gif), 造成页面加载变慢. 瀑布图是使用Firebug 1.3 beta来产生的(你也可以使用httpwatch基调网络webwatch工具来查看效果)。 新版本的Firebug在onload事件发生的地方标记了一条红竖线. (蓝竖线是DOMContentLoaded事件.) 对于普通Script标记 来说, onload 事件在第487毫秒产生.

异步加载脚本

对初始页面渲染来说,脚本sorttable-async.js是没有必要的 - 表格被渲染之后才会排序. 这种情况(外部脚本不会被初始页面使用)是可以使用异步脚本加载的主要特征 . 例子异步加载脚本 使用DOM方式异步加载:

var script = document.createElement('script');
script.src = "sorttable-async.js";
script.text = "sorttable.init()"; // 这会在下面解释
document.getElementsByTagName('head')[0].appendChild(script);

异步加载脚本的HTTP瀑布图见图2。注意我是如何使用异步加载技术来避免阻塞行为的 - sorttable-async.js和arrow-right-20×9.gif 被同时下载. onload时间为429毫秒.

异步加载脚本
图2: 异步加载脚本的HTTP瀑布图

John Resig介绍的 Degrading Script Tags 模式

例子异步加载脚本使页面加载更快了,但仍旧有进一步提高的空间. 默认sorttable排序是通过在onload事件中增加sorttable.init()来触发。当外部脚本被加载完毕后内嵌脚本立即调用sorttable.init()能进一步提升性能. 在这种情况下,我使用的API仅仅是一个函数,但是我将尝试一个足够灵活的模式来支持更复杂的情况。

前面我列出了各种内嵌脚本和外部异步脚本耦合的方法: window’s onload, script’s onreadystatechange, 和 hardcoded callback. 这里,我使用了来自John Resig的被称为Degrading Script Tags模式的技术。 John描述了如何耦合一个内嵌脚本和外部脚本,例如:

<script src="jquery.js">
jQuery("p").addClass("pretty");
</script>

他提到的这个方法是使内联脚本在外部脚本下载完毕之后才开始执行。使用这种方式耦合内嵌脚本和外部脚本有几个好处:

  • 更简单 - 将2个script标记替换为1个script标记
  • 更清晰 - 内嵌代码依赖于外部脚本的关系更为明显
  • 更安全 - 如果外部脚本下载失败,内嵌脚本就不会执行,避免抛出未定义的符号错误

当使用异步加载外部脚本时这也是一个很棒的模式。为了使用这个技术,我必须修改我的内嵌代码和外部脚本. 对于内嵌代码, 我增加了第3行来设置 script.text的属性. 为了耦合代码, 我在sorttable-async.js末尾增加了如下代码:

var scripts = document.getElementsByTagName("script");
var cntr = scripts.length;
while ( cntr ) {
var curScript = scripts[cntr-1];
if ( -1 != curScript.src.indexOf('sorttable-async.js') ) {
eval( curScript.innerHTML );
break;
}
cntr--;
}

此代码遍历网页的所有脚本,直到它找到脚本块本身 (此时脚本的src属性包含sorttable-async.js),然后利用eval将代码(sorttable.init ())增加到脚本触发运行. (备注:虽然内嵌代码使用text属性增加代码内容,但是需要使用innerHTML获取代码. 这是代码跨浏览器工作的必要保证) 经过这样的优化,外部脚本不会阻塞其它资源的下载,同时,内嵌代码也会尽可能早的执行.

延迟加载

通过延迟加载能更快的加载页面 (通过onload事件动态加载). 例如 Lazyload 是在onload 事件中包含如下代码:

window.onload = function() {
var script = document.createElement('script');
script.src = "sorttable-async.js";
script.text = "sorttable.init()";
document.getElementsByTagName('head')[0].appendChild(script);
}

这种情况绝对需要脚本耦合技术,在onload事件里面的代码sorttable.init()不会被执行,因为此时onload事件已经发生,而sorttable-async.js还没被下载。延迟加载的好处是使onload事件更快的发生,见图3。红竖线表明onload事件发生在第320毫秒.

延迟加载
图3: 延迟加载的HTTP瀑布图

结论

通过避免通常的阻塞行为,异步加载脚本和延迟加载脚本可以提高网页的加载时间. 下面是增加不同版本的sorttable排序例子代码:

以上时间指的是onload事件发生的时间。



posted @ 2009-11-04 15:25 二胡 阅读(228) | 评论 (0)编辑 收藏

posted @ 2009-11-03 09:40 二胡 阅读(203) | 评论 (0)编辑 收藏

        在JAVA原代码中可以看到ArrayList类的实现.其中定义ArrayList类的时候,如下

        public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
        
        在这里我有个疑惑,ArrayList继承了AbstractList,而AbstractList实现了List接口.为什么不直接这样写呢,如下:

        public class ArrayList<E> extends AbstractList<E>
            implements RandomAccess, Cloneable, java.io.Serializable

        那个能解释一下!谢谢先!
posted @ 2009-10-27 08:53 二胡 阅读(1886) | 评论 (10)编辑 收藏

转 http://www.playgoogle.com/view.asp?id=58

在JavaScript开发中,被人问到:null与undefined到底有啥区别?
    一时间不好回答,特别是undefined,因为这涉及到undefined的实现原理。于是,细想之后,写下本文,请各位大侠拍砖。
    总所周知:null == undefined
    但是:null !== undefined
    那么这两者到底有啥区别呢?
    请听俺娓娓道来…

null
    这是一个对象,但是为空。因为是对象,所以 typeof null  返回 ‘object’ 。
    null 是 JavaScript 保留关键字。
    null 参与数值运算时其值会自动转换为 0 ,因此,下列表达式计算后会得到正确的数值:
表达式:123 + null 结果值:123
表达式:123 * null 结果值:0

undefined
undefined是全局对象(global)的一个特殊属性,其值是未定义的。但 typeof undefined 返回 ‘undefined’ 。
      虽然undefined是有特殊含义的,但它确实是一个属性,而且是全局对象(window)的属性。请看下面的代码:
    alert(’undefined’ in window);   //输出:true
     var anObj = {};
     alert(’undefined’ in anObj);    //输出:false

从中可以看出,undefined是window对象的一个属性,但却不是anObj对象的一个属性。

注意:
尽管undefined是有特殊含义的属性,但却不是JavaScript的保留关键字。
undefined参与任何数值计算时,其结果一定是NaN。
顺便说一下,NaN是全局对象(global)的另一个特殊属性,Infinity也是。这些特殊属性都不是JavaScript的保留关键字!全局对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。全局对象不是任何对象的属性,所以它没有名称。全局对象只是一个对象,而不是类。既没有构造函数,也无法实例化一个新的全局对象。(感谢sunder同学的留言)

提高undefined性能
当我们在程序中使用undefined值时,实际上使用的是global对象的undefined属性。
同样,当我们定义一个变量但未赋予其初始值,例如:
var aValue;
这时,JavaScript在所谓的预编译时会将其初始值设置为对window.undefined属性的引用,
于是,当我们将一个变量或值与undefined比较时,实际上是与window对象的undefined属性比较。这个比较过程中,JavaScript会搜索window对象名叫’undefined’的属性,然后再比较两个操作数的引用指针是否相同。
由 于window对象的属性值是非常多的,在每一次与undefined的比较中,搜索window对象的undefined属性都会花费时 间。在需要频繁与undefined进行比较的函数中,这可能会是一个性能问题点。因此,在这种情况下,我们可以自行定义一个局部的undefined变 量,来加快对undefined的比较速度。例如:


    function anyFunc()
    {
        var undefined;          //自定义局部undefined变量
        
        if(x == undefined)      //作用域上的引用比较
        
        
        while(y != undefined)   //作用域上的引用比较
        
    };

 

其 中,定义undefined局部变量时,其初始值会是对window.undefined属性值的引用。新定义的局部undefined变 量存在与该函数的作用域上。在随后的比较操作中,JavaScript代码的书写方式没有任何的改变,但比较速度却很快。因为作用域上的变量数量会远远少 于window对象的属性,搜索变量的速度会极大提高。
这就是许多前端JS框架为什么常常要自己定义一个局部undefined变量的原因!



posted @ 2009-10-22 22:14 二胡 阅读(232) | 评论 (0)编辑 收藏

转 http://code.google.com/p/grace/wiki/DojoStyle

前言

相当不错的 Javascript 编程风格规范,建议大家采用此规范编写 Javascript。原文链接: http://dojotoolkit.org/developer/StyleGuide

翻译(Translated by):i.feelinglucky{at}gmail.com from http://www.gracecode.com ,转载请注明出处、作者和翻译者,谢谢配合。

本文地址: http://code.google.com/p/grace/wiki/DojoStyle

Any violation to this guide is allowed if it enhances readability.

所有的代码都要变成可供他人容易阅读的。

快读参考

核心 API 请使用下面的风格:

 

结构 规则 注释
模块 小写 不要使用多重语义(Never multiple words)
骆驼
公有方法 混合 其他的外部调用也可以使用 lower_case(),这样的风格
公有变量 混合
常量 骆驼 或 大写

下面的虽然不是必要的,但建议使用:

 

结构 规则
私有方法 混合,例子:_mixedCase
私有变量 混合,例子:_mixedCase
方法(method)参数 混合,例子:_mixedCase, mixedCase
本地(local)变量 混合,例子:_mixedCase, mixedCase

命名规范

  1. 变量名称 必须为 小写字母。
  2. 类的命名使用骆驼命名规则,例如:
  3. Account, EventHandler
  4. 常量 必须 在对象(类)或者枚举变量的前部声明。枚举变量的命名必须要有实际的意义,并且其成员 必须 使用骆驼命名规则或使用大写:
  5. var NodeTypes = {
       
    Element : 1,
        DOCUMENT
    : 2
    }
  6. 简写单词 不能使用 大写名称作为变量名:
  7. getInnerHtml(), getXml(), XmlDocument
  8. 方法的命令 必须 为动词或者是动词短语:
  9. obj.getSomeValue()
  10. 公有类的命名 必须 使用混合名称(mixedCase)命名。
  11. CSS 变量的命名 必须 使用其对应的相同的公共类变量。
  12. 私有类的变量属性成员 必须 使用混合名称(mixedCase)命名,并前面下下划线(_)。例如:
  13. var MyClass = function(){
       
    var _buffer;
       
    this.doSomething = function(){
       
    };
    }
  14. 变量如果设置为私有,则前面 必须 添加下划线。
  15. this._somePrivateVariable = statement;
  16. 通用的变量 必须 使用与其名字一致的类型名称:
  17. setTopic(topic) // 变量 topic 为 Topic 类型的变量
  18. 所有的变量名 必须 使用英文名称。
  19. 变量如有较广的作用域(large scope),必须使用全局变量;此时可以设计成一个类的成员。相对的如作用域较小或为私有变量则使用简洁的单词命名。
  20. 如果变量有其隐含的返回值,则避免使用其相似的方法:
  21. getHandler(); // 避免使用 getEventHandler()
  22. 公有变量必须清楚的表达其自身的属性,避免字义含糊不清,例如:
  23. MouseEventHandler,而非 MseEvtHdlr
    请再次注意这条规定,这样做得的好处是非常明显的。它能明确的表达表达式所定义的含义。例如:
    dojo.events.mouse.Handler // 而非 dojo.events.mouse.MouseEventHandler
  24. 类/构造函数 可以使用 扩展其基类的名称命名,这样可以正确、迅速的找到其基类的名称:
  25. EventHandler
    UIEventHandler
    MouseEventHandler
    基类可以在明确描述其属性的前提下,缩减其命名:
    MouseEventHandler as opposed to MouseUIEventHandler.

特殊命名规范

  1. 术语 "get/set" 不要和一个字段相连,除非它被定义为私有变量。
  2. 前面加 "is" 的变量名 应该 为布尔值,同理可以为 "has", "can" 或者 "should"。
  3. 术语 "compute" 作为变量名应为已经计算完成的变量。
  4. 术语 "find" 作为变量名应为已经查找完成的变量。
  5. 术语 "initialize" 或者 "init" 作为变量名应为已经实例化(初始化)完成的类或者其他类型的变量。
  6. UI (用户界面)控制变量应在名称后加控制类型,例如: leftComboBox, TopScrollPane。
  7. 复数必须有其公共的名称约定(原文:Plural form MUST be used to name collections)。
  8. 带有 "num" 或者 "count" 开头的变量名约定为数字(对象)。
  9. 重复变量建议使用 "i", "j", "k" (依次类推)等名称的变量。
  10. 补充用语必须使用补充词,例如: get/set, add/remove, create/destroy, start/stop, insert/delete, begin/end, etc.
  11. 能缩写的名称尽量使用缩写。
  12. 避免产生歧义的布尔变量名称,例如:
  13. isNotError, isNotFound 为非法
  14. 错误类建议在变量名称后加上 "Exception" 或者 "Error"。
  15. 方法如果返回一个类,则应该在名称上说明返回什么;如果是一个过程,则应该说明做了什么。

文件

  1. 缩进请使用 4 个空白符的制表位。
  2. 如果您的编辑器支持 文件标签_(file tags),请加添如下的一行使我们的代码更容易阅读:
  3. // vim:ts=4:noet:tw=0:

译注:老外用 VIM 编辑器比较多,此条可以选择遵循。

  1. 代码折叠必须看起来是完成并且是合乎逻辑的:
  2. var someExpression = Expression1
       
    + Expression2
       
    + Expression3;

    var o = someObject.get(
       
    Expression1,
       
    Expression2,
       
    Expression3
    );
    注:表达式的缩进与变量声明应为一致的。
注:函数的参数应采用明确的缩进,缩进规则与其他块保持一致。

变量

  1. 变量必须在声明初始化以后才能使用,即便是 NULL 类型。
  2. 变量不能产生歧义。
  3. 相关的变量集应该放在同一代码块中,非相关的变量集不应该放在同一代码块中。
  4. 变量应该尽量保持最小的生存周期。
  5. 循环/重复变量的规范:
    1. 只有循环控制块的话,则必须使用 FOR 循环。
    2. 循环变量应该在循环开始前就被初始化;如使用 FOR 循环,则使用 FOR 语句初始化循环变量。
    3. "do ... while" 语句是被允许的。
    4. "break" 和 "continue" 语句仍然允许使用(但请注意)。
  6. 条件表达式
    1. 应该尽量避免复杂的条件表达式,如有必要可以使用临时布尔变量。
    2. The nominal case SHOULD be put in the "if" part and the exception in the "else" part of an "if" statement.
    3. 应避免在条件表达式中加入块。
  7. 杂项
    1. 尽量避免幻数(Magic numbers),他们应该使用常量来代替。
    2. 浮点变量必须指明小数点后一位(即使是 0)。
    3. 浮点变量必须指明实部,即使它们为零(使用 0. 开头)。

布局

  1. 普通代码段 应该 看起来如下:
  2. while (!isDone){
            doSomething
    ();
        isDone
    = moreToDo();
    }
  3. IF 语句 应该 看起来像这样:
  4. if (someCondition){
            statements
    ;
    } else if (someOtherCondition){
        statements
    ;
    } else {
        statements
    ;
    }
  5. FOR 语句 应该 看起来像这样:
  6. for (initialization; condition; update){
            statements
    ;
    }
  7. WHILE 语句 应该 看起来像这样:
  8. while (!isDone) {
            doSomething
    ();
        isDone
    = moreToDo();
    }
  9. DO ... WHILE 语句 应该 看起来像这样:
  10. do {
            statements
    ;
    } while (condition);
  11. SWITCH 语句 应该 看起来像这样:
  12. switch (condition) {
    case ABC:
        statements
    ;
       
    //  fallthrough
    case DEF:
        statements
    ;
       
    break;
    default:
            statements
    ;
       
    break;
    }
  13. TRY ... CATCH 语句 应该 看起来像这样:
  14. try {
        statements
    ;
    } catch(ex) {
        statements
    ;
    } finally {
        statements
    ;
    }
  15. 单行的 IF - ELSE,WHILE 或者 FOR 语句也 必须 加入括号,不过他们可以这样写:
  16. if (condition){ statement; }
    while (condition){ statement; }
    for (intialization; condition; update){ statement; }

空白

  1. 操作符 建议 使用空格隔开(包括三元操作符)。
  2. 下面的关键字 避免使用 空白隔开:
  3. 下面的关键字必须使用空白隔开:
  4. 逗号(,) 建议 使用空白隔开。
  5. 冒号(:) 建议 使用空白隔开。
  6. 点(.) 在后部 建议 使用空白隔开。
  7. 点(.) 避免 在前部使用空白。
  8. 函数调用和方法 避免 使用空白,例如: doSomething(someParameter); // 而非 doSomething (someParameter)
  9. 逻辑块 之间使用空行。
  10. 声明 建议 对齐使其更容易阅读。

注释

  1. 生涩的代码就 没有必要 添加注释了,首先您需要 重写 它们。
  2. 所有的注释请使用英文。
  3. 从已解决的方案到未开发的功能,注释 必须 与代码相关。
  4. 大量的变量申明后 必须 跟随一段注释。
  5. 注释需要说明的是代码段的用处,尤其是接下来的代码段。
  6. 注释 没有必要 每行都添加。

文档

下面提供了一些基本的函数或者对象的描述方法:

基本函数信息

function(){
   
// summary: Soon we will have enough treasure to rule all of New Jersey.
   
// description: Or we could just get a new roomate.
   
//          Look, you go find him.  He don't yell at you.
   
//          All I ever try to do is make him smile and sing around
   
//          him and dance around him and he just lays into me.
   
//          He told me to get in the freezer 'cause there was a carnival in there.
   
// returns:  Look, a Bananarama tape!
}

对象函数信息

没有返回值描述

{
   
// summary: Dingle, engage the rainbow machine!
   
// description:
   
//          Tell you what, I wish I was--oh my g--that beam,
   
//          coming up like that, the speed, you might wanna adjust that.
   
//          It really did a number on my back, there. I mean, and I don't
   
//          wanna say whiplash, just yet, cause that's a little too far,
   
//          but, you're insured, right?
}

函数的声明

在有的情况下,对于函数的调用和声明是隐义(invisible)的。在这种情况下,我们没有办法在函数中加入说明等(供程序调用)。如果您遭遇了这种情况,您可以使用一个类来封装函数。

注:此此方法只能在函数没有初始化的参数情况下。如过不是,则它们会被忽略。

dojo.declare(
   
"foo",
   
null,
   
{
       
// summary: Phew, this sure is relaxing, Frylock.
       
// description:
       
//              Thousands of years ago, before the dawn of
       
//              man as we knew him, there was Sir Santa of Claus: an
       
//              ape-like creature making crude and pointless toys out
       
//              of dino-bones, hurling them at chimp-like creatures with
       
//              crinkled hands regardless of how they behaved the
       
//              previous year.
       
// returns: Unless Carl pays tribute to the Elfin Elders in space.
       
}
);

参数

  1. 简单类型
  2. 简单的类型的参数可以直接在函数参数定义中注释说明。
    function(/*String*/ foo, /*int*/ bar)...
  3. 可变类型参数
  4. 下面是几个修饰符供参考:
  5. 全局参数描述
  6. 如果你想增加一个描述,你可以将它们移至初始化块。
基本信息格式为: *关键字* 描述字段 *key* Descriptive sentence
参数和变量的格式为: *关键字* ~*类型*~ 描述字段 *key* ~*type*~ Descriptive sentence
注: *关键字* 和 ~*类型*~ 可以使用任何字母和数字表述。
function (foo, bar) {
   
// foo: String
   
//          used for being the first parameter
   
// bar: int
   
//          used for being the second parameter
}

变量

由于实例变量、原型变量和外部变量的声明是一致的,所以有很多的方法声明、修改变量。具体的如何定义和定位应在变量最先出现的位置指明变量的名称、类型、作用域等信息。

function foo() {
   
// myString: String
   
// times: int
   
//          How many times to print myString
   
// separator: String
   
//          What to print out in between myString*
   
this.myString = "placeholder text";
   
this.times = 5;
}

foo
.prototype.setString = function (myString) {
   
this.myString = myString;
}

foo
.prototype.toString = function() {
   
for(int i = 0; i < this.times; i++) {
        dojo
.debug(this.myString);
        dojo
.debug(foo.separator);
       
}
}
foo
.separator = "=====";

对象中的变量注释

应使用和对象值和方法一致的标注方式,比如在他们声明的时候:

{
   
// key: String
   
//          A simple value
    key
: "value",
   
// key2: String
   
//          Another simple value
}

返回值

因为函数可以同时返回多个不同(类型)的值,所以应每个返回值之后加入返回类型的注释。注释在行内注释即可,如果所有的返回值为同一类型,则指明返回的类型;如为多个不同的返回值,则标注返回类型为"mixed"。

function() {
       
if (arguments.length) {
               
return "You passed argument(s)"; // String
       
} else {
       
return false; // Boolean
   
}
}

伪代码(有待讨论)

有时候您需要在函数或者类中添加对于此函数和类的功能性流程描述。如果您打算这样做,您可以使用 /*======== (= 字符最好出现 5 次或者更多),这样做的好处就是可以不用将这些东西加入代码(译注:原作者的意思可能为代码管理系统)。

这样看起来在 /*===== =====*/ 会有非常长的一段注释,等待功能调整完毕以后就可以考虑是否删除。

/*=====
module.pseudo.kwArgs = {
        // url: String
    //          The location of the file
    url: "",
    // mimeType: String
    //          text/html, text/xml, etc
    mimeType: ""
}
=====*/


function(/*module.pseudo.kwArgs*/ kwArgs){
    dojo
.debug(kwArgs.url);
        dojo
.debug(kwArgs.mimeType);
}
posted @ 2009-10-22 13:40 二胡 阅读(203) | 评论 (0)编辑 收藏