??xml version="1.0" encoding="utf-8" standalone="yes"?> 修改bin目录下的catalina.bat文g 查找?" rem Guess CATALINA_HOME if not defined " q句 rem set JAVA_OPTS=-Xms256m -Xmx256m -server ps:什么意思我也不知道目前 然后启动tomcat你会发现多了?"[GC 8623K->4876K(65088K), 0.0134872 secs]"的文?/p>
现在你要做的是使用samurai1_2q个软g对这些文字进行处?/p>
如何处理? @echo on q句话的意思就是把tomcat启动的信息都写到logs目录下的gc.log文g? ============================================================================== %_EXECJAVA%
%JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS%
-Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%"
-Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%"
-Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS%
%ACTION% PS:好象是这?如果不是,也是?:doneSetArgs"中类D句的语句,当时忘记拯出来p我改?br />
l改?/p>
rem
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS%
-Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%"
-Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%"
-Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS%
%ACTION% q些做的目的是Ztomcat启动的时?不要先打开一个cmd控制?然后关闭又打开另外一? 作?mailto:wujianyu2000#hotmail.com VB 3.0已l提供了一个很特别很有用的函数SendkeysQ能模拟键盘的操作,能以极ؓ单的方式实现许多演示或自动化工作。可惜PB中一直不能实玎ͼ即用AQ;实现在v来非常复杂,功能也不AutoITx内核好ƈ且调用方便) 本系l是老外写的一个comlgQ原理是Ҏ从windows98开始windows自带提供了Microsoft's scripting engines来包装的调用?/p> Microsoft's scripting enginescM于DOS时代?bat处理文gQ提供了许多Ҏ(以com对象的方?来方便用戯用windows的许多功能?/p> 如果你在电脑中搜?*.vbs文gQ一般都在windows目录下)会找C些例E,仔细阅读q些例题你将会发现非常有用。包括了有控制excelQ网l共享名的联接方式?/p> 本AutoItX提供了许多强大的功能Q如下,其中W?,2Ҏ我认为最有用的功能?br />(cool!)1.支持sendkeys Q除ctrl+alt+del不允许外Q其余的M键你都可以模拟发送。包括组合键。还有特D按? 调用C(test.hta代码) <script language="VBScript"> End Sub 下面的命令是在屏qx=50, y=200的位|模拟点击mouse左键 下面的命令是模拟按下l合键ctrl + v 关于具体的键盘代码对应表可见其帮助文? 1.4版本的帮助文件名?AutoItX.chm 注意截止到写本文的时候最新版本是 2.63, 因ؓ我用1.4版本试后已l完全满了sendkeys功能Q如果你需要在xp?000下调用AutoItX的关机等功能Q则你下?.63版本?br /> 2.63已经支持 windows 2000/xpQ同时提供activex或dll方式的调用,q提供了书写scriptq编译成exe独自执行的功能(即你可以不用W三方的软gQ如pb,vb,delphi来写)
unix 1个用户session 对应一个操作系l?process
?windows体现在线E?br />
------------------------------------------------------------------------------
修改ORACLE最大进E数Q?br />
使用sysQ以sysdba权限dQ?br />
SQL> show parameter processes;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
aq_tm_processes integer 1
db_writer_processes integer 1
job_queue_processes integer 10
log_archive_max_processes integer 1
processes integer 150
SQL> alter system set processes=300 scope = spfile;
pȝ已更攏V?br />
SQL> show parameter processes;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
aq_tm_processes integer 1
db_writer_processes integer 1
job_queue_processes integer 10
log_archive_max_processes integer 1
processes integer 150
SQL> create pfile from spfile;
文g已创建?br />
重启数据库,
SQL> show parameter processes;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
aq_tm_processes integer 1
db_writer_processes integer 1
job_queue_processes integer 10
log_archive_max_processes integer 1
processes integer 300
搞定!
]]>
在这句前面加入下列代?/p>
set JAVA_OPTS=-Xms64m -Xmx128m
set CATALINA_OPTS=-verbose:gc
在bin目录下徏立start_with_gc.bat批处理文?文g名可以改
内容如下:
.\startup.bat >> ..\logs\gc.log 2>&1
q样做就是ؓ下面使用软g分析tomcat日志做准备的
使用samurai1_2软g打开logs目录下的gc文g,接下来你应该都知道了,
双出现了系l内存时间等{的资源?
如果Qgc.log文g中只有几条环境变量的信息,而没?[GC 8623K->4876K(65088K), 0.0134872 secs]字样,
那可能你需要改一个地?
在catalina.bat??:doneSetArgs"q句下面有一行代码如?
%JAVA_HOME%\bin\java.exe %JAVA_OPTS% %CATALINA_OPTS%
%DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath
"%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%"
-Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
而是所有的昄信息都在一个cmd中打开,以便能通过那个批处理文件一起写到日志中
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=723803
]]>
说明: 陶清 ( taoqing@163.net )
本地下蝲QAutoItx是免费组? cool!
1.4版本 http://www.pdriver.com/pb02/10/autoit14.zip (size: 62kb)
2.63版本 http://www.pdriver.com/pb02/10/AutoIt263.exe (size: 612kb)
例如最常见的组合键, ctrl + a , 只需要用sendkeys (
(cool!)2.重启,开机,注册销{操?2.63版本支持windows98/me/nt/2000)Q如你用nt 4.0Q强烈推荐要升到sp6
3.支持H口控制函数Q最化Q隐藏,恢复Q等待某H口出现(如某messagebox)Q将指定的窗口放到最前面
4.sleep命o(pb中有)
5.ini的读?pb中有)
6.对windows的剪贴板的copy, paste操作
7.模拟mouse的移动,点击Q拖拽?/p>
如果你下载的?.4版本Q先使用regsvr32 AutoItX.dll的方式注?
Sub RunProgram
Dim oShell
Dim oAutoIt
Set oShell = CreateObject("WScript.Shell")
Set oAutoIt = CreateObject("AutoItX.Control")
oShell.Run "C:\Progra~1\swglxt\SWGLXT.exe", 1, FALSE
oAutoIt.WinWaitActive "登陆", ""
'oAutoIt.Send "myname"
'oAutoIt.Send "{TAB}"
'oAutoIt.Send "mypassword"
'oAutoIt.Send "{ENTER 2}"
</script>
<input type="button" value="test" onclick="RunProgram">
myoleobject.LeftClick( 50, 200)
myoleobject.send("{CTRLDOWN}v{CTRLUP}")
2.63下蝲后可以直接安装?br /> 1.4版本的提供的.vbs例程我已l修改了Q可以用于简体windows下面Q?.63版本因ؓ光对英文windows所写的sampleQ所以有些地方你需要修改,例如其中一个例E?br />C:\Program Files\AutoIt\Examples\_Run_Me_First.aut
其中有一个等待写字板出现的函数调用如下:
WinWait, Untitled - Notepad
你需要将它改?br />WinWait, 无标?- C?br />才能正常q行。否则winwait会一直等到有一个窗口标题ؓUntitled - Notepad的窗口出现才l箋执行script
]]>
W一U方?/font>:修改$CATALINA_HOME\conf\server.xml,?font color="#ff0000"><GlobalNamingResources>中添?
<Resource name="jdbc/dsname" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="200"
driverClassName="@DB-DRIVERNAME@"
username="@DB-USERNAME@" password="@DB-PASSWORD@"
url="@DB-URL@"
defaultAutoCommit="true" removeAbandoned="true"
removeAbandonedTimeout="60" logAbandoned="true"/>
然后?CATALINA_HOME\conf\Catalina\localhost,创徏应用相关?.xml文g,在此文g?lt;context>中添?
<ResourceLink
global="jdbc/dsname"
name="jdbc/dsname"
type="javax.sql.DataSourcer"/>
W二U方?直接?CATALINA_HOME\conf\Catalina\localhost,创徏应用相关?.xml文g,在此文g?lt;context>中添?
<Resource name="jdbc/dsname" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="200"
driverClassName="@DB-DRIVERNAME@"
username="@DB-USERNAME@" password="@DB-PASSWORD@"
url="@DB-URL@"
defaultAutoCommit="true" removeAbandoned="true"
removeAbandonedTimeout="60" logAbandoned="true"/>
q有一U是官方配置:
1.修改$CATALINA_HOME\conf\server.xml,Context对应你的web应用的目录名,攑ֈ<host>中间:
<Context docBase="test" path="/test" debug="5" reloadable="true" crossContext="true">
<Resource name="jdbc/dsname" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="200"
driverClassName="@DB-DRIVERNAME@"
username="@DB-USERNAME@" password="@DB-PASSWORD@"
url="@DB-URL@"
defaultAutoCommit="true" removeAbandoned="true"
removeAbandonedTimeout="60" logAbandoned="true"/>
</Context>
2.在你的WEB应用的web.xml中添?
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/dsname</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
W一U和W三U差不多,W一U第一D其实就是用http://localhost:8080/admindDataSource后生成的,要多写一个WEB应用相关的XML来绑定连接池,W三U把q个文g集成Cserver.xml?和连接池的绑定交l了web.xml,但共同不方便的是如果TOMCAT下有多个应用,在开发中可能有的应用是不需要启动的,那你pM改server.xml.
W二U方法的优点也正是另外两U方法的~点,个h比较喜欢W二U方?一个是TOMCAT版本更换比较方便,是的之前备䆾应用相关XML可以了;二是如果不需要启动不相关的应用直接把文g名改一?比如说加?bak后缀可以了.
C3P0:
因ؓTOMCAT自带的DBCP有很多BUGQ所有有时会使用C3P0来替代,配置Ҏ和上边的l构基本一P注意几个参数名称不一样就可以了,另外q要把C3P0的JAR包放到classpath
<Resource name="jdbc/name" auth="Container" type="com.mchange.v2.c3p0.ComboPooledDataSource"
maxPoolSize="30" minPoolSize="1" initialPoolSize="5" acquireIncrement="2"
idleConnectionTestPeriod="60" maxIdleTime="60"
driverClass="@DB-DRIVERNAME@"
user="@DB-USERNAME@" password="@DB-PASSWORD@"
jdbcUrl="@DB-URL@"
factory="org.apache.naming.factory.BeanFactory"/>
其实q有其它的方?另外需要注意的一Ҏ数据库相关的JDBC驱动要放?CATALINA_HOME\common\lib下边,不然会class not found!
Javascript有许多内建的Ҏ来生对话框Q如Qwindow.alert(), window.confirm(),window.prompt().{?然而IE提供更多的方法支持对话框。如Q?
showModalDialog() (IE 4+ 支持)
showModelessDialog() (IE 5+ 支持)
window.showModalDialog()Ҏ用来创徏一个显CHTML内容的模态对话框Q由于是对话框,因此它ƈ没有一般用window.open()打开的窗口的所有属性?/p>
window.showModelessDialog()Ҏ用来创徏一个显CHTML内容的非模态对话框?
当我们用showModelessDialog()打开H口Ӟ不必用window.close()d闭它Q当以非模态方式EIE5Q打开Ӟ 打开对话框的H口仍可以进行其他的操作Q即对话框不L最上面的焦点,当打开它的H口QRQ改变时Q它自动关闭。而模态EQIQ]方式的对话框始终有焦点(焦点不可U走Q直到它关闭Q。模态对话框和打开它的H口相联p,因此我们打开另外的窗口时Q他们的链接关系依然保存Qƈ且隐藏在zdH口的下面?/p>
使用Ҏ如下Q?br /> vReturnValue = window.showModalDialog(sURL [, vArguments] [, sFeatures])
vReturnValue = window.showModelessDialog(sURL [, vArguments] [, sFeatures])
参数说明Q?br /> sURL
必选参敎ͼcdQ字W串。用来指定对话框要显C的文档的URL?br /> vArguments
可选参敎ͼcdQ变体。用来向对话框传递参数。传递的参数cd不限Q包括数l等。对话框通过window.dialogArguments来取得传递进来的参数?br /> sFeatures
可选参敎ͼcdQ字W串。用来描q对话框的外观等信息Q可以用以下的一个或几个Q用分号?”隔开?br /> dialogHeight 对话框高度,不小于1Q0pxQテQ4中dialogHeight ?dialogWidth 默认的单位是emQ而テQ5中是pxQؓ方便其见Q在定义modal方式的对话框Ӟ用px做单位?br /> dialogWidth: 对话框宽度?br /> dialogLeft: 距离桌面左的距离?br /> dialogTop: L面上的距R?br /> center: {yes | no | 1 | 0 }Q窗口是否居中,默认yesQ但仍可以指定高度和宽度?br /> help: {yes | no | 1 | 0 }Q是否显C帮助按钮,默认yes?br /> resizable: {yes | no | 1 | 0 } QテQ5Q]Q是否可被改变大。默认no?br /> status: {yes | no | 1 | 0 } QIE5+Q:是否昄状态栏。默认ؓyes[ Modeless]或no[Modal]?br /> scroll:{ yes | no | 1 | 0 | on | off }Q指明对话框是否昄滚动条。默认ؓyes?/p>
q有几个属性是用在HTA中的Q在一般的|页中一般不使用?br /> dialogHide:{ yes | no | 1 | 0 | on | off }Q在打印或者打印预览时对话框是否隐藏。默认ؓno?br /> edge:{ sunken | raised }Q指明对话框的边框样式。默认ؓraised?br /> unadorned:{ yes | no | 1 | 0 | on | off }Q默认ؓno?/p>
传入参数Q?br /> 要想对话框传递参敎ͼ是通过vArguments来进行传递的。类型不限制Q对于字W串cdQ最大ؓ4096个字W。也可以传递对象,例如Q?/p>
test1.htm
<script>
var mxh1 = new Array("mxh","net_lover","孟子E?)
var mxh2 = window.open("about:blank","window_mxh")
// 向对话框传递数l?br /> window.showModalDialog("test2.htm",mxh1)
// 向对话框传递window对象
window.showModalDialog("test3.htm",mxh2)
</script>test2.htm
<script>
var a = window.dialogArguments
alert("您传递的参数为:" + a)
</script>
test3.htm
<script>
var a = window.dialogArguments
alert("您传递的参数为window对象Q名Uͼ" + a.name)
</script>
可以通过window.returnValue向打开对话框的H口q回信息Q当然也可以是对象。例如:
test4.htm
<script>
var a = window.showModalDialog("test5.htm")
for(i=0;i<a.length;i++) alert(a[i])
</script>test5.htm
<script>
function sendTo()
{
var a=new Array("a","b")
window.returnValue = a
window.close()
}
</script>
<body>
<form>
<input value="q回" type=button onclick="sendTo()">
</form>
常见问题Q?br />1Q如何在模态对话框中进行提交而不新开H口Q?br /> 如果??览器是IE5.5+,可以在对话框中用带name属性的iframeQ提交时可以制定targetiframe的name。对于IE4+Q你可以用高度ؓ0的frame来作。例如:
test6.htm
<script>
window.showModalDialog("test7.htm")
</script> test7.htm
if(window.location.search) alert(window.location.search)
<frameset rows="0,*">
<frame src="about:blank">
<frame src="test8.htm">
</frameset> test8.htm
<form target="_self" method="get">
<input name=txt value="test">
<input type=submit>
</form>
<script>
if(window.location.search) alert(window.location.search)
</script>
2,可以通过http://servername/virtualdirname/test.htm?name=mxh方式直接向对话框传递参数吗Q?br /> {案是不能。但在frame里是可以的?br />
一、showModalDialog和showModelessDialog有什么不同?
showModalDialogQ被打开后就会始l保持输入焦炏V除非对话框被关闭,否则用户无法切换CH口。类似alert的运行效果?br /> showModelessDialogQ被打开后,用户可以随机切换输入焦点。对ȝ口没有Q何媄?最多是被挡住一下而以?P)
二、怎样才让在showModalDialog和showModelessDialog的超q接不弹出新H口Q?br /> 在被打开的网里加上<base target="_self">可以了。这句话一般是攑֜<html>?lt;body>之间的?/p>
三、怎样才刷新showModalDialog和showModelessDialog里的内容Q?br /> 在showModalDialog和showModelessDialog里是不能按F5h的,又不能弹单。这个只能依靠javascript了,以下是相关代码:
<body onkeydown="if (event.keyCode==116){reload.click()}">
<a id="reload" href="filename.htm" style="display:none">reload...</a>
filename.htm替换成网늚名字然后它攑ֈ你打开的网里Q按F5可以刷CQ注意,q个要配?lt;base target="_self">使用Q不然你按下F5会弹出新H口的?/p>
四、如何用javascriptxshowModalDialog(或showModelessDialog)打开的窗口?br /> <input type="button" value="关闭" onclick="window.close()">
也要配合<base target="_self">Q不然会打开一个新的IEH口Q然后再x的?/p>
五、showModalDialog和showModelessDialog数据传递技巧?br /> (作者语Q本来想用一问一{Ş式来写的Q但是我想不个怎么问,所以只好这样了?
q个东西比较ȝQ我改了好几ơ了不是没办法说明白(语文水^来差?Q只好用个例子说明了?br /> 例子Q?br /> 现在需要在一个showModalDialog(或showModelessDialog)里读取或讄一个变量var_name
一般的传递方式:
window.showModalDialog("filename.htm",var_name)
//传递var_name变量
在showModalDialog(或showModelessDialog)d和设|时Q?br /> alert(window.dialogArguments)//dvar_name变量
window.dialogArguments="oyiboy"http://讄var_name变量
q种方式是可以满的Q但是当你想在操作var_name同时再操作第二个变理var_id时呢Q就无法再进行操作了。这是q种传递方式的局限性?br />
以下是我使用的传递方式:
window.showModalDialog("filename.htm",window)
//不管要操作什么变量,只直传递主H口的window对象
在showModalDialog(或showModelessDialog)d和设|时Q?br /> alert(window.dialogArguments.var_name)//dvar_name变量
window.dialogArguments.var_name="oyiboy"http://讄var_name变量
同时我也可以操作var_id变量
alert(window.dialogArguments.var_id)//dvar_id变量
window.dialogArguments.var_id="001"http://讄var_id变量
同样q可以对ȝ口的M对象q行操作Q如form对象里的元素?br /> window.dialogArguments.form1.index1.value="q是在设|index1元素的?
六、多个showModelessDialog的相互操作?br /> 因ؓ光说很费Ԍ我就L懒,直接用代码来说了Q如果不明白的话那就直接来信(oyiboy#163.net(使用时请?Ҏ@))问我吧?/p>
以下代码的主要作用是在一个showModelessDialog里移动别一个showModelessDialog的位|?/p>
L件的部䆾js代码?br /> var s1=showModelessDialog('控制.htm',window,"dialogTop:1px;dialogLeft:1px"Q?/打开控制H口
var s2=showModelessDialog('about:blank',window,"dialogTop:200px;dialogLeft:300px"Q //打开被控制窗?/p>
控制.htm的部份代码?br /> <script>
//操作位置数据Q因为窗口的位置数据?xxxpx"方式的,所以需要这L一个特D操作函数?br /> function countNumber(A_strNumber,A_strWhatdo)
{
A_strNumber=A_strNumber.replace('px','')
A_strNumber-=0
switch(A_strWhatdo)
{
case "-":A_strNumber-=10;break;
case "+":A_strNumber+=10;break;
}
return A_strNumber + "px"
}
</script>
<input type="button" onclick="window.dialogArguments.s2.dialogTop=countNumber(window.dialogArguments.s2.dialogTop,'-')" value="上移">
<input type="button" onclick="window.dialogArguments.s2.dialogLeft=countNumber(window.dialogArguments.s2.dialogLeft,'-')" value="左移">
<input type="button" onclick="window.dialogArguments.s2.dialogLeft=countNumber(window.dialogArguments.s2.dialogLeft,'+')" value="右移">
<input type="button" onclick="window.dialogArguments.s2.dialogTop=countNumber(window.dialogArguments.s2.dialogTop,'+')" value="下移">
以上关键部䆾是:
H口命名方式Qvar s1=showModelessDialog('控制.htm',window,"dialogTop:1px;dialogLeft:1px"Q?br /> 变量讉K方式Qwindow.dialogArguments.s2.dialogTop
q个例子只是现实showModelessDialog与showModelessDialog之间的位|操作功能,通过q个原理Q在showModelessDialog之间怺控制各自的显C页面,传递变量和数据{。这要看各位的发挥了?/p>
CODE:
class SortFile {
long size;
long date;
String name;
public SortFile(String name, long date, long size) {
this.name = name;
this.date = date;
this.size = size;
}
public static SortFile[] sort(SortFile[] src, String mark, boolean rule) {
if (rule) {//升序
for (int i = src.length; i > 1; i--) {
for (int j = 0; j < i - 1; j++) {
boolean change = false;
if (mark.equals("name")) {
if (src[j].name.compareTo(src[j + 1].name) > 0)
change = true;
} else if (mark.equals("date")) {
if (src[j].date > src[j + 1].date)
change = true;
} else {
if (src[j].size > src[j + 1].size)
change = true;
}
if (change) {
SortFile temp = src[j];
src[j] = src[j + 1];
src[j + 1] = temp;
}
}
}
} else {
//降序只要?gt;Ҏ<
}
return src;
}
}
CODE:
ArrayList al = new ArrayList();
File f = new File(dir);
String[] names = f.list();
for (int i = 0; i < names.length; i++) {
File fs = new File(f, names[i]);
SortFile sf = new SortFile(name[i], fs.length(), fs.lastModified);
al.add(sf);
}
DOM适合于当今流行的各种语言Q包括Java,JavaScripte,VB,VBScriptQPerl,C,C++{。它了ؓHTML和XML文提供了一个可应用于不同^台的~程接口。W3C DOM的最C息可从http://www.w3.org/TR2001/WD-DOM-Lever-3-Core-20010913查阅。微软在http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk30/htm/xmconxmldomuserguide.asp上也有DOM的详l技术信息?/P>
DOM的设计ؓ了适用于不同的语言Q它保留了不同语a中非常相似的API。但是它q不适合于Java~程者的习惯。而JDOM作ؓ一U轻量API被制定,它最核心的要求是以JavaZ心,只适合于Java语言Q它遵@DOM的接口主要规则,除去了DOM中ؓ了兼容各语言而与Java习惯的不同?/P>
二、用JDOM的前提条?BR> 要有SAX、DOM解析器的cLӞJDOM只是一U适合JavaE序员来使用的Java XML解析器,目前行的Java XML解析器还有:Apache Xerces Java、JAXP?BR>Xerces Java解析器是完全用Java~写的XML解析器,最新版本是2.5Q它支持以下标准和APIQ?BR>Q?Q?XML1.0规范Q第二版本)
Q?Q?XML命名I间规范
Q?Q?DOM2核心标准规范
Q?Q?SAX2核心扩展
Q?Q?JAXP1.2 Q是Sun提供的用Java处理XML的接口API?BR>Q?Q?XML Schemal构和数据类型标?/P>
q有最好的是它开放源代码Q我们可以在http://xml.apache.org/dist/xerces-j/ 处去下蝲。下载文件Xerces-J-bin.2.5.0.zip?BR>解压下蝲文gQ得到四个压~包加到目的\径中Q其实不要全加,但不熟的情况下考虑q么做)?BR>JDOM的二q制版本下蝲Qhttp://www.jdom.org/downloads/index.html
把解压后的jdom.jar文g加到目的类路径中,另外便于调试Q还要下载它的源代码?/P>
三、用JDOM解析XML
好了Q现在该是正题了。下面通过一个简单的例子说明一下怎么用JDOMq一适合JavaE序员习惯的工具包来解析XML文?BR>Z单,我用了如下XML作ؓ要解析的XML文gQ?BR><?xml version="1.0" encoding="gb2312"?>
<books>
<book email="zhoujunhui">
<name>rjzjh</name>
<price>60.0</price>
</book>
</books>
够简单的吧,但它对于我们兛_的东襉K有了Q子节点Q属性?BR>下面是用于解析这个XML文g的Java文gQ?BR>
1 public class JDomParse { 2 public JDomParse(){ 3 String xmlpath="library.xml"; 4 SAXBuilder builder=new SAXBuilder(false); 5 try { 6 Document doc=builder.build(xmlpath); 7 Element books=doc.getRootElement(); 8 List booklist=books.getChildren("book"); 9 for (Iterator iter = booklist.iterator(); iter.hasNext();) { 10 Element book = (Element) iter.next(); 11 String email=book.getAttributeValue("email"); 12 System.out.println(email); 13 String name=book.getChildTextTrim("name"); 14 System.out.println(name); 15 book.getChild("name").setText("alterrjzjh"); 16 17 } 18 19 XMLOutputter outputter=new XMLOutputter(); 20 outputter.output(doc,new FileOutputStream(xmlpath)); 21 22 } catch (JDOMException e) { 23 e.printStackTrace(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 public static void main(String[] args) { 29 new JDomParse(); 30 } 31}不到30行代码,现在我对代码解释一下:
1. 你要传送的文g装在DataHandler中,然后DataHandler对象或DataHandler数组Q多个文件传送的时候)作ؓ客户端调用函数的参数Q从客户端上传文件到服务器)Axis服务的返回类型(从服务器端下载文件到客户端)q行传输?/P>
2. q有一U方式是直接修改soap信封的内容,附件信息加到soap信封中发送?/P>
q里我们只讨论第一U方法,因ؓ它实现v来非常简单。关于第二种Ҏ在Axis包的webapps/attachments/TestRf.java中有详细的原码可以参考?/P>
下面的例子是把文件从服务器端下蝲到客LQ?/P>
1.服务端程序:
假设传输多个文gQ在服务器端文件取出来Qƈ文件封装在DataHandler数组中?BR>代码如下Q?/P>
DataHandler[] ret = new DataHandler[totalFileNum];
... ...
java.io.File myFile = new java.io.File(filePath);
if(myFile.isFile() && myFile.canRead())
{
String fname = myFile.getAbsoluteFile().getCanonicalPath();
DataHandler[0] = new DataHandler(new FileDataSource(fname));
}
... ...
return ret;
上面的代码将所有的文g装在了DataHandler数组中,q返回?/P>
2. 客户端的讉KQ?/P>
代码如下Q?BR> Service service = new Service();
Call call = (Call) service.createCall();
call.registerTypeMapping(DataHandler.class, qnameAttachment, JAFDataHandlerSerializerFactory.class,JAFDataHandlerDeserializerFactory.class); //为附Ӟ即DataHandlerc)创徏序列化生成器
call.addParameter("source", XMLType.XSD_STRING ,ParameterMode.IN); //讄服务调用Ҏ的传入参数类?BR> call.setReturnType(XMLType.SOAP_ARRAY); //讄调用服务Ҏ的返回类型,׃q回的是DataHandler数组Q所以设|ؓSOAP_ARRAYcd
javax.activation.DataHandler[] ret = (javax.activation.DataHandler[])call.invoke(new Object[]{null}); //调用Ҏ
for (i = 0; i < ret.length; ++i)
{
DataHandler recDH = ret[i];
java.io.File receivedFile = new java.io.File(recDH.getName()); //文g生成
}
3. 服务的部|Ԍ
注意Q你要在部v的时候,定义DataHandler的序列化生成器?/P>
<parameter name="className" value="samples.att_STC.att_STC_Server"/>
<parameter name="allowedMethods" value="echoDir"/>
<typeMapping deserializer="org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory"
languageSpecificType="java:javax.activation.DataHandler" qname="ns1:DataHandler"
serializer="org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</service>
</deployment>
q行java org.apache.axis.client.AdminClient %* deploy.wsddQ部|服务?/P>
虽然今天一大早早上7Ҏ匆匆上了Internet看看Borland的宣布会造成什么媄响,不过心中却早已底定,因ؓ1:我知道这一定会在开发者社生巨大的冲击Q?:qg事在昨天晚上台北旉下午5:30左右我已l知道这件事了?/P>
许多朋友和网友一早就开始不断的问我的意见,我在Internet上也看到许多人的响应Q我静静的看着Q咀嚼着不同的h不同的回应。其实静下心观察现有的响应是很有的Q因Z是悲伤的,悲观的,乐观的,观望的,生气的,骂h的,甚至对Borland说再见的都代表这个用者群l强大的力量Q强大的渲染力,和强大的凝聚力?/P>
其实Ҏ个h而言Q我觉得q样做是对的Q因Z在Borland工作的h不会知道我们q些怿开发工P喜欢开发工L人在Borland为开发工兯战是多么的辛苦QBorland已经定要走ALM的\Q因此几乎把所有的资源都投入了ALMQ就像David I Blog中说的一栗虽然开发工具仍然是赚钱的生意,但是开发工具部门ƈ没有得到应该有的照顾和资源,Chuck争的累了QDanny争的也篏了,我们许多人都累了Q因些h中大多数只是技术h员,我们不是Borland的高层h员,我们无法军_Borland的走向?/P>
让开发工具部门脱Borland臛_可以让这些我们喜q开发工具得到应有的资源Q每一分赚来的钱都可以投入做ؓ下一代更好品的投资Q这臛_对开发工具部门是公^的。我一直认为开发工具和ALMq不相左QALM的中心仍然是开发工PALM是ؓ了帮企业增加价|q些增加价值的部䆾来自更高的生产力和高质量的Y件开发,qƈ不相互违背,无奈……?/P>
。。。。。。。。。。?/P>
10多年前我从G.I.T.毕业时只惛_Borlander或是MicrosofterQ没惛_在ؓBorland工作了这么多q之后我又站在了十字路口。我q会是我曄引以为傲的『Borlander』吗? 我也不知道,也许{案要等C出现之后事情׃明朗了?/P>
Cq一天,?006q??日?Q因Z你喜不喜欢BorlandQ这一天在未来Z回顾IT历史Ӟ是软g界重要的一日?/P>
阅读全文请到 李维的BLog
与Q何技术一P使用Ajax在相当多的方面都可能范错误。我在这儿讨论的问题目前都缺解x案,q将会随着Ajax的成熟而解x提高。随着开?Ajax应用l验的不断获取,开发者社Z会出现最好的实践l验与指导方针?/FONT>
1、XMLHttpRequest的有效?/STRONG>
Ajax开发者面对的一个最大问题是当XMLHttpRequest不可用时如何反应。虽然大部分C览器支持XMLHttpRequestQ但q是有少量的用户Q他们的览器不能支持,或由于浏览器安全讄而阻止对XMLHttpRequest的用。若你的Web应用发布于公司内部的 Intranet上,你很可能可以指定支持哪种览器,q可以确保XMLHttpRequest是可用的。若你在公共WEB上发布,则你必须意识到由于假定XMLHttpRequest是可用的Q所有就L了老浏览器、手持设备浏览器{等用户来用你的系l?/FONT>
然而,你应该尽力保证应用系l“正帔RU”用,在系l中保留适用于不支持XMLHttpRequest的浏览器的功能。在购物车例子中Q最好的Ҏ是有一个Add to Cart按钮Q可以进行常规的提交处理Qƈh面来反映购物R状态的变化。Ajax行卫可以在页面被载入旉过JavaScriptd到页面中Q只?XMLHttpRequest可用的情况下Qؓ每个Add to Cart按钮加上JavaScript处理函数。另一个方法是在用L录时XMLHttpRequestQ再军_是提供Ajax版本q是常规Z form提交的版本?/FONT>
2、可用性考虑
围绕着Ajax应用的大部分问题都是很普通的问题。例如,让用L道他们的输入已经被注册ƈ处理Q是很重要的Q因为在XMLHttpRequest处理q程中ƈ不能提供通常的漏斗旋转光标。一U方法是“确认”按扭上的文本替换ؓ“正在更C…”,以避免用户在{待响应时多ơ点L钮?/FONT>
另一个问题是Q用户可能没有注意到他们正在观看的页面已l被更新。可以通过使用各种视觉技巧来用L眼光吸引到页面的更新区域。还有一个问题是通过 Ajax更新面打断了浏览器“退回前”按钮的正常工作Q地址栏中的URL不能反映面的全部状态,q且不能使用书签功能。参见Resource章节中列出的|站地址上的文章来了解更多Ajax应用关于可用性方面的问题?/FONT>
3、服务器负蝲
使用Ajax界面代替传统的基于form的界面可能戏剧性地增加传递到服务器的h数量。例如,一个普通的Google搜烦l服务器造成一ơ命中,q在用户认搜烦表单时发生。然而,Google SuggestQ将会试图自动完成你的搜索词Q在用户打字时将会往服务器发送多个请求。在开发一个Ajax应用Ӟ要注意到你将会发送多请求到用户器端Q以及服务器的负载指标。你可以通过在客L适当地缓存请求、与服务器响应来~减负蝲压力。你也应该在设计Ajax应用时尽量在客户端处理更多的逻辑Q而不用与服务器端通讯?/FONT>
4、处理异?/STRONG>
一定要CQ没有Q何东西可以保证XMLHttpRequest会按照它们被发送的序来依ơ结束。实际上Q你在设计系l时Q脑子里应该始终假定它们不会按原来顺序结束。在购物车例子中Q用了一个最后更新的旉x保证最新的数据不会被改写。这个非常基本的Ҏ可以在购物R场景中工作,但可能不能在其它情况下工作。在设计时刻p考虑你该如何处理异步服务器响应?/FONT>
l论
你现在应该对于Ajax的基本原则有了一个良好的了解Q另外,你应该理解一些更高的随AjaxҎ而来的设计问题。创Z个成功的Ajax应用需要一pd的方法—从JavaScript UI设计到服务器端架构—但是你现在应该已经具备了需要用到的Ajax核心知识?/FONT>
什么是web 2.0?
到目前ؓ止,关于Web2.0q没有清晰的定义。业内普遍的一U说法是Q微内容是Web2.0的一个关键词。其中,微内容包括个人所形成的Q何数?比如一则网志、一个评论、一q图片、收藏的书签、喜好的音乐列表、想l交的朋友等{。这些微内容Q充斥在了h们的生活、工作和学习的方斚w面。而Web2.0重点要解决的正是对这些微内容的重新发现和利用。于是,我们看到了这L现象Q只要是和微内容相关的技术和架构Q都是以Web2.0为名义的?/FONT>
q前的发展情况而言QWeb2.0是以 Flickr、Craigslist、Linkedin、Tribes、Ryze?Friendster、Del.icio.us?3Things.com{网站ؓ代表Q以Blog、TAG、SNS、RSS、wiki{应用ؓ核心Q依据六度分隔、xml、ajax{新理论和技术实现的互联|新一代模式?/FONT>
什么是博客(Blog)?
BLOG也就是WEB LOG的羃写简单来说就是网l日记。一U极其简易便L|络个h出版形式Q得Q何一位网民都可以在几分钟之内拥有自己的个人网站,自由挥写。但是,简单越隑֮义,Z对于博客的理解千姿百态,:博客代表着“新d?.0?旧媒体→新媒体→互媒?谷最著名的IT专栏作家丹·吉摩);博客是E-mail、BBS、ICQ(IM)之后的第四种|络交流方式;博客是一个h未经~辑的声?戴夫·温纳);博客是互联网上独立的思想泡(JamesSnell);博客是媒体的开放源代码q动(方兴?;博客是“个人出?.0?孙坚?;博客是用文字q行对话的网上咖啡屋(《博客手册?……著名IT记者和专栏作家保罗·安得鲁斯认ؓQ博客以及其他网l新ȝ崛vQ在一定程度上是因为媒?/FONT>巨头在公信力斚w的快速衰落,他们要努力推Ml媒体的“守门h?“新一cL闻记者正在兴P他们以直接来自新L的‘原始素材’ؓ基础。这些记者正在进行新的试水……是对体制官僚化的媒体的报复性破坏……博客改变了‘新闠Z从个h传播到公众的信息动的本性……只要一摁‘张贴’键QQ何h都可以出版自q作品Q这改变传l媒体出版模式。?/FONT>
什么是播客?
播客Q即英文的Podcast或PodcastingQ这个词来源自苹果电脑的"iPod"?q播"(broadcast)的合成词Q其指的是一U在互联|上发布文gq允许用戯阅feed以自动接收新文g的方法,或用此方法来制作的电台节目。这U新Ҏ?004q下半年开始在互联|上行以用于发布音频文件?/FONT>
播客与其他音频内容传送的区别在于其订阅模式,它用RSS 2.0文g格式传送信息。该技术允怸行创Z发布Q这U新的传播方式得h人可以说Z们想说的话?/FONT>
什么是Tag?
Tag(中文叫做“标{䏀? 是一U新的组l和理在线信息的方式。它不同于传l的、针Ҏ件本w的关键字检索,而是一U模p化、智能化的分cR?Tag是一U更为灵zR有的分类方式Q您可以为每日志、每个帖子或者每张图片等d一个或多个Tag(标签)Q你可以看到|站上所有和您用了相同Tag的内容,由此和他Z生更多的联系。Tag体现了群体的力量Q得内容之间的相关性和用户之间的交互性大大增强?/FONT>
什么是RSS?
RSS是一U简单的信息发布和传递方式,使得一个网站可以方便地调用其他提供RSS订阅服务的网站的内容Q从而Ş成“新闻聚合”,让网站发布的内容在更大的范围内传播?/FONT>
如果从RSS阅读者的角度来看QRSS获取信息的模式与加入邮g列表获取信息有一定的怼之处Q也是可以不必d各个提供信息的网站而通过客户端浏览方?UCؓ“RSS阅读器?或者在URSS阅读方式q些内容?/FONT>
什么是Wiki?
Wiki一词来源于夏威夯?"wee kee wee kee" Q原本是“快点”的意思。在q里Wiki指一U超文本pȝ。这U超文本pȝ支持面向C的协作式写作Q同时也包括一l支持这U写作的辅助工具。我们可以在Web的基上对Wiki文本q行览、创建、更改,而且创徏、更攏V发布的代hq比HTML文本为小;同时Wikipȝq支持面向社的协作式写作,为协作式写作提供必要帮助;最后,Wiki的写作者自然构成了一个社,Wikipȝ个社提供简单的交流工具。与其它文本系l相比,wiki有用方便及开攄特点Q所以wikipȝ可以帮助我们在一个社内׃n某领域的知识?/FONT>
什么是AJAX?
Ajaxq不是一U技术。它实际上是几种已经在各自领域大行其道技术的强强l合。Ajax混合?
*ZXHTML/CSS
* 由DOM(Document Object Model)实现动态显CZ交互
* 通过XML和XSLTq行数据交换及处?/FONT>
* 使用JavaScript整合上述技?/FONT>
直观一点的说Ajax能够实现不刷新浏览器H口(当然更不用安装额外的插g)而满用L操作Q现在一些看上去很Cool的网站,很多是用q项技术实现的Q其中包?orkut、Gmail、Google Group、Google Suggest、Google Maps、Flickr?/FONT>A9.com{?/FONT>
什么是SNS?
SNS:Social Network SofwaretQ社会性网lYӞ依据六度理论Q以认识朋友的朋友ؓ基础Q扩展自q。ƈ且无限扩张自qQ在需要的时候,可以随时获取一点,得到该h脉的帮助?/FONT>
六度关系理论:国著名C会心理学家c_gu(Stanley Milgram)?0世纪60q代最先提出,在h际脉l中Q要l识M一位陌生的朋友Q这中间最多只要通过六个朋友p辑ֈ目的。就是说你想认识一个hQ托朋友找朋友找认识他的人,之间不会过六个人?/FONT>
在经高速发展的今天Qh际关pȝ作用愈发明显Qh脉资源对于一个h的成功非帔R要。目前很多职业h士在人际资源斚w其实都比较匮乏,因此SNSq种新兴的网l社交方式一出现Q迅速流行欧国Ӟ已经成ؓ_英阶层拓展人际关系的主要方式之一?/FONT>
在第一部分中,我们讨论了AJAX基础——徏立从脚本到服务器的通讯的能力,q正是HTML面h动态能力的原因所在。然而,q就意味着我们已准备好抛弃我们自己版本的Yahoo邮g?不,q没有。原因在?AJAX是一个合的福。一斚wQ它使我们能够在Web上创Z富的桌面U的应用E序;另一斚wQ如果我们把"页面式"的Web应用E序与客L/服务器或Swing版本的程序进行比较,那么会看到其开发实践ƈ不很相同。我们将需要习惯于q样的事?构徏一个丰富的UI需要时间。须知,允许用户实现更大的灵zL也q应地需要付出更多的旉Z仗?/FONT>
最后的{案当然要依赖于大量的组件库、框架以及具有工业力量的开发工兗且不考虑工具Q本文集中于讨论在今天对于AJAX热心者有哪些技术是可用的。在需要构建可重用的商业组件的同时Q本文将重点分析"隐含?JavaScript中的面向对象的力量。另外,在强调需要构建定制的UIlg的同Ӟ本文介l一个简便的Ҏ——用定制的客LHTML标签来封装描q逻辑?/FONT>
二?AJAX语言——对象面向的JavaScript
由定义来看,JavaScript是典型的AJAX语言。不同于JavaQJavaScriptq不OO风格的编码。然而,令h吃惊的是JavaScript居然全面支持所有的OO语言的主要属?装、承和多态性。Douglas Crockford甚至UJavaScript?世界上最易被误解的编E语a"。让我们回顾一下JavaScript的面向对象的地方吧?/FONT>
数据cd
在Java中,一个类定义了一个数据和它的相关行ؓ的组合。尽JavaScript保留了class关键字,但是它不支持与常规OOP语言一L语义?/FONT>
q听h可能觉得奇怪,但是在JavaScript中,对象是用函数来定义的。事实上Q通过在下面的CZ中定义一个函敎ͼ你就定义了一个简单的I类Calculator:
function Calculator() {}
一个新的实例的创徏与在Java中相?使用new操作W?
var myCalculator = new Calculator();
上面q个函数不仅定义一个类Q而且q担当了一个构造器。在此,操作Wnew实现了这一术-实例化一个类Calculator的对象ƈ且返回一个对象参考而不是只调用该函数?/FONT>
创徏q样的空cL没错Q但在实际中q没有多大用处。下面,我们准备使用一个Java-脚本原型l构来填充类定义。JavaScript使用原型当作创徏对象的模ѝ所有的原型属性和Ҏ被参考引用地复制C个类的每个对象中Q所以它们都h相同的倹{你可以改变一个对象中的原型属性的|q且该新g覆盖从原型中复制q来的缺省|但是q仅对于在一个实例中。下列语句将把一个新属性添加到Calculator对象的原型上:
Calculator.prototype._prop = 0;
既然JavaScriptq没有提供一个方法来从句法上表示一个类定义Q那么我们将使用with语句来标记该cȝ定义边界。这也将使得CZ代码更ؓ短小Q因with语句被允许在一个指定的对象上执行一pd的语句而不需要限制属性?/FONT>
function Calculator() {};
with (Calculator) {
prototype._prop = 0;
prototype.setProp = function(p) {_prop = p};
prototype.getProp = function() {return _prop};
}
到目前ؓ止,我们定义了ƈ且初始化了公共变量_propQƈ且ؓ它提供了getter和setterҎ?/FONT>
需要定义一个静态变?你可以把静态变量当作是为类所拥有的一个变量。因为在JavaScript中的cȝ函数对象来描qͼ所以我们只需要把一个新属性添加到该函C:
Calculator.iCount=0;
现在Q既然这个iCount变量是一个Calculator对象的属性,那么它将会被cCalculator的所有实例所׃n?/FONT>
function Calculator() {Calculator.iCount++;};
装
通过使用如上面所定义?Calculator"Q我们可以存取所有的"class"数据;然而,q增加了zcM命名冲突的危险性。我们明昑֜需要封装以把对象看作自包含的实体?/FONT>
数据装的一U标准语a机制是用私有变量。ƈ且一个常用的仿效一个私有变量的JavaScript技术是在构造器中定义一个局部变?q样以来Q该局部变量的存取只能l由getter和setter来实?它们是该构造器中的内部函数。在下列实例中,_prop变量在Calculator函数中定义ƈ且在函数范围外不可见。其中有两个匿名的内部函?分别被赋予setProp和getProp属?让我们存?U有"变量。另外,h意,q里this的?十分怼于在Java中的用法:
function Calculator() {
var _prop = 0;
this.setProp = function (p){_prop = p};
this.getProp = function() {return _prop};
};
常常被忽视的是在JavaScript中作如此装所付出的代仗须知,q种代h可能是巨大的Q因为内部函数对象对于该"class"的每一个实例被不断地重复创建?/FONT>
因此Q既然基于原型构建对象速度更快q且消费更少些的内存Q那么我们在最性能的场所特别支持使用公共的变量。请注意Q你可以使用命名惯例来避免名U冲H?例如Q在公共的变量的前面加上该类名?/FONT>
l承
乍看之下QJavaScript~Z对类层次的支持,q很怼于面向对象语a的程序员对于C语言的期盹{然而,管JavaScript句法没有象Java一h持类l承Q但是我们仍然能够在JavaScript中实现?通过把已定义cȝ一个实例拷贝到其派生类的原型当中?/FONT>
在我们提供D例之前,我们需要介l一个constructor属性。JavaScript保证每一个原型中包含constructor-它拥有到该构造器函数的一个参考。换句话_Calculator.prototype.constructor包含一个到Calculator()的参考?/FONT>
现在Q下面的代码昄了怎样从基cCalculatorzcArithmeticCalculator。其中,"W一?取得cCalculator的所有的属性,?W二?把原型constructor的值恢复成ArithmeticCalculator:
function ArithmeticCalculator() { };
with (ArithmeticCalculator) {
ArithmeticCalculator .prototype = new Calculator();//W一?BR> prototype.constructor = ArithmeticCalculator;//W二?BR>}
q上面的实例看h象一个合成体而不象是l承Q但是JavaScript引擎q是清楚q个原型铄。特别是Qinstanceof操作W会正确地适用于基cdzcR假定你创徏cArithmeticCalculator的一个新实例:
var c = new ArithmeticCalculator;
表达式c instanceof Calculator和c instanceof ArithmeticCalculator都会成立?/FONT>
注意Q在上面CZ中的基类的constructor是在初始化ArithmeticCalculator原型时被调用的,而在创徏zcȝ实例时是不被调用的。这可能会带来不惌的负面媄响,而且Z实现初始化你应该考虑创徏一个独立的函数。由于该构造器q不是一个成员函敎ͼ所以它无法通过this参考引用调用。我们将需要一个能调用类?Calculator"成员函数:
function Calculator(ops) { ...};
with (Calculator) { prototype.Calculator=Calculator;}
现在Q我们可以写一个承类-它显式地调用基类的构造器:
function ArithmeticCalculator(ops) { this.Calculator(ops);};
with (ArithmeticCalculator) {
ArithmeticCalculator .prototype = new Calculator;
prototype.constructor = ArithmeticCalculator;
prototype.ArithmeticCalculator = ArithmeticCalculator;
}
多态?/STRONG>
JavaScript是一U非cd化的语言-在此Q一切都是对象。因此,如果有两个类A和BQ它们都定义一个foo()Q那么JavaScript允许在A和B的实例上多态地调用foo()-即不存在层ơ关p?虽然是可实现?。从q一角度来看QJavaScript提供一个比Java更宽的多态性。这U灵zL,象往怸P也要付出代h。在q种情况中,代h是把cd查工作代理到应用E序代码。具体地_如果需要检查一个参考确实指向一个所希望的基c,那么q可以通过instanceof操作W来实现?/FONT>
另一斚wQJavaScriptq不查函数调用中的参?q可以防止用一L命名和不同的参数来定义多态函?q且让编译器选择正确的签?。代之的是,JavaScript提供了一个Java 5风格的函数范围内的argument对象-它允怽Ҏ参数的类型和数量的不同而实C个不同的行ؓ?/FONT>
三?CZ展示
本文所附源码列?实现了一个计器-它可以计以一个逆向波兰式标志的表达式。该CZ展示了本文中所介绍的主要技术ƈ且也介绍了一些独特的JavaScriptҎ的用法Q例如在一个动态函数调用中以一个数l元素的方式讉K对象属性?/FONT>
Z使列?工作Q我们需要另外准备一些代?它们用于实例化该计算器对象ƈ且调用evaluateҎ:
var e = new ArithmeticCalcuator([2,2,5,"add","mul"]);
alert(e.evaluate());
四?AJAXlg授权
所有的AJAXlg授权Ҏ在今天被逻辑地分成两l。具体地_W一l用于与ZHTML的UI定义的无~集成。第二组把HTML当作一个UI定义语言以支持某UXML。在本文中,我们从第一l中来展CZU方?虽然它存在于览器之中却是类gJSP标签。这些浏览器特定的组件授权扩展在IE情Ş下称作元素行为,而在最q版本的FirefoxQMozilla和Netscape 8情Ş下称作可扩展的绑定?/FONT>
五?定制标签
Internet ExplorerQ从版本5.5开始,支持定制的客LHTML元素的JavaScript授权。不象JSP标签Q这些对象ƈ没有在服务器端被预处理到HTML中。而是Q它们成Z标准HTML对象模型的合法扩展,q且包括构造控件在内的一切事情,都是动态地发生在客L的。同PZGecko-引擎的浏览器能够用一个可重用功能动态地装饰M现有的HTML元素?/FONT>
因此Q我们有可能用具有HTML语法的方法、事件和属性来构徏一个具有丰富的UIlg的库。这Llg可以被自由地混合于标准HTML中。内部地Q这些组件将会与应用E序服务器进行通讯-以AJAX风格。换句话_你有可能(q且相对单地)构徏自己的AJAX对象模型?/FONT>
q种IE风味的方法被UCؓHTC或HTMLlg;其Gecko版本被称为XBL-可扩展的l定语言(eXtensible Bindings Language)。ؓ了实现本文目的,我们集中于讨论IE?/FONT>
六?输入HTMLlg-HTC
HTC或HTMLlg也被UC行ؓ。它们被划分ZU类?一U是依附的行?用一l属性、事件和Ҏ装饰M现有的HTML元素;另一U是元素行ؓ-看上去象宿主面的定制的HTML标签的一个扩展集合。依附的行ؓ和元素行Zh供了开发组件和应用E序的一U简单方案。在此,我们展CZ下最为综合的情Ş-元素行ؓ?/FONT>
数据l定复选框控g
Z展示元素行ؓQ我们将构徏一个定制的数据l定复选框。构样一个控件背后的基本原因在于Q一个标准HTML复选框h下面若干显著的缺?
·需要应用程序编码来?checked"属性的值映到商业域|例如"Y[es]"/"N[o]"Q?M[ale]"/"F[emale]"Q等{。HTML复选框使用"checked"属性,而许多其它HTML控g使用的则?value"属性?/FONT>
·需要应用程序编码来l持该控件的状?修改q的/未修改过?。这实际上是在所有的HTML控g普遍存在的一个问题?/FONT>
·需要应用程序编码才能创Z个关联标{?它应该接受鼠标点dƈ相应地改变该复选框的状态?/FONT>
·标准HTML复选框不支?校验"事g以允许取消一个GUI行ؓQ而这U要求可能存在于某些应用E序中?/FONT>
现在Q让我们看一个正在构建的该控件的用法CZQ它的用法可能如下情?
Qcheckbox id="cbx_1" value="N" labelonleft="true" 另外Q我们的控g支持可取消的事件onItemChanging和通知事gonItemChanged?BR> 定义定制标签 从结构上Ԍ一个定制标{是一个具有一个HTC扩展名的文g-它在QPUBLIC:COMPONENTQ和Q?PUBLIC:COMPONENTQ标志之间对它的属性,Ҏ和事件加以描q?/FONT> Z定义一个定制CHECKBOX标签Q我们创Z个如下列代码片断中的文gcheckbox.htc-其中Q第一行负责设|该lg的标{: QPUBLIC:COMPONENT NAME="cbx" tagName="CHECKBOX"Q?BR>QPROPERTY NAME="value" GET="getValue" PUT="putValue" /Q?BR>//我们把组件的所有另外的属性放在这?BR>QMETHOD NAME="show" /Q?BR>//我们把组件的所有另外的Ҏ攑֜q里 使用定制标签 管HTC文g的内Ҏ较重要,但是q与其文件名是什么无兟뀂值得注意的是Q指向该HTC文g的URL需要被使用IMPORT指o指定-q必d相应的定制标{一ơ出C?在页面上)完成。下面是最单的可能的页面用一个定制的复选框可能看上ȝ样子-假定该页面和HTC文g处理同一个文件夹? QHTML xmlns:mynsQ?BR>Q?IMPORT namespace="myns" implementation="checkbox.htc" Q?BR>QBODYQ?BR>Qmyns:checkbox id='cbx_1' label='Hello'/Q?BR>Q?BODYQ?BR>Q?HTMLQ?/FONT> h意,定制CHECKBOX是怎样在打开的HTML标签中被映射C个非~省的命名空?myns"的。这个IMPORT指o实现把HTC同步加蝲到浏览器的内存ƈ且还指示览器怎样为适当的命名空间实现名U确定的(HTC到命名空间的兌可能是多对一??/FONT> 定制标签的构造器 最好的初始化HTC的方法是Q一旦它被装载就处理oncontentready事g。因此,我们可以定义处理器函?Z概念清晰赯Q我们称之ؓ构造器: QATTACH EVENT="oncontentready" HANDLER="constructor" /Q?/FONT> constructor()的逻辑是简单的:Ҏ属性labelonleft的?见下面的属性定?按顺序连接一个常规HTML复选框和HTML标签: function constructor() { 定义定制标签属?/FONT> Z定义属性labelonleftQ我们又?/FONT> QPROPERTY NAME="labelonleft" VALUE="true"/Q?/FONT> h意,q个属性ƈ没有包含getter?或setterҎ。属性onValue和offValue不仅提供了从复选框状态到一个商业值域的映而且不需要getters和setters: QPROPERTY NAME="onValue" VALUE="true"/Q?BR>QPROPERTY NAME="offValue" VALUE="false" /Q?/FONT> 然而,属性checked是用两个getter和setter定义? QPROPERTY NAME="checked" GET="getChecked" PUT="putChecked" /Q?/FONT> 因此Q?FONT face=Verdana>我们在<SCRIPTQ部分徏立了上面两个Ҏ的定义。正如你所见,setter putChecked()-在每次复选框状态改变时Ȁ?把value属性设|ؓ下面两个变体之一QonValue或OffValue。请注意QputChecked()不仅可由在复选框-宿主面中的脚本触发Q而且也能通过在checkbox.htc中的相应的Q何赋值操作触发?/FONT> var _value;
label="Show Details:" onValue="Y" offValue="N"/Q?/FONT>
QEVENT NAME="onItemChanging" ID="onItemChanging"/Q?BR>//我们把组件将向应用程序激zȝ所有另外的事g攑֜q里
QATTACH EVENT="oncontentready" HANDLER="constructor" /Q?BR>//我们把组件自己处理的另外的事件放在这?BR>QSCRIPTQ?BR>//我们把所有的ҎQ属性getters和setters和事件处理器攑֜q里
Q?SCRIPTQ?BR>Q?PUBLIC:COMPONENTQ?/FONT>
//我们把一个HTML复选框和标{添加到元素?BR> //详细情Ş见列?
}
function putChecked( newValue ) {
value = (newValue?onValue:offValue);
}
function getChecked(){
return ( _value == onValue);
}
七?为定制标{֮义事?/STRONG>
让我们看一下onItemChanging和onItemChanged事g的定义以及这些事件是怎样在value属性的setter内部被激发和处理的(见所附源码中的列?Q。方法putValue()有几个让人感兴趣的地斏V首先,在分析CHECKBOX标签期间Q可以调用这个方?只要指定q个HTMLvalue属性。这正解释了Z么我们ؓ非构造对象徏立一个单独的逻辑分支-为把构造过E与一个对用户击键的反应区别开来。其ơ,在此我们展示了定制事件onItemChanging的创建和处理-它允许应用程序取消行为。请注意Q通过q种方式Q无论是击键q是通过~程方式实现赋值都能达到取消的目的?/FONT>
事g取消
Z取消事gQ一个应用程序应该拦截该事gq且把event.returnValue讄为false。下面的代码片断展示了应用程序是怎样实现取消事gq程的:
cbx_1::onItemChanging() {
. . . . .
if (canNotBeAllowed) {
event.returnValue=false;
. . . . .
}
如果事g没被取消QputValue()把内部的普通HTML复选框的checked属性设|ؓ每个相应的当前?如果它等于onValueQ这个内部复选框被选中Q如果它{于offValue(不存在第三种选择)Q复选框不被选中(完整的列表见本文所附源码中的列?)?/FONT>
复选框的HTML内幕
我们控g的绘制是通过助理函数addLabel()和addCheckBox()来实现的q且从一个constructor()内部调用。这些函数把HTML注入q元素的innerHTML。这U注入式HTML的一U简化Ş式如下所C:
QLABEL for=cb_{uniqueID}QShow Details:Q?LABELQ?BR>QINPUT id=cb_{uniqueID} type=checkbox /Q?/FONT>
在此QuniqueID是一个由IE所生成的唯一的(在一个页面内Q字W串-它用来识别HTC的实例?/FONT>
八?再封?/STRONG>
在我们的CHECKBOX中有一个缺炏V按照我们徏立它的方式,在constructor()期间被注入的HTML隶属于宿主该HTC的页面的DOM。而且Q全局的JavaScript变量like_value属于它们所在的文的全局范围。这是危险的Q因为我们偶然会遇到命名冲突的可能性:最明显的情形是使用同一个组件的多个实例。另外这q会D一个可能?我们的控件可能会偶然地用相同的名U参考其它对象,反之也如此?/FONT>
为简化v见,需要徏立一U专门的机制来ؓ对象授权启动一个真正模块化Ҏ。幸好,HTC技术支持一U智能答?viewLink?BR>
把一个控件声明ؓ装的最Ҏ的方法是把一个额外声明放到打开和关闭的PUBLIC:COMPONENT标签之间Q?/FONT>
QPUBLIC:DEFAULTS viewLinkContent/Q?nbsp;
该控件立卛_变成装性的Q而且它有自己的HTML文?成ؓL的原子lg。该对象的每个实例有它自q实例值的集合q且只有公共Ҏ和属性能够从外界代码中加以存取。换句话_该viewLink机制充分地启动了复杂的Web应用E序的设计和实现-通过使用一U真正的OO的基于组件的Ҏ?/FONT>
特别圎ͼ我们可以化代?通过从内部复选框和HTML标签的定义中删除uniqueID后缀Q因为我们不再担心命名冲H。因此,我们可以替换下面q一行:
eval( 'cb_'+uniqueID).checked = ( _value == onValue );
?/FONT>
cb.checked = ( _value == onValue );
q相应地改变addCheckbox()和addLabel()?/FONT>
九?l论
既然AJAX竞赛刚刚开始,那么׃存在什么AJAX标准q且没有现成的你可以依赖以构Z的应用程序的可广为接受的RAD工具。虽然Y件供应商们可能还需要较长一D|间来创徏q种强健的开发^収ͼAJAX热心者已l开始着手准?通过一些良好定义的API把可重用的代码块装为商业组件?/FONT>
以这U方向导航,本文概括了AJAX语言的OO"力量"-JavaScript。另外,q展CZ一U可用的lg-授权{略-客户端定制标{技术。我们在仅描qIE特定的定制标{同时Q还另外提供了一个可下蝲的实?适于Mozilla览器的可扩展的l定实例?/FONT>
q个名字代表了异步JavaScript+XMLHTTPRequestQƈ且意味着你可以在Z览器的JavaScript和服务器之间建立套接字通讯。其实AJAXq不是一U新技术,而是已经成功地用于现代浏览器中的若干成功技术的可能性组合。所有的AJAX应用E序实现了一U“丰富的”UI——这是通过JavaScript操作HTML文对象模型q且l由XMLHttpRequest实现的精定位的数据索来实现的。典型的CZAJAX应用E序是Google Labs(http://labs.google.com)的Google Maps和Google Suggest。这些应用程序现场监视用戯入ƈ且提供实时的面更新。最重要的是Q在用户通过地图D或输入一个查扑֭W串的同Ӟq些事g不需要刷新页面?/FONT>
事实上,支持q些令h感到惊讶的应用的技术已l出CD|间了Q尽它们要求复杂的技能以及用浏览器的技巧。一些专利品就提供了相似的能力——如Macromedia Flash插gQJava Applets?NETq行时——在辑ֈ实用上已l有一D|间了。把一U可与服务器通话的脚本组件引入到览器中的思想早在IE 5.0中就已经存在。Firefox和其它流行的览器也加入到浏览器大军中ƈ以一U内|对象Ş式支持XMLHTTPRequest。随着跨^台浏览器的出玎ͼq些技术得C认可q在2004q?月一家称为Adaptive Path的公怸正式提出了AJAX?/FONT>
而言之,׃来自于Google的支持和安装了一点可用的览器技术,加上Z一U?更好的用户体?Q每个h都在把客L技术添加到Web应用E序上?/FONT>
? AJAX与传l应用程序的区别
一个传lWeb应用E序模型实际上是一U基本的事g——用戯q提交表单以实现面交换。也是_表单提交和页面传送无法得C?q有更坏的情形——用户需要再ơ点凅R这与AJAX截然不同-——数据跨q线路而不是完整的HTML面传输。这U数据交换是l由特定的浏览器对象:XMLHttpRequest实现?再由适当的逻辑来处理每个数据请求的l果Q页面的特定区域而不是完整的面被更新。结果是更快的速度Q更的拥挤和更好的信息传送控制?/FONT>
传统?click-refresh"Web应用E序用户中断工作q程而等待页面的重装。通过引入AJAX技术,一个客L脚本能够异步C服务器通话Q而用户仍能保持输入数据。除了对用户透明之外Q这L异步意味着服务器可以有更多旉来处理请求?/FONT>
传统Web应用E序把所有的处理代理到服务器q且服务器进行状态管理。AJAX允许灉|划分应用E序逻辑以及客户和服务器之间的状态管理。这消除了一U?click-refresh"依赖性ƈ且提供更好的服务器可伸羃性。当该状态存储在客户端,你就不必跨越服务器来l持会话或保?l束状?其用期限是由客L来定义的?/FONT>
? AJAX——分布式的MVC
管AJAX应用E序依靠JavaScript来实现描q层Q然而处理能力和知识库仍然存在于服务器上。此ӞAJAX应用E序大量的与J2EE服务器通讯——把数据输入/输出Web服务和servlets。具有基于AJAX的描q层的J2EE应用E序和标准J2EE应用E序之间的区别首先在于,MVC是通过U\分布的。通过使用AJAXQ视图是本地的,而模型和控制器是分布式的——这使得开发者能够灵zd军_哪些部g会是Z客户端的。具体地_本地视图通过巧妙地操作HTML DOM而生成图?控制器局部地处理用户输入q且Ҏ开发者的判断扩展到服务器的处理——经由HTTPh(Web服务QXML/RPC或其?实现;模型的远E部分是Ҏ客户端需要而下载的以达到实时更新客L面;q且状态是在客L攉的?/FONT>
在以后的AJAX文章中,我们比较深入地讨论q里的每一U组件ƈ提供有关它们联合在一赯行应用的CZ。现在,先不多说Q让我们详细地分析一个简单的AJAXCZ?/FONT>
? 邮政区号校验和查?/STRONG>
我们创Z个包含三个INPUT字段(ZipQCity和State)的HTML面。我们将保证Q只要用戯入邮政区L前三个数字,该页面上的字D就会用W一个匹配的状态值填充。一旦用戯入了所有五位邮政区hQ我们将立即军_和填充相应的城市。如果邮政区h?在服务器的数据库没有扑ֈ)Q那么我们将把邮政区L边界讄为红艌Ӏ这L可视化线索有助于用户q且在现代浏览器中已l成ZU标?作ؓ一实例Q当Firefox扑ֈ一个HTML面中的匚w关键字时Q它会高亮与你在览器查扑֟输入的内容一致的部分)?/FONT>
让我们首先创Z个简单的包含三个INPUT字段的HTML:zipQcity和state。请注意Q一旦一个字W输入进邮政区号字段域中Q即调用ҎzipChanged()。JavaScript函数zipChanged()(见下)在当zip长度?时调用函数updateState()Q而在当zip长度?时调用函数up-dateCity()。而updateCity()和updateState()把大部分的工作代理到另一个函数ask()?/FONT>
Zip:Qinput id="zipcode" type="text" maxlength="5" onKeyUp="zipChanged()"
style="width:60"/Q?BR>City: Qinput id="city" disabled maxlength="32" style="width:160"/Q?BR>State:Qinput id="state" disabled maxlength="2" style="width:30"/Q?BR>Qscript src="xmlhttp.js"Q</scriptQ?BR>QscriptQ?BR>var zipField = null;
function zipChanged(){
zipField = document.getElementById("zipcode")
var zip = zipField.value;
zip.length == 3?updateState(zip):zip.length == 5?updateCity(zip):"";
}
function updateState(zip) {
var stateField = document.getElementById("state");
ask("resolveZip.jsp?lookupType=state&zip="+zipQ?stateFieldQ?zipField);
}
function updateCity(zip) {
var cityField = document.getElementById("city");
ask("resolveZip.jsp? lookupType=city&zip="+zipQ?cityFieldQ?zipField);
}
Q?scriptQ?BR>
函数ask()与服务器q行通讯q分配一个回调函数来处理服务器的响应(见下列代?。后面,我们分析具有双重特点的resolveZip.jsp的内?它根据zip字段中的字符数查找city或state信息。重要的是,ask()使用了具有异步特点的XmlHttpRequestQ这样填充state和city字段或着色zip字段边界可以不必减慢数据入口而得以实现。首先,我们调用request.open()-它用服务器打开套接字频道,使用一个HTTP动词(GET或POST)作ؓW一个参数ƈ且以数据提供者的URL作ؓW二个参数。request.open()的最后一个参数被讄为true-它指Ch的异步特性。注意,该请求还没有被提交。随着对request.send()的调用,开始提?q可以ؓPOST提供M必要的有效蝲荗在使用异步hӞ我们必须使用request.onreadystatechanged属性来分配h的回调函数?如果h是同步的话,我们应该能够在调用request.send之后立即处理l果Q但是我们也有可能阻断用P直到该请求完成ؓ止?
HTTPRequest = function () {
var xmlhttp=null;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (_e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (_E) { }
}
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp = false;
}
}
return xmlhttp;
}
function ask(urlQ?fieldToFillQ?lookupField) {
var http = new HTTPRequest();
http.open("GET"Q?urlQ?true);
http.onreadystatechange = function (){ handleHttpResponse(httpQ?fieldToFillQlookupField)};
http.send(null);
}
function handleHttpResponse(httpQ?fieldToFillQ?lookupField) {
if (http.readyState == 4) {
result = http.responseText;
if ( -1 != result.search("null") ) {
lookupField.style.borderColor = "red";
fieldToFill.value = "";
} else {
lookupField.style.borderColor = "";
fieldToFill.value = result;
}
}
}
为ask()所使用的HttpRequest()函数(见上)是一跨浏览器的XMLHTTPRequest的一个实例的构造器;E后我们分析它。到目前为止Q请注意对于handleResponse()的调用是如何用一匿名函数包装?q个函数是function(){handleHttpResponse(httpQfieldToFillQ?lookupField)}?/FONT>
该函数的代码是动态创建的q且在每ơ我们给http.onreadstatechange属性赋值时被编译。结果,JavaScript创徏一个指向上下文(所有的变量都可以存取正在结束的Ҏ-ask())的指针。这样以来,匿名函数和handleResponse()p够被保证充分存取所有的上下文宿ȝ变量Q直臛_匿名函数的参考被垃圾回收站收集ؓ止。换句话_无论何时我们的匿名函数被调用Q它都能无缝地参考requestQfieldToFill和lookupField变量Q就象它们是全局的一栗而且Q每ơask()调用都将创徏环境的一个独立拷贝,q且此时q些变量中保存有该函数将l束时的倹{?/FONT>
现在Q让我们分析一下函数handleResponse()。既然它能够在请求处理的不同状态下Ȁz,那么该函数将忽略所有的情Ş-除了该请求处理完成之?q相应于request.readyState属性等?("Completed")。此Ӟ该函数读取服务器的响应文本。与它的名字所暗示的相反,XmlHttpRequest的输入和输出都不必限于XML格式。特别地Q我们的resolveZip.jsp(见源码中的列?)q回普通文本。如果返回gؓ"unknown"Q那么该函数假定邮政区h无效的ƈ且把查找字段(zip)边界颜色|ؓU色。否则,q回D用于填充字段state或cityQƈ且zip的边界被赋予一U缺省颜艌Ӏ?BR>
XMLHttpRequest-传输对象
让我们返回到我们的XMLHTTPRequest的跨览器实现。最后一个列表包含一个HttpRequest()函数-它向上兼容于IE5.0和Mozilla 1.8/FireFox。ؓ化v见,我们只创Z个微软XMLHTTPRequest对象Q而且如果创徏p|Q我们假定它是Firefox/Mozilla?/FONT>
该函数的核心是XMLHTTPRequest-q是一个本机浏览器对象Q它为包括HTTP协议的Q何东西与服务器之间的通讯提供方便。它允许指定MHTTP动词Q头部和有效载荷Qƈ且能够以异步或同步方式工作。不需要下载也不需要安装Q何插?管在IE的情形下QXMLHTTPRequest是一个集成到览器内部的ActiveX。因而,"Run ActiveX Control and Plugins"默认IE权限应该正好适合使用它?/FONT>
最重要的是QXMLHTTPRequest允许一个到服务器的RPC风格的编E查询而不需要Q何页面刷新。它以一U可预测的,可控制的方式来实现此-提供了到HTTP协议的所有细节的完整存取-包括头部和数据的M定制格式。在以后的文章中Q我们将向你展示其它一些业界协?你可以在q些传输协议(如Web服务和XML-RPC)之上q行-它们极大地简化大规模应用E序的开发和l护?/FONT>
?服务器端逻辑
最后,服务器端的resolveZip.jsp被从函数ask()中调?见所附源码中的列?)。这个resolveZip.jsp在两U由当前的邮政区号长度所区分的独立的场所下被调用(见zipChanged()函数)。请求参数lookupType的值或者是state或者是city。ؓ化v见,我们假定,两个文gstate.properties和city.properties都位于服务器中C驱动器的根目录下。resolveZip.jsp逻辑负责用适当的预装蝲的文件返回查扑ր{?/FONT>
我们的支持AJAX的页面现在已l准备好了?/FONT>
?q程脚本技?一U可选方?/STRONG>
一些更旧的AJAX实现是基于所谓的q程脚本技术。这U思想是,用户的行为导致经由IFRAMEҎ务器q行查询Q而服务器用JavaScript作出响应Q该脚本一旦到辑֮L立即被执行。这与XMLHttpRequestҎ相比存在较大的区别,在后者情况下Q服务器响应数据而客L解释数据。其好处是这U解x案支持更旧的览器?/FONT>
ZIFRAMECZ的HTML部分(见所附源码中的列?)与我们在XMLHTTPRequest场合下所用的极相|但是q次我们引入另外一个IFRAME元素-controller:
Zip:Qinput id="zipcode" type="text" maxlength="5" onKeyUp="zipChanged()" 我们保持每次击键都调用zipChanged()一ơ,但是q一ơ,从zipChanged()中被调用的函数ask()(见所附源码中的列?)负责讄IFRAME的src属性,而不是调用一个XMLHTTPRequest: function ask(urlQ?fieldToFillQ?lookupField){ 服务器端逻辑׃个粗略的resolveZip.jsp(见所附源码中的列?)所描述。它与它的XMLHTTPRequest对应物相区别-它返回JavaScript语句Q这些语句设|变量字Dlookup和city的全局|而且一旦它到达览器即从全局H口的执行上下文中调用函数response()?/FONT> 函数response()是一修改版本的handleResponse()-q一函数可以免于处理未完成的h(详见本文所附源码中的列?)?/FONT> ? N 为简化v见,让我?俯看"一下在我们的示例代码中的一些重要的问题: 1.事实-XMLHTTPRequest对象实例和回调函数调用在被用以后ƈ没被破坏-在每ơ调用后q有可能D内存泄漏。适当~写的代码应该破坏或重用对象池中的这些实例。而且Q客L必须使用与服务器软g相同的对象管理技术?/FONT> 2.在大多数情况下,错误往往得不到有效处理。例如,在方法ask()中对request.open()的调用可能引发一个异常,q是必须要捕获和处理的,即在浏览器中没有设|JavaScript异常自动捕获功能。而handleResponse()函数又是另外一个例子。它必须要ؓ可能的服务器端和通讯错误而检查headers和responseText倹{在发生错误的情况下Q它必须力恢复q?或者报告错误。正开发的AJAX应用E序要尽可能避免"提交"松散的数据,因ؓ往往存在U\断开和其它低U通讯的问?所以这些程序必d立一个强壮的和自恢复的框架ؓ此提供支持?/FONT> 3.当前服务器端框架提供相当多的功能-它们可以与一U自由刷新方法和谐相处。例如,让我们考虑一个定制的在指定时间内的服务器端认证的问题。在q种情况下,我们必须拦截到XMLHTTPRequest调用的安全系l响应,昄d屏幕Q然后在用户被认证后重新发出h?/FONT> 所有的q些问题只是一些典型的用低UAPI工作的Q何应用程序代码,而且所有这些问题都能被解决。好消息是,解决q些问题所需要的技术十分相g大多数Java开发技术,如Web服务Q定制标{֒XML/XSLT。唯一的区别在于,现在q些技术以下列形式用于客户? ·Web服务-使用SOAP/REST/RPC{简单通讯标准 ·客户端定制标{?打包丰富的客L控gq成AJAX功能 ·数据操作-ZXML和基于XSLT技?/FONT> ? 结 AJAXҎ能够向h们提供一U与桌面应用E序相同的丰富的互联|体验。但是,我们必须有选择C用AJAX技术,如当你仍在线购物Ӟ你绝对不惌你的信用卡通过后台处理悄悄地开始付ƾ。AJAX会成ZU持l的动力?我们当然希望q样。在q去的五q时间内我们一直在努力开发AJAX应用E序q且能证明它是健全ƈ且很有效的。然而,它要求一个开发者必ȝ通大量技术而不是在传统?click-refresh"Web应用E序中所使用的那些?/FONT>
style="width:60" size="20"/Q?BR>City: Qinput id="city" disabled maxlength="32" style="width:160" size="20"/Q?BR>State:Qinput id="state" disabled maxlength="2" style="width:30" size="20"/Q?BR>Qiframe id="controller" style="visibility:hidden;width:0;height:0"Q</iframeQ?/FONT>
var controller = document.getElementById("controller");
controller.src= url+"&field="+fieldToFill.id+"&zip="+lookupField.id;
}
本文介绍了Java?NET开发的Web Services怺调用的技术。本文包括两个部分,W一部分介绍?A class=bluekey target=_blank>如何?/A>.NET做客L调用Java写的Web Services,W二部分介绍了如何用Java做客L调用.NET开发的Web Services?/P>
?目需要的工具
Windows2000 Server(IIS)
Jbuilder9.0( 含有Tomcat , axis)
JDK1.4+Java Web Services Develop
VS.Net 2003
备注:如果没有JBuilder的话需要自׃载安装Tomcat4.1 以及 Axis的开发包Qƈ做相应配|。由于网上有很多q样的文章,q里׃一一说明了?/P>
??NET做客L调用Java写的Web Services
1. 生成一个Java Web Services
使用JBuilder 生成一个Web Services是非常简单的Q我完全是按照它的帮助做的,只要一步步做下d可以了。具体\径是Developing Web Services -> tutorials : Web Services(Axis) -> Creating a simple Web Services
2. 发布q个Web Servicesq得到它?A class=bluekey target=_blank>WSDL
Web Services生成好之后,F9q行q个目。然后,单击View览现有的Web 服务Q单击Bean1的WSDLq接Q我们可以在览器中察看它的WSDL描述。在览?A class=bluekey target=_blank>地址?/A>复制WSDL地址Qؓ下一步?NET开发客L调用E序做准备?/P>
3. 用VS.NET生成一?NET的客L
新徏一个项?WinForm,ASP.net都可?Q我在这里用的是一个Asp.Net目。在起始面上放|一个文本输入框用来昄调用Web Services的结果,攄一个按钮,用来单击调用Web Services。然后,选择dWeb 引用Q在WSDL一栏中把刚才得到的WSDL地址复制q来QWeb 引用的名U输入JavaServiceQ单L加引用按钮就可以了。此Ӟ我们可以在VS.net 的Solution Explore中看到这个Web 引用?/P>
在按钮的单击事g中输入下列代?
JavaService.Bean1 bean = new JavaService.Bean1();
TextBox1.Text = bean.getSample.ToString ();
q样Q一?NET客户端就完成了,试一下,工作正常QOK.
?用Java做客L调用.NET写的 Web Services
有了上面的成功,使我以ؓ用Java做客L调用也是一件十分容易的事情Q可实际情况却耗费了我两天旉才得以实现?/P>
1. 用VS.NET新徏一个Asp Web Services工程Q添加一个web 服务Q命名ؓSumService.asmx。新增一个web methodQ代码如?
[WebMethod]
public int IntAdd(int a,int b)
{
return a+b ;
}
然后q行它,q利用IEq行试成功?/P>
2. 打开jbuilder9.0,新徏一个项目,d一个java class Q命名ؓTestNetServiceQ输入下列代?
package MyWebServiceJavaClient;
import java.util.Date;
import java.text.DateFormat;
import java.util.Date;
import java.text.DateFormat;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
import java.lang.Integer;
import javax.xml.rpc.ParameterMode;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class TestNetService {
public TestNetService() {
}
public static void main(String[] args) {
try {
Integer i = new Integer(1);
Integer j = new Integer(2);
String endpoint="http://localhost/MyServices/WebServiceTest/SumService.asmx";
Service service = new Service();
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName(new QName("http://www.my.com/SU","IntAdd"));
call.addParameter("a",org.apache.axis.encoding.XMLType.XSD_DATE,javax.xml.rpc.ParameterMode.IN);
call.addParameter("b",org.apache.axis.encoding.XMLType.XSD_DATE,javax.xml.rpc.ParameterMode.IN);
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_INT);
call.setUseSOAPAction(true);
call.setSOAPActionURI("http://www.my.com/Rpc");
Integer k = (Integer)call.invoke(new Object[]{i,j});
System.out.println( "result is " + k.toString() + ".");
}
catch (Exception e) {System.err.println(e.toString());}
}
}
q行上面的java客户端程序,你会发现pȝ会抛Z个SoapAction异常。奇怪,怎么会错误呢?惛_了我开发的asp web services没有指定SoapActionQ于是在SumService.asmx中的 [web method] 的上一行添加下列代?
[SoapRpcMethod(Action="http://www.my.com/Rpc",
RequestNamespace="http://www.my.com/SU",
ResponseNamespace="http://www.my.com/SU")]
重新~译q行asp web services后,在执行javaE序Q这时会发现输出了正的l果3?/P>
q样Q用java调用.net生成的web services也算初步完成了,好像也不是很复杂是吧。其实,在实际工作中Q我一开始ƈ没有在网上找C个很好的代码例子Q全部是依靠jbuilder ?axis的帮助完成的, 可L提示什么找不到相应的SoapAction。而实际上Q我在运行了asp web services后是可以在IE览器中看到那个SoapAction的。我试验q将默认的SoapAction拯到java代码中,但是java客户端依然抛出同L异常Q这要我也很qh?/P>
?ȝ
l过两天的试验,l于从技术上明确了通过Web Services实现.net ?java的互通是可能的。当然有几点是需要注意的:
1. 在提供Web Services的时候,量使用xml schema中支持的变量cd做参数。如果?net 中的datasetq种cdQ对于java来说解析h是一个灾难,当然Q理Z是可以解析的。但是从效率角度来说Q在Web Services与客L交换信息的过E中Q始l有一个序列化和反序列化的问题。如果用datasetq种cdQ系l还需要对它进行序列化操作Q这是一个很耗费资源的过E。而用stringcd简单很多?/P>
2. 如果使用了soap header{扩展功能,例如使用了微软提供的WSE技术,它们之间的相互通信需要作Ҏ处理?BR>
从表面上看,Web service 是一个应用程序,它向外界暴露Z个能够通过Webq行调用的API。也是_可以利用~程的方法通过Web来调用这个应用程序?/P>
对Web service 更精的解释: Web services是徏立可互操作的分布式应用程序的新^台。Web serviceq_是一套标准,它定义了应用E序如何在Web上实C操作性。你可以用Q何你喜欢的语aQ在M你喜Ƣ的q_上写Web service Q只要我们可以通过Web service标准对这些服务进行查询和讉K?/P>
不管你的Web service是用什么工P什么语a写出来的Q只要你用SOAP协议通过HTTP来调用它QMl构都一致。通常Q你用你自己喜欢的语a(如VB 6或者VB.NET)来构Z的Web serviceQ然后用SOAP Toolkit或?NET的内建支持来把它暴露lWeb客户。于是,M语言QQ何^C的客户都可以阅读其WSDL文Q以调用q个Web service。客h据WSDL描述文Q会生成一个SOAPh消息。Web service都是攑֜Web服务?(如IIS) 后面的,客户生成的SOAPh会被嵌入在一个HTTP POSTh中,发送到Web服务器来。Web服务器再把这些请求{发给Web serviceh处理器。请求处理器的作用在于,解析收到的SOAPhQ调用Web serviceQ然后再生成相应的SOAP应答。Web服务器得到SOAP应答后,会再通过HTTP应答的方式把它送回到客L?/P>
基本概念
SOAP
XML和XSD
WSDL(Web Services Description Language)
WSML(Web Services Meta Language)
什么时候用Web Services
Web service是创建可互操作的分布式应用程序的新^台。Web service 的主要目标是跨^台的可互操作性。ؓ了达到这一目标QWeb service 是完全基于XML、XSD{独立于q_、独立于软g供应?/A>的标准的?/P>
Web service在应用程序跨q_和跨|络q行通信的时候是非常有用的。Web service适用于应用程序集成、B2B集成、代码和数据重用Q以及通过Webq行客户端和服务器的通信的场合?/P>
当然QWeb service也不是万能的Q你不能到处滥用Web service。在有些情况下,Web service 会降低应用程序的性能Q而不会带来Q何好处。例如,一台机器或一个局域网里面q行的同构应用程序就不应该用Web service q行通信?/P>
如何调用Web Services 客户?取得服务?/A>的服务描q文件WSDLQ解析该文g的内容,了解服务端的服务信息Q以及调用方式。根据需要,生成恰当的SOAPh消息(指定调用的方法,已经调用的参?Q发往服务端。等待服务端q回的SOAP回应消息Q解析得到返回倹{?/P>
服务?生成服务描述文gQ以供客L获取。接收客L发来的SOAPh消息Q解析其中的Ҏ调用和参数格式。根据WSDL和WSML的描qͼ调用相应的COM对象来完成指定功能,q把q回值放入SOAP回应消息q回l用戗?/P>
高层接口 使用高层接口Q不需要知道SOAP和XML的Q何信息,可以生成和使用一个WebService。Soap Toolkit 2.0通过提供两个COM对象――SoapClient和SoapServerQ来完成q些功能?/P>
在客LQ只需要生成一个SoapClient实例Qƈ用WSDL作ؓ参数来调用其中的mssoapinitҎ。SoapClient对象会自动解析WSDL文gQƈ在内部生成所有Web Service的方法和参数信息。之后,你就可以像调用IDispatch接口里的Ҏ一P调用里面所有的Ҏ。在VB或是脚本语言里,你甚臛_以直接在SoapClient对象名后面直接加?Ҏ(参数?q行调用?BR> 要用低层接口,你必dSOAP和XML有所了解。你可以对SOAP的处理过E进行控Ӟ特别是要做特D处理的时候?/P>
在客LQ首先要创徏一个HttpConnector对象Q负责HTTPq接。设定Connector的一些头部信息,比如EndPoinURL和SoapAction{。如果网l连接需要用代理服务器Q那也要在这里设定相关的信息。接着创徏SoapSerializer对象Q用于生成Soap消息。按照WSDL里定义,把所有参数按序序列化,得到一个完整的SOAPh消息。该Soap消息Q作为Payload通过HttpConnector被发送到服务端。最后,生成一个SoapReader对象Q负责读取服务端q回的SOAP消息Q取得其中的q回倹{?/P>
相关文章链接 Web服务pd教学-如何调用WebService(5) 使用vbscript脚本调用web服务
低层接口
Web服务pd教学-如何调用WebService(4)
Web服务pd教学-如何调用WebService(3)
Web服务pd教学-如何调用WebService(2)
Web服务pd教学-如何调用WebService(1)
Java?NET 的Web Services怺调用
ASP调用WebService时的问题
从非windows客户端调?NET Web服务
Java WS和C#调用
使用ASP.NET的客L证书调用Web服务
.aspx 面调用 Web 服务的性能优化
]]>
1. 数组的基本特?/SPAN>
数组与其它种cȝ容器(List/Set/Map)之间的区别在于效率、确定的cd和保存基本类型数据的能力。数l是一U高效的存储和随问对象引用序列的方式Q用数l可以快速的讉K数组中的元素。但是当创徏一个数l对?/SPAN>(注意和对象数l的区别)后,数组的大也固定了Q当数组I间不的时候就再创Z个新的数l,把旧的数l中所有的引用复制到新的数l中?/SPAN>
Java中的数组和容器都需要进行边界检查,如果界׃得到一?/SPAN>RuntimeException异常。这点和C++中有所不同Q?/SPAN>C++?/SPAN>vector的操作符[]不会做边界检查,q在速度上会有一定的提高Q?/SPAN>Java的数l和容器会因为时d在的边界查带来一些性能上的开销?/SPAN>
Java中通用的容器类不会以具体的cd来处理对象,容器中的对象都是?/SPAN>Objectcd处理的,q是Java中所有类的基cR另外,数组可以保存基本cdQ而容器不能,它只能保存Q意的Java对象?/SPAN>
一般情况下Q考虑到效率与cd查,应该可能考虑使用数组。如果要解决一般化的问题,数组可能会受C些限Ӟq时可以使用Java提供的容器类?/SPAN>
2. 操作数组的实用功?/SPAN>
?/SPAN>java.util.ArrayscMQ有许多static静态方法,提供了操作数l的一些基本功能:
equals()Ҏ----用于比较两个数组是否相等Q相{的条g是两个数l的元素个数必须相等Qƈ且对应位|的元素也相{?/SPAN>
fill()Ҏ----用以某个值填充整个数l,q个Ҏ有点W?/SPAN>
asList()Ҏ----接受L的数lؓ参数Q将其{变ؓList容器?/SPAN>
binarySearch()Ҏ----用于在已l排序的数组中查扑օ素,需要注意的是必L已经排序q的数组。当Arrays.binarySearch()扑ֈ了查扄标时Q该Ҏ返回一个等于或大于0的|否则返回一个负|表示在该数组目前的排序状态下此目标元素所应该插入的位|。负值的计算公式?/SPAN>?x
sort()Ҏ----Ҏl进行升序排序?/SPAN>
?/SPAN>Java标准cd中,另有staticҎSystem.arraycopy()用来复制数组Q它针对所有类型做了重载?/SPAN>
3. 数组的排?/SPAN>
?/SPAN>Java1.0?/SPAN>1.1两个版本中,cd~少基本的算法操作,包括排序的操作,Java2Ҏq行了改善。在q行排序的操作时Q需要根据对象的实际cd执行比较操作Q如果ؓ每种不同的类型各自编写一个不同的排序ҎQ将会得代码很难被复用。一般的E序设计目标应是“将保持不变的事物与会发改变的事物相分离”。在q里Q不变的是通用的排序算法,变化的是各种对象怺比较的方式?/SPAN>
Java有两U方式来实现比较的功能,一U是实现java.lang.Comparable接口Q该接口只有一?/SPAN>compareTo()ҎQƈ以一?/SPAN>ObjectcMؓ参数Q如果当前对象小于参数则q回负|如果相等q回Ӟ如果当前对象大于参数则返回正倹{另一U比较方法是采用{略(strategy)设计模式Q将会发生变化的代码装在它自己的类({略对象)中,再将{略对象交给保持不变的代码中Q后者用此{略实现它的法。因此,可以Z同的比较方式生成不同的对象,它们用在同L排序E序中。在此情况下Q通过定义一个实CComparator接口的类而创Z一个策略,q个{略cLcompare()?/SPAN>equals()两个ҎQ一般情况下实现compare()Ҏ卛_?/SPAN>
使用上述两种Ҏ卛_对Q意基本类型的数组q行排序Q也可以对Q意的对象数组q行排序。再提示一遍,基本cd数组无法使用Comparatorq行排序?/SPAN>
Java标准cd中的排序法针对排序的类型进行了优化——针对基本类型设计了“快速排序”,针对对象设计的“稳定归q排序”。一般不用担心其性能?BR>
Tracker:http://www.tkk7.com/flyingis/archive/2005/12/15/24089.html
1.Map的功能方?/SPAN>
Map(interface): l护label?/SPAN>value的关联性,使得可以通过label查找value?/SPAN>
HashMap: MapZ散列表的实现Q取代了Hashtable。插入和查询label/value的开销是固定的Qƈ且可以通过构造器讄定w和负载因子,以调整容器的性能?/SPAN>
LinkedHashMap: ?/SPAN>HashMap的基上做了一些改q,在P代遍历它Ӟ取得label/value的顺序是其插入的ơ序Q或者是最q最?/SPAN>(LRU)的次序,速度上比HashMap要慢一点,但在q代讉K旉度会更快,主要原因是它使用了链表维护内部次序?/SPAN>
TreeMap: 查看label?/SPAN>label/valueӞ元素会被排序Q其ơ序?/SPAN>Comparable?/SPAN>Comparator军_Q因此查询所得到的结果是l过排序的。另外,它是唯一带有subMap()Ҏ?/SPAN>Map具体c,卌回一个子树。它也是SortedMap接口的唯一实现Q?/SPAN>subMap()Ҏ也是从该接口l承的?/SPAN>
WeakHashMap: Weak Key映射Q允讔R放映所指向的对象。当映射之外没有引用指向某个labelӞ?/SPAN>label可以被垃圾收集器回收?/SPAN>
IdentityHashMap: 使用==代替equals()?/SPAN>labelq行比较的散列映?/SPAN>
2.hashCode()
当用标准库中的c?/SPAN>Integer作ؓHashMap?/SPAN>labelӞE序能够正常q行Q但是用自己创建的cM?/SPAN>HashMap?/SPAN>labelӞ通常犯一个错误?/SPAN>
?/SPAN>HashMap中通过label查找valueӞ实际上是计算label对象地址的散列码来确?/SPAN>value的。一般情况下Q我们是使用基类Object的方?/SPAN>hashCode()来生成散列码Q它默认是用对象的地址来计的Q因此由W一个对?/SPAN>new Apple(5)和第二个对象new Apple(5)生成的散列码是不同的Q不能完成正的查找。通常Q我们可以编写自qhashCode()Ҏ来覆盖基cȝ原始ҎQ但与此同时Q我们必d时实?/SPAN>equals()Ҏ来判断当前的label是否与表中存在的label相同。正的equals()Ҏ满五个条gQ?/SPAN>
(1) 自反性。对于Q意的xQ?/SPAN>x.equals(x)一定返?/SPAN>true?/SPAN>
(2) 对称性。对于Q意的x?/SPAN>yQ如?/SPAN>y.equals(x)q回trueQ则x.equals(y)也返?/SPAN>true?/SPAN>
(3) 传递性。对于Q意的x?/SPAN>y?/SPAN>zQ如果有x.equals(y)q回trueQ?/SPAN>y.equals(z)q回trueQ则x.equals(z)一定返?/SPAN>true?/SPAN>
(4) 一致性。对于Q意的x?/SPAN>yQ如果对象中用于{h比较的信息没有改变,那么无论调用x.equals(y)多少ơ,q回的结果应该保持一_要么一直是trueQ要么一直是false?/SPAN>
(5) 对Q何不?/SPAN>null?/SPAN>xQ?/SPAN>x.equals(null)一定返?/SPAN>false?/SPAN>
equals()比较的是对象的地址Q如果要使用自己的类作ؓHashMap?/SPAN>labelQ必d旉?/SPAN>hashCode()?/SPAN>equals()Ҏ?/SPAN>
使用散列的目的:惌使用一个对象来查找另一个对象。?/SPAN>TreeSet?/SPAN>TreeMap也能实现此目的。另外,q可以自己实C?/SPAN>MapQ此Ӟ必须提供Map.entrySet()Ҏ来生?/SPAN>Map.Entry对象?/SPAN>Set?/SPAN>
使用散列的h|速度Q散列得查询可以快速进行。散列将label保存载数l中方便快速查询,因ؓ存储一l元素最快的数据l构是数l,用它来表C?/SPAN>label的信?/SPAN>(后面有信息的描述)Q而不?/SPAN>label本n。通过label对象计算得到一个数字,作ؓ数组的下标,q个数字是散列?/SPAN>(卛_面所q的信息)。该散列码具体是通过定义在基c?/SPAN>Object中,可能q序员自定义的c覆盖的hashCode()ҎQ即散列函数生成。ؓ了解xl容量带来的限制Q可以不同?/SPAN>label生成相同的下标,保存在一个链?/SPAN>list中,每一个链表就是数l的一个元素。查?/SPAN>label时就可以通过?/SPAN>list中的信息q行查找Q当散列函数比较好,数组的每个位|中?/SPAN>list长度较短Q则可以快速查扑ֈ数组元素list中的某个位置Q提高了整体速度?/SPAN>
散列表中?/SPAN>slot通常UCؓbucketQؓ了散列分步均匀Q?/SPAN>bucket的g般取质数。但事实证明Q质数实际上q不是散?/SPAN>bucket的理惛_量,q来Java散列实现都?/SPAN>2的幂Q具体如何验证以后再l?/SPAN>
3.HashMap的性能因子
定w(capacity): 散列表中bucket的数量?/SPAN>
初始化容?/SPAN>(initial capacity): 创徏散列表时bucket的数量。可以在构造方法中指定HashMap?/SPAN>HashSet的初始化定w?/SPAN>
寸(size): 散列表中记录的数量?/SPAN>(数组的元素个敎ͼ?/SPAN>list中元素d)
负蝲因子(load factor): 寸/定w。负载因子ؓ0Q表C空的散列表Q?/SPAN>0.5表示半满的散列表。轻负蝲的散列表h冲突,适宜插入与查询的特点Q但是用P代器遍历会比较慢。较高的负蝲会减所需I间大小。当负蝲辑ֈ指定值时Q容器会自动成倍地增加定wQƈ原有的对象重新分配Q存入新?/SPAN>bucket中,q个q程UCؓ“重散列”?/SPAN>
4.重写hashCode()的关?/SPAN>
(1) 对同一个对象调?/SPAN>hashCode()都应该生成同L倹{?/SPAN>
(2) hashCode()Ҏ不要依赖于对象中易变的数据,当数据发生变化时Q?/SPAN>hashCode()׃生成一个不同的散列码,即生了一个不同的label?/SPAN>
(3) hashCode()不应依赖于具有唯一性的对象信息Q例如对象地址?/SPAN>
(4) 散列码应该更兛_速度Q而不是唯一性,因ؓ散列码不必是唯一的?/SPAN>
(5) 好的hashCode()应该产生分步均匀的散列码。在Effective Java(Addison-Wesley 2001)中,Joshua Blochl?/SPAN>hashCode()l出了设计指|可以参考?/SPAN>
容器cd以大大提高编E效率和~程能力Q在Java2中,所有的容器都由SUN公司?/SPAN>Joshua Blochq行了重新设计,丰富了容器类库的功能?/SPAN>
Java2容器cȝ库的用途是“保存对象”,它分Zc:
Collection----一l独立的元素Q通常q些元素都服从某U规则?/SPAN>List必须保持元素特定的顺序,?/SPAN>Set不能有重复元素?/SPAN>
Map----一l成对的“键值对”对象,卛_元素是成对的对象Q最典型的应用就是数据字典,q且q有其它q泛的应用。另外,Map可以q回其所有键l成?/SPAN>Set和其所有值组成的CollectionQ或光值对l成?/SPAN>SetQƈ且还可以像数l一h展多l?/SPAN>MapQ只要让Map中键值对的每个“值”是一?/SPAN>Map卛_?/SPAN>
q代器是一U设计模式,它是一个对象,它可以遍历ƈ选择序列中的对象Q而开发h员不需要了解该序列的底层结构。P代器通常被称为“轻量”对象,因ؓ创徏它的代h?/SPAN>
Java中的Iterator功能比较单,q且只能单向UdQ?/SPAN>
(1) 使用Ҏiterator()要求容器q回一?/SPAN>Iterator。第一ơ调?/SPAN>Iterator?/SPAN>next()ҎӞ它返回序列的W一个元素?/SPAN>
(2) 使用next()获得序列中的下一个元素?/SPAN>
(3) 使用hasNext()查序列中是否q有元素?/SPAN>
(4) 使用remove()P代器新返回的元素删除?/SPAN>
Iterator?/SPAN>Javaq代器最单的实现QؓList设计?/SPAN>ListIteratorh更多的功能,它可以从两个方向遍历ListQ也可以?/SPAN>List中插入和删除元素?/SPAN>
2.List的功能方?/SPAN>
List(interface): ơ序?/SPAN>List最重要的特点;它确保维护元素特定的序?/SPAN>List?/SPAN>Collectiond了许多方法,使得能够?/SPAN>List中间插入与移除元?/SPAN>(只推?/SPAN>LinkedList使用)。一?/SPAN>List可以生成ListIteratorQ用它可以从两个方向遍?/SPAN>ListQ也可以?/SPAN>List中间插入和删除元素?/SPAN>
ArrayList: 由数l实现的List。它允许对元素进行快速随问,但是?/SPAN>List中间插入与移除元素的速度很慢?/SPAN>ListIterator只应该用来由后向前遍?/SPAN>ArrayListQ而不是用来插入和删除元素Q因?/SPAN>LinkedList开销要大很多?/SPAN>
LinkedList: 寚w序访问进行了优化Q向List中间插入与删除得开销不大Q随问则相对较慢(可用ArrayList代替)。它hҎaddFirst()?/SPAN>addLast()?/SPAN>getFirst()?/SPAN>getLast()?/SPAN>removeFirst()?/SPAN>removeLast()Q这些方?/SPAN>(没有在Q何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用?/SPAN>
3.Set的功能方?/SPAN>
Set(interface): 存入Set的每个元素必L唯一的,因ؓSet不保存重复元素。加?/SPAN>Set?/SPAN>Object必须定义equals()Ҏ以确保对象的唯一性?/SPAN>Set?/SPAN>Collection有完全一L接口?/SPAN>Set接口不保证维护元素的ơ序?/SPAN>
HashSet: 为快速查找而设计的Set。存?/SPAN>HashSet的对象必d?/SPAN>hashCode()?/SPAN>
TreeSet: 保持ơ序?/SPAN>SetQ底层ؓ树结构。用它可以?/SPAN>Set中提取有序的序列?/SPAN>
LinkedHashSet: hHashSet的查询速度Q且内部使用链表l护元素的顺?/SPAN>(插入的次?/SPAN>)。于是在使用q代器遍?/SPAN>SetӞl果会按元素插入的次序显C?/SPAN>
HashSet采用散列函数对元素进行排序,q是专门为快速查询而设计的Q?/SPAN>TreeSet采用U黑树的数据l构q行排序元素Q?/SPAN>LinkedHashSet内部使用散列以加快查询速度Q同时用链表维护元素的ơ序Q得看h元素是以插入的顺序保存的。需要注意的是,生成自己的类ӞSet需要维护元素的存储序Q因此要实现Comparable接口q定?/SPAN>compareTo()Ҏ?/SPAN>
AJAXTag 是一lJSP标签Q用来简化AJAX 技术在JSP面中的使用。它提供了一些常见功能的标签如下拉联选择Q用户在文本框中输入字符自动从指定的数据中匹配用戯入的字符{。它构徏在JavaScript框架之上?
报道中指出,该新版本主要是一个漏z修补版本。希望之前所有用户都来获取升U版本?/P>
下蝲地址Q?A >http://sourceforge.net/projects/ajaxtags/