早在ASP.NET 2.0 beta1时.NET就已经包含了一个异步技术叫Callback。本文将使用Java/JSP+JavaScript实现ASP.NET的Callback技术。
1.ASP.NET 2.0的Callback技术
ASP网页必须实现ICallbackEventHandler的RaiseCallbackEvent方法和GetCallbackResult方法
RaiseCallbackEvent方法负责接收Client端JavaScript所送进来的参数。GetCallbackResult负责返回结果传给Client段。
例如
Public partial class ClientCallbackSimple:System.Web.UI.page, System.Web.UI.ICallbackEventHandler
{
Public void RaiseCallbackEvent(string arg){
//do something.
}
Public sting GetCallbackResult(){
//do someting
}
}
ASP
<
title
>
Callback Test
</
title
>
<
script
type
=
"text/JavaScript"
>
function
OnCallback(data)
{
Results.innerText=data;
}
</
script
>
</
head
>
<
body
>
<
div
>
<
form
id
=
"form1"
action
=
"#"
>
<
input
type
=
"text"
id
=
"arg"
value
=
"0"
/>
<input
type
=
”
button
”
value
=
”
Callback
”
onclick
=
”
<%=ClientScript.GetCallbackEventReference(this,
”
document.form1.arg.value
”
,
”
OnCallback
”
,null) %>
”
/>
<
div
ID
=
"Results"
></
div
>
</
form
>
</
div
>
</
body
>
</
html
>
其中ClientScript类负责注册Callback JavaScript函数。当按钮被点击后,程序会调用Server的RaiseCallbackEvent 方法和GetCallbackResult 方法,之后返回Client段,并调用OnCallback函数。
2.Callback的java实现
1.ICallbackEventHandler接口
接口定义为:
package
org.colimas.callback;
public
interface
ICallbackEventHandler {
public
Object RaiseCallbackEvent(String arg);
}
本文删掉GetCallbackResult方法,RaiseCallbackEvent方法直接返回一个结果。
2.EventHandler工厂
CallbackEventFactory类负责生成EventHandler实例。
package
org.colimas.callback;
import
java.util.HashMap;
public
class
CallbackEventFactory {
private
static
HashMap
handlers
;
//singleton
private
CallbackEventFactory(){
}
/**
*
init
*
@param
path
*/
public
static
void
init(String path){
handlers
=
new
HashMap();
Object value;
try
{
//put all handles into handlers;
//following is a sample by only one handle.
value = Class.forName(
"org.colimas.handlers.ReadData"
).newInstance();
handlers
.put(
"read_data"
, value);
}
catch
(InstantiationException e) {
//
TODO
自動生成された catch ブロック
e.printStackTrace();
}
catch
(IllegalAccessException e) {
//
TODO
自動生成された catch ブロック
e.printStackTrace();
}
catch
(ClassNotFoundException e) {
//
TODO
自動生成された catch ブロック
e.printStackTrace();
}
}
/**
*
get
event
handler
by
handle
name
*
@param
handlerName
*
@return
*/
public
static
ICallbackEventHandler getEventHandler(String handlerName){
return
(ICallbackEventHandler)
handlers
.get(handlerName);
}
}
3.Callback Servlet
初始化CallbackEventFactory
获得Request参数,并根据参数获得EventHandler实例,调用RaiseCallbackEvent并返回结果给客户端。
package org.colimas.callback;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class for Servlet: CallbackServlet
* call event handler.
* return result.
*
*/
public class CallbackServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
private static final long serialVersionUID = 1L;
/**
* init CallbackEventFactory
*/
public void init() throws ServletException {
super.init();
CallbackEventFactory.init(this.getInitParameter("handler_path"));
}
/**
* process request
* get event handle by name
* call event handle
* return result to resposne.
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String handlerName=(String)request.getParameter("handle");
String arg=(String)request.getParameter("arg");
if(arg==null)
arg="";
ICallbackEventHandler eventHandler=CallbackEventFactory.getEventHandler(handlerName);
String result=(String)eventHandler.RaiseCallbackEvent(arg);
response.getWriter().print(result);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
部署Servlet
<
servlet
>
<
servlet-name
>
CallbackServlet
</
servlet-name
>
<
display-name
>
CallbackServlet
</
display-name
>
<
description
></
description
>
<
servlet-class
>
org.colimas.callback.CallbackServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
handler_path
</
param-name
>
<
param-value
>
conf/handlers.properties
</
param-value
>
</
init-param
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
CallbackServlet
</
servlet-name
>
<
url-pattern
>
/callback
</
url-pattern
>
</
servlet-mapping
>
4.ClientScript的实现
生成下面JavaScript代码
createXMLHttpRequest('/callback','handle=value&arg=value');
package
org.colimas.callback;
/**
*
register
callback
event.
*
@author
tyrone
*
*/
public
class
ClientScript {
public
static
String GetCallbackEventReference(String arg,String handle){
StringBuffer js=
new
StringBuffer();
js.append(
"createXMLHttpRequest('/callback"
);
js.append(
"','handle="
);
js.append(handle);
js.append(
"&arg='+"
);
js.append(arg+
")"
);
return
js.toString();
}
}
5.Common JSP
Common.jsp负责公用代码实现。包括,XmlHttp的实例化,发送URL请求,Server端返回后的Client端OnCallback调用。
<%@
page
import
=
"org.colimas.callback.ClientScript"
%>
<
script
type
=
"text/javascript"
>
var
xmlHttp;
function
createXMLHttpRequest(url,query)
{
if
(window.ActiveXObject)
{
xmlHttp=
new
ActiveXObject(
"Microsoft.XMLHTTP"
);
}else if
(window.XMLHttpRequest)
{
xmlHttp=
new
XMLHttpRequest();
}
var
path=
"
<%=
request.getContextPath()
%>
"
+url+
"?"
+query;
xmlHttp.onreadystatechange=callback;
xmlHttp.open(
"GET"
,path,
true
);
xmlHttp.send(
null
);
}
function
callback()
{
if
(xmlHttp.readyState==4)
{
if
(xmlHttp.status==200)
{
var
data=xmlHttp.responseText;
OnCallback(data);
}
}
}
</
script
>
6.测试
创建CallbackEventHandler类,自定义ICallbackEventHandler接口实现,根据Client段传送的参数,计算一个随机数。
package org.colimas.handlers;
import org.colimas.callback.ICallbackEventHandler;
import java.util.Random;
public class ReadData implements ICallbackEventHandler {
public Object RaiseCallbackEvent(String arg) {
if(arg!=null){
String data="";
Random r=new Random();
float f=r.nextFloat()* Float.valueOf(arg).floatValue();
data=new Float(f).toString();
return data;
}
return null;
}
}
创建JSP页面,每个1秒钟,向服务器段请求一次。:
<!
DOCTYPE
html
PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd"
>
<%@
page
language
=
"java"
contentType
=
"text/html; charset=UTF-8"
%>
<
html
>
<
meta
http-equiv
=
"Pragma"
content
=
"no-cache"
>
<
head
>
<
title
>
Callback Test
</
title
>
<%@
include
file
=
"/jsp/common.jsp"
%>
<
script
type
=
"text/JavaScript"
>
function
DoGet()
{
//Register callbackevent
//createXMLHttpRequest('/callback','handle=read_data&arg='+form1.arg.value);
//
注册
CallbackEventhandle
<%=
ClientScript.GetCallbackEventReference(
"form1.arg.value"
,
"read_data"
)
%>
;
}
//OnCallback
函数定义。
function
OnCallback(data)
{
Results.innerText=data;
}
</
script
>
</
head
>
<
body
onload
=
"setInterval('DoGet()',1000)"
>
<
div
>
<
form
id
=
"form1"
action
=
"#"
>
<
input
type
=
"text"
id
=
"arg"
value
=
"0"
/>
<
div
ID
=
"Results"
></
div
>
</
form
>
</
div
>
</
body
>
</
html
>
运行结果:
每次修改输入框内的值,下面的Text值都回动态改变。