网络编程

SimpleFramework系列之 - AjaxRequest

发布制作:admin  发布日期:2011/6/8

一、综述

AjaxRequest是一个非常重要的组件,在一个基于SimpleFramework的项目中,AjaxRequest被使用的概率几乎在50%以上,甚至更多。

在开始介绍AjaxRequest之前,我们首先看看HttpServletRequest,下图介绍一个完整Http请求到响应的生命周期。


点击浏览下一页

一些Web框架(比如:Struts)扩展了Servlet,并通过提供的接口,实现了基于MVC的编程模式,从而取代传统的Servlet编程。如下图:

点击浏览下一页

随着Ajax的流行,基于Ajax的请求变的越来越流行,一般要通过如下几个步骤来实现:

  1. 编写客户端代码(javascript)
    1. 编写请求代码
    2. 通过回调函数处理返回的结果
  2. 编写Servlet处理类
  3. 返回结果(可以是html、xml、text或json),等待客户端回调函数的处理

点击浏览下一页

一些流行的javascript框架,比如Prototype、jQuery等都提供了对Ajax的封装,您可以很容易的编写客户端的请求代码,这里以Prototype为例:

ew Ajax.Request("/test.action", {
? postBody: "p1=v1&p2=v2",
? encoding: "UTF-8",
? onComplete:function(req) {
??? var txt = req.responseText;
??? //do data
? }
);

ldquo;/test.action”请求一个Servlet类,并通过业务处理,把需要的数据返回给前端回调函数onComplete。

看似简单的流程,却有很多问题需要关注:

  1. 实际的项目有上百个甚至更多Ajax请求,那么前端javascript的数量和Servlet的数量就会增长很快。当javascript出现错误或更改javascript代码都会相当麻烦,至于Servlet,您可以通过Struts等技术替代
  2. 提交表单需要拼接参数,有没有更好的办法?
  3. 返回数据的解析。建议在Servlet中直接生成json格式
  4. 如果返回数据包含javascript文件(脚本)、CSS文件等,如何动态添加到dom中,如果dom中已经存在这些文件,那又该如何处理
  5. 需要对返回数据进行缓存,是否可以处理?

解决以上的问题,你需要付出太多的代价,不过,没关系,SimpleFramework提供的AjaxRequest组件,让您用声明的方式,快速完成Ajax请求。

二、原理

三、实践

现在就开始我们的AjaxRequest之旅吧!

3.1 组件的声明

impleFramework使用xml文件来描述组件,您可以参考http://simpleframework.net/doc/d2/2.4.1.html获取更为详细的信息。

以下是声明的代码片段:

lt;ajaxRequest name="ajaxTestAction"? handleClass="net.simpleframework.demo.TestAction"
?? handleMethod="testMethod">
</ajaxRequest>

在组件声明中,名称是必须的,且不能和其它组件名称重复,因为SimpleFramework通过Filter发现如上的定义,就会自动为客户端生成 一个$Actions[“ajaxTestAction”]的javascript对象。在客户端,您就可以通过这个唯一的名称获取其 javascript对 象的引用。

如果您不了解$Actions,可以通过http://simpleframework.net/doc/d2/2.4.2.html来了解更多内容。

3.2 与HTML页面元素的事件绑定

HTML页面元素(比如button)如何绑定到AjaxRequest组件“ajaxTestAction”呢?SimpleFramework采用了最原始的方式,代码如下:

lt;input type="button" value="提交" onclick="$Actions[‘ajaxTestAction’]();" />

很简单吧,SimpleFramework并没有改变现有的编程习惯,没有标签库,仅仅是简单的HTML和javascript。

3.3 如何提交数据

Ajax可以通过Get或POST来提交数据,但您必须自己拼接参数序列,这个非常麻烦。SimpleFramework提供了一个属性formSelector,快速提交HTML里您关心的数据区域,参考以下代码:

lt;ajaxRequest name="ajaxTestAction"? handleClass="net.simpleframework.demo.TestAction"
?? handleMethod="testMethod" formSelector=".div1, .div2 select">

再看一下HTML表单的定义:

lt;div class="div1">
... ...
</div>
<div class="div2">
... ...
</div>
<input type="button" value="提交" onclick="$Actions[‘ajaxTestAction’]();" />

关于selector,如果您了解Prototype、jQuery等javascript框架,那就一定非常熟悉。如果不了解,建议先在网上Google一下,先了解什么是CSS选择器。

上述含义是提交类名为“div1”下的所有表单元素和类名为“div2”下的select元素,这是不是比定义一个form标签要简单很多呢。

注:如果提交二进制文件,需使用submit组件或swfUpload组件。

3.4 编写HandleClass

AjaxRequest组件的HandleClass可以理解为Struts的Action,其接口的定义如下:

ackage net.simpleframework.web.page.component.base.ajaxrequest;

ublic interface IAjaxRequestHandle extends IComponentHandle {

? IForward ajaxProcess(ComponentParameter compParameter) throws Exception;

}

如果没有指定handleMethod,则ajaxProcess将会执行,如果指定了handleMethod,则执行名称为handleMethod的方法,其方法结构和ajaxProcess是一样的。

建议您继承AbstractAjaxRequestHandle而不是实现IAjaxRequestHandle,因为抽象父类会提供一些有意义的方法给您使用,对于任何其它组件,这一原则总是适用的。

3.5 IForward介绍

handleClass将会返回IForward接口,类似Struts的ActionForward,但有不同。IForward有三个具体的实现:

  1. TextForward,返回纯文本
  2. JsonForward,返回Json格式的文本,构造时需传递Map、List、Array等类型
  3. UrlForward,返回HTML,构造时需传递url地址

大部分情况,JsonForward是一个更好的选择。

3.6 编写回调脚本

定义回调脚本,参考如下代码:

lt;ajaxRequest name="ajaxTestAction"? handleClass="net.simpleframework.demo.TestAction"
?? handleMethod="testMethod">
?? <jsCompleteCallback>
????? alert(json);
????? alert(responseText);
?? </jsCompleteCallback>

</ajaxRequest>

3.6.1 回调函数原型

在编写jsCompleteCallback的时候,很多用户不知道如何下手,更不知道返回的数据在哪。其实,jsCompleteCallback就是一个javascript函数,只不过采用xml描述,把传递给你的参数省略了。请看jsCompleteCallback原型的定义:

jsCompleteCallback = function(req, responseText, json)? {
}

解释一下三个参数:

  1. req:原生ajax response对象
  2. responseText:返回的文本对象
  3. json:如果handleClass返回的是JsonForward,则json为解析过的JSON对象

3.6.2 通过属性直接绑定到HTML区域

ajaxRequest很多应用都是返回一段HTML,然后更新到某个区域,如果通过jsCompleteCallback一定会很简单,下面是一段代码样例:

var div = $("divid");
div.innerHTML = responseText;

ajaxRequest同时还提供了一个属性updateContainerId,可以不用写jsCompleteCallback,而直接绑定到updateContainerId指定的区域id,不光如此,还能执行responseText中的js函数,代码如下:

lt;ajaxRequest name="ajaxTestAction"? handleClass="net.simpleframework.demo.TestAction"
?? handleMethod="testMethod" updateContainerId="divid">
</ajaxRequest>

四、高级特性

4.1 动态传递参数

如果提交的数据是变化的,或则ajaxRequest组件是一个,但绑定的HTML元素事件是多个,又该怎么处理呢?

举个实例,比如“发送邮件”,一般分为“保存到草稿”、“直接发送”,因为提交的数据是一样的,则可以通过动态参数传递,在两个按钮的事件上分别绑定到同一个ajaxRequest组件。假设ajaxRequest组件的名称为sentMail,参考如下代码:

lt;input type="button" value="保存到草稿" onclick="$Actions[‘sentMail’]('type=0');" />
<input type="button" value="直接发送" onclick="$Actions[‘sentMail’]('type=1');" />

$Actions[‘sentMail’]其实就是一个函数,你在调用的时候,可以设置参数为拼接的字符串(见代码红色部分),这是一个经常使用的特性。还需要注意一点,参数传递的优先级是高于formSelector的。

4.2 自动加载js及css文件

自动加载js及css文件是ajaxRequest组件一个非常重要的特性,您可以直接在Ajax的返回数据中定义js或css文件,而不必担心它们是否已加载,如何加载等一系列问题。

您可以通过firebug来体验自动加载过程:)

