XmlHttpRequest对象直接把浏览器连接到一台远程主机,要么是加载页面的Web服务器,要么是从另一个完全不同的服务器。正如您所想像的,这里为恶意软件提供了大量的机会。例如,一段恶意的JavaScript可能等着用户输入口令字段,然后把口令传递给一个远程浏览器,而用户却不知道,甚至还没有单击页面上的提交按钮。如果把口令换为信用卡号码,事情就变得更加有趣了。
为了避免这种风险,Mozilla拒绝到为Web页面提供服务的主机之外的任意主机的连接。用户不会看到错误消息,因为它根本就不会运行!
Internet Explorer (IE)采用另一种方法。当要求连接到远程主机时,将使用一个对话框通知用户,而用户可以决定执行什么操作。但是要注意,该对话框不会告诉用户要连接到哪个站点,所以用户缺乏可以用于做出决策的信息。

图 4. 没有有用的信息!
这个问题的解决方案是使用一个Java servlet作为到Web服务的代理。该servlet获得所有的参数,并把它们传递给远程服务,接着将响应返回给Web站点。通过让servlet运行在创建Web页面的Web服务器上,Mozilla就会认为服务是本地的。注意,这是企业服务总线(比如AquaLogic Service Bus)的一个绝好用例。
使用XmlHttpRequest对象
包含 XmlHttpRequest对象的XmlHttp库最初是随Internet Explorer 4一起发行的ActiveX控件。Mozilla包含一个兼容的函数库,所以没有什么好担心的。我仍然推荐使用一个开源库,比如Sarissa或DWR。然而,它们在将XML数据传递到对象的方式上存在着细微的区别。
更新DOM节点
Mozilla和IE之间最令人恼火的区别就是Web页面中对DOM(Document Object Model,文档对象模型)的处理。大多数函数的工作方式是一样的(至少在DOM Level 2上),但是仍然有很多值得注意的地方。下面给出两个例子。
innerHtml与innerText的使用
当使用新的动态内容更新<div>标签时,IE用户有两个选择:可以更新节点的innerText或innerHTML。二者的区别很细微,但是却能在信息的显示方面造成很大的差别,尤其是当要显示的文本是XML格式或者包含HTML实体(比如尖括号或&符号)时。使用 innerHTML时假定内容与标签是一起放入的(不管内容是什么)。假设我们试着把以下文本放入一个节点中:
var txt = <b>This is a test</b>
document.getElementById('mydivtext').innerText = txt;
document.getElementById('mydivhtml').innerHTML = txt;
<div id="mydivhtml">部分在浏览器中看起来如下:
This is a test
<div id="mydivtext">部分看起来则是下面这样:
<b>This is a test</b>
基本上,innerText节点对输入字符串进行转义,这样显示在用户面前的就是内容原来的样子。但是Mozilla在DOM节点上不支持 innerText属性,所以更好的方法是用户亲自对文本进行转义,并始终使用innerHTML。Sarissa有一个帮助器函数用于实现这一项功能:
document.getElementById('mydivtext').innerHTML =
Sarissa.escape("<b>This is a test</b>")
我们将得到同样的结果,如下:
document.getElementById('mydivtext').innerText =
"<b>This is a test</b>")
在门户中使用独有名称
当某个门户页面由WebLogic Portal(或任何门户)进行解析时,每个portlet均作为完整的Web页面放在HTML文档中,包括<body>标签(有时甚至包括 <html>标签)。因此,如果在每个portlet中始终以相同的ID来命名<div>标签(理论上来说,这似乎是使编程标准化的一种良好方法),那么将获得不正确的结果。考虑如果有两个ID为“result_data”的元素,那么解析后的门户页面将会是什么样子。
// Outer portal shell
<html>
// First portlet
...
<div id="result_data"></div>
...
// Second portlet
...
<div id="result_data"></div>
...
</html>
现在,进行一次如下的调用:
document.getElementById('result_data').innerText = "stuff";
哪个元素将被更新呢?答案基本上会随浏览器的不同而不同,但是一般的答案就是“第一个”。
因此,这里的非常好的实践是使用portlet名称作为HTML标签中所有ID的前缀。
结束语
传统的Web应用程序已经无法满足客户的要求。由于Google之类的公司提供了更新、更快和交互性更强的Web站点,客户的期望值变得越来越高。构建使客户可以提高工作速度和效率的用户界面始终是一项战略性挑战。
Ajax编程是Web应用程序交互方面的新的事实标准,它为紧密耦合的数据和应用程序筒仓提供了部分解决方案。特别是在与BEA WebLogic平台结合使用时,Ajax代表了Web编程的未来方向,并预示着构建具有高度的交互性和响应灵敏度的Web站点的新潮流。
在本系列的第二部分中,我将使用具体的例子说明如何在WebLogic Portal环境中使用Ajax。具体来说,我将演示大量portlet,以说明如何从JavaScript调用Web服务以及使用结果更新页面、如何实现代理servlet来处理对外部Web服务的调用、如何使用Ajax把Web页面嵌入到另一个Web页面中,以及如何更新您自己的可更新数据库表小构件。