﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-LifeNote -随笔分类-Javascript</title><link>http://www.blogjava.net/lifenote/category/27923.html</link><description>&amp;nbsp;
Try to find something different in your life and then write it down&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;strong&gt;Java乐园：&lt;a href='http://www.java-bj.cn' target='_blank'&gt;&lt;font color='red' size="+1"&gt;www.java-bj.cn&lt;/font&gt;&lt;/a&gt;  资料下载&lt;/strong&gt;
&lt;div style="float:left"&gt;
&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-4636496036365579";
/* 468x60, 创建于 08-4-23 */
google_ad_slot = "3356926921";
google_ad_width = 468;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;
&lt;/div&gt;
&lt;div style="float:left"&gt;
&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-4636496036365579";
/* 468x60, 创建于 08-4-23 */
google_ad_slot = "5017273295";
google_ad_width = 468;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;
&lt;/div&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 24 Apr 2008 07:38:51 GMT</lastBuildDate><pubDate>Thu, 24 Apr 2008 07:38:51 GMT</pubDate><ttl>60</ttl><item><title>Eclipse下的Java反编译插件：Jode Decompiler</title><link>http://www.blogjava.net/lifenote/archive/2008/04/24/195588.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Thu, 24 Apr 2008 07:05:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/04/24/195588.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/195588.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/04/24/195588.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/195588.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/195588.html</trackback:ping><description><![CDATA[这个工具感觉非常方便 介绍给大家<br />
安装方法： <br />
&nbsp;&nbsp;&nbsp;&nbsp;help =&gt; Software Updates =&gt; Find and Install... =&gt; Search for new features to install,单击"New Remote Site..." 在URL栏输入 <a onclick="showLinkBubble(this);return false" href="http://www.technoetic.com/eclipse/update" target="_blank" link="http://www.technoetic.com/eclipse/update">http://www.technoetic.com/eclipse/update</a><wbr>.然后下一步，就可以看到&#8220;jode decompiler plugin *.*&#8221;，选上安装就可以了。 <br />
<br />
安装好后可以看到Window =&gt; Preferences... =&gt; Java =&gt; Jode Decompiler选项卡。 <br />
<br />
配置：Window =&gt; Preferences... =&gt; General =&gt; Editors =&gt; File Associations找到"*.class"在"Associated editors"里面可以看到"Jode class file viewer"选中它再单击Default按钮. <br />
<br />
在Eclipse中展开jar文件,双击class文件即可看到反编译之后的源代码.<br />
<img src ="http://www.blogjava.net/lifenote/aggbug/195588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-04-24 15:05 <a href="http://www.blogjava.net/lifenote/archive/2008/04/24/195588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何获得鼠标的当前位置</title><link>http://www.blogjava.net/lifenote/archive/2008/03/27/189055.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Thu, 27 Mar 2008 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/03/27/189055.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/189055.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/03/27/189055.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/189055.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/189055.html</trackback:ping><description><![CDATA[用window.event对象的属性，总共有四对属性用来取得鼠标位置,分别是： &nbsp; <br />
&nbsp; clientX和clientY &nbsp; &nbsp; &nbsp; &nbsp; screenX和screenY &nbsp; &nbsp; &nbsp; offsetX和offsetY &nbsp; &nbsp; &nbsp; &nbsp; x和y &nbsp; <br />
&nbsp; 一 &nbsp; clientX和clientY &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 设置或接收相对于浏览器窗口客户区的鼠标x、y坐标，客户区不包括窗口滚动条及边框 &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 大小(MSDN原文:Sets &nbsp; or &nbsp; retrieves &nbsp; the &nbsp; x-coordinate/y-coordinate &nbsp; of &nbsp; the &nbsp; mouse &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pointer's &nbsp; position &nbsp; relative &nbsp; to &nbsp; the &nbsp; client &nbsp; area &nbsp; of &nbsp; the &nbsp; window, &nbsp; excluding &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; window &nbsp; decorations &nbsp; and &nbsp; scroll &nbsp; bars.) &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 在IE4里，这一对属性只读不可写，IE5及以后版本里则可读可写(MSDN原文:The &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; property &nbsp; is &nbsp; read-only &nbsp; in &nbsp; Microsoft&amp;reg; &nbsp; Internet &nbsp; Explorer &nbsp; 4.0, &nbsp; and &nbsp; read/write &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; in &nbsp; Microsoft&amp;reg; &nbsp; Internet &nbsp; Explorer &nbsp; 5 &nbsp; and &nbsp; later.) &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 语法: &nbsp; &nbsp; event.clientX=[iPos] &nbsp; &nbsp; event.clientY=[iPos] &nbsp; &nbsp; &nbsp; &nbsp; iPos应该是一个整数 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; 二 &nbsp; screenX和screenY &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 设置或接收相对于用户屏幕的鼠标坐标 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 在IE4里，这一对属性只读不可写，IE5及以后版本里则可读可写 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 语法: &nbsp; &nbsp; event.screenX=[iSize] &nbsp; &nbsp; event.screenY=[iSize] &nbsp; &nbsp; &nbsp; &nbsp; iSize应该是一个整数 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; 三 &nbsp; offsetX和offsetY &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 设置或接收鼠标指针在鼠标所在的元素上的偏移量 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 在IE4里，这一对属性只读不可写，IE5及以后版本里则可读可写 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 语法: &nbsp; &nbsp; event.screenX=[iCoord] &nbsp; &nbsp; event.screenY=[iCoord] &nbsp; &nbsp; &nbsp; iCoord应该是一个整数 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; 四 &nbsp; x和y &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 设置或接收相对于鼠标所在的元素的父元素的坐标(MSDN原文:Sets &nbsp; or &nbsp; retrieves &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; the &nbsp; &nbsp; x-coordinate, &nbsp; in &nbsp; pixels, &nbsp; of &nbsp; the &nbsp; mouse &nbsp; pointer's &nbsp; position &nbsp; relative &nbsp; to &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; the &nbsp; parent &nbsp; element.) &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 在IE4里，这一对属性只读不可写，IE5及以后版本里则可读可写,但IE5以前的版式本里 &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x和y坐标并不相对于鼠标所在的元素的父元素，只相对于浏览器窗口的客户区 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 如果在检测鼠标位置时，鼠标却在浏览器窗口的外面，则x和y都返回-1&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; <br />
<img src ="http://www.blogjava.net/lifenote/aggbug/189055.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-03-27 16:52 <a href="http://www.blogjava.net/lifenote/archive/2008/03/27/189055.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Javascript----文件操作</title><link>http://www.blogjava.net/lifenote/archive/2008/03/25/188417.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Tue, 25 Mar 2008 01:39:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/03/25/188417.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/188417.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/03/25/188417.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/188417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/188417.html</trackback:ping><description><![CDATA[一、功能实现核心：FileSystemObject 对象 <br />
&nbsp;&nbsp;&nbsp;&nbsp;要在javascript中实现文件操作功能，主要就是依靠FileSystemobject对象。<br />
二、FileSystemObject编程 <br />
使用FileSystemObject 对象进行编程很简单，一般要经过如下的步骤： 创建FileSystemObject对象、应用相关方法、访问对象相关属性 。 <br />
（一）创建FileSystemObject对象 <br />
创建FileSystemObject对象的代码只要1行： <br />
var fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
上述代码执行后，fso就成为一个FileSystemObject对象实例。 <br />
（二）应用相关方法 <br />
创建对象实例后，就可以使用对象的相关方法了。比如，使用CreateTextFile方法创建一个文本文件： <br />
var fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
var f1 = fso.createtextfile("c:\\myjstest.txt",true"); <br />
（三）访问对象相关属性 <br />
要访问对象的相关属性，首先要建立指向对象的句柄，这就要通过get系列方法实现：GetDrive负责获取驱动器信息，GetFolder负责获取文件夹信息，GetFile负责获取文件信息。比如，指向下面的代码后，f1就成为指向文件c:\test.txt的句柄： <br />
var fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
var f1 = fso.GetFile("c:\\myjstest.txt"); <br />
然后，使用f1访问对象的相关属性。比如： <br />
var fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
var f1 = fso.GetFile("c:\\myjstest.txt"); <br />
alert("File last modified: " + f1.DateLastModified); <br />
执行上面最后一句后，将显示c:\myjstest.txt的最后修改日期属性值。 <br />
但有一点请注意：对于使用create方法建立的对象，就不必再使用get方法获取对象句柄了，这时直接使用create方法建立的句柄名称就可以： <br />
var fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
var f1 = fso.createtextfile("c:\\myjstest.txt",true"); <br />
alert("File last modified: " + f1.DateLastModified); <br />
三、操作驱动器（Drives） <br />
使用FileSystemObject对象来编程操作驱动器（Drives）和文件夹（Folders）很容易，这就象在Windows文件浏览器中对文件进行交互操作一样，比如：拷贝、移动文件夹，获取文件夹的属性。 <br />
（一）Drives对象属性 <br />
Drive对象负责收集系统中的物理或逻辑驱动器资源内容，它具有如下属性： <br />
l TotalSize：以字节（byte）为单位计算的驱动器大小。 <br />
l AvailableSpace或FreeSpace：以字节（byte）为单位计算的驱动器可用空间。 <br />
l DriveLetter：驱动器字母。 <br />
l DriveType：驱动器类型，取值为：removable（移动介质）、fixed（固定介质）、network（网络资源）、CD-ROM或者RAM盘。 <br />
l SerialNumber：驱动器的系列码。 <br />
l FileSystem：所在驱动器的文件系统类型，取值为FAT、FAT32和NTFS。 <br />
l IsReady：驱动器是否可用。 <br />
l ShareName：共享名称。 <br />
l VolumeName：卷标名称。 <br />
l Path和RootFolder：驱动器的路径或者根目录名称。 <br />
（二）Drive对象操作例程 <br />
下面的例程显示驱动器C的卷标、总容量和可用空间等信息： <br />
var fso, drv, s =""; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
drv = fso.GetDrive(fso.GetDriveName("c:\\")); <br />
s += "Drive C:" + " - "; <br />
s += drv.VolumeName + "\n"; <br />
s += "Total Space: " + drv.TotalSize / 1024; <br />
s += " Kb" + "\n"; <br />
s += "Free Space: " + drv.FreeSpace / 1024; <br />
s += " Kb" + "\n"; <br />
alert(s); <br />
四、操作文件夹（Folders） <br />
涉及到文件夹的操作包括创建、移动、删除以及获取相关属性。 <br />
Folder对象操作例程 :<br />
下面的例程将练习获取父文件夹名称、创建文件夹、删除文件夹、判断是否为根目录等操作： <br />
var fso, fldr, s = ""; <br />
// 创建FileSystemObject对象实例 <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
// 获取Drive 对象 <br />
fldr = fso.GetFolder("c:\\"); <br />
// 显示父目录名称 <br />
alert("Parent folder name is: " + fldr + "\n"); <br />
// 显示所在drive名称 <br />
alert("Contained on drive " + fldr.Drive + "\n"); <br />
// 判断是否为根目录 <br />
if (fldr.IsRootFolder) <br />
alert("This is the root folder."); <br />
else <br />
alert("This folder isn't a root folder."); <br />
alert("\n\n"); <br />
// 创建新文件夹 <br />
fso.CreateFolder ("C:\\Bogus"); <br />
alert("Created folder C:\\Bogus" + "\n"); <br />
// 显示文件夹基础名称，不包含路径名 <br />
alert("Basename = " + fso.GetBaseName("c:\\bogus") + "\n"); <br />
// 删除创建的文件夹 <br />
fso.DeleteFolder ("C:\\Bogus"); <br />
alert("Deleted folder C:\\Bogus" + "\n"); <br />
五、操作文件（Files） <br />
对文件进行的操作要比以上介绍的驱动器（Drive）和文件夹（Folder）操作复杂些，基本上分为以下两个类别：对文件的创建、拷贝、移动、删除操作和对文件内容的创建、添加、删除和读取操作。下面分别详细介绍。 <br />
（一）创建文件 <br />
一共有3种方法可用于创建一个空文本文件，这种文件有时候也叫做文本流（text stream）。 <br />
第一种是使用CreateTextFile方法。代码如下： <br />
var fso, f1; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
f1 = fso.CreateTextFile("c:\\testfile.txt", true); <br />
第二种是使用OpenTextFile方法，并添加上ForWriting属性，ForWriting的值为2。代码如下： <br />
var fso, ts; <br />
var ForWriting= 2; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
ts = fso.OpenTextFile("c:\\test.txt", ForWriting, true); <br />
第三种是使用OpenAsTextStream方法，同样要设置好ForWriting属性。代码如下： <br />
var fso, f1, ts; <br />
var ForWriting = 2; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
fso.CreateTextFile ("c:\\test1.txt"); <br />
f1 = fso.GetFile("c:\\test1.txt"); <br />
ts = f1.OpenAsTextStream(ForWriting, true); <br />
（二）添加数据到文件 <br />
当文件被创建后，一般要按照&#8220;打开文件－&gt;填写数据－&gt;关闭文件&#8221;的步骤实现添加数据到文件的目的。 <br />
打开文件可使用FileSystemObject对象的OpenTextFile方法，或者使用File对象的OpenAsTextStream方法。 <br />
填写数据要使用到TextStream对象的Write、WriteLine或者WriteBlankLines方法。在同是实现写入数据的功能下，这3者的区别在于：Write方法不在写入数据末尾添加新换行符，WriteLine方法要在最后添加一个新换行符，而WriteBlankLines则增加一个或者多个空行。 <br />
关闭文件可使用TextStream对象的Close方法。 <br />
（三）创建文件及添加数据例程 <br />
下面的代码将创建文件、添加数据、关闭文件几个步骤结合起来进行应用： <br />
var fso, tf; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
// 创建新文件 <br />
tf = fso.CreateTextFile("c:\\testfile.txt", true); <br />
// 填写数据，并增加换行符 <br />
tf.WriteLine("Testing 1, 2, 3.") ; <br />
// 增加3个空行 <br />
tf.WriteBlankLines(3) ; <br />
// 填写一行，不带换行符 <br />
tf.Write ("This is a test."); <br />
// 关闭文件 <br />
tf.Close(); <br />
（四）读取文件内容 <br />
从文本文件中读取数据要使用TextStream对象的Read、ReadLine或ReadAll 方法。Read方法用于读取文件中指定数量的字符；ReadLine方法读取一整行，但不包括换行符；ReadAll方法则读取文本文件的整个内容。读取的内容存放于字符串变量中，用于显示、分析。在使用Read或ReadLine方法读取文件内容时，如果要跳过一些部分，就要用到Skip或SkipLine方法。 <br />
下面的代码演示打开文件、填写数据，然后读取数据： <br />
var fso, f1, ts, s; <br />
var ForReading = 1; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
// 创建文件 <br />
f1 = fso.CreateTextFile("c:\\testfile.txt", true); <br />
// 填写一行数据 <br />
f1.WriteLine("Hello World"); <br />
f1.WriteBlankLines(1); <br />
// 关闭文件 <br />
f1.Close(); <br />
// 打开文件 <br />
ts = fso.OpenTextFile("c:\\testfile.txt", ForReading); <br />
// 读取文件一行内容到字符串 <br />
s = ts.ReadLine(); <br />
// 显示字符串信息 <br />
alert("File contents = '" + s + "'"); <br />
// 关闭文件 <br />
ts.Close(); <br />
（五）移动、拷贝和删除文件 <br />
对于以上三种文件操作，javascript各有两种对应的方法：File.Move 或 FileSystemObject.MoveFile用于移动文件；File.Copy 或 FileSystemObject.CopyFile用于拷贝文件；File.Delete 或 FileSystemObject.DeleteFile用于删除文件。 <br />
下面的代码演示在驱动器C的根目录下创建一个文本文件，填写一些内容，然后将文件移动到\tmp目录下，再在目录\temp下面建立一个文件拷贝，最后删除这两个目录的文件： <br />
var fso, f1, f2, s; <br />
fso = new ActiveXObject("Scripting.FileSystemObject"); <br />
f1 = fso.CreateTextFile("c:\\testfile.txt", true); <br />
// 写一行 <br />
f1.Write("This is a test."); <br />
// 关闭文件 <br />
f1.Close(); <br />
// 获取C:\根目录下的文件句柄 <br />
f2 = fso.GetFile("c:\\testfile.txt"); <br />
// 移动文件到\tmp目录下 <br />
f2.Move ("c:\\tmp\\testfile.txt"); <br />
// 拷贝文件到\temp目录下 <br />
f2.Copy ("c:\\temp\\testfile.txt"); <br />
// 获取文件句柄 <br />
f2 = fso.GetFile("c:\\tmp\\testfile.txt"); <br />
f3 = fso.GetFile("c:\\temp\\testfile.txt"); <br />
// 删除文件 <br />
f2.Delete(); <br />
f3.Delete(); <br />
六、结 语 <br />
通过以上对FileSystemObject的各种对象、属性和方法的介绍和示例，相信你已经对如何使用javascript语言在页面中操作驱动器、文件和文件夹有了清晰的认识。但是上述提及的例程都非常简单，要全面、灵活地掌握javascript文件操作技术，还需要大量的实践练习。而且还有一点提醒大家，由于涉及到在浏览器中进行文件读写这样的高级操作，对于默认的浏览器安全级别而言，在代码运行前都会有一个信息提示，这点请在实际环境中提示访问者注意。
<img src ="http://www.blogjava.net/lifenote/aggbug/188417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-03-25 09:39 <a href="http://www.blogjava.net/lifenote/archive/2008/03/25/188417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入理解Tapestry的Rewind</title><link>http://www.blogjava.net/lifenote/archive/2008/03/08/184695.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Sat, 08 Mar 2008 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/03/08/184695.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/184695.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/03/08/184695.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/184695.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/184695.html</trackback:ping><description><![CDATA[Tapestry的rewind一直是学习和使用Tapestry的难点，rewind是用来处理表单提交的，表单默认使用的是DirectService来提交。在详细介绍之前，先说明下此文中需要用到的一些概念，首先是表单组件，我这里指的是指继承自AbstractFormComponent类的组件，例如：TextField、TextArea、Checkbox等，而不是具体的Form组件，表单组件使用时必须在Form组件中，这些组件在rewind时调用继承自AbstractFormComponent的rewindFormComponent来读取数据，并将数据赋值给容器或者页面。 <br />
我们来看一下最简单的TextField组件，组件定义如下 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/article/41724#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;input&nbsp;&nbsp;jwcid=</span><span class="string">"price@TextField"</span><span>&nbsp;type=</span><span class="string">"text"</span><span>&nbsp;value=</span><span class="string">"ognl:picture.price"</span><span>&nbsp;&nbsp;translator=</span><span class="string">"translator:number,pattern=##.##"</span><span>&nbsp;&nbsp;validators=</span><span class="string">"validators:min=0"</span><span>&nbsp;displayName=</span><span class="string">"价格"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"input_text"</span><span>/&gt;&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;input  jwcid="price@TextField" type="text" value="ognl:picture.price"  translator="translator:number,pattern=##.##"  validators="validators:min=0" displayName="价格" class="input_text"/&gt;</pre>
<br />
再看一下TextField中的rewindFormComponent组件方法 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/article/41724#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;rewindFormComponent(IMarkupWriter&nbsp;writer,&nbsp;IRequestCycle&nbsp;cycle)&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//从请求中得到参数值 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;=&nbsp;cycle.getParameter(getName()); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//用translator来转换值 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;object&nbsp;=&nbsp;getTranslatedFieldSupport().parse(</span><span class="keyword">this</span><span>,&nbsp;value); &nbsp;&nbsp;</span></span>
    <li><span class="comment">//用validators来验证值 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getValidatableFieldSupport().validate(</span><span class="keyword">this</span><span>,&nbsp;writer,&nbsp;cycle,&nbsp;object); &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//赋值给容器或者页面 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setValue(object); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(ValidatorException&nbsp;e)&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getForm().getDelegate().record(e); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) {
//从请求中得到参数值
String value = cycle.getParameter(getName());
try {
//用translator来转换值
Object object = getTranslatedFieldSupport().parse(this, value);
//用validators来验证值
getValidatableFieldSupport().validate(this, writer, cycle, object);
//赋值给容器或者页面
setValue(object);
} catch (ValidatorException e) {
getForm().getDelegate().record(e);
}
}</pre>
<br />
可以看到在rewindFormComponent中，主要是从请求中取得用户输入的值，然后进行处理，最后赋值给容器或者页面，上面的例子中会调用页面类的getPicture().setPrice(&#8220;用户输入的值&#8221;)来进行赋值。这样整个表单的提交就可以理解为所有的表单组件读取用户输入的值并赋值给页面的过程。 <br />
整个表单提交的详细处理过程如下： <br />
<ul>* initialize():页面初始化 <br />
    * pageBeginRender() ("rewind"):getRequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>()为true <br />
    * rewind of the form / setting of properties:所有表单组件调用rewindFormComponent来取值赋值 <br />
    * Deferred listeners (for Submit components):调用Submit组件的listener <br />
    * Form's listener：调用Form组件的listener <br />
    * pageEndRender() ("rewind"): getRequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>()为true <br />
    * pageBeginRender() (normal): getRequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>()为false <br />
    * pageEndRender() (normal): getRequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>()为false</ul>
    我们可以看到pageBeginRender和pageEndRender被调用了两次，两次中的区别为RequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>，因为我们在使用时经常利用pageBeginRender的初始化值，所以这里有很多使用上的误区，如果在pageBeginRender中从数据库读取数据来初始化跟表单提交无关的变量的话，就可能被调用两次，这个是应该避免的。什么叫跟表单提交无关的变量呢，就是表单组件中跟赋值无关的，例如上边提到的value="ognl:picture.price",这时picture就是与表单提交相关的变量，如果你没有初始化，那么在赋值时调用getPicture().setPrice()就会出现空指针异常，因为这是的picture为null。我们举个例子来看一下表单无关的变量，假如这个picture页面会显示一个创建picture的表单和所有picture的列表，那这个picture的列表就是与表单提交无关的变量，如果你在pageBeginRender中初始化的话，就需要区分是否rewind，否则表单提交时就会被初始化两次，让我们看一下代码： <br />
    <div class="dp-highlighter">
    <div class="bar">
    <div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/article/41724#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
    </div>
    <ol class="dp-j">
        <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">abstract</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setPictures(List&lt;Picture&gt;&nbsp;pictures); &nbsp;&nbsp;</span></span>
        <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">abstract</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setPictureInList();</span><span class="comment">//用于For中的value </span><span>&nbsp;&nbsp;</span></span>
        <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">abstract</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setPicture(Picture&nbsp;picture);</span><span class="comment">//用于表单创建 </span><span>&nbsp;&nbsp;</span></span>
        <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">abstract</span><span>&nbsp;Picture&nbsp;getPicture(); &nbsp;&nbsp;</span></span>
        <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;pageBeginRender(PageEvent&nbsp;event)&nbsp;{ &nbsp;&nbsp;</span></span>
        <li><span class="keyword">if</span><span>(getPicture()==</span><span class="keyword">null</span><span>){ &nbsp;&nbsp;</span></span>
        <li><span>setPicture(</span><span class="keyword">new</span><span>&nbsp;Picture()); &nbsp;&nbsp;</span></span>
        <li><span>} &nbsp;&nbsp;</span>
        <li><span>setPictures(getPictureService().findAll()); &nbsp;&nbsp;</span>
        <li><span>}&nbsp;&nbsp;</span> </li>
    </ol>
    </div>
    <pre class="java" style="display: none" name="code">public abstract void setPictures(List&lt;Picture&gt; pictures);
    public abstract void setPictureInList();//用于For中的value
    public abstract void setPicture(Picture picture);//用于表单创建
    public abstract Picture getPicture();
    public void pageBeginRender(PageEvent event) {
    if(getPicture()==null){
    setPicture(new Picture());
    }
    setPictures(getPictureService().findAll());
    }</pre>
    判断picture是否为null并赋值在页面显示和rewind中都是需要的，因为页面显示时，需要调用getPicture().getPrice(),页面rewind时，需要调用getPicture().setPrice(),这两个阶段中的picture都不能为null。但setPictures会在表单提交时被调用两次，在rewind阶段初始化它是没有用处的，所以这时就要对是否rewind进行判断。修改后的代码如下： <br />
    <div class="dp-highlighter">
    <div class="bar">
    <div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/article/41724#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
    </div>
    <ol class="dp-j">
        <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;pageBeginRender(PageEvent&nbsp;event)&nbsp;{ &nbsp;&nbsp;</span></span>
        <li><span class="keyword">if</span><span>(getPicture()==</span><span class="keyword">null</span><span>){ &nbsp;&nbsp;</span></span>
        <li><span>setPicture(</span><span class="keyword">new</span><span>&nbsp;Picture()); &nbsp;&nbsp;</span></span>
        <li><span>} &nbsp;&nbsp;</span>
        <li><span class="keyword">if</span><span>&nbsp;(!event.getRequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>())&nbsp;{ &nbsp;&nbsp;</span></span>
        <li><span>setPictures(getPictureService().findAll()); &nbsp;&nbsp;</span>
        <li><span>} &nbsp;&nbsp;</span>
        <li><span>}&nbsp;&nbsp;</span> </li>
    </ol>
    </div>
    <pre class="java" style="display: none" name="code">public void pageBeginRender(PageEvent event) {
    if(getPicture()==null){
    setPicture(new Picture());
    }
    if (!event.getRequestCycle().<span class="hilite1"><span class="hilite1">isRewinding</span></span>()) {
    setPictures(getPictureService().findAll());
    }
    }</pre>
    这样就可以避免在rewind时对pictures进行不必要的赋值。这里还要提到的一点是页面显示和提交后的页面很可能不是同一个页面类的实例，大家都知道页面类的实例是从实例池取到的，用户打开页面显示表单完后的页面类实例和用户提交表单时的用来rewind的页面类实例不一定是同一个，即使是一个实例，也是被重新初始化过的，不要想当然的认为显示表单后再提交那个实例应该保存原来显示的东西，这个应该理清楚。 <br />
    <br />
    原文地址：http://www.javaeye.com/article/41724
<img src ="http://www.blogjava.net/lifenote/aggbug/184695.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-03-08 16:03 <a href="http://www.blogjava.net/lifenote/archive/2008/03/08/184695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSF中文输入乱码问题解决方法</title><link>http://www.blogjava.net/lifenote/archive/2008/01/31/178680.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Thu, 31 Jan 2008 07:05:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/01/31/178680.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/178680.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/01/31/178680.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/178680.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/178680.html</trackback:ping><description><![CDATA[<p class="content">该方法已知适用的版本tomact5.0.18,tomcat5.0.9。<br />
已知不适用的版本为tomcat5.0.28。<br />
问题描述：<br />
在inputtext中输入中文，然后在输出，显示为乱码。<br />
解决方法：<br />
1、自定义转器<br />
package util;<br />
import java.util.Map;<br />
import javax.faces.component.UIComponent;<br />
import javax.faces.convert.Converter;<br />
import javax.faces.context.FacesContext;<br />
import javax.faces.convert.ConverterException; </p>
<p class="content">public class StringConverter implements Converter {<br />
&nbsp;public Object getAsObject(FacesContext context, UIComponent component,<br />
&nbsp;&nbsp;&nbsp;String newValues) throws ConverterException {<br />
&nbsp;&nbsp;String newstr = "";<br />
&nbsp;&nbsp;if (newValues == null) {<br />
&nbsp;&nbsp;&nbsp;newValues = "";<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;byte[] byte1 = null;<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;byte1 = newValues.getBytes("ISO-8859-1");<br />
&nbsp;&nbsp;&nbsp;newstr = new String(byte1, "GB2312");<br />
&nbsp;&nbsp;&nbsp;UIInput input=(UIInput)component;//<br />
&nbsp;&nbsp;&nbsp;input.setSubmittedValue(newstr);<br />
&nbsp;&nbsp;} catch (UnsupportedEncodingException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}</p>
<p class="content">&nbsp;&nbsp;return newstr;</p>
<p class="content">&nbsp;}</p>
<p class="content">&nbsp;public String getAsString(FacesContext context, UIComponent component,<br />
&nbsp;&nbsp;&nbsp;Object Values) throws ConverterException {&nbsp;<br />
&nbsp;&nbsp;return (String) Values;<br />
&nbsp;}<br />
}</p>
<p class="content">2、注册转换器<br />
faces-config.xml片段<br />
&lt;converter&gt;<br />
&nbsp; &lt;converter-id&gt;util.stringconverter&lt;/converter-id&gt;<br />
&nbsp; &lt;converter-class&gt;util.StringConverter&lt;/converter-class&gt;<br />
&lt;/converter&gt;</p>
<p class="content">3、在页面使用转换器<br />
&lt;h:inputText id="account" value="#{util.account}" required="true" styleClass="input" &gt;&nbsp;<br />
&nbsp;&lt;f:converter converterId="utilstringconverter"/&gt;</p>
<img src ="http://www.blogjava.net/lifenote/aggbug/178680.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-01-31 15:05 <a href="http://www.blogjava.net/lifenote/archive/2008/01/31/178680.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat,Weblogic 等服务器  SSL 安全登陆的例子---附证书文件生成器</title><link>http://www.blogjava.net/lifenote/archive/2008/01/15/175432.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Tue, 15 Jan 2008 04:32:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/01/15/175432.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/175432.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/01/15/175432.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/175432.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/175432.html</trackback:ping><description><![CDATA[<p>公司今天一个登陆的地方要修改，需要加一个SSL安全登陆,于是查些资料并总结如下，希望对有用的着的朋友有帮助<br />
文件打包地址：http://www.blogjava.net/Files/lifenote/tomcat配置ssl.rar<br />
一下为帮助说明：<br />
<br />
1.1.&nbsp;安全登录 SSL<br />
1.1.1&nbsp;&nbsp;WebLogic下面SSL配置：<br />
1．生成 keystoreFile：<br />
&nbsp;* keystoreFile 文件的生成：<br />
%Java_Home%\bin\keytool -genkey -alias localhost-weblogic -keyalg RSA -validity 365 -keystore ./testKey.jks</p>
<p>&nbsp;* csr 文件的生成：<br />
%Java_Home%\bin\keytool -certreq -alias localhost-weblogic -sigalg MD5withRSA -file ./testServer.csr -keystore ./testKey.jks</p>
<p>&nbsp;* 注意： http 的默认端口是80，https 的默认端口是433，ftp 的默认端口是21。<br />
2．部署keystore 文件<br />
在 &lt;http://hostname:7001/console&gt;&nbsp; 中配置刚才生成的 testKey.jks 文件。</p>
<p>1.1.2&nbsp;Tomcat 下面SSL配置</p>
<p><br />
1．生成 keystoreFile：<br />
&nbsp;* keystoreFile 文件的生成：<br />
%Java_Home%\bin\keytool -genkey -alias localhost-weblogic -keyalg RSA -validity 365 -keystore ./testKey.jks</p>
<p>Example for inner test：<br />
[root@localhost ~]# <br />
/home/tomcat/jdk1.5.0_12/bin/keytool -genkey -alias localhost-tomcat -keyalg RSA -validity 365 -keystore /home/tomcat/apache-tomcat-5.5.23/conf/VCMarketKey.jks<br />
Enter keystore password:&nbsp; someday2007<br />
What is your first and last name?<br />
&nbsp; [Unknown]:&nbsp; lifenote<br />
What is the name of your organizational unit?<br />
&nbsp; [Unknown]:&nbsp; Java<br />
What is the name of your organization?<br />
&nbsp; [Unknown]:&nbsp; Sunxc<br />
What is the name of your City or Locality?<br />
&nbsp; [Unknown]:&nbsp; Beijing<br />
What is the name of your State or Province?<br />
&nbsp; [Unknown]:&nbsp; Beijing<br />
What is the two-letter country code for this unit?<br />
&nbsp; [Unknown]:&nbsp; ZH<br />
Is CN=lifenote, OU=Java, O=Sunxc, L=Beijing, ST=Beijing, C=ZH correct?<br />
&nbsp; [no]:&nbsp; y</p>
<p>Enter key password for &lt;localhost-tomcat&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (RETURN if same as keystore password):&nbsp; someday2007<br />
[root@localhost ~]#</p>
<p>&nbsp;</p>
<p>&nbsp;* csr 文件的生成：<br />
%Java_Home%\bin\keytool -certreq -alias localhost-weblogic -sigalg MD5withRSA -file ./testServer.csr -keystore ./testKey.jks</p>
<p>&nbsp;* 注意： http 的默认端口是80，https 的默认端口是433，ftp 的默认端口是21。</p>
<p><br />
2．部署keystore 文件<br />
&nbsp; 打开 server.xml 文件，修改内容如下：<br />
&nbsp;<br />
&nbsp;* 只需去掉 server.xml 中对SSL定义的注释，在加上 keystoreFile、keystorePass 这两个属性即可。<br />
&nbsp; &lt;Service<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="Catalina"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;Connector<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; port="8080"<br />
&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp; &lt;/Connector&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&lt;!-- Define a SSL HTTP/1.1 Connector on port 8443 --------------------- 要加入的内容在这里 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;Connector port="8443" maxHttpHeaderSize="8192"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" disableUploadTimeout="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100" scheme="https" secure="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystoreFile="e:/temp_E/ssl/testKey.jks" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="aaaaaa"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;Connector<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; port="8009"<br />
&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp; &lt;/Connector&gt;<br />
&nbsp;...<br />
Example for inner test：<br />
&nbsp;&nbsp;&nbsp; &lt;Connector port="443" maxHttpHeaderSize="8192"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" disableUploadTimeout="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100" scheme="https" secure="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystoreFile="/home/tomcat/apache-tomcat-5.5.23/conf/VCMarketKey.jks"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="password"/&gt;</p>
<p><br />
&nbsp;注意需默认要使用 443 而不是 8443，要使用8443要在apache中配置，保证从apache请求tomcat 采用 &lt;https://ip:8443/&gt;... 的格式。</p>
<p><br />
1.1.3&nbsp;使用http访问WebService s的客户端配置<br />
Servlet服务器配置好SSL之后，客户端可以使用https访问了。<br />
对于用户使用浏览器访问https的方式，浏览器会弹出安装证书的对话框，确认之后可以正常使用https访问。<br />
&nbsp;对于WebService 通过https方式访问，按照一下步骤：<br />
1．&nbsp;WebService客户端要先取得keyStore文件；<br />
2．&nbsp;虚拟机系统使用 System.setProperties(&#8230;) 设置keyStore信息；<br />
3．&nbsp;使用 url=&lt;https://ip:port/...&gt; 访问WebService服务</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/lifenote/aggbug/175432.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-01-15 12:32 <a href="http://www.blogjava.net/lifenote/archive/2008/01/15/175432.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Prototype 1.4.0 源码解读----全文注释版</title><link>http://www.blogjava.net/lifenote/archive/2008/01/11/174600.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Fri, 11 Jan 2008 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2008/01/11/174600.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/174600.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2008/01/11/174600.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/174600.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/174600.html</trackback:ping><description><![CDATA[<p>dae739ba<br />
AJAX之旅：由prototype_1.4<br />
还是决定冠上ajax的头衔，毕竟很多人会用这个关键词搜索。虽然我认为这只是个炒作的概念，不过不得不承认ajax叫起来要方便多了。所以ajax的意思我就不详细解释了。<br />
写这个教程的起因很简单：经过一段时间的ajax学习，有一些体会，并且越发认识到ajax技术的强大，所以决定记录下来，顺便也是对自己思路的整理。有关这个教程的后续，请关注<a href="http://www.x2design.net/">http://www.x2design.net</a><br />
前几年，javascript在一般人眼里，功能还很狭窄，所能做的要么是一些简单的表单验证，要么是许多华而不实的网页特效。随着flash的出现，大家已经不像以前那样热衷于js特效。似乎js能做的事情更加少了。但这时候，ajax的概念冒了出来，以gmail为典型代表的ajax应用受到很多人的关注，ajax一下子成为一种很热门的技术，当javascript和xml，和dom模型结合起来，其所能做的事情常常令人匪夷所思，甚至有些功能已经可以和桌面程序相当。<br />
好了废话就不多说了，现在就从一个javascript的开发框架prototype_1.3.1（下面简称为prototype）开始。我本来是想先介绍一下javascript的高级应用，但怕水平不够，说的没有条理，所以就结合prototype来说，顺便会提及js的语法使用。dae739ba<br />
下面是框架最前面的两段代码：<br />
var Prototype = {<br />
&nbsp; Version: '1.3.1',<br />
&nbsp; emptyFunction: function() {}<br />
}<br />
var Class = {<br />
&nbsp; create: function() {<br />
&nbsp;&nbsp;&nbsp; return function() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.initialize.apply(this, arguments);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
}<br />
首先，让我们来看下面两个语法的区别：<br />
var o={};<br />
var f=function(){};</p>
<p>后面一个很容易理解，它等价于function f(){};定义一个函数f。但前面一个就不常见了：这其实是创建一个对象，在{}中可以指定对象的成员，比如上面的Prototype，就是一个对象，有两个成员，第一个是版本号，第二个是一个空方法（函数）。像这种不用定义类，就能直接创建对象的功能可能只有js能做到。后面一种语法其实还有一个功能，就是定义一个类f。如果你在函数体中用了this，那么this后面的变量就是类的成员。<br />
不仅this可以定义类成员，还有一种语法：<br />
function c(){<br />
&nbsp;member1:value,<br />
&nbsp;member2:function(){}<br />
}</p>
<p>这等价于:<br />
function c(){<br />
&nbsp;this.member1=value;<br />
&nbsp;this.member2=function(){};<br />
}</p>
<p>需要注意的是，用前一种办法时，最后一个成员的最后不能加逗号，我想这种语法应该和数组有关。<br />
在js里，函数和类是没有区别的，都可以new，new的作用是把函数体的语句都执行一遍，然后返回一个对象。如果函数里有this，那么this后面的变量会作为对象成员；如果没有，那么new的作用只是返回一个没有任何成员的空对象。所以你用typeof查看一个所谓类的类型时，仍然会返回function。在js里也基本没有类型的概念，所有变量的声明都用var，即使是函数，也是如此。函数，其实也只是一个变量。<br />
说函数是变量，可能很多人不解。但是你试试下面的做法：<br />
function fTest(){<br />
&nbsp;var a=1;<br />
&nbsp;alert(a);<br />
}<br />
alert(fTest);</p>
<p>你会发现显示的是fTest这个函数的函数体，所以我们可以认为，所谓函数，仅仅是js引擎可以解析的一段代码字符串。函数名变量存储的只是这个字符串。说的更准确一点，函数名是一个指针变量，它存储的是这个代码字符串在内存中的位置。这样就不难理解将函数作为参数传递，可以作为值返回了，这是以后会大量使用的技术。因为类也是函数，所以理解了函数，也就理解了类。<br />
虽然在js里函数和类没有区别，但是类的概念却可以方便我们进行程序设计，于是prototype很有创意的创建了一个全局对象Class：<br />
var Class = {<br />
&nbsp; create: function() {<br />
&nbsp;&nbsp;&nbsp; return function() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.initialize.apply(this, arguments);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
}</p>
<p>Class是一个全局对象，它的唯一方法就是create，作用返回一个函数，前面已经讲过函数作为返回值的机制，这里不再遨述。返回的函数包括一条语句：<br />
this.initialize.apply(this, arguments);</p>
<p>前面讲过，new一个函数时，会执行函数里的代码，最后返回对象。所以当使用Class.create()创建了一个函数，再new这个返回的函数时，首先会执行这条语句。后面可以看到，这其实是为了调用类的构造函数。<br />
就是这样，Class成为了整个prototype的类型创建模型，并且能很好的把类和函数在代码上区分开来。Class.create()仅仅是返回一个空类，而且它会默认为这个类是具有initialize方法的，所以要使用这个类，至少需要有一个构造函数，这就需要使用到类的继承。类只是一个函数，那么函数怎么继承呢？看起来匪夷所思，javascript能做到这一点，prototype使得实现更为优雅，至于它是怎么做到的，且听下回分解。<br />
AJAX之旅(2)：javascript中类的深入研究－实现和继承 <br />
上回说到了类的定义，prototype通过一个全局对象Class从形式上将函数和类区别开来。既然是类，那么就有抽象类，具体类，类的继承，同时，类的成员可以有实例成员和静态成员。下面来看一下prototype是怎么做到这些的。<br />
先看prototype中的以下的代码： </p>
<p>var Abstract = new Object(); <br />
&nbsp;Object.extend = function(destination, source) {<br />
&nbsp;&nbsp; for (property in source) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; destination[property] = source[property];<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; return destination;<br />
&nbsp;} <br />
&nbsp;Object.prototype.extend = function(object) {<br />
&nbsp;&nbsp; return Object.extend.apply(this, [this, object]);<br />
&nbsp;}<br />
第一个声明了一个对象Abstract，Object其实是一个函数，他没有任何成员，所以是一个空类，所以Abstract也就没有任何成员。这个暂时不说，后面可以看到这是抽象类的基础。先解释以下这个语法：<br />
function.member=function(){}<br />
在这种情况下，function一般都是已经定义过的，这条语句的作用是给function增加一个静态成员member，member的内容是等号后面的。如上面第二段代码Object.extend=&#8230;&#8230;，就是给Object这个类增加了一个静态方法extend。ok，我们知道了怎样给一个类定义静态成员，那么你一定很想知道实例成员怎么定义，很简单，在类名和成员名之间加上prototype： </p>
<p>function.prototype.member=function(){}<br />
&nbsp;<br />
prototype不仅可以这么使用，还可以： <br />
&nbsp;function.prototype={<br />
&nbsp; member1:function(){&#8230;&#8230;},<br />
&nbsp; member2:"abc",<br />
&nbsp; member3:function(){&#8230;&#8230;}<br />
&nbsp;}<br />
这样就是实现了实例成员的定义。但prototype代表什么意思呢？在第一篇我说过，直接用{}括起来，表示一个对象，如Prototype，Class都是这样定义的全局对象。而看下面一种用法，prototype后面就是一个{}的结构，难道它也是对象？是的，没错，prototype其实也是一个对象！在javascript里，一个对象我们可以任意增加它的成员，用如下的语法：<br />
object.member=function(){&#8230;&#8230;};<br />
只要经过这样的定义，一个对象就可以立刻具有member这个方法！javascript就是这么神奇！<br />
好，我们现在知道了prototype是一个对象，而function是一个函数或者类，那么我们可以认为prototype是任何一个类（函数）都内部保留的一个静态成员。它的功能就是存储这个类的所有成员指针，但这些成员都只是原型，没有经过初始化，这也符合prototype的原义。你可以随时通过prototype这个对象来扩充成员。在new一个类时，prototype的成员就经过初始化，然后赋给了实例化的对象。<br />
上面第三段代码Object.prototype.extend=&#8230;&#8230;，就是给Object增加了一个实例方法extend，实例方法中就可以引用this指针，指向由这个类实例化的对象本身。当然，这个对象就具有成员extend。<br />
继续之前，先了解一下两个语句： <br />
for(var p in object){}<br />
&nbsp;method.apply(object,arguments);<br />
第一句：列举出一个变量的所有成员，如果是函数，那么是所有静态成员；如果是对象，那就是所有实例成员，p的类型是一个字符串。表示成员的名称。引用一个成员不仅可以用variabel.member，还可以用variabel["member"]。反过来，赋值也是如此。这就给枚举一个变量的成员带来了很大方便。<br />
第二条语句：将method这个方法应用到object去执行，参数是arguments这个数组。注意：method并不是object的成员。但是，我们可以认为这条语句执行的意思就是：object.method(arguments)。这是一个很重要的方法，后面会经常用到，你也会逐渐熟悉它的。<br />
下面继续extend，它是一个非常重要的方法，可以看到它既是类Object的静态成员，也是其实例成员，那它有什么作用呢？让我们来看：它接收两个参数，destination和source，如果destination和source都是类，那么它的功能是把类source的所有静态成员都复制给类destination，如果destination和source都是对象，那么是把所有实例成员都复制过来。这时destination中如果已经有同名成员，那么这个成员将被覆盖。也就是说让destination具有了source的所有成员，并且函数返回这个destination。下面看extend作为Object的实例成员：<br />
Object.prototype.extend = function(object) {<br />
&nbsp;&nbsp; return Object.extend.apply(this, [this, object]);<br />
&nbsp;}<br />
开始有点晕了，不过不要急，还是可以看懂的，apply语法刚刚已经讲过了，它的调用者是一个方法，而Object.extend是一个静态方法，它被应用到this上面，也就是Object的实例，假设为obj，后面方括号是一个数组，包括两个成员，this和object。这个数组实际上就是Object静态成员extend的arguments参数。那么这条语句就相当于执行 <br />
obj.extend(this,object);<br />
this不解释了，表示本身。object是什么？参数，恩，是实例方法extend传来的参数，不要混淆。extend呢？obj并没有定义extend实例成员，但通过apply，它可以把Object的静态成员extend拿来使用，再看一下extend的函数体： <br />
Object.extend = function(destination, source) {<br />
&nbsp;&nbsp; for (property in source) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; destination[property] = source[property];<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; return destination;<br />
&nbsp;}<br />
因为obj是对象，object也是对象，即destination和source都是对象，于是函数的作用就是使obj具有object的所有成员。并且会返回obj。听起来有点拗口，但逻辑很简单：让obj&#8220;继承于&#8221;object！很好，我们看到了继承，但你肯定会问，对象的继承，第一次听说啊，我们讲继承都是讲的类的继承。没错，现在的确还没有看到真正的类继承，但已经近在眼前了：类不就是有个prototype吗，而prototype是对象！<br />
好，想到这一点，类的继承语法看似很简单了： <br />
b.prototype.extend(a.prototype);<br />
让b继承a。<br />
可是事实却没那么简单：prototype是存放方法原型指针，extend方法没有初始化，不能使用！要使用extend，就必须实例化一个对象。还是看看prototype是怎么做的吧：<br />
b.prototype=(new a()).extend(b.prototype);<br />
很高明的办法！充分说明了函数其实也是一个变量的道理。先实例化a对象，然后在它基础上调用extend，将所有的成员b.prototype的成员覆盖到a的对象，然后把这个a对象再赋值给b.prototype。完成了b从a继承的工作。在实际使用中，一般的用法都是：<br />
b.prototype=(new a()).extend({});<br />
因为让一个b继承自a，通常b之前都是一个未定义的类，所以后面的{}中其实就可以定义类成员。当然，你也可以先定义，再继承，只是和传统概念有所区别了。</p>
<p>AJAX之旅（3）：javascript中的事件设计模式 <br />
今天暂时抛开prototype1.3.1，分享一下我的javscript事件设计心得。其实现的技术基础在于函数的本质，这在前面两篇中有详细叙述（更多请关注：<a href="http://www.x2design.net/">http://www.x2design.net</a>）。<br />
javascript内置的对象都有事件功能，比如button就有onclick事件，input就有onchange事件。那么如何在我们自定义的类中实现事件呢？很简单：<br />
var myClass=Class.create();<br />
myClass.prototype={<br />
&nbsp;show:function(){<br />
&nbsp; //statement<br />
&nbsp; onshow();<br />
&nbsp;},<br />
&nbsp;onshow:function(){}<br />
}<br />
这段代码其实就是实现了onshow事件，在myClass实例show的时候触发，你可以给onshow绑定一个函数，从而使用事件功能。在javascript中，内置的对象事件使用方法都是如此，其内部实现应该也是基于这样的模式。但是，这样的实现却有两个突出的问题：<br />
1.只能绑定一个回调函数。如果要实现多绑定，必须自己写很多代码来封装要回调的函数到一个函数中。<br />
2.不能传递参数。因为onshow只能赋给函数名，即函数体本身，并不能传递参数进去，为了传递参数，我曾写过一篇：《用外壳包装法给javascript触发器传递参数》，可见，同样需要写很多代码。<br />
那么，这些问题怎么解决呢？javascript内置对象的事件使用我们就暂时不管，来考虑一下怎么在自己实现的类中避免如上两个问题。实现之前，先来考虑下面这个问题，或许有助于理解实现这个功能的意义：<br />
我的页面需要用javascript进行一些初始化，但初始化必须在页面载入完成之后进行。通常我们会将代码放到html文件最下面。但此时，在页面载入完成之前，页面上的按钮点击需要调用必须经过初始化的方法，如果不作判断，那么就很容易出现脚本错误。因为还没有初始化，一个简单的想法是：用一个bool变量loaded来判断，初始为false，初始化完成后为true，那么按钮点击时遇到false就简单返回。这实现固然简单，但有可能造成用户发现点击无效，而不知其所以然。所以完善的做法应该是能捕获这个方法，将其绑定到页面载入完成事件上，当页面载入完成后自动调用。<br />
好，现在看事件设计模式的实现代码：<br />
var myClass=Class.create();<br />
myClass.prototype={<br />
&nbsp;initialize:function(){<br />
&nbsp; this.initEvent=new Object();<br />
&nbsp;},<br />
&nbsp;init:function(){<br />
&nbsp; //初始化要执行的语句<br />
&nbsp; <br />
&nbsp; //下面是调用绑定的回调函数<br />
&nbsp; for(var p in this.initEvent){<br />
&nbsp;&nbsp; //extend是内置方法，不可作为回调关键字<br />
&nbsp;&nbsp; if(p=="extend")continue;<br />
&nbsp;&nbsp; this.initEvent[p].apply(_object,[]);<br />
&nbsp; }<br />
&nbsp;},<br />
&nbsp;attachOnInit:function(_key,_object,_method,_arguments){<br />
&nbsp; this.initEvent[_key]=createFunction(_object,_method,_arguments);<br />
&nbsp;},<br />
}<br />
function createFunction(_object,_method,_arguments){<br />
&nbsp;return function(){<br />
&nbsp; _method.apply(_object,_arguments);<br />
&nbsp;}<br />
}<br />
这段代码就实现了一个类myClass，具有init方法，触发oninit事件，使用时要想绑定一个事件，可以调用attachOnInit方法，参数的意思分别为：_key，回调参函数的唯一标识，如果重复，后者覆盖前者；_object回调函数的对象，如果是直接在script中的函数，可以传递this指针进去，即document对象；_method，要回调的函数，注意，这是一个函数名，不是字符串；_arguments，回调函数的参数数组。还有一个函数是createFunction，作用是包装一个函数，使其内置参数，这是外壳包装法那篇文章的一个通用实现。如果大家看过ajax之旅系列的前两篇文章，应该容易理解上面的代码，如果有什么问题，欢迎评论。<br />
使用示例：<br />
function myFunc(s){<br />
&nbsp;alert(s);<br />
}<br />
var myObj=new myClass();<br />
myClass.attach("key1",this,myFunc,[123]);<br />
myClass.init();</p>
<p>这就将myFunc函数绑定到myObj的init函数，执行后会弹出对话框123。<br />
&nbsp;<br />
Ajax::prototype 源码解读 之 prototype.js 一[转载] <br />
/** <br />
&nbsp;* 定义一个全局对象, 属性 Version 在发布的时候会替换为当前版本号 <br />
&nbsp;*/ <br />
var Prototype = { <br />
&nbsp; Version: <a href="mailto:'@@VERSION@@'">'@@VERSION@@'</a> <br />
} </p>
<p>/** <br />
&nbsp;* 创建一种类型，注意其属性 create 是一个方法，返回一个构造函数。 <br />
&nbsp;* 一般使用如下&nbsp; <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; var X = Class.create();&nbsp; 返回一个类型，类似于 java 的一个Class实例。 <br />
&nbsp;* 要使用 X 类型，需继续用 new X()来获取一个实例，如同 java 的 Class.newInstance()方法。 <br />
&nbsp;* <br />
&nbsp;* 返回的构造函数会执行名为 initialize 的方法， initialize 是 Ruby 对象的构造器方法名字。 <br />
&nbsp;* 此时initialize方法还没有定义，其后的代码中创建新类型时会建立相应的同名方法。 <br />
&nbsp;* <br />
&nbsp;* 如果一定要从java上去理解。你可以理解为用Class.create()创建一个继承java.lang.Class类的类。当然java不允许这样做，因为Class类是final的 <br />
&nbsp;* <br />
&nbsp;*/ <br />
var Class = { <br />
&nbsp; create: function() { <br />
&nbsp;&nbsp;&nbsp; return function() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.initialize.apply(this, arguments); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* 创建一个对象，从变量名来思考，本意也许是定义一个抽象类，以后创建新对象都 extend 它。 <br />
&nbsp;* 但从其后代码的应用来看， Abstract 更多是为了保持命名空间清晰的考虑。 <br />
&nbsp;* 也就是说，我们可以给 Abstract 这个对象实例添加新的对象定义。 <br />
&nbsp;* <br />
&nbsp;* 从java去理解，就是动态给一个对象创建内部类。 <br />
&nbsp;*/ <br />
var Abstract = new Object(); </p>
<p>/** <br />
&nbsp;* 获取参数对象的所有属性和方法，有点象多重继承。但是这种继承是动态获得的。 <br />
&nbsp;* 如： <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; var a = new ObjectA(), b = new ObjectB(); <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; var c = a.extend(b); <br />
&nbsp;* 此时 c 对象同时拥有 a 和 b 对象的属性和方法。但是与多重继承不同的是，c instanceof ObjectB 将返回false。 <br />
&nbsp;*/ <br />
Object.prototype.extend = function(object) { <br />
&nbsp; for (property in object) { <br />
&nbsp;&nbsp;&nbsp; this[property] = object[property]; <br />
&nbsp; } <br />
&nbsp; return this; <br />
} </p>
<p>/** <br />
&nbsp;* 这个方法很有趣，它封装一个javascript函数对象，返回一个新函数对象，新函数对象的主体和原对象相同，但是bind()方法参数将被用作当前对象的对象。 <br />
&nbsp;* 也就是说新函数中的 this 引用被改变为参数提供的对象。 <br />
&nbsp;* 比如： <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; &lt;input type="text" id="aaa" value="aaa"&gt; <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; &lt;input type="text" id="bbb" value="bbb"&gt; <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; ................. <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; &lt;script&gt; <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var aaa = document.getElementById("aaa"); <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var bbb = document.getElementById("bbb"); <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aaa.showValue = function() {alert(this.value);} <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aaa.showValue2 = aaa.showValue.bind(bbb); <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; &lt;/script&gt; <br />
&nbsp;*&nbsp; 那么，调用aaa.showValue 将返回"aaa", 但调用aaa.showValue2 将返回"bbb"。 <br />
&nbsp;* <br />
&nbsp;* apply 是ie5.5后才出现的新方法(Netscape好像很早就支持了)。 <br />
&nbsp;* 该方法更多的资料参考MSDN <a href="http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthApply.asp">http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthApply.asp</a> <br />
&nbsp;* 还有一个 call 方法，应用起来和 apply 类似。可以一起研究下。 <br />
&nbsp;*/ <br />
Function.prototype.bind = function(object) { <br />
&nbsp; var method = this; <br />
&nbsp; return function() { <br />
&nbsp;&nbsp;&nbsp; method.apply(object, arguments); <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* 和bind一样，不过这个方法一般用做html控件对象的事件处理。所以要传递event对象 <br />
&nbsp;* 注意这时候，用到了 Function.call。它与 Function.apply 的不同好像仅仅是对参数形式的定义。 <br />
&nbsp;* 如同 java 两个过载的方法。 <br />
&nbsp;*/ <br />
Function.prototype.bindAsEventListener = function(object) { <br />
&nbsp; var method = this; <br />
&nbsp; return function(event) { <br />
&nbsp;&nbsp;&nbsp; method.call(object, event || window.event); <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* 将整数形式RGB颜色值转换为HEX形式 <br />
&nbsp;*/ <br />
Number.prototype.toColorPart = function() { <br />
&nbsp; var digits = this.toString(16); <br />
&nbsp; if (this &lt; 16) return '0' + digits; <br />
&nbsp; return digits; <br />
} </p>
<p>/** <br />
&nbsp;* 典型 Ruby 风格的函数，将参数中的方法逐个调用，返回第一个成功执行的方法的返回值 <br />
&nbsp;*/ <br />
var Try = { <br />
&nbsp; these: function() { <br />
&nbsp;&nbsp;&nbsp; var returnValue; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; arguments.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var lambda = arguments[i]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; returnValue = lambda(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (e) {} <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return returnValue; <br />
&nbsp; } <br />
} </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* 一个设计精巧的定时执行器 <br />
&nbsp;* 首先由 Class.create() 创建一个 PeriodicalExecuter 类型， <br />
&nbsp;* 然后用对象直接量的语法形式设置原型。 <br />
&nbsp;* <br />
&nbsp;* 需要特别说明的是 rgisterCallback 方法，它调用上面定义的函数原型方法bind, 并传递自己为参数。 <br />
&nbsp;* 之所以这样做，是因为 setTimeout 默认总以 window 对象为当前对象，也就是说，如果 registerCallback 方法定义如下的话： <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; registerCallback: function() { <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTimeout(this.onTimerEvent, this.frequency * 1000); <br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;* 那么，this.onTimeoutEvent 方法执行失败，因为它无法访问 this.currentlyExecuting 属性。 <br />
&nbsp;* 而使用了bind以后，该方法才能正确的找到this，也就是PeriodicalExecuter的当前实例。 <br />
&nbsp;*/ <br />
var PeriodicalExecuter = Class.create(); <br />
PeriodicalExecuter.prototype = { <br />
&nbsp; initialize: function(callback, frequency) { <br />
&nbsp;&nbsp;&nbsp; this.callback = callback; <br />
&nbsp;&nbsp;&nbsp; this.frequency = frequency; <br />
&nbsp;&nbsp;&nbsp; this.currentlyExecuting = false; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.registerCallback(); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; registerCallback: function() { <br />
&nbsp;&nbsp;&nbsp; setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; onTimerEvent: function() { <br />
&nbsp;&nbsp;&nbsp; if (!this.currentlyExecuting) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.currentlyExecuting = true; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.callback(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.currentlyExecuting = false; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.registerCallback(); <br />
&nbsp; } <br />
} </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* 这个函数就 Ruby 了。我觉得它的作用主要有两个 <br />
&nbsp;* 1.&nbsp; 大概是 document.getElementById(id) 的最简化调用。 <br />
&nbsp;* 比如：$("aaa") 将返回上 aaa 对象 <br />
&nbsp;* 2.&nbsp; 得到对象数组 <br />
&nbsp;* 比如: $("aaa","bbb") 返回一个包括id为"aaa"和"bbb"两个input控件对象的数组。 <br />
&nbsp;*/ <br />
function $() { <br />
&nbsp; var elements = new Array(); <br />
&nbsp; <br />
&nbsp; for (var i = 0; i &lt; arguments.length; i++) { <br />
&nbsp;&nbsp;&nbsp; var element = arguments[i]; <br />
&nbsp;&nbsp;&nbsp; if (typeof element == 'string') <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element = document.getElementById(element); </p>
<p>&nbsp;&nbsp;&nbsp; if (arguments.length == 1) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return element; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; elements.push(element); <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; return elements; <br />
}</p>
<p><br />
Ajax::prototype 源码解读 之 prototype.js 二[转载] <br />
/** <br />
&nbsp;* 定义 Ajax 对象, 静态方法 getTransport 方法返回一个 XMLHttp 对象 <br />
&nbsp;*/ <br />
var Ajax = { <br />
&nbsp; getTransport: function() { <br />
&nbsp;&nbsp;&nbsp; return Try.these( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function() {return new ActiveXObject('Msxml2.XMLHTTP')}, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function() {return new ActiveXObject('Microsoft.XMLHTTP')}, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function() {return new XMLHttpRequest()} <br />
&nbsp;&nbsp;&nbsp; ) || false; <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; emptyFunction: function() {} <br />
} </p>
<p>/** <br />
&nbsp;* 我以为此时的Ajax对象起到命名空间的作用。 <br />
&nbsp;* Ajax.Base 声明为一个基础对象类型 <br />
&nbsp;* 注意 Ajax.Base 并没有使用 Class.create() 的方式来创建，我想是因为作者并不希望 Ajax.Base 被库使用者实例化。 <br />
&nbsp;* 作者在其他对象类型的声明中，将会继承于它。 <br />
&nbsp;* 就好像 java 中的私有抽象类 <br />
&nbsp;*/ <br />
Ajax.Base = function() {}; <br />
Ajax.Base.prototype = { <br />
&nbsp; /** <br />
&nbsp;&nbsp; * extend (见prototype.js中的定义) 的用法真是让人耳目一新 <br />
&nbsp;&nbsp; * options 首先设置默认属性，然后再 extend 参数对象，那么参数对象中也有同名的属性，那么就覆盖默认属性值。 <br />
&nbsp;&nbsp; * 想想如果我写这样的实现，应该类似如下： <br />
&nbsp;&nbsp;&nbsp;&nbsp; setOptions: function(options) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.options.methed = options.methed? options.methed : 'post'; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .......... <br />
&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp; 我想很多时候，java 限制了 js 的创意。 <br />
&nbsp;&nbsp; */ <br />
&nbsp; setOptions: function(options) { <br />
&nbsp;&nbsp;&nbsp; this.options = { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; method:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'post', <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; asynchronous: true, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; parameters:&nbsp;&nbsp; '' <br />
&nbsp;&nbsp;&nbsp; }.extend(options || {}); <br />
&nbsp; } <br />
} </p>
<p><br />
/** <br />
&nbsp;* Ajax.Request 封装 XmlHttp <br />
&nbsp;*/ <br />
Ajax.Request = Class.create(); </p>
<p>/** <br />
&nbsp;* 定义四种事件(状态)， 参考<a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp">http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp</a> <br />
&nbsp;*/ <br />
Ajax.Request.Events = <br />
&nbsp; ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; </p>
<p>/** <br />
&nbsp;* <br />
&nbsp;*/ <br />
Ajax.Request.prototype = (new Ajax.Base()).extend({ <br />
&nbsp; initialize: function(url, options) { <br />
&nbsp;&nbsp;&nbsp; this.transport = Ajax.getTransport(); <br />
&nbsp;&nbsp;&nbsp; this.setOptions(options); <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; try { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.options.method == 'get') <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url += '?' + this.options.parameters + '&amp;_='; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; /** <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 此处好像强制使用了异步方式，而不是依照 this.options.asynchronous 的值 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.open(this.options.method, url, true); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; /** <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 这里提供了 XmlHttp 传输过程中每个步骤的回调函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.options.asynchronous) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.onreadystatechange = this.onStateChange.bind(this); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.setRequestHeader('X-Prototype-Version', Prototype.Version); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.options.method == 'post') { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.setRequestHeader('Connection', 'close'); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.setRequestHeader('Content-type', <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'application/x-www-form-urlencoded'); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.transport.send(this.options.method == 'post' ? <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.options.parameters + '&amp;_=' : null); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; } catch (e) { <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp; }, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; onStateChange: function() { <br />
&nbsp;&nbsp;&nbsp; var readyState = this.transport.readyState; <br />
&nbsp;&nbsp; /** <br />
&nbsp;&nbsp;&nbsp; * 如果不是 Loading 状态，就调用回调函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp; if (readyState != 1) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.respondToReadyState(this.transport.readyState); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 回调函数定义在 this.options 属性中，比如: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var option = { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onLoaded : function(req) {...}; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...... <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Ajax.Request(url, option); <br />
&nbsp;&nbsp; */ <br />
&nbsp; respondToReadyState: function(readyState) { <br />
&nbsp;&nbsp;&nbsp; var event = Ajax.Request.Events[readyState]; <br />
&nbsp;&nbsp;&nbsp; (this.options['on' + event] || Ajax.emptyFunction)(this.transport); <br />
&nbsp; } <br />
}); </p>
<p>/** <br />
&nbsp;* Ajax.Updater 用于绑定一个html元素与 XmlHttp调用的返回值。类似与 buffalo 的 bind。 <br />
&nbsp;* 如果 options 中有 insertion(from dom.js) 对象的话, insertion 能提供更多的插入控制。 <br />
&nbsp;*/ <br />
Ajax.Updater = Class.create(); <br />
Ajax.Updater.prototype = (new Ajax.Base()).extend({ <br />
&nbsp; initialize: function(container, url, options) { <br />
&nbsp;&nbsp;&nbsp; this.container = $(container); <br />
&nbsp;&nbsp;&nbsp; this.setOptions(options); <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (this.options.asynchronous) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.onComplete = this.options.onComplete; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.options.onComplete = this.updateContent.bind(this); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.request = new Ajax.Request(url, this.options); <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (!this.options.asynchronous) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.updateContent(); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; updateContent: function() { <br />
&nbsp;&nbsp;&nbsp; if (this.options.insertion) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new this.options.insertion(this.container, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.request.transport.responseText); <br />
&nbsp;&nbsp;&nbsp; } else { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.container.innerHTML = this.request.transport.responseText; <br />
&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp; if (this.onComplete) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTimeout((function() {this.onComplete(this.request)}).bind(this), 10); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; } <br />
});<br />
Ajax::prototype 源码解读 之 prototype.js 三[转载] <br />
/** <br />
&nbsp;* 针对 页面元素对象 的工具类，提供一些简单静态方法 <br />
&nbsp;*/ <br />
var Field = { <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 清除参数引用对象的值 <br />
&nbsp;&nbsp; */ <br />
&nbsp; clear: function() { <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; arguments.length; i++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(arguments[i]).value = ''; <br />
&nbsp; }, </p>
<p>&nbsp; /** <br />
&nbsp;&nbsp; * 使参数引用对象获取焦点 <br />
&nbsp;&nbsp; */ <br />
&nbsp; focus: function(element) { <br />
&nbsp;&nbsp;&nbsp; $(element).focus(); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 判断参数引用对象值是否为空，如为空，返回false, 反之true <br />
&nbsp;&nbsp; */ <br />
&nbsp; present: function() { <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; arguments.length; i++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ($(arguments[i]).value == '') return false; <br />
&nbsp;&nbsp;&nbsp; return true; <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 使选中参数引用对象 <br />
&nbsp;&nbsp; */ <br />
&nbsp; select: function(element) { <br />
&nbsp;&nbsp;&nbsp; $(element).select(); <br />
&nbsp; }, </p>
<p>&nbsp; /** <br />
&nbsp;&nbsp; * 使参数引用对象处于可编辑状态 <br />
&nbsp;&nbsp; */ <br />
&nbsp; activate: function(element) { <br />
&nbsp;&nbsp;&nbsp; $(element).focus(); <br />
&nbsp;&nbsp;&nbsp; $(element).select(); <br />
&nbsp; } <br />
} </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* 表单工具类 <br />
&nbsp;*/ <br />
var Form = { <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 将表单元素序列化后的值组合成 QueryString 的形式 <br />
&nbsp;&nbsp; */ <br />
&nbsp; serialize: function(form) { <br />
&nbsp;&nbsp;&nbsp; var elements = Form.getElements($(form)); <br />
&nbsp;&nbsp;&nbsp; var queryComponents = new Array(); <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; elements.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var queryComponent = Form.Element.serialize(elements[i]); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (queryComponent) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queryComponents.push(queryComponent); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return queryComponents.join('&amp;'); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 得到表单的所有元素对象 <br />
&nbsp;&nbsp; */ <br />
&nbsp; getElements: function(form) { <br />
&nbsp;&nbsp;&nbsp; form = $(form); <br />
&nbsp;&nbsp;&nbsp; var elements = new Array(); </p>
<p>&nbsp;&nbsp;&nbsp; for (tagName in Form.Element.Serializers) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tagElements = form.getElementsByTagName(tagName); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var j = 0; j &lt; tagElements.length; j++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elements.push(tagElements[j]); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; return elements; <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 将指定表单的元素置于不可用状态 <br />
&nbsp;&nbsp; */ <br />
&nbsp; disable: function(form) { <br />
&nbsp;&nbsp;&nbsp; var elements = Form.getElements(form); <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; elements.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var element = elements[i]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.blur(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.disable = 'true'; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; }, </p>
<p>&nbsp; /** <br />
&nbsp;&nbsp; * 使表单的第一个非 hidden 类型而且处于可用状态的元素获得焦点 <br />
&nbsp;&nbsp; */ <br />
&nbsp; focusFirstElement: function(form) { <br />
&nbsp;&nbsp;&nbsp; form = $(form); <br />
&nbsp;&nbsp;&nbsp; var elements = Form.getElements(form); <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; elements.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var element = elements[i]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (element.type != 'hidden' &amp;&amp; !element.disabled) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Field.activate(element); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; }, </p>
<p>&nbsp; /* <br />
&nbsp;&nbsp; * 重置表单 <br />
&nbsp;&nbsp; */ <br />
&nbsp; reset: function(form) { <br />
&nbsp;&nbsp;&nbsp; $(form).reset(); <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* 表单元素工具类 <br />
&nbsp;*/ <br />
Form.Element = { <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 返回表单元素的值先序列化再进行 URL 编码后的值 <br />
&nbsp;&nbsp; */ <br />
&nbsp; serialize: function(element) { <br />
&nbsp;&nbsp;&nbsp; element = $(element); <br />
&nbsp;&nbsp;&nbsp; var method = element.tagName.toLowerCase(); <br />
&nbsp;&nbsp;&nbsp; var parameter = Form.Element.Serializers[method](element); <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (parameter) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return encodeURIComponent(parameter[0]) + '=' + <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encodeURIComponent(parameter[1]);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; *&nbsp; 返回表单元素序列化后的值 <br />
&nbsp;&nbsp; */ <br />
&nbsp; getValue: function(element) { <br />
&nbsp;&nbsp;&nbsp; element = $(element); <br />
&nbsp;&nbsp;&nbsp; var method = element.tagName.toLowerCase(); <br />
&nbsp;&nbsp;&nbsp; var parameter = Form.Element.Serializers[method](element); <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (parameter) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return parameter[1]; <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* prototype 的所谓序列化其实就是将表单的名字和值组合成一个数组 <br />
&nbsp;*/ <br />
Form.Element.Serializers = { <br />
&nbsp; input: function(element) { <br />
&nbsp;&nbsp;&nbsp; switch (element.type.toLowerCase()) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'hidden': <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'password': <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'text': <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Form.Element.Serializers.textarea(element); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'checkbox':&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'radio': <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Form.Element.Serializers.inputSelector(element); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; return false; <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; inputSelector: function(element) { <br />
&nbsp;&nbsp;&nbsp; if (element.checked) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return [element.name, element.value]; <br />
&nbsp; }, </p>
<p>&nbsp; textarea: function(element) { <br />
&nbsp;&nbsp;&nbsp; return [element.name, element.value]; <br />
&nbsp; }, </p>
<p>&nbsp; /** <br />
&nbsp;&nbsp; * 看样子，也不支持多选框(select-multiple) <br />
&nbsp;&nbsp; */ <br />
&nbsp; select: function(element) { <br />
&nbsp;&nbsp;&nbsp; var index = element.selectedIndex; <br />
&nbsp;&nbsp;&nbsp; var value = element.options[index].value || element.options[index].text; <br />
&nbsp;&nbsp;&nbsp; return [element.name, (index &gt;= 0) ? value : '']; <br />
&nbsp; } <br />
} </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* Form.Element.getValue 也许会经常用到，所以做了一个快捷引用 <br />
&nbsp;*/ <br />
var $F = Form.Element.getValue; </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* Abstract.TimedObserver 也没有用 Class.create() 来创建，和Ajax.Base 意图应该一样 <br />
&nbsp;* Abstract.TimedObserver 顾名思义，是套用Observer设计模式来跟踪指定表单元素， <br />
&nbsp;* 当表单元素的值发生变化的时候，就执行回调函数 <br />
&nbsp;* <br />
&nbsp;* 我想　Observer 与注册onchange事件相似，不同点在于 onchange 事件是在元素失去焦点的时候才激发。 <br />
&nbsp;* 同样的与 onpropertychange 事件也相似，不过它只关注表单元素的值的变化，而且提供timeout的控制。 <br />
&nbsp;* <br />
&nbsp;* 除此之外，Observer 的好处大概就在与更面向对象，另外可以动态的更换回调函数，这就比注册事件要灵活一些。 <br />
&nbsp;* Observer 应该可以胜任动态数据校验，或者多个关联下拉选项列表的连动等等 <br />
&nbsp;* <br />
&nbsp;*/ <br />
Abstract.TimedObserver = function() {} </p>
<p>/** <br />
&nbsp;* 这个设计和 PeriodicalExecuter 一样，bind 方法是实现的核心 <br />
&nbsp;*/ <br />
Abstract.TimedObserver.prototype = { <br />
&nbsp; initialize: function(element, frequency, callback) { <br />
&nbsp;&nbsp;&nbsp; this.frequency = frequency; <br />
&nbsp;&nbsp;&nbsp; this.element&nbsp;&nbsp; = $(element); <br />
&nbsp;&nbsp;&nbsp; this.callback&nbsp; = callback; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.lastValue = this.getValue(); <br />
&nbsp;&nbsp;&nbsp; this.registerCallback(); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; registerCallback: function() { <br />
&nbsp;&nbsp;&nbsp; setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; onTimerEvent: function() { <br />
&nbsp;&nbsp;&nbsp; var value = this.getValue(); <br />
&nbsp;&nbsp;&nbsp; if (this.lastValue != value) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.callback(this.element, value); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.lastValue = value; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.registerCallback(); <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* Form.Element.Observer 和 Form.Observer 其实是一样的 <br />
&nbsp;* 注意 Form.Observer 并不是用来跟踪整个表单的，我想大概只是为了减少书写(这是Ruby的一个设计原则) <br />
&nbsp;*/ <br />
Form.Element.Observer = Class.create(); <br />
Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({ <br />
&nbsp; getValue: function() { <br />
&nbsp;&nbsp;&nbsp; return Form.Element.getValue(this.element); <br />
&nbsp; } <br />
}); </p>
<p>Form.Observer = Class.create(); <br />
Form.Observer.prototype = (new Abstract.TimedObserver()).extend({ <br />
&nbsp; getValue: function() { <br />
&nbsp;&nbsp;&nbsp; return Form.serialize(this.element); <br />
&nbsp; } <br />
});<br />
Ajax::prototype 源码解读 之 prototype.js 四[转载] <br />
/** <br />
&nbsp;* 根据 class attribute 的名字得到对象数组，支持 multiple class <br />
&nbsp;* <br />
&nbsp;*/ <br />
document.getElementsByClassName = function(className) { <br />
&nbsp; var children = document.getElementsByTagName('*') || document.all; <br />
&nbsp; var elements = new Array(); <br />
&nbsp; <br />
&nbsp; for (var i = 0; i &lt; children.length; i++) { <br />
&nbsp;&nbsp;&nbsp; var child = children[i]; <br />
&nbsp;&nbsp;&nbsp; var classNames = child.className.split(' '); <br />
&nbsp;&nbsp;&nbsp; for (var j = 0; j &lt; classNames.length; j++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (classNames[j] == className) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elements.push(child); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; return elements; <br />
} </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* Element 就象一个 java 的工具类，主要用来 隐藏/显示/销除 对象，以及获取对象的简单属性。 <br />
&nbsp;* <br />
&nbsp;*/ <br />
var Element = { <br />
&nbsp; toggle: function() { <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; arguments.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var element = $(arguments[i]); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.display = <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (element.style.display == 'none' ? '' : 'none'); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; }, </p>
<p>&nbsp; hide: function() { <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; arguments.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var element = $(arguments[i]); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.display = 'none'; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; }, </p>
<p>&nbsp; show: function() { <br />
&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; arguments.length; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var element = $(arguments[i]); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.display = ''; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; }, </p>
<p>&nbsp; remove: function(element) { <br />
&nbsp;&nbsp;&nbsp; element = $(element); <br />
&nbsp;&nbsp;&nbsp; element.parentNode.removeChild(element); <br />
&nbsp; }, <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp; getHeight: function(element) { <br />
&nbsp;&nbsp;&nbsp; element = $(element); <br />
&nbsp;&nbsp;&nbsp; return element.offsetHeight; <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* 为 Element.toggle 做了一个符号连接，大概是兼容性的考虑 <br />
&nbsp;*/ <br />
var Toggle = new Object(); <br />
Toggle.display = Element.toggle; </p>
<p>/*--------------------------------------------------------------------------*/ </p>
<p>/** <br />
&nbsp;* 动态插入内容的实现，MS的Jscript实现中对象有一个 insertAdjacentHTML 方法(http: //msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertadjacenthtml.asp) <br />
&nbsp;* 这里算是一个对象形式的封装。 <br />
&nbsp;*/ <br />
Abstract.Insertion = function(adjacency) { <br />
&nbsp; this.adjacency = adjacency; <br />
} </p>
<p>Abstract.Insertion.prototype = { <br />
&nbsp; initialize: function(element, content) { <br />
&nbsp;&nbsp;&nbsp; this.element = $(element); <br />
&nbsp;&nbsp;&nbsp; this.content = content; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (this.adjacency &amp;&amp; this.element.insertAdjacentHTML) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.element.insertAdjacentHTML(this.adjacency, this.content); <br />
&nbsp;&nbsp;&nbsp; } else { <br />
&nbsp;&nbsp;&nbsp;&nbsp; /** <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * gecko 不支持 insertAdjacentHTML 方法，但可以用如下代码代替 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.range = this.element.ownerDocument.createRange(); <br />
&nbsp;&nbsp;&nbsp;&nbsp; /** <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 如果定义了 initializeRange 方法，则实行，这里相当与定义了一个抽象的 initializeRange 方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.initializeRange) this.initializeRange(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.fragment = this.range.createContextualFragment(this.content); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; /** <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * insertContent 也是一个抽象方法，子类必须实现 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.insertContent(); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp; } <br />
} </p>
<p>/** <br />
&nbsp;* prototype 加深了我的体会，就是写js 如何去遵循　Don&#8217;t Repeat Yourself (DRY) 原则 <br />
&nbsp;* 上文中 Abstract.Insertion 算是一个抽象类，定义了名为　initializeRange 的一个抽象方法 <br />
&nbsp;* var Insertion = new Object()　建立一个命名空间 <br />
&nbsp;* Insertion.Before|Top|Bottom|After 就象是四个java中的四个静态内部类，而它们分别继承于Abstract.Insertion，并实现了initializeRange方法。 <br />
&nbsp;*/ <br />
var Insertion = new Object(); </p>
<p>Insertion.Before = Class.create(); <br />
Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({ <br />
&nbsp; initializeRange: function() { <br />
&nbsp;&nbsp;&nbsp; this.range.setStartBefore(this.element); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 将内容插入到指定节点的前面, 与指定节点同级 <br />
&nbsp;&nbsp; */ <br />
&nbsp; insertContent: function() { <br />
&nbsp;&nbsp;&nbsp; this.element.parentNode.insertBefore(this.fragment, this.element); <br />
&nbsp; } <br />
}); </p>
<p>Insertion.Top = Class.create(); <br />
Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({ <br />
&nbsp; initializeRange: function() { <br />
&nbsp;&nbsp;&nbsp; this.range.selectNodeContents(this.element); <br />
&nbsp;&nbsp;&nbsp; this.range.collapse(true); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 将内容插入到指定节点的第一个子节点前，于是内容变为该节点的第一个子节点 <br />
&nbsp;&nbsp; */ <br />
&nbsp; insertContent: function() {&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.element.insertBefore(this.fragment, this.element.firstChild); <br />
&nbsp; } <br />
}); </p>
<p>Insertion.Bottom = Class.create(); <br />
Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({ <br />
&nbsp; initializeRange: function() { <br />
&nbsp;&nbsp;&nbsp; this.range.selectNodeContents(this.element); <br />
&nbsp;&nbsp;&nbsp; this.range.collapse(this.element); <br />
&nbsp; }, <br />
&nbsp; <br />
&nbsp; /** <br />
&nbsp;&nbsp; * 将内容插入到指定节点的最后，于是内容变为该节点的最后一个子节点 <br />
&nbsp;&nbsp; */ <br />
&nbsp; insertContent: function() { <br />
&nbsp;&nbsp;&nbsp; this.element.appendChild(this.fragment); <br />
&nbsp; } <br />
}); </p>
<p><br />
Insertion.After = Class.create(); <br />
Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({ <br />
&nbsp; initializeRange: function() { <br />
&nbsp;&nbsp;&nbsp; this.range.setStartAfter(this.element); <br />
&nbsp; }, </p>
<p>&nbsp; /** <br />
&nbsp;&nbsp; * 将内容插入到指定节点的后面, 与指定节点同级 <br />
&nbsp;&nbsp; */ <br />
&nbsp; insertContent: function() { <br />
&nbsp;&nbsp;&nbsp; this.element.parentNode.insertBefore(this.fragment, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.element.nextSibling); <br />
&nbsp; } <br />
});</p>
<p>&nbsp;</p>
<p>Ajax::prototype 源码解读 之 prototype.js 五[转载] <br />
prototype 还有两个源码文件 effects.js compat.js 就不贴出来了。两者并不常用，effects.js 看example 做花哨的效果还不错，不过代码中没有太多新鲜的东西。 </p>
<p>需要指出的就是 <br />
compat.js 中 Funcation.prototype.apply 的实现有两个错误（应该是拼写错误）， 我分别贴出来，大家比较一下就清楚了。</p>
<img src ="http://www.blogjava.net/lifenote/aggbug/174600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2008-01-11 13:27 <a href="http://www.blogjava.net/lifenote/archive/2008/01/11/174600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IE6 和 IE7下均能显示的本地图片预览</title><link>http://www.blogjava.net/lifenote/archive/2007/12/28/171117.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Fri, 28 Dec 2007 03:13:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/28/171117.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/171117.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/28/171117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/171117.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/171117.html</trackback:ping><description><![CDATA[<p>客户端也不能换图片。（只能用滤镜来替换）</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">&lt;!--</span><span style="color: #000000">以下均支持IE6和IE7，不支持Firefox2.</span><span style="color: #000000">0</span><span style="color: #000000">，其他浏览器未经测试</span><span style="color: #000000">--&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000">&lt;</span><span style="color: #000000">script&nbsp;type</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">text/javascript</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
function&nbsp;CloseWin()<br />
{&nbsp;<br />
window.opener</span><span style="color: #000000">=</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
window.open(</span><span style="color: #000000">""</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">_self</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
window.close();&nbsp;<br />
}<br />
<br />
function&nbsp;Preview(imgFile)<br />
{&nbsp;<br />
document.getElementById(</span><span style="color: #000000">"</span><span style="color: #000000">pic</span><span style="color: #000000">"</span><span style="color: #000000">).filters.item(</span><span style="color: #000000">"</span><span style="color: #000000">DXImageTransform.Microsoft.AlphaImageLoader</span><span style="color: #000000">"</span><span style="color: #000000">).src&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;imgFile.value;<br />
<br />
}&nbsp;<br />
</span><span style="color: #000000">&lt;/</span><span style="color: #000000">script</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
<br />
</span><span style="color: #000000">&lt;</span><span style="color: #000000">a&nbsp;href</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">javascript:CloseWin();</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;点击这里无提示关闭当前窗口</span><span style="color: #000000">&lt;/</span><span style="color: #000000">a</span><span style="color: #000000">&gt;&lt;</span><span style="color: #000000">br&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;<br />
<br />
请选择要预览的图片：</span><span style="color: #000000">&lt;</span><span style="color: #000000">input&nbsp;type</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">file</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;onchange</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">javascript:Preview(this);</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;&lt;</span><span style="color: #000000">br&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000">&lt;</span><span style="color: #000000">div&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">pic</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;style</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);width:400px;height:200px;</span><span style="color: #000000">"</span><span style="color: #000000">&gt;&lt;/</span><span style="color: #000000">div</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
</span></div>
<br />
<br />
<img src ="http://www.blogjava.net/lifenote/aggbug/171117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-28 11:13 <a href="http://www.blogjava.net/lifenote/archive/2007/12/28/171117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>博客搬家程序是如何实现的</title><link>http://www.blogjava.net/lifenote/archive/2007/12/27/170914.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Thu, 27 Dec 2007 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/27/170914.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/170914.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/27/170914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/170914.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/170914.html</trackback:ping><description><![CDATA[如题，找有开发过这样功能的朋友介绍一下，是分析html代码么&nbsp; 那比如sina 的和163的 代码肯定不一样的 那不是要写很多这样的程序 疑惑中。。。
<img src ="http://www.blogjava.net/lifenote/aggbug/170914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-27 16:28 <a href="http://www.blogjava.net/lifenote/archive/2007/12/27/170914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>后退按钮失效 </title><link>http://www.blogjava.net/lifenote/archive/2007/12/23/169806.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Sun, 23 Dec 2007 08:09:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/23/169806.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/169806.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/23/169806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/169806.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/169806.html</trackback:ping><description><![CDATA[强制浏览器重新访问服务器下载页面，而不是从缓存读取页面。使用这种方法时，编程者的主要任务是创建一个会话级的变量，<br />
通过这个变量确定用户是否仍旧可以查看那个不适合通过后退按钮访问的页面。由于浏览器不再缓存这个页面，当用户点击<br />
后退按钮时浏览器将重新下载该页面，此时程序就可以检查那个会话变量，看看是否应该允许用户打开这个页面。<br />
<br />
这是使网页过期:<br />
&lt;% <br />
response.setHeader("Pragma","no-cache");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //禁止http1.1缓存 <br />
response.setHeader("Cache-Control","no-store"); &nbsp;//禁止http1.2缓存<br />
response.setDateHeader("Expires",-1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;//禁止proxy缓存,-1:立即过期;0:不使用缓存<br />
%&gt; <br />
<br />
<br />
javascript防止後退:<br />
<br />
&nbsp;&lt;script &nbsp; &nbsp;language= &nbsp; &nbsp;"JavaScript &nbsp; &nbsp;" &nbsp; &nbsp;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp;&lt;!-- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;javascript:window.history.forward(1); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
//--&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp;&lt;/script &nbsp; &nbsp;&gt; <br />
<img src ="http://www.blogjava.net/lifenote/aggbug/169806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-23 16:09 <a href="http://www.blogjava.net/lifenote/archive/2007/12/23/169806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>★★oracle易忘函数用法★★</title><link>http://www.blogjava.net/lifenote/archive/2007/12/14/167677.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Fri, 14 Dec 2007 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/14/167677.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/167677.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/14/167677.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/167677.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/167677.html</trackback:ping><description><![CDATA[<p>===================★★oracle易忘函数用法★★=====================================<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;开发积累资料<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Author:SunXianchao<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2006年于湖南长沙<br />
==============================================================================<br />
一般的to_char是这样用的to_char(sysdate,'YYYY-MM-DD hh:mi:ss AM') ，也有几个突出点的用法：</p>
<p>to_char(sysdate, 'dd') 查看今天是几号to_char(sysdate, 'ww') 查看这是这个月第几个星期</p>
<p>to_char(sysdate, 'mm')&nbsp; 查看这是一年中第几个月</p>
<p>to_char(sysdate, 'yyyy') 查看年份last_day(to_date('2007-02-01','YYYY-MM-DD'))查看一个月的最后一天，add_months(sysdate,10)查看若干个月后的今天，next_day(sysdate,'星期五')给个日期查看后面的最近的星期几的日期，不过这个星期五要是换成英文居然有问题，第2个参数可以是数字1-7，分别表示周日到周六。</p>
<p>下面贴个全的，需要的时候顺便查一下。</p>
<p>一、PL/SQL单行函数和组函数详解</p>
<p>函数是一种有零个或多个参数并且有一个返回值的程序。在SQL中Oracle内建了一系列函数，这些函数都可被称为SQL或PL/SQL语句，函数主要分为两大类：单行函数和组函数。</p>
<p>本文将讨论如何利用单行函数以及使用规则。<br />
1、SQL中的单行函数</p>
<p>SQL和PL/SQL中自带很多类型的函数，有字符、数字、日期、转换、和混合型等多种函数用于处理单行数据，因此这些都可被统称为单行函数。这些函数均可用于SELECT,WHERE、ORDER BY等子句中，例如下面的例子中就包含了TO_CHAR,UPPER,SOUNDEX等单行函数。</p>
<p>SELECT ename,TO_CHAR(hiredate,'day,DD-Mon-YYYY')FROM empWhere UPPER(ename) Like 'AL%'ORDER BY SOUNDEX(ename) </p>
<p><br />
单行函数也可以在其他语句中使用，如update的SET子句，INSERT的VALUES子句，DELET的WHERE子句,认证考试特别注意在SELECT语句中使用这些函数，所以我们的注意力也集中在SELECT语句中。</p>
<p>2、NULL和单行函数</p>
<p>在如何理解NULL上开始是很困难的，就算是一个很有经验的人依然对此感到困惑。NULL值表示一个未知数据或者一个空值，算术操作符的任何一个操作数为NULL值，结果均为提个NULL值,这个规则也适合很多函数，只有CONCAT,DECODE,DUMP,NVL,REPLACE在调用了NULL参数时能够返回非NULL值。在这些中NVL函数时最重要的，因为他能直接处理NULL值，NVL有两个参数:NVL(x1,x2),x1和x2都式表达式，当x1为null时返回X2,否则返回x1。</p>
<p>下面我们看看emp数据表它包含了薪水、奖金两项，需要计算总的补偿。</p>
<p>column name emp_id salary bonuskey type pk nulls/unique nn,u nnfk table datatype number number numberlength 11.2 11.2 </p>
<p><br />
不是简单的将薪水和奖金加起来就可以了，如果某一行是null值那么结果就将是null，比如下面的例子：</p>
<p>update empset salary=(salary+bonus)*1.1 </p>
<p><br />
这个语句中，雇员的工资和奖金都将更新为一个新的值，但是如果没有奖金，即 salary + null,那么就会得出错误的结论，这个时候就要使用nvl函数来排除null值的影响。</p>
<p>所以正确的语句是：</p>
<p>update empset salary=(salary+nvl(bonus,0)*1.1 </p>
<p><br />
3、单行字符串函数</p>
<p>单行字符串函数用于操作字符串数据，他们大多数有一个或多个参数，其中绝大多数返回字符串。</p>
<p>ASCII()</p>
<p>c1是一字符串，返回c1第一个字母的ASCII码，他的逆函数是CHR()</p>
<p>SELECT ASCII('A') BIG_A,ASCII('z') BIG_z FROM empBIG_A BIG_z65 122 </p>
<p><br />
CHR()[NCHAR_CS]</p>
<p>i是一个数字，函数返回十进制表示的字符。</p>
<p>select CHR(65),CHR(122),CHR(223) FROM empCHR65 CHR122 CHR223A z B </p>
<p><br />
CONCAT(,)</p>
<p>c1,c2均为字符串，函数将c2连接到c1的后面，如果c1为null,将返回c2.如果c2为null,则返回c1，如果c1、c2都为null，则返回null。他和操作符||返回的结果相同</p>
<p>select concat('slobo ','Svoboda') username from dualusernameslobo Syoboda <br />
INITCAP()</p>
<p>c1为一字符串。函数将每个单词的第一个字母大写其它字母小写返回。单词由空格，控制字符，标点符号限制。</p>
<p>select INITCAP('veni,vedi,vici') Ceasar from dualCeasarVeni,Vedi,Vici </p>
<p><br />
INSTR(,[,[,]])</p>
<p>c1,c2均为字符串，i,j为整数。函数返回c2在c1中第j次出现的位置，搜索从c1的第i个字符开始。当没有发现需要的字符时返回0,如果i为负数，那么搜索将从右到左进行，但是位置的计算还是从左到右，i和j的缺省值为1。</p>
<p>select INSTR('Mississippi','i',3,3) from dualINSTR('MISSISSIPPI','I',3,3)11select INSTR('Mississippi','i',-2,3) from dualINSTR('MISSISSIPPI','I',3,3)2 </p>
<p><br />
INSTRB(,[,i[,j])</p>
<p>与INSTR()函数一样，只是他返回的是字节，对于单字节INSTRB()等于INSTR()。</p>
<p>LENGTH()</p>
<p>c1为字符串，返回c1的长度，如果c1为null，那么将返回null值。</p>
<p>select LENGTH('Ipso Facto') ergo from dualergo10 </p>
<p><br />
LENGTHb()</p>
<p>与LENGTH()一样，返回字节。</p>
<p>lower()</p>
<p>返回c的小写字符，经常出现在where子串中。</p>
<p>select LOWER(colorname) from itemdetail WHERE LOWER(colorname) LIKE '%white%'COLORNAMEWinterwhite </p>
<p><br />
LPAD(,[,])</p>
<p>c1,c2均为字符串，i为整数。在c1的左侧用c2字符串补足致长度i,可多次重复，如果i小于c1的长度，那么只返回i那么长的c1字符，其他的将被截去。c2的缺省值为单空格，参见RPAD。</p>
<p>select LPAD(answer,7,'') padded,answer unpadded from question;PADDED UNPADDED Yes YesNO NOMaybe maybe </p>
<p><br />
LTRIM(,)</p>
<p>把c1中最左边的字符去掉，使其第一个字符不在c2中，如果没有c2，那么c1就不会改变。</p>
<p>select LTRIM('Mississippi','Mis') from dualLTRppi </p>
<p><br />
RPAD(,[,])</p>
<p>在c1的右侧用c2字符串补足致长度i,可多次重复，如果i小于c1的长度，那么只返回i那么长的c1字符，其他的将被截去。c2的缺省值为单空格,其他与LPAD相似。</p>
<p>RTRIM(,)</p>
<p>把c1中最右边的字符去掉，使其第后一个字符不在c2中，如果没有c2，那么c1就不会改变。</p>
<p>REPLACE(,[,])</p>
<p>c1,c2,c3都是字符串，函数用c3代替出现在c1中的c2后返回。</p>
<p>select REPLACE('uptown','up','down') from dualREPLACEdowntown </p>
<p><br />
STBSTR(,[,])</p>
<p>c1为一字符串，i,j为整数，从c1的第i位开始返回长度为j的子字符串，如果j为空，则直到串的尾部。</p>
<p>select SUBSTR('Message',1,4) from dualSUBSMess </p>
<p><br />
SUBSTRB(,[,])</p>
<p>与SUBSTR大致相同，只是I,J是以字节计算。</p>
<p>SOUNDEX()</p>
<p>返回与c1发音相似的词。</p>
<p>select SOUNDEX('dawes') Dawes SOUNDEX('daws') Daws, SOUNDEX('dawson') from dualDawes Daws DawsonD200 D200 D250 </p>
<p><br />
TRANSLATE(,,)</p>
<p>将c1中与c2相同的字符以c3代替</p>
<p>select TRANSLATE('fumble','uf','ar') test from dualTEXTramble </p>
<p><br />
TRIM([[]] from c3)</p>
<p>将c3串中的第一个，最后一个，或者都删除。</p>
<p>select TRIM(' space padded ') trim from dual TRIMspace padded </p>
<p><br />
UPPER()</p>
<p>返回c1的大写，常出现where子串中</p>
<p>select name from dual where UPPER(name) LIKE 'KI%'NAMEKING </p>
<p><br />
4、单行数字函数</p>
<p>单行数字函数操作数字数据，执行数学和算术运算。所有函数都有数字参数并返回数字值。所有三角函数的操作数和值都是弧度而不是角度，oracle没有提供内建的弧度和角度的转换函数。</p>
<p>ABS()</p>
<p>返回n的绝对值</p>
<p>ACOS()</p>
<p>反余弦函数，返回-1到1之间的数。n表示弧度</p>
<p>select ACOS(-1) pi,ACOS(1) ZERO FROM dualPI ZERO3.14159265 0 </p>
<p><br />
ASIN()</p>
<p>反正弦函数，返回-1到1，n表示弧度</p>
<p>ATAN()</p>
<p>反正切函数，返回n的反正切值，n表示弧度。</p>
<p>CEIL()</p>
<p>返回大于或等于n的最小整数。</p>
<p>COS()</p>
<p>返回n的余玄值，n为弧度</p>
<p>COSH()</p>
<p>返回n的双曲余玄值，n 为数字。</p>
<p>select COSH(&lt;1.4&gt;) FROM dualCOSH(1.4)2.15089847 </p>
<p><br />
EXP()</p>
<p>返回e的n次幂，e=2.71828183.</p>
<p>FLOOR()</p>
<p>返回小于等于N的最大整数。</p>
<p>LN()</p>
<p>返回N的自然对数，N必须大于0</p>
<p>LOG(,)</p>
<p>返回以n1为底n2的对数</p>
<p>MOD()</p>
<p>返回n1除以n2的余数<br />
POWER(,)</p>
<p>返回n1的n2次方</p>
<p>ROUND(,)</p>
<p>返回舍入小数点右边n2位的n1的值，n2的缺省值为0，这回将小数点最接近的整数，如果n2为负数就舍入到小数点左边相应的位上，n2必须是整数。</p>
<p>select ROUND(12345,-2),ROUND(12345.54321,2) FROM dualROUND(12345,-2) ROUND(12345.54321,2)12300 12345.54 </p>
<p><br />
SIGN()</p>
<p>如果n为负数，返回-1,如果n为正数，返回1，如果n=0返回0</p>
<p>SIN()</p>
<p>返回n的正玄值,n为弧度。</p>
<p>SINH()</p>
<p>返回n的双曲正玄值,n为弧度。</p>
<p>SQRT()</p>
<p>返回n的平方根,n为弧度</p>
<p>TAN()</p>
<p>返回n的正切值,n为弧度</p>
<p>TANH()</p>
<p>返回n的双曲正切值,n为弧度</p>
<p>TRUNC(,)</p>
<p>返回截尾到n2位小数的n1的值，n2缺省设置为0，当n2为缺省设置时会将n1截尾为整数，如果n2为负值，就截尾在小数点左边相应的位上。</p>
<p>5、单行日期函数</p>
<p>单行日期函数操作DATA数据类型，绝大多数都有DATA数据类型的参数，绝大多数返回的也是DATA数据类型的值。</p>
<p>ADD_MONTHS(,)</p>
<p>返回日期d加上i个月后的结果。i可以使任意整数。如果i是一个小数，那么数据库将隐式的他转换成整数，将会截去小数点后面的部分。</p>
<p>LAST_DAY()</p>
<p>函数返回包含日期d的月份的最后一天</p>
<p>MONTHS_BETWEEN(,)</p>
<p>返回d1和d2之间月的数目,如果d1和d2的日的日期都相同，或者都使该月的最后一天，那么将返回一个整数，否则会返回的结果将包含一个分数。</p>
<p>NEW_TIME(,,)</p>
<p>d1是一个日期数据类型，当时区tz1中的日期和时间是d时，返回时区tz2中的日期和时间。tz1和tz2时字符串。</p>
<p>NEXT_DAY(,)</p>
<p>返回日期d后由dow给出的条件的第一天，dow使用当前会话中给出的语言指定了一周中的某一天，返回的时间分量与d的时间分量相同。</p>
<p>select NEXT_DAY('01-Jan-2000','Monday') "1st Monday",NEXT_DAY('01-Nov-2004','Tuesday')+7 "2nd Tuesday") from dual;1st Monday 2nd Tuesday03-Jan-2000 09-Nov-2004 </p>
<p><br />
ROUND([,])</p>
<p>将日期d按照fmt指定的格式舍入，fmt为字符串。</p>
<p>SYADATE</p>
<p>函数没有参数，返回当前日期和时间。</p>
<p>TRUNC([,])</p>
<p>返回由fmt指定的单位的日期d<br />
6、单行转换函数</p>
<p>单行转换函数用于操作多数据类型，在数据类型之间进行转换。</p>
<p>CHARTORWID()</p>
<p>c 使一个字符串，函数将c转换为RWID数据类型。</p>
<p>SELECT test_id from test_case where rowid=CHARTORWID('AAAA0SAACAAAALiAAA') </p>
<p><br />
CONVERT(,[,])</p>
<p>c尾字符串，dset、sset是两个字符集，函数将字符串c由sset字符集转换为dset字符集，sset的缺省设置为数据库的字符集。</p>
<p>HEXTORAW()</p>
<p>x为16进制的字符串，函数将16进制的x转换为RAW数据类型。</p>
<p>RAWTOHEX()</p>
<p>x是RAW数据类型字符串，函数将RAW数据类转换为16进制的数据类型。</p>
<p>ROWIDTOCHAR()</p>
<p>函数将ROWID数据类型转换为CHAR数据类型。</p>
<p>TO_CHAR([[,)</p>
<p>x是一个data或number数据类型，函数将x转换成fmt指定格式的char数据类型，如果x为日期nlsparm=NLS_DATE_LANGUAGE 控制返回的月份和日份所使用的语言。如果x为数字nlsparm=NLS_NUMERIC_CHARACTERS 用来指定小数位和千分位的分隔符，以及货币符号。</p>
<p>NLS_NUMERIC_CHARACTERS ="dg", NLS_CURRENCY="string" </p>
<p><br />
TO_DATE([,[,)</p>
<p>c表示字符串，fmt表示一种特殊格式的字符串。返回按照fmt格式显示的c,nlsparm表示使用的语言。函数将字符串c转换成date数据类型。</p>
<p>TO_MULTI_BYTE()</p>
<p>c表示一个字符串，函数将c的担子截字符转换成多字节字符。</p>
<p>TO_NUMBER([,[,)</p>
<p>c表示字符串，fmt表示一个特殊格式的字符串，函数返回值按照fmt指定的格式显示。nlsparm表示语言，函数将返回c代表的数字。</p>
<p>TO_SINGLE_BYTE()</p>
<p>将字符串c中得多字节字符转化成等价的单字节字符。该函数仅当数据库字符集同时包含单字节和多字节字符时才使用</p>
<p>7、其它单行函数</p>
<p>BFILENAME(,) </p>
<p><br />
dir是一个directory类型的对象，file为一文件名。函数返回一个空的BFILE位置值指示符，函数用于初始化BFILE变量或者是BFILE列。</p>
<p>DECODE(,,[,,,[])</p>
<p>x是一个表达式，m1是一个匹配表达式，x与m1比较，如果m1等于x，那么返回r1,否则,x与m2比较，依次类推m3,m4,m5....直到有返回结果。</p>
<p>DUMP(,[,[,[,]]])</p>
<p>x是一个表达式或字符，fmt表示8进制、10进制、16进制、或则单字符。函数返回包含了有关x的内部表示信息的VARCHAR2类型的值。如果指定了n1,n2那么从n1开始的长度为n2的字节将被返回。</p>
<p>EMPTY_BLOB()</p>
<p>该函数没有参数，函数返回 一个空的BLOB位置指示符。函数用于初始化一个BLOB变量或BLOB列。</p>
<p>EMPTY_CLOB()</p>
<p>该函数没有参数，函数返回 一个空的CLOB位置指示符。函数用于初始化一个CLOB变量或CLOB列。</p>
<p>GREATEST()</p>
<p>exp_list是一列表达式，返回其中最大的表达式，每个表达式都被隐含的转换第一个表达式的数据类型，如果第一个表达式是字符串数据类型中的任何一个，那么返回的结果是varchar2数据类型，同时使用的比较是非填充空格类型的比较。<br />
LEAST()</p>
<p>exp_list是一列表达式，返回其中最小的表达式，每个表达式都被隐含的转换第一个表达式的数据类型，如果第一个表达式是字符串数据类型中的任何一个，将返回的结果是varchar2数据类型，同时使用的比较是非填充空格类型的比较。</p>
<p>UID</p>
<p>该函数没有参数，返回唯一标示当前数据库用户的整数。</p>
<p>USER</p>
<p>返回当前用户的用户名</p>
<p>USERENV()</p>
<p>基于opt返回包含当前会话信息。opt的可选值为：</p>
<p>ISDBA　 会话中SYSDBA脚色响应，返回TRUE</p>
<p>SESSIONID 　返回审计会话标示符</p>
<p>ENTRYID 返回可用的审计项标示符</p>
<p>INSTANCE在会话连接后，返回实例标示符。该值只用于运行Parallel 服务器并且有 多个实例的情况下使用。</p>
<p>LANGUAGE返回语言、地域、数据库设置的字符集。</p>
<p>LANG返回语言名称的ISO缩写。</p>
<p>TERMINAL为当前会话使用的终端或计算机返回操作系统的标示符。</p>
<p>VSIZE()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x是一个表达式。返回x内部表示的字节数。</p>
<p>二、SQL中的组函数</p>
<p>组函数也叫集合函数，返回基于多个行的单一结果，行的准确数量无法确定，除非查询被执行并且所有的结果都被包含在内。与单行函数不同的是，在解析时所有的行都是已知的。由于这种差别使组函数与单行函数有在要求和行为上有微小的差异.</p>
<p>1、组(多行)函数</p>
<p>与单行函数相比，oracle提供了丰富的基于组的，多行的函数。这些函数可以在select或select的having子句中使用，当用于select子串时常常都和GROUP BY一起使用。</p>
<p>AVG([{DISYINCT|ALL}])</p>
<p>返回数值的平均值。缺省设置为ALL</p>
<p>SELECT AVG(sal),AVG(ALL sal),AVG(DISTINCT sal) FROM scott.empAVG(SAL) AVG(ALL SAL) AVG(DISTINCT SAL)1877.94118 1877.94118 1916.071413 </p>
<p><br />
COUNT({*|DISTINCT|ALL} )</p>
<p>返回查询中行的数目，缺省设置是ALL,*表示返回所有的行。</p>
<p>MAX([{DISTINCT|ALL}])</p>
<p>返回选择列表项目的最大值，如果x是字符串数据类型，他返回一个VARCHAR2数据类型，如果X是一个DATA数据类型，返回一个日期，如果X是numeric数据类型，返回一个数字。注意distinct和all不起作用，应为最大值与这两种设置是相同的。</p>
<p>MIN([{DISTINCT|ALL}])</p>
<p>返回选择列表项目的最小值。</p>
<p>STDDEV([{DISTINCT|ALL}])</p>
<p>返回选者的列表项目的标准差，所谓标准差是方差的平方根。</p>
<p>SUM([{DISTINCT|ALL}])</p>
<p>返回选择列表项目的数值的总和。</p>
<p>VARIANCE([{DISTINCT|ALL}])</p>
<p>返回选择列表项目的统计方差。</p>
<p>2、用GROUP BY给数据分组</p>
<p>正如题目暗示的那样组函数就是操作那些已经分好组的数据，我们告诉数据库用GROUP BY怎样给数据分组或者分类，当我们在SELECT语句的SELECT子句中使用组函数时，我们必须把为分组或非常数列放置在GROUP BY子句中，如果没有用group by进行专门处理，那么缺省的分类是将整个结果设为一类。</p>
<p>select stat,counter(*) zip_count from zip_codes GROUP BY state;ST ZIP_COUNT-- ---------AK 360AL 1212AR 1309AZ 768CA 3982 </p>
<p><br />
在这个例子中，我们用state字段分类;如果我们要将结果按照zip_codes排序,可以用ORDER BY语句，ORDER BY子句可以使用列或组函数。</p>
<p>select stat,counter(*) zip_count from zip_codes GROUP BY state ORDER BY COUNT(*) DESC;ST COUNT(*)-- --------NY 4312PA 4297TX 4123CA 3982 </p>
<p><br />
3、用HAVING子句限制分组数据</p>
<p>现在你已经知道了在查询的SELECT语句和ORDER BY子句中使用主函数，组函数只能用于两个子串中，组函数不能用于WHERE子串中，例如下面的查询是错误的：</p>
<p>错误SELECT sales_clerk,SUN(sale_amount) FROM gross_sales WHERE sales_dept='OUTSIDE' AND SUM(sale_amount)&gt;10000 GROUP BY sales_clerk</p>
<p>这个语句中数据库不知道SUM()是什么，当我们需要指示数据库对行分组，然后限制分组后的行的输出时，正确的方法是使用HAVING语句：</p>
<p>SELECT sales_clerk,SUN(sale_amount) FROM gross_sales WHERE sales_dept='OUTSIDE' GROUP BY sales_clerkHAVING SUM(sale_amount)&gt;10000; </p>
<p><br />
4、嵌套函数</p>
<p>函数可以嵌套。一个函数的输出可以是另一个函数的输入。操作数有一个可继承的执行过程。但函数的优先权只是基于位置，函数遵循由内到外，由左到右的原则。嵌套技术一般用于象DECODE这样的能被用于逻辑判断语句IF....THEN...ELSE的函数。</p>
<p>嵌套函数可以包括在组函数中嵌套单行函数，或者组函数嵌套入单行函数或组函数中。比如下面的例子：</p>
<p>SELECT deptno, GREATEST(COUNT(DISTINCT job),COUNT(DISTINCT mgr) cnt,COUNT(DISTINCT job) jobs,COUNT(DISTINCT mgr) mgrsFROM empGROUP BY deptno;DEPTNO CNT JOBS MGRS------ --- ---- ----10 4 4 220 4 3 430 3 3 2 </p>
<p><br />
&nbsp;</p>
<img src ="http://www.blogjava.net/lifenote/aggbug/167677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-14 10:02 <a href="http://www.blogjava.net/lifenote/archive/2007/12/14/167677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 软件空间</title><link>http://www.blogjava.net/lifenote/archive/2007/12/14/167656.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Fri, 14 Dec 2007 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/14/167656.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/167656.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/14/167656.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/167656.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/167656.html</trackback:ping><description><![CDATA[<a href="http://web.99081.com/sysweb/RegTrans.aspx?CodeProvider=sunxian99">注册了一个网站，使用的是下面的这个空间，常来网，无限空间大小完全免费，上传速度很不错，感觉挺好推荐给大家，来注册一个空间上传资料使用<br />
http://web.99081.com/sysweb/RegTrans.aspx?CodeProvider=sunxian99</a><br />
  <img src ="http://www.blogjava.net/lifenote/aggbug/167656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-14 09:23 <a href="http://www.blogjava.net/lifenote/archive/2007/12/14/167656.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry 开发笔记（积累）</title><link>http://www.blogjava.net/lifenote/archive/2007/12/13/167528.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Thu, 13 Dec 2007 08:21:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/13/167528.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/167528.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/13/167528.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/167528.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/167528.html</trackback:ping><description><![CDATA[<p>====================================================================================<br />
'&nbsp;说明：Tapestry 开发笔记<br />
'&nbsp;Note Author:&nbsp;Sunxianchao<br />
'&nbsp;阅读日期：&nbsp;2007-9-18(北京.七彩谷)<br />
'====================================================================================<br />
<br />
<br />
<br />
'先做个小广告 免费的无限空间还可以就是要积分 下面是我的注册地址 直接注册就可以了 奖励10个积分<br />
http://web.99081.com/sysweb/RegTrans.aspx?CodeProvider=sunxian99<br />
麻烦帮忙顶一个 多谢<br />
<br />
<br />
【各种组建使用】<br />
说明：只是说明一些需要注意的东西，更多的学习参考Tapestry官方文档<br />
1、For<br />
source:是对应的java类里的List 对象或者是个数组 需要抽象 或者提供set get方法<br />
value:是循环这个source对象代表当前的一个 ，需要在page文件中设置问一个属性，可以不在对应的java类里有这个属性<br />
index:是循环的索引值 同value一样 在page文件中设置一个属性即可 &lt;property name="index"/&gt;<br />
在循环的时候 会自动为vlaue和index赋当前的值</p>
<p>2、Foreach 和For一样使用</p>
<p>3、Hidden组件 总是多余S的处理<br />
&nbsp;&lt;input jwcid="@Hidden" type="hidden" value="ognl:blahblah" encode="false"/&gt;</p>
<p><br />
4、 Insert 组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;input type="text" jwcid="name@Insert" value="ognl:user.name"/&gt; <br />
&nbsp;&nbsp;&nbsp; 页面表现时,将会到页面类中寻找getUser().getName()方法获取初值并输出 <br />
&nbsp;&nbsp;&nbsp; 相当于在页面上显示数据.</p>
<p>5、 TextField 组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;input type="text" jwcid="username@TextField" value="ognl:username"/&gt; <br />
&nbsp;&nbsp;&nbsp; 页面表现时,将会到页面类中寻找getUsername()方法获取初值 <br />
&nbsp;&nbsp;&nbsp; *如果是修改信息页面,通常初始值要在页面表现之前由setUsername()手动设置从数据库中读取出来的值 <br />
&nbsp;&nbsp;&nbsp; 表单提交时,通过setUsername()写入新值(即用户输入值),在类中通过getUsername()获取新值 <br />
&nbsp;&nbsp;&nbsp; 相当于在修改个人信息时,首先读出用户名赋予文本框(用户名)初值,用户修改时填入新值,后台获取之 <br />
&nbsp;&nbsp;&nbsp; *Hidden属性区分是普通文本输入框(默认false)和密码输入框(hidden="ognl:true") <br />
&nbsp;&nbsp;&nbsp; readonly属性设置只读 readonly="true"为只读(后台可读取) <br />
&nbsp;&nbsp;&nbsp; *disabled属性设置是否可写 diabled="true"为不可写(后台也不可读取)</p>
<p>6、 TextArea 组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;textarea jwcid="content@TextArea" value="ognl:content" cols="40" rows="10"&gt;&lt;/textarea&gt; <br />
&nbsp;&nbsp;&nbsp; 页面表现时,将会到页面类中寻找getContent()方法获取初值 <br />
&nbsp;&nbsp;&nbsp; 工作原理同TextField</p>
<p>7、 RadioGroup/Radio 组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="headImage@RadioGroup" selected="ognl:headImage"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input jwcid="@Radio" type="radio" value="1"/&gt;头像1 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input jwcid="@Radio" type="radio" value="2"/&gt;头像2 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input jwcid="@Radio" type="radio" value="3"/&gt;头像3 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input jwcid="@Radio" type="radio" value="4"/&gt;头像4 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input jwcid="@Radio" type="radio" value="5"/&gt;头像5 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input jwcid="@Radio" type="radio" value="6"/&gt;头像6 <br />
&nbsp;&nbsp;&nbsp; &lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; RadioGroup为每一个Radio提供一个唯一的ID。RadioGroup跟踪当前被选中的属性值，并且只有一个Radio能够被选中. <br />
&nbsp;&nbsp;&nbsp; 页面提交时，RadioGroup组件就利用OGNL表达式向headImage字段写入被选中的Radio组件的value参数值. <br />
&nbsp;&nbsp;&nbsp; 页面表现时(修改页面),将会到页面类中寻找getHeadImage()方法获取初值,然后寻找@Radio组件中与其相同的组件并勾选上.</p>
<p>8、 PropertySelection 组件 <br />
&nbsp;&nbsp;&nbsp; 使用PropertySelection组件必须要构造一个类来实现IPropertySelectionModel接口，并且重写该接口的5个方法. <br />
&nbsp;&nbsp;&nbsp; public int getOptionCount() //提供下拉菜单的长度 <br />
&nbsp;&nbsp;&nbsp; public Object getOption(int index) //提供select标签的option <br />
&nbsp;&nbsp;&nbsp; public String getLabel(int index) //提供select标签的Label值，也就是下拉菜单显示的内容 <br />
&nbsp;&nbsp;&nbsp; public String getValue(int index) //提供select标签的value值 <br />
&nbsp;&nbsp;&nbsp; public Object translateValue(String value) //selected后的返回值，value值未必就是我们需要的返回值，可以在这个方法里面对返回的value做对应的转换或修改. <br />
e.g.1. 性别下拉框 <br />
&nbsp;&nbsp;&nbsp; &lt;select jwcid="gender@ProPertySelection" name="genderSelect" value="ognl:gender" model="supportedGender"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;option selected&gt;先生&lt;/option&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;option&gt;女士&lt;/option&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/select&gt; </p>
<p><br />
代码<br />
GenderSelectionModel.java&nbsp;&nbsp; <br />
public class GenderSelectionModel implements IPropertySelectionModel {&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static final String male = "先生";&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static final String female = "女士";&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static final String[] genderOptions = { male, female };&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public int getOptionCount() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return genderOptions.length;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Object getOption(int index) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.translateValue(genderOptions[index]);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String getLabel(int index) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return genderOptions[index].toString();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String getValue(int index) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return genderOptions[index];&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Object translateValue(String value) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (value.equals("先生")) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "1";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "0";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
}&nbsp; </p>
<p>&nbsp;</p>
<p>代码<br />
ModUserInfo.java&nbsp;&nbsp; <br />
public IPropertySelectionModel getSupportedGender() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return new GenderSelectionModel();&nbsp;&nbsp; <br />
}&nbsp; </p>
<p><br />
&nbsp;&nbsp;&nbsp; 存入数据库中"1"代表先生,"0"代表女士,通过translateValue(String value)方法转换 <br />
&nbsp;&nbsp;&nbsp; 页面表现时,通过model属性给出的IPropertySelectionModel获取下拉选项,即getSupportedGender(). <br />
&nbsp;&nbsp;&nbsp; 然后通过getGender()方法获取初值,比如获取"0",则在页面显示时寻找value值为"0"的选项即为"女士",并选择之作为初始选择项.</p>
<p>e.g.2. 日志类型下拉框 <br />
&nbsp;&nbsp;&nbsp; &lt;select jwcid="logType@PropertySelection" name="typeSelect" value="ognl:logType" model="supportedType"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;option&gt;心情日记&lt;/option&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;option&gt;情感天地&lt;/option&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;option&gt;生活感触&lt;/option&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/select&gt; </p>
<p><br />
代码<br />
TypeSelectionModel.java&nbsp;&nbsp; <br />
public class TypeSelectionModel implements IPropertySelectionModel {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private List typeList = new ArrayList();&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public TypeSelectionModel(List typeList) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.typeList = typeList;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public int getOptionCount() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return typeList.size();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Object getOption(int index) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((LogType)typeList.get(index)).getValue();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String getLabel(int index) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((LogType) typeList.get(index)).getName();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String getValue(int index) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((LogType) typeList.get(index)).getValue();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Object translateValue(String value) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return value;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
}&nbsp; </p>
<p>&nbsp;</p>
<p>代码<br />
ModLog.java&nbsp;&nbsp; <br />
public IPropertySelectionModel getSupportedType() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; TypeSelectionModel typeSelectionModel =&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new TypeSelectionModel(loadType(getUser().getUserId()));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return typeSelectionModel;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
&nbsp; <br />
private List loadType(int userid) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; ...//从数据库载入该用户的日志类型列表&nbsp;&nbsp; <br />
}&nbsp; </p>
<p><br />
&nbsp;&nbsp;&nbsp; 页面表现时,通过model属性给出的IPropertySelectionModel获取下拉选项,即getSupportedType(). <br />
&nbsp;&nbsp;&nbsp; 然后通过value属性给出的初始值即,getLogType()方法获取初值,比如获取"2",则在页面显示时寻找value值为"2"的选项即为"生活感触",并选择之作为初始选择项.</p>
<p>9、 Form组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;form jwcid="logForm@Form"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... <br />
&nbsp;&nbsp;&nbsp; &lt;/form&gt; <br />
&nbsp;&nbsp;&nbsp; Form的监听(listener)方法可以有两种方式: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. 在Form组件中声明. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form jwcid="logForm@Form" listener="ognl:listener:onLogin"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/form&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. 在submit类型组件中声明. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input type="submit" jwcid="onLogin@Submit" listener="listener:onLogin" value="发表"/&gt;或者 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;span jwcid="@ImageSubmit" image="..." listener="listener:onLogin"&gt;&lt;img src="..." width="" height=""/&gt;&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前一种方式当Form中只要有submit就会触发监听方法,后一种方式是Form中有多个submit,各自实现不同的监听方法.</p>
<p>G) Foreach 组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@Foreach" source="ognl:logList" value="ognl:item"&gt; <br />
&nbsp;&nbsp;&nbsp; 循环组件,遍历source参数,在表现其内容前更新value参数,将Foreach组件所包含的内容重复表现,其中可以通过value参数获取所需显示内容. <br />
&nbsp;&nbsp;&nbsp; 本例中,页面表现时通过getLogList()方法获取日志列表,循环取出其中数据更新item(日志对象)并予以显示.其中item需要在页面规范(.page)文件中声明: <br />
&nbsp;&nbsp;&nbsp; &lt;property name="item"/&gt; <br />
&nbsp;&nbsp;&nbsp; *class参数用来寻找类似CSS的文件对Foreach进行修饰. <br />
&nbsp;&nbsp;&nbsp; Foreach组件: class="ognl:beans.evenOdd.next" <br />
&nbsp;&nbsp;&nbsp; Page文件: &lt;bean name="evenOdd" class="org.apache.tapestry.bean.EvenOdd"/&gt; <br />
&nbsp;&nbsp;&nbsp; CSS文件: tr.odd{background-color: #ffffff;}tr.even{background-color: #eeeeee;}</p>
<p>10、 Conditional 组件 <br />
e.g. <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@Conditional" condition='ognl:item.sex.equals("1")'&gt;先生&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@Conditional" condition='ognl:item.sex.equals("0")'&gt;女士&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; conditional参数为true时运行Conditional组件中的HTML模板内容. <br />
&nbsp;&nbsp;&nbsp; 在Tapestry4.0以后就不支持该组件了, 可以使用其他组件来实现: <br />
&nbsp;&nbsp;&nbsp; 1. Contrib:Choose和Contrib:When <br />
&nbsp;&nbsp;&nbsp; &lt;library id="contrib" specification-path="classpath:/org/apache/tapestry/contrib/Contrib.library"/&gt;(.application文件中引入Contrib类包) <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@contrib:Choose"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;span jwcid="@contrib:When" condition='ognl:user.gender.equals("1")'&gt;先生&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;span jwcid="@contrib:When" condition='ognl:user.gender.equals("0")'&gt;女士&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; 2. If组件 <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@If" condition='ognl:item.sex.equals("1")'&gt;先生&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@If" condition='ognl:item.sex.equals("0")'&gt;女士&lt;/span&gt; <br />
&nbsp;&nbsp;&nbsp; 3. Else组件<br />
&nbsp;&nbsp;&nbsp; &lt;span jwcid="@Else"&gt;man&lt;/span&gt; </p>
<p>【============================ts的函数执行顺序========================================】<br />
对之前的该文章进行了一些修正，主要是针对finishLoad()方法。 <br />
我觉得对初学者会有一些帮助。 <br />
下面这几个函数是我在使用的，它们的执行顺序依次从上到下。 <br />
1.protected void finishLoad() {} *** <br />
2.public void pageValidate(PageEvent event) {} <br />
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {} <br />
4.public void pageBeginRender(PageEvent event) {} <br />
// 如果有表单提交，则将form中的各字段的值赋给页面类 <br />
5. ...... 赋值 <br />
6.public void submit() // 表单提交等用listenter:调用的方法 <br />
7.protected void prepareForRender(IRequestCycle cycle) {} <br />
---------------------------------------------------- <br />
1.protected void finishLoad() {} <br />
这个函数最先执行，但是它实际上没有什么用处（我感觉）。因为： <br />
　　这个函数只在页面池中没有某一个页面类、需要生成一个新的页面对象时才调用。这里就有一个陷阱：如果你的tomcat启动时使用了-Dorg.apache.tapestry.disable-caching=true(为了调试方便而设)，那么你每次刷新页面时，它都会执行（因为每个request都会新生成一个页面类对象），造成了它总是执行的假象。在实际的部署时，会使用caching，则这个函数执行的机会很少。所以要注意。 <br />
　　初始化的代码放在4 pageBeginRender()中 <br />
2.public void pageValidate(PageEvent event) {} <br />
如果实现了PageValidateListener接口，则可以在这里进行验证，比如访问权限等。执行完1后，它就开始执行。 <br />
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {} <br />
如果实现了IExternalPage接口，则可以从这里取得由外面传过来的参数。执行2后，执行到这里。在这里可以把那些参数取出，赋给页面类。 <br />
4.public void pageBeginRender(PageEvent event) {} <br />
执行完3后，将执行本函数。但是这时从客户端传过来的参数还没有被赋值(如果提交了表单的话)。这里可以进行一些初始化操作。 <br />
5.执行完4后，如果有表单提交，在这里将会取出那些值，赋给对应的字段。(注意：只是将表单中有的值赋过来) <br />
6.public void submit() <br />
如果有表单提交的话，在这里将进行对应的操作。因为此时各字段已经取好值了，所以可以拿来直接用。 <br />
7.protected void prepareForRender(IRequestCycle cycle) {} <br />
最后才执行这个方法。我们可以在其中进行为了在页面上显示数据而进行的操作，比如取得什么对象什么的，因为这里页面类的属性赋值已经结束，可以直接拿来使用了。 <br />
注意：如果执行了6，则还要执行4，再执行7。如果没有6，4完了就直接是7。 <br />
以上是我所总结的执行顺序，不当之处请指出。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>----------------------------------------------------- <br />
最开始学tapestry的时候，觉得&#8220;怎么有这么多地方需要持久啊&#8221;。原来以前只知道pageBeginRender这个函数，什么初始化操作都放在它里面。可是它是在赋值之前执行，所以拿到的字段多都是空的，却都以为是没有持久化的缘故。所以在客户端里放了一大堆的@Hidden，或者session中持久，非常麻烦，，，对tapestry也产生的怀疑。现在才知道那些需要取得客户端传来的参数的代码，最好放在prepareForRender里，很多不必要的持久都可以省掉了</p>
 <img src ="http://www.blogjava.net/lifenote/aggbug/167528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-13 16:21 <a href="http://www.blogjava.net/lifenote/archive/2007/12/13/167528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转自BeanSoft----JSP 中 AJAX 的表单提交中文问题的简单解决方案 - GBK 版本</title><link>http://www.blogjava.net/lifenote/archive/2007/12/12/167132.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Wed, 12 Dec 2007 01:51:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/12/167132.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/167132.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/12/167132.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/167132.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/167132.html</trackback:ping><description><![CDATA[<p>作者: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#98;&#101;&#97;&#110;&#115;&#111;&#102;&#116;&#64;&#49;&#50;&#54;&#46;&#99;&#111;&#109;">beansoft@126.com</a> 2007.01.03</p>
<p>下载本文源码: <a href="http://www.blogjava.net/Files/beansoft/ajaxform_gbk.zip">ajaxform_gbk.zip</a> 6KB<br />
</p>
转载请注明原创作者, 尊重他人劳动成果.
<p>更新:<br />
<strong>2007-01-03<br />
</strong>修复了 AJAXFormer 中第二个参数 resultDiv 处理不当的问题;<br />
增加了从服务器端返回脚本并加以执行的功能;<br />
增加了表单提交后网络出错的错误显示功能.<br />
这些新功能都已经放在示例页面中了.</p>
<p>测试通过: Resin 3.0.18, Tomcat 5.0.30, 5.5.20; 浏览器: IE 6/Firefox 2.0.<br />
</p>
<p>上一篇文章 <a href="http://www.blogjava.net/beansoft/archive/2006/12/25/89835.html">JSP 中 AJAX 的表单提交中文问题的简单解决方案</a> 主要是针对 UTF-8 版本的进行处理的, 鉴于中国大陆地区大部分还是用 GBK 编码写 JSP, 因此本文就针对 GBK 的实践结果进行介绍.</p>
<p>有朋友提到 <a href="http://www.blogjava.net/errorfun/archive/2006/12/30/91000.html">当AJAX遭遇GBK的尴尬</a> 里说当 AJAX 使用 GBK 编码后, 表单提交将出现乱码. 如前文所述, 只要全部采用 UTF-8 编码, 是没有任何问题的. 那么都用 GBK 呢?</p>
<p>首先要讲的是我们的文章还是一样的原则: 尽可能少的改动原来的代码来解决中文乱码问题. 所以本文的示例没有用过滤器等方法.</p>
<p>那么使用 GBK 编码到底有没有乱码问题呢?</p>
<p>第一个关键点就是 AJAX 的表单提交代码必须正确的按照 HTTP 规范实现, 即要保持原来的 GET/POST 方式不变, 也要保持里面的内容和浏览器提交的内容一摸一样. 以下内容摘自我编写的内部培训教材:</p>
<p>----------------- 引用开始 -----------------</p>
<p>首先必须要介绍一下 HTTP 协议和 GET, POST 的工作方式.</p>
<p>当用户在Web浏览器地址栏中输入一个带有http://前缀的URL并按下Enter后,或者在Web页面中某个以http://开头的超链接上单击鼠标,HTTP事务处理的第一个阶段--建立连接阶段就开始了.HTTP的默认端口是80.<br />
随着连接的建立,HTTP就进入了客户向服务器发送请求的阶段.客户向服务器发送的请求是一个有特定格式的ASCII消息,其语法规则为:</p>
<table>
    <tbody>
        <tr>
            <td>6KB<br />
            </td>
        </tr>
    </tbody>
    <tbody>
        <tr>
            <td width="100%">&lt; Method &gt; &lt; URL &gt; &lt; HTTP Version &gt; &lt;\n&gt;<br />
            { &lt;Header&gt;:&lt;Value&gt; &lt;\n&gt;}*<br />
            &lt;\n&gt;<br />
            { Entity Body }</td>
        </tr>
    </tbody>
</table>
<p>请求消息的顶端是请求行,用于指定方法,URL和HTTP协议的版本,请求行的最后是回车换行.方法有GET,POST,HEAD,PUT,DELETE等.<br />
在请求行之后是若干个报头(Header)行.每个报头行都是由一个报头和一个取值构成的二元对,报头和取值之间以":"分隔;报头行的最后是回车换行. 常见的报头有Accept(指定MIME媒体类型),Accept_Charset(响应消息的编码方式),Accept_Encoding(响应消息的字符集),User_Agent(用户的浏览器信息)等.<br />
在请求消息的报头行之后是一个回车换行,表明请求消息的报头部分结束.在这个\n之后是请求消息的消息实体(Entity Body).<br />
Web服务器在收到客户请求并作出处理之后,要向客户发送应答消息.与请求消息一样,应答消息的语法规则为:</p>
<table style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td width="100%">&lt; HTTP Version&gt; &lt;Status Code&gt; [&lt;Message&gt;]&lt;\n&gt;<br />
            { &lt;Header&gt;:&lt;Value&gt; &lt;\n&gt; } *<br />
            &lt;\n&gt;<br />
            { Entity Body }</td>
        </tr>
    </tbody>
</table>
<p>应答消息的第一行为状态行,其中包括了HTTP版本号,状态码和对状态码进行简短解释的消息;状态行的最后是回车换行.状态码由3位数字组成,有5类:<br />
</p>
<ul>
    <li>1XX 保留
    <li>2XX 表示成功
    <li>3XX 表示URL已经被移走
    <li>4XX 表示客户错误
    <li>5XX 表示服务器错误</li>
</ul>
<p>例如:415,表示不支持改媒体类型;503,表示服务器不能访问.最常见的是200,表示成功.常见的报头有:Last_Modified(最后修改时间),Content_Type(消息内容的MIME类型),Content_Length(内容长度)等.<br />
在报头行之后也是一个回车换行,用以表示应答消息的报头部分的结束,以及应答消息实体的开始.<br />
下面是一个应答消息的例子:</p>
<table style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td width="100%">HTTP/1.0 200 OK<br />
            Date: Moday,07-Apr-97 21:13:02 GMT<br />
            Server:NCSA/1.1<br />
            MIME_Version:1.0<br />
            Content_Type:text/html<br />
            Last_Modified:Thu Dec 5 09:28:01 1996<br />
            Coentent_Length:3107<br />
            <br />
            &lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;...&lt;/HTML&gt;</td>
        </tr>
    </tbody>
</table>
<p>那么 GET 和 POST 有什么区别? 区别就是一个在 URL 请求里面附带了表单参数和值, 一个是在 HTTP 请求的消息实体中. 用下面的例子可以很容易的看到同样的数据通过GET和POST来发送的区别, 发送的数据是 username=张三 :</p>
<p>　GET 方式, 浏览器键入 http://localhost?username=张三<br />
</p>
<table style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td width="100%">GET /?username=%E5%BC%A0%E4%B8%89 HTTP/1.1<br />
            Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*<br />
            Accept-Language: zh-cn<br />
            Accept-Encoding: gzip, deflate<br />
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)<br />
            Host: localhost<br />
            Connection: Keep-Alive</td>
        </tr>
    </tbody>
</table>
<p>POST 方式:</p>
<table style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td width="100%">POST / HTTP/1.1<br />
            Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*<br />
            Accept-Language: zh-cn<br />
            Content-Type: application/x-www-form-urlencoded<br />
            Accept-Encoding: gzip, deflate<br />
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)<br />
            Host: localhost<br />
            Content-Length: 28<br />
            Connection: Keep-Alive<br />
            <br />
            username=%E5%BC%A0%E4%B8%89</td>
        </tr>
    </tbody>
</table>
<p>比较一下上面的两段文字, 您会发现 GET 方式把表单内容放在前面的请求头中, 而 POST 则把这些内容放在请求的主体中了, 同时 POST 中把请求的 Content-Type 头设置为 application/x-www-form-urlencoded. 而发送的正文都是一样的, 可以这样来构造一个表单提交正文:</p>
<p><em>encodeURIComponent(arg1)=encodeURIComponent(value1)&amp;encodeURIComponent(arg2)=encodeURIComponent(value2)&amp;.....</em></p>
<p>注: <strong>encodeURIComponent</strong> 返回一个包含了 <em>charstring</em> 内容的新的 <strong>String</strong> 对象（Unicode 格式）， 所有空格、标点、重音符号以及其他非 ASCII 字符都用 <strong>%</strong><em>xx</em> 编码代替，其中 <em>xx</em> 等于表示该字符的十六进制数。 例如，空格返回的是 "%20" 。 字符的值大于 255 的用 <strong>%u</strong><em>xxxx</em> 格式存储。参见 JavaScript 的 encodeURIComponent() 方法.</p>
<p>下面就讨论一下如何在 JavaScript 中执行一个 GET 或者 POST 请求. 如果您用过 Java, 那么您可能熟悉下列的用 java.net.URLConnection 类进行 POST 操作的代码(参考 <span style="font-size: 0.9em; font-family: verdana,arial,helvetica"><a href="http://www.javaworld.com/javatips/jw-javatip34.html">Java Tip 34: POSTing via Java</a> ):<br />
　</span></p>
<table id="table1" style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td><code><span style="font-size: 0.75em; color: rgb(0,0,0); font-family: Courier New">URL url;<br />
            URLConnection urlConn;<br />
            DataOutputStream printout;<br />
            <span style="color: rgb(0,128,0)">// URL of CGI-Bin or jsp, asp script.<br />
            </span>url = <strong>new</strong> URL (<span style="color: rgb(0,0,128)">"somepage"</span>);<br />
            <span style="color: rgb(0,128,0)">// URL connection channel.<br />
            </span>urlConn = url.openConnection();<br />
            <span style="color: rgb(0,128,0)">// ......<br />
            // No caching, we want the real thing.<br />
            </span>urlConn.setUseCaches (<strong>false</strong>);<br />
            <span style="color: rgb(0,128,0)">// Specify the content type.<br />
            </span>urlConn.setRequestProperty(<span style="color: rgb(0,0,128)">"Content-Type"</span>, <span style="color: rgb(0,0,128)">"application/x-www-form-urlencoded"</span>);<br />
            <span style="color: rgb(0,128,0)">// Send POST output.<br />
            </span>printout = <strong>new</strong> DataOutputStream (urlConn.getOutputStream ());<br />
            String content = <span style="color: rgb(0,0,128)">"name="</span> + URLEncoder.encode (<span style="color: rgb(0,0,128)">"Buford Early"</span>) + <span style="color: rgb(0,0,128)">"&amp;email="</span> + URLEncoder.encode (<span style="color: rgb(0,0,128)">"buford@known-space.com"</span>);<br />
            printout.writeBytes (content);<br />
            printout.flush ();<br />
            printout.close ();</span></code></td>
        </tr>
    </tbody>
</table>
<p><code>以上的代码向 somepage 发送了一次 POST 请求, 数据为 name = Buford Early, email = buford@known-space.com.<br />
用</code><span style="font-size: 0.9em; font-family: verdana,arial,helvetica"><code>JavaScript 来执行 POST/GET 请求是同样的原理, 下面的代码展示了分别用 XMLHttpRequest 对象向 somepage 用 GET 和 POST 两种方式发送和上例相同的数据的具体过程:<br />
GET 方式</code></span></p>
<table id="table2" style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td><code><span style="font-size: 0.75em; color: rgb(0,0,0); font-family: Courier New"><strong>var</strong> postContent =<br />
            <span style="color: rgb(0,0,128)">"name="</span> + encodeURIComponent(<span style="color: rgb(0,0,128)">"Buford Early"</span>) + <span style="color: rgb(0,0,128)">"&amp;email="</span> + encodeURIComponent(<span style="color: rgb(0,0,128)">"buford@known-space.com"</span>);<br />
            xmlhttp.open(<span style="color: rgb(0,0,128)">"GET"</span>, <span style="color: rgb(0,0,128)">"somepage"</span> + <span style="color: rgb(0,0,128)">"?"</span> + postContent, <strong>true</strong>);<br />
            xmlhttp.send(<strong>null</strong>);</span></code></td>
        </tr>
    </tbody>
</table>
<p><span style="font-size: 0.75em">POST 方式</span></p>
<table id="table3" style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td><code><span style="font-size: 0.75em; color: rgb(0,0,0); font-family: Courier New"><strong>var</strong> postContent =<br />
            <span style="color: rgb(0,0,128)">"name="</span> + encodeURIComponent(<span style="color: rgb(0,0,128)">"Buford Early"</span>) + <span style="color: rgb(0,0,128)">"&amp;email="</span> + encodeURIComponent(<span style="color: rgb(0,0,128)">"buford@known-space.com"</span>);<br />
            xmlhttp.open(<span style="color: rgb(0,0,128)">"POST"</span>, <span style="color: rgb(0,0,128)">"somepage"</span>, <strong>true</strong>);<br />
            xmlhttp.setRequestHeader(<span style="color: rgb(0,0,128)">"Content-Type"</span>, <span style="color: rgb(0,0,128)">"application/x-www-form-urlencoded"</span>);<br />
            xmlhttp.send(postContent);</span></code></td>
        </tr>
    </tbody>
</table>
<p>至此希望你已经能够理解如何用 JavaScript 中的 XMLHttpRequest 对象来执行 GET/POST 操作, 剩下的工作就是您如何来构造这些提交的参数了, 最后我给出一个将现有的 form 提交代码修改为异步的 AJAX 提交的代码(注意目前作者还不知道如何让 file 上传表单域也能异步上传文件). 首先请看两个 JavaScript 函数:</p>
<table id="table4" style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" bgcolor="#ebe9ed" border="1">
    <tbody>
        <tr>
            <td>
            <pre xml:space="preserve"><code><span style="font-size: 0.75em; font-family: Courier New"><span style="color: rgb(0,128,0)">// form - the form to submit<br />
            // resultDivId - the division of which to display result text in, in null, then<br />
            // create an element and add it to the end of the body<br />
            </span><strong>function </strong>ajaxSubmitForm(form, resultDivId) {<br />
            <strong>var </strong>elements = form.elements;<span style="color: rgb(0,128,0)">// Enumeration the form elements<br />
            </span><strong>var </strong>element;<br />
            <strong>var </strong>i;<br />
            <br />
            <strong>var </strong>postContent = <span style="color: rgb(0,0,128)">""</span>;<span style="color: rgb(0,128,0)">// Form contents need to submit<br />
            <br />
            </span><strong>for</strong>(i=<span style="color: rgb(255,102,0)">0</span>;i&lt;elements.length;++i) {<br />
            <strong>var </strong>element=elements[i];<br />
            <br />
            <strong>if</strong>(element.type==<span style="color: rgb(0,0,128)">"text" </span>|| element.type==<span style="color: rgb(0,0,128)">"textarea" </span>|| element.type==<span style="color: rgb(0,0,128)">"hidden"</span>) {<br />
            postContent += encodeURIComponent(element.name) + <span style="color: rgb(0,0,128)">"=" </span>+ encodeURIComponent(element.value) + <span style="color: rgb(0,0,128)">"&amp;"</span>;<br />
            }<br />
            <strong>else if</strong>(element.type==<span style="color: rgb(0,0,128)">"select-one"</span>||element.type==<span style="color: rgb(0,0,128)">"select-multiple"</span>) {<br />
            <strong>var </strong>options=element.options,j,item;<br />
            <strong>for</strong>(j=<span style="color: rgb(255,102,0)">0</span>;j&lt;options.length;++j){<br />
            item=options[j];<br />
            <strong>if</strong>(item.selected) {<br />
            postContent += encodeURIComponent(element.name) + <span style="color: rgb(0,0,128)">"=" </span>+ encodeURIComponent(item.value) + <span style="color: rgb(0,0,128)">"&amp;"</span>;<br />
            }<br />
            }<br />
            } <strong>else if</strong>(element.type==<span style="color: rgb(0,0,128)">"checkbox"</span>||element.type==<span style="color: rgb(0,0,128)">"radio"</span>) {<br />
            <strong>if</strong>(element.checked) {<br />
            postContent += encodeURIComponent(element.name) + <span style="color: rgb(0,0,128)">"=" </span>+ encodeURIComponent(element.value) + <span style="color: rgb(0,0,128)">"&amp;"</span>;<br />
            }<br />
            } <strong>else if</strong>(element.type==<span style="color: rgb(0,0,128)">"file"</span>) {<br />
            <strong>if</strong>(element.value != <span style="color: rgb(0,0,128)">""</span>) {<br />
            postContent += encodeURIComponent(element.name) + <span style="color: rgb(0,0,128)">"=" </span>+ encodeURIComponent(element.value) + <span style="color: rgb(0,0,128)">"&amp;"</span>;<br />
            }<br />
            } <strong>else </strong>{<br />
            postContent += encodeURIComponent(element.name) + <span style="color: rgb(0,0,128)">"=" </span>+ encodeURIComponent(element.value) + <span style="color: rgb(0,0,128)">"&amp;"</span>;<br />
            }<br />
            }<br />
            <br />
            alert(postContent);<br />
            <br />
            ajaxSubmit(form.action, form.method, postContent);<br />
            }<br />
            <br />
            <span style="color: rgb(0,128,0)">// url - the url to do submit<br />
            // method - "get" or "post"<br />
            // postContent - the string with values to be submited<br />
            // resultDivId - the division of which to display result text in, in null, then<br />
            // create an element and add it to the end of the body<br />
            </span><strong>function </strong>ajaxSubmit(url, method, postContent, resultDivId)<br />
            {<br />
            <strong>var </strong>loadingDiv = document.getElementById(<span style="color: rgb(0,0,128)">'loading'</span>);<br />
            <span style="color: rgb(0,128,0)">// call in new thread to allow ui to update<br />
            </span>window.setTimeout(<strong>function </strong>() {<br />
            loadingDiv.innerText = <span style="color: rgb(0,0,128)">"Loading...."</span>;<br />
            loadingDiv.style.display = <span style="color: rgb(0,0,128)">""</span>;<br />
            }, <span style="color: rgb(255,102,0)">1</span>);<br />
            <br />
            <span style="color: rgb(0,128,0)">// code for Mozilla, etc.<br />
            </span><strong>if </strong>(window.XMLHttpRequest)<br />
            {<br />
            xmlhttp=<strong>new </strong>XMLHttpRequest();<br />
            }<br />
            <span style="color: rgb(0,128,0)">// code for IE<br />
            </span><strong>else if </strong>(window.ActiveXObject)<br />
            {<br />
            xmlhttp=<strong>new </strong>ActiveXObject(<span style="color: rgb(0,0,128)">"Microsoft.XMLHTTP"</span>);<br />
            }<br />
            <br />
            <strong>if</strong>(xmlhttp) {<br />
            xmlhttp.onreadystatechange = <strong>function</strong>() {<br />
            <span style="color: rgb(0,128,0)">// if xmlhttp shows "loaded"<br />
            </span><strong>if </strong>(xmlhttp.readyState==<span style="color: rgb(255,102,0)">4</span>)<br />
            {<br />
            <strong>if</strong>(resultDivId) {<br />
            document.getElementByID(resultDivId).innerHTML = xmlhttp.responseText;<br />
            } <strong>else </strong>{<br />
            <strong>var </strong>result = document.createElement(<span style="color: rgb(0,0,128)">"DIV"</span>);<br />
            result.style.border=<span style="color: rgb(0,0,128)">"1px solid #363636"</span>;<br />
            result.innerHTML = xmlhttp.responseText;<br />
            document.body.appendChild(result);<br />
            }<br />
            <br />
            loadingDiv.innerHTML =<br />
            <span style="color: rgb(0,0,128)">"Submit finnished!"</span>;<br />
            }<br />
            <br />
            };<br />
            <br />
            <strong>if</strong>(method.toLowerCase() == <span style="color: rgb(0,0,128)">"get"</span>) {<br />
            xmlhttp.open(<span style="color: rgb(0,0,128)">"GET"</span>, url + <span style="color: rgb(0,0,128)">"?" </span>+ postContent, <strong>true</strong>);<br />
            xmlhttp.send(<strong>null</strong>);<br />
            } <strong>else if</strong>(method.toLowerCase() == <span style="color: rgb(0,0,128)">"post"</span>) {<br />
            xmlhttp.open(<span style="color: rgb(0,0,128)">"POST"</span>, url, <strong>true</strong>);<br />
            xmlhttp.setRequestHeader(<span style="color: rgb(0,0,128)">"Content-Type"</span>, <span style="color: rgb(0,0,128)">"application/x-www-form-urlencoded"</span>);<br />
            xmlhttp.send(postContent);<br />
            }<br />
            } <strong>else </strong>{<br />
            loadingDiv.innerHTML =<br />
            <span style="color: rgb(0,0,128)">"Can't create XMLHttpRequest object, please check your web browser."</span>;<br />
            }<br />
            <br />
            }</span></code></pre>
            </td>
        </tr>
    </tbody>
</table>
<p>函数 <code><span style="font-size: 0.75em; font-family: Courier New">ajaxSubmitForm 将表单要提交的内容进行封装, 然后调用 ajaxSubmit 函数来执行真正的异步提交, 表单提交后所返回的结果则显示在给定的 DIV 容器中或者没有指定参数时用 DOM 对象动态生成一个 DIV 容器来显示结果并添加到页面末尾. 这样, 对原来的表单只需要改动一个地方就可以将原来的表单提交改为异步模式, 即在 form 标签里加入: <span style="background-color: rgb(235,233,237)">onSubmit="ajaxSubmitForm(this);return false;"</span> 即可, return false 确保表单不会被浏览器同步提交. 完整的例子请看<a href="http://www.myjavaserver.com/%7Ebeansoft/ajax/ajax_form_submit.htm">这里</a>.</span></code></p>
<br />
<p>----------------- 引用结束 -----------------</p>
<p>OK, 希望至此为止您已经理解了如何用 AJAX 来正确的执行 GET/POST. 如果这个问题您解决了, 可是说后台的乱码问题就和你直接通过表单提交几乎没有区别了. 这个方法的具体封装已经在附件的 ajax_common.js 中了.</p>
<p>至此也该贴出来我们的 GBK 编码的客户端页面的内容了:</p>
<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)">
<p>&lt;html&gt;</p>
<p>&lt;head&gt;<br />
&lt;meta http-equiv="Content-Type" content="text/html; charset=gbk"&gt;<br />
&lt;title&gt;AJAX Form Submit Test&lt;/title&gt;<br />
&lt;script src='ajax_common.js'&gt;&lt;/script&gt;</p>
<p>&lt;/head&gt;</p>
<p>&lt;body&gt;<br />
本页面的编码是中文.&lt;br/&gt;<br />
&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=gbk"&amp;gt;&lt;br/&gt;<br />
&lt;b&gt;测试过的服务器:&lt;/b&gt;&lt;br/&gt;<br />
Resin 3.0.18&lt;br/&gt;<br />
Tomcat 5.5.20&lt;br/&gt;<br />
Tomcat 5.0.30&lt;br/&gt;<br />
&lt;h3&gt;AJAX Form Submit Test&lt;/h3&gt;<br />
Fill the form and then click submit&lt;br&gt;<br />
提交方式: POST&lt;br&gt;<br />
&lt;form method="POST" id="form1" name="form1"<br />
action="form_action.jsp"<br />
onSubmit="former.ajaxSubmitForm();return false;"&gt;<br />
&lt;p&gt;&lt;input type="hidden" name="hidden1" value="hiddenValue"&gt;<br />
text:&lt;input type="text" name="textf&amp;1" size="20" value="text文本&amp;amp;1"&gt;<br />
checkbox:&lt;input type="checkbox" name="checkbox1" value="ON" checked&gt;<br />
radio:&lt;input type="radio" value="V1" checked name="radio1"&gt;<br />
select:&lt;select size="1" name="select1"&gt;<br />
&lt;option selected value="option1"&gt;D1&lt;/option&gt;<br />
&lt;/select&gt;<br />
&lt;br&gt;<br />
&lt;br&gt;<br />
&lt;input type="submit" name="B1" value="submit"&gt;<br />
&lt;input type="reset" name="B2" value="reset"&gt;<br />
&lt;/p&gt;<br />
&lt;/form&gt;</p>
<p>提交方式: GET&lt;br&gt;<br />
&lt;form method="GET" id="form2" name="form2"<br />
action="form_action.jsp"<br />
onSubmit="former2.ajaxSubmitForm();return false;"&gt;<br />
&lt;p&gt;&lt;input type="hidden" name="hidden1" value="hiddenValue"&gt;<br />
text:&lt;input type="text" name="text文本&amp;amp;2" size="20" value="text文本&amp;amp;2"&gt;<br />
checkbox:&lt;input type="checkbox" name="checkbox1" value="ON" checked&gt;<br />
radio:&lt;input type="radio" value="V1" checked name="radio1"&gt;<br />
select:&lt;select size="1" name="select1"&gt;<br />
&lt;option selected value="option1"&gt;D1&lt;/option&gt;<br />
&lt;/select&gt;<br />
&lt;br&gt;<br />
&lt;br&gt;<br />
&lt;input type="submit" name="B1" value="submit"&gt;<br />
&lt;input type="reset" name="B2" value="reset"&gt;<br />
&lt;/p&gt;<br />
&lt;/form&gt;</p>
<p>&lt;div id="loading" style="display:none; position:absolute;<br />
border:1px solid orange; height:20px; width:600; left: 93px; top: 112px;<br />
background-color: #FFFFCC; cursor:pointer;" title="Click to hide" onClick="this.style.display='none';"&gt;&lt;/div&gt;</p>
<p>&lt;div id="resultDiv" style="border:1px solid orange; background-color: #FFFFCC; cursor:pointer;" title="Click to hide" onClick="this.style.display='none';"&gt;<br />
Form 1 的提交结果将会显示在这里.<br />
&lt;/div&gt;</p>
<p><br />
&lt;script type="text/javascript"&gt;<br />
var former = new AjaxFormer($('form1'), 'resultDiv');<br />
var former2 = new AjaxFormer($('form2'));<br />
&lt;/script&gt;<br />
&lt;/body&gt;</p>
<p>&lt;/html&gt;</p>
</div>
可以看到我们的确使用的是 GBK 编码, 浏览器打开的时候自动选择的编码也是简体中文.<br />
<p>那么第二个关键点就是服务器端的表单数据读取了.这个问题跟具体的服务器有很大关系. 对于 Resin 服务器来说, 问题很少, 基本上不论是 POST 和 GET, 出乱码的概率都比较小. 但是 Tomcat 就不敢恭维了, 这大概也是开源产品和商业产品的区别, 缺乏前后一致性和兼容性, 因为开源的不需要提供技术支持. Tomcat 的 GET/POST 的编码处理方式不同的版本都不一样, 就像 Eclipse/Netbeans 新版本从来不需要兼容老版本的插件 API 一样, Hibernate/Struts/Spring 也是一样, 所以学 Java 的很累. 当然, 这就是免费/开源的代价. 跑题了. 因此我们的服务器端代码大部分都是对 Tomcat 的乱码问题的解决(POST的没有问题, 主要是 GET 方法的).<br />
</p>
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)">
<p><span style="color: rgb(0,0,255)">&lt;%@ page contentType="text/html; charset=gbk" pageEncoding="gbk"%&gt;<br />
&lt;html&gt;<br />
&lt;%<br />
//Send some headers to keep the user's browser from caching the response.<br />
response.addHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT" );<br />
response.addHeader("Last-Modified", new java.util.Date().toGMTString());<br />
response.addHeader("Cache-Control", "no-cache, must-revalidate" );<br />
response.addHeader("Pragma", "no-cache" );<br />
// This will emulate a network delay, for 2 sec.<br />
//Thread.currentThread().sleep(2000);</span></p>
<p><span style="color: rgb(0,0,255)">request.setCharacterEncoding("utf-8");<br />
%&gt;</span></p>
<p><span style="color: rgb(0,0,255)">&lt;%!</span></p>
<p><span style="color: rgb(0,0,255)">/**<br />
* 转换字符串的内码.<br />
*<br />
* @param input<br />
* 输入的字符串<br />
* @param sourceEncoding<br />
* 源字符集名称<br />
* @param targetEncoding<br />
* 目标字符集名称<br />
* @return 转换结果, 如果有错误发生, 则返回原来的值<br />
*/<br />
public static String changeEncoding(String input, String sourceEncoding,<br />
String targetEncoding) {<br />
if (input == null || input.equals("")) {<br />
return input;<br />
}</span></p>
<p><span style="color: rgb(0,0,255)">try {<br />
byte[] bytes = input.getBytes(sourceEncoding);<br />
return new String(bytes, targetEncoding);<br />
} catch (Exception ex) {<br />
}<br />
return input;<br />
}</span></p>
<p><span style="color: rgb(0,0,255)">/**<br />
* 一个类似于 JavaScript 的 escape 函数的功能, 确保乱码可以正确传输.<br />
*/<br />
public static String escape(String src) {<br />
int i;<br />
char j;<br />
StringBuffer tmp = new StringBuffer();<br />
tmp.ensureCapacity(src.length() * 6);<br />
for (i = 0; i &lt; src.length(); i++) {<br />
j = src.charAt(i);<br />
if (Character.isDigit(j) || Character.isLowerCase(j)<br />
|| Character.isUpperCase(j))<br />
tmp.append(j);<br />
else if (j &lt; 256) {<br />
tmp.append("%");<br />
if (j &lt; 16)<br />
tmp.append("0");<br />
tmp.append(Integer.toString(j, 16));<br />
} else {<br />
tmp.append("%u");<br />
tmp.append(Integer.toString(j, 16));<br />
}<br />
}<br />
return tmp.toString();<br />
}<br />
%&gt;</span></p>
<p><span style="color: rgb(0,0,255)">&lt;head&gt;<br />
&lt;title&gt;Test form action page&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
这是 GBK 编码版本的后台表单提交页面.&lt;br/&gt;</span></p>
<p><span style="color: rgb(0,0,255)">&lt;%<br />
boolean isTomcat = application.getServerInfo().toLowerCase().indexOf("tomcat") != -1;<br />
%&gt;</span></p>
<p><span style="color: rgb(0,0,255)">Form submit method:&lt;%=request.getMethod()%&gt;&lt;br/&gt;<br />
The form content u send is:&lt;br/&gt;<br />
&lt;%<br />
java.util.Enumeration e = request.getParameterNames();</span></p>
<p><span style="color: rgb(0,0,255)">while (e.hasMoreElements()) {<br />
String name = (String)e.nextElement();<br />
String value = request.getParameter(name);</span></p>
<p><span style="color: rgb(0,0,255)">if(isTomcat &amp;&amp; request.getMethod().equalsIgnoreCase("GET")) {<br />
name = changeEncoding(name, "ISO8859-1", "UTF-8");<br />
value = changeEncoding(value, "ISO8859-1", "UTF-8");<br />
}<br />
out.println("&lt;b&gt;" + name + "&lt;/b&gt; = " + value + "&lt;br/&gt;");<br />
}</span></p>
<p><span style="color: rgb(0,0,255)">// 给前台返回一个可以执行的脚本<br />
//response.addHeader("response_script", changeEncoding("alert('提交完成');", "ISO8859-1", "UTF-8"));<br />
response.addHeader("response_script", escape("alert('提交完成');"));<br />
%&gt;</span></p>
<p><span style="color: rgb(0,0,255)">&lt;/body&gt;<br />
&lt;/html&gt;</span></p>
</div>
<p><span style="color: rgb(0,0,255); background-color: rgb(245,245,245)">boolean</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">isTomcat</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">=</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">application.getServerInfo().toLowerCase().indexOf(</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">"</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">tomcat</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">"</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">) !</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">=</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">-</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">1</span><span style="color: rgb(0,0,0); background-color: rgb(245,245,245)">; 这一句主要针对 Tomcat 进行处理, 如果是 GET 方法的话, 就需要将表单参数从 ISO8859-1 转换到 UTF-8 (注意不是 GBK, 貌似 Tomcat 很喜欢 UTF-8?). 其它的地方和原来的 UTF-8 版本的没有区别. 当然如果您的站点应该用过滤器来更方便的解决这个问题.</span><br />
</p>
<p>小结:<br />
<br />
1. 使用一致的字符集很重要, 要么全是 GBK, 要么全是 UTF-8, 如果有条件, 就全部用 UTF-8, 那样工作量是最小的;<br />
<br />
2. 用 AJAX 提交的时候一定要按照 HTTP 的规范来, 做到和浏览器尽量兼容, 尤其是 POST 的时候不要再往 URL 地址里加参数了, 你那样是违规! 后果就是有的服务器会不搭理你传递的这些参数! 还是如我所讲, 参数提交之前要用 encodeURIComponent() 来转化, 这也是为了符合浏览器的习惯做法.<br />
<br />
3. 后台如果读取参数有乱码, 就尽量多在 ISO8859-1, GBK, UTF-8 中间多转换几次试试, 可以试试偶写的那个 changeEncoding() 方法, 把几个转换后的表单值都列出来, 一定有一个是正确的, 总是可以解决问题的. 这个本来不应该是偶们的任务, 但是写服务器的人是老美, 尤其是 Tomcat 作者, 只熟悉 ISO8859-1.<br />
<br />
4. 鉴于 TOMCAT 读取 POST 参数的时候很少出问题, 因此建议AJAX提交表单的时候多用 POST 方法, 尽量不用 GET.<br />
<br />
运行截屏:</p>
<p><img alt="http://www.blogjava.net/images/blogjava_net/beansoft/18680/o_AJAX%20Form%20Submit%20GBK.png" src="http://www.blogjava.net/images/blogjava_net/beansoft/18680/o_AJAX%20Form%20Submit%20GBK.png" /></p>
<p>其它的一些资料可以参考Blogjava上的一篇原创文章: <a href="http://www.blogjava.net/errorfun/archive/2006/12/09/86584.html">[原创]struts,ajax乱码解决方案</a><br />
</p>
<p>欢迎发表建议和更好的观点. 谢谢! 重申本文无意代替您的 AJAX 框架, 不过在你抓狂的时候可以考虑看看他们表单提交的代码, 改改它!<br />
<br />
本人翻译的 XMLHttpRequest 对象介绍:</p>
<h2>The XMLHttpRequest Object Reference XMLHttpRequest 对象参考</h2>
<h3>Methods 方法</h3>
<table style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr valign="top">
            <th align="left" width="45%">Method 方法</th>
            <th align="left" width="55%">Description 描述</th>
        </tr>
        <tr valign="top">
            <td>abort()</td>
            <td>Cancels the current request<br />
            取消当前请求</td>
        </tr>
        <tr valign="top">
            <td>getAllResponseHeaders()</td>
            <td>Returns the complete set of http headers as a string<br />
            将完整的 HTTP 头部做为一个字符串返回</td>
        </tr>
        <tr valign="top">
            <td>getResponseHeader("headername")</td>
            <td>Returns the value of the specified http header<br />
            返回给定的 HTTP 头的值</td>
        </tr>
        <tr valign="top">
            <td>open("method","URL",async,"uname","pswd")</td>
            <td>Specifies the method, URL, and other optional attributes of a request
            <p>The method parameter can have a value of "GET", "POST", or "PUT" (use "GET" when requesting data and use "POST" when sending data (especially if the length of the data is greater than 512 bytes.</p>
            <p>The URL parameter may be either a relative or complete URL.</p>
            <p>The async parameter specifies whether the request should be handled asynchronously or not. true means that script processing carries on after the send() method, without waiting for a response. false means that the script waits for a response before continuing script processing<br />
            指定表单提交方法, URL, 以及请求的可选属性<br />
            <br />
            method 参数可以是"GET", "POST" 或者 "PUT" 这些值中之一(使用"GET"来请求数据, 特别的, 当发送的数据长度大于512字节时使用 "POST").<br />
            <br />
            URL 参数可以为相对的和完整的 URL.<br />
            <br />
            async 参数指定请求是否为异步方式处理. true 意味着调用 send() 方法后脚本继续向下执行, 不需要等待响应. false 意味着脚本将等待响应之后才能继续执行</p>
            </td>
        </tr>
        <tr valign="top">
            <td>send(content)</td>
            <td>Sends the request<br />
            发送请求</td>
        </tr>
        <tr valign="top">
            <td>setRequestHeader("label","value")</td>
            <td>Adds a label/value pair to the http header to be sent<br />
            在要发送的 HTTP 头中添加 标签/取值</td>
        </tr>
    </tbody>
</table>
<h3>Properties 属性</h3>
<table style="border-collapse: collapse" bordercolor="#000000" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr valign="top">
            <th align="left" width="30%">Property 属性</th>
            <th align="left" width="70%">Description 描述</th>
        </tr>
        <tr valign="top">
            <td>onreadystatechange</td>
            <td>An event handler for an event that fires at every state change<br />
            每次状态改变时除非的事件处理器</td>
        </tr>
        <tr valign="top">
            <td>readyState</td>
            <td>Returns the state of the object:
            <p>0 = uninitialized<br />
            1 = loading<br />
            2 = loaded<br />
            3 = interactive<br />
            4 = complete<br />
            返回对象的状态<br />
            <br />
            0 = 未初始化<br />
            1 = 载入中<br />
            2 = 已载入<br />
            3 = 交互<br />
            4 = 完成</p>
            </td>
        </tr>
        <tr valign="top">
            <td>responseText</td>
            <td>Returns the response as a string<br />
            将响应做为字符串返回</td>
        </tr>
        <tr valign="top">
            <td>responseXML</td>
            <td>Returns the response as XML. This property returns an XML document object, which can be examined and parsed using W3C DOM node tree methods and properties<br />
            将响应做为XML返回. 这个属性返回一个 XML 文档对象, 可以用 W3C 的 DOM 节点树方法和属性进行检索分析</td>
        </tr>
        <tr valign="top">
            <td>status</td>
            <td>Returns the status as a number (e.g. 404 for "Not Found" or 200 for "OK")<br />
            将状态做为数字返回(例如 404 为"Not Found" 或者 200 为 "OK")</td>
        </tr>
        <tr valign="top">
            <td>statusText</td>
            <td>Returns the status as a string (e.g. "Not Found" or "OK")<br />
            将状态做为字符串返回(例如 "Not Found" 或者 "OK")</td>
        </tr>
    </tbody>
</table>
 <img src ="http://www.blogjava.net/lifenote/aggbug/167132.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-12 09:51 <a href="http://www.blogjava.net/lifenote/archive/2007/12/12/167132.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类似google的拖动效果--转</title><link>http://www.blogjava.net/lifenote/archive/2007/12/10/166709.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Mon, 10 Dec 2007 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/10/166709.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/166709.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/10/166709.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/166709.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/166709.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &lt;html&gt;&lt;head&gt;&lt;title&gt;DRAG&nbsp;the&nbsp;DIV&lt;/title&gt;&lt;meta&nbsp;http-equiv="Content-Type"&nbsp;content="text/html;&nbsp;charset=gb2312"&gt;&lt;style&gt;*{font-size:12p...&nbsp;&nbsp;<a href='http://www.blogjava.net/lifenote/archive/2007/12/10/166709.html'>阅读全文</a><img src ="http://www.blogjava.net/lifenote/aggbug/166709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-10 16:49 <a href="http://www.blogjava.net/lifenote/archive/2007/12/10/166709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>扩展 prototype.js，增加 $T() 与 $N()</title><link>http://www.blogjava.net/lifenote/archive/2007/12/10/166702.html</link><dc:creator>LifeNote</dc:creator><author>LifeNote</author><pubDate>Mon, 10 Dec 2007 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/lifenote/archive/2007/12/10/166702.html</guid><wfw:comment>http://www.blogjava.net/lifenote/comments/166702.html</wfw:comment><comments>http://www.blogjava.net/lifenote/archive/2007/12/10/166702.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/lifenote/comments/commentRss/166702.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lifenote/services/trackbacks/166702.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 项目中使用了prototype这个框架，一直在学习感觉还是比较好用的，推荐给大家<br />
原prototype.js有$()相当于&nbsp;getElementById，却没有&nbsp;getElementsByName&nbsp;与&nbsp;getElementsByTagName，因此这里可以做个扩展，定义&nbsp;$N()&nbsp;的功能等于getElementsByName，代码如下：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">function&nbsp;$N()&nbsp;{<br />
</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;document.getElementsByName(arguments[</span><span style="color: #000000">0</span><span style="color: #000000">]);<br />
}</span></div>
需要注意的是，getElementsByName前面必须是document，不能为其他object，并且这里的ByName是很宽松的，只要元素的&nbsp;name&nbsp;或&nbsp;id&nbsp;属性值等于指定的值，就都返回回来。<br />
<br />
扩展&nbsp;getElementsByTagName&nbsp;为&nbsp;$T()，代码如下：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">function&nbsp;$T()&nbsp;{&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;$T('input','box')</span><span style="color: #008000"><br />
</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(arguments.length</span><span style="color: #000000">==</span><span style="color: #000000">1</span><span style="color: #000000">){<br />
</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;document.getElementsByTagName(arguments[</span><span style="color: #000000">0</span><span style="color: #000000">]);<br />
}</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(arguments.length</span><span style="color: #000000">==</span><span style="color: #000000">2</span><span style="color: #000000">){<br />
</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(typeof(arguments[</span><span style="color: #000000">1</span><span style="color: #000000">])</span><span style="color: #000000">==</span><span style="color: #000000">"</span><span style="color: #000000">object</span><span style="color: #000000">"</span><span style="color: #000000">){<br />
</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;arguments[</span><span style="color: #000000">1</span><span style="color: #000000">].getElementsByTagName(arguments[</span><span style="color: #000000">0</span><span style="color: #000000">]);<br />
}</span><span style="color: #0000ff">else</span><span style="color: #000000">{<br />
</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;$(arguments[</span><span style="color: #000000">1</span><span style="color: #000000">]).getElementsByTagName(arguments[</span><span style="color: #000000">0</span><span style="color: #000000">]);<br />
}<br />
}&nbsp;<br />
}<br />
</span></div>
$T()&nbsp;可以带两个参数，第一个参数是元素标签的名字，即tagName，第二个参数是指定查找的范围，可以是id也可以是object，如&nbsp;$T("input",$("box"))&nbsp;与&nbsp;$T("input","box")&nbsp;都是相同的意思，返回值都是在box元素下面的所有标签名为input的元素数组。其中第二个参数可选。<br />
在线中文帮助文档：https://compdoc2cn.dev.java.net/prototype/html/prototype.js.cn.html<br />
prototype框架及帮助文档下载 提取码为：d155a5cd <br />
仅提供12天的下载<br />
http://exs.mail.qq.com/cgi-bin/downloadfilepart?svrid=5&amp;fid=6830e473b59fc3f7eae8c086806aa76a84d3e9ce19ec44d1 
<img src ="http://www.blogjava.net/lifenote/aggbug/166702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lifenote/" target="_blank">LifeNote</a> 2007-12-10 16:38 <a href="http://www.blogjava.net/lifenote/archive/2007/12/10/166702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>