在我们的第一个例子中,我使用XmlHttpRequest实现AJAX,我称之为原始的AJAX实现,那么,使用隐藏帧来实现AJAX,则可称之为史前的AJAX实现了。这是AJAX最早的实现方法,事实上,Google的主页及Gmail都是使用隐藏帧技术实现的AJAX。
隐藏帧技术描述如下:使用一个隐藏的frame/iframe,主页面发送请求时,指定返回页面为该隐藏帧,这样,整个页面就不会被刷新,然后,主页面到隐藏帧中去取得返回的数据并进行处理即可。
使用隐藏帧技术实现AJAX有如下好处:
- 只需浏览器支持HTML 4即可,不须ActiveX之类的支持
- 可以维护浏览器历史,用户仍然可以使用浏览器上的后退和前进按钮。
尤其是第2个优点,如果用户有很强烈的要求的话,使用隐藏帧几乎就成了惟一的选择(如果使用AJAX),曾经看到有人提出了在使用AJAX的情况下如何保持前进/后退按钮的功能,主要就是如可以时间键存储页面信息,JS代码写得繁复无比,并且也没有完全解决这个问题。呵呵,如果使用隐藏帧技术,就不用这么麻烦了。
使用隐藏帧的缺点是如果隐藏帧载入失败,用户得不到任何出错信息,调试起来会比较费力一点。
好了,言归正传,我使用隐藏帧技术实现前面例子的简单功能,根据页面传入的一个字符串参数后台生成一个字符串,并在前台显示,为了显示前进/后退按钮是可用的,我加了一个时间标记。
本例包含如下几个文件:
- hidden_frame.jsp: 用于发送AJAX请求
- ajax_callback.jsp: 用于隐藏帧,接收AJAX请求
- HiddenFrameAjaxServlet.java: 后台的servlet类
- web.xml
4.1 hidden_frame.jsp
<%
...
@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"
%>
<!
DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
>
<
html
>
<
head
>
<
meta
http-equiv
="Content-Type"
content
="text/html; charset=GB18030"
>
<
title
>
Insert title here
</
title
>
</
head
>
<
body
>
<
form
name
="form1"
>
<
input
type
='button'
value
='Hello'
onclick
='hello()'
/>
</
form
>
<
div
id
="div1"
></
div
>
<
iframe
id
="frame1"
src
="about:blank"
width
="0"
height
="0"
style
="display:none"
>
</
iframe
>

<
script
type
="text/javascript"
>
...

function hello()

...{
var user = "London";
var hid_frame = document.getElementById("frame1");
hid_frame.src = "HiddenFrameAjax.do?uname=" + user + "&reqid=" + Math.random();
}
function callbackAjax(msg)

...{
document.getElementById("div1").innerHTML = msg;
}
</
script
>
</
body
>
</
html
>
页面里我定义了一个iframe,使用CSS属性定义为隐藏,对于Firefox,仅设其高度和宽度为0是不够的,你会看到有一个小点,呵呵,不晓得Mozila这样的目的是啥。
4.2 ajax_callback.jsp
<%
...
@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"
%>
<!
DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
>
<
html
>
<
head
>
<
meta
http-equiv
="Content-Type"
content
="text/html; charset=GB18030"
>
<
title
>
Insert title here
</
title
>
</
head
>
<
body
>
<
h1
>
aaa
</
h1
>
<
div
id
="div1"
>
${uname}
</
div
>

<
script
type
="text/javascript"
>
...
window.onload = function()

...{
var retstr = document.getElementById("div1").innerHTML;
parent.callbackAjax(retstr);
}
</
script
>
</
body
>
</
html
>
这个页面功能更简单,用于接收请求结果,该页面是要放到隐藏帧中的。关键在于设定window.onload事件,在页面载入完成后调用父页面的响应函数callbackAjax。
4.3 HiddenFrameAjaxServlet.java
package
lld.test.ajax;

import
java.io.IOException;
import
java.util.Date;

import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;

public
class
HiddenFrameAjaxServlet
extends
HttpServlet

...
{
private static final long serialVersionUID = -595334169176542957L;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException

...{
this.doPost(req, resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException

...{
String uname = req.getParameter("uname");
System.out.println("get uname = " + uname);
String retstr = "Hello, " + uname + ", " + (new Date());
req.setAttribute("uname", retstr);
req.getRequestDispatcher("/ajax_callback.jsp").forward(req, resp);
}

}
这是用于处理请求的普通Servelt,与非AJAX的Servlet完全一样,这是与前几例不同的地方。使用隐藏帧,功夫全在前台javascript上,后台不用去操心。
4.4 web.xml
添加Servlet描述
<
servlet
>
<
servlet-name
>
HiddenFrameAjax
</
servlet-name
>
<
servlet-class
>
lld.test.ajax.HiddenFrameAjaxServlet
</
servlet-class
>
</
servlet
>

<
servlet-mapping
>
<
servlet-name
>
HiddenFrameAjax
</
servlet-name
>
<
url-pattern
>
/HiddenFrameAjax.do
</
url-pattern
>
</
servlet-mapping
>
4.5 Post方式
上例我是使用了Get方式发送请求,如果要使用post方式的话,只需要一个简单的小技巧,那就是使用form标签的target属性,将其设为隐藏帧即可。
还是那句话, 如果哪位需要示例的完整代码, 可发送邮件至lldwolf@163.com