4.3 作为其它组件的引用

组件的引用是SimpleFramework组件体系一个非常实用的功能。比如,window组件通过引用ajaxRequest组件来装载window面板内容,代码如下:

lt;ajaxRequest name="ajaxTestPage">
? <urlForward>/window_content.jsp</urlForward>
</ajaxRequest>
<window name="testWindow" contentRef="ajaxTestPage" width="480" height="600">
</window>

当调用了testWindow组件,ajaxTestPage将被触发并返回/window_content.jsp生成的数据到window面板。以后还会对此特性做更多的介绍。

4.4 缓存返回的数据

ajaxRequest组件的缓存功能非常简单,设置属性updateContainerCache=true即可。如果您是注册用户,可以在SimpleFramework站点上体验一下:右上方的个人属性编辑,采用的是标签页,当标签页被打开后,下次将使用缓存功能。

4.5 一些不常用的属性

  1. disabledTriggerAction,当组件被调用时,是否禁止调用元素,默认为true,目的是防止被多次调用,比如用户连续的点击操作
  2. parallel,是否允许并行执行,默认为false,在连续调用ajaxRequest时,在允许并行时,才可同时执行,否则将抛弃当前的调用
  3. jobExecute,执行权限,该属性依赖机构模块
  4. confirmMessage,客户端需要确认的消息
  5. throwException(window、alert),异常的展示方式。提供alert展示或window组件展示,window组件展示可获取更多的异常信息
  6. showLoading,是否显示装载进度(右上角显示),默认为true

五、总结

留给读者吧:)

下次将详细介绍Pager和TablePager组件,敬请期待。

?

原文地址: http://simpleframework.net/blog/v/18624.html