南京酷得软件-陈朕

Web 开发总结

JS - 常用語句

1.document.write(""); 输出语句
2.JS中的注释为//
3.传统的HTML文档顺序是:
    document->html->(head,body)
4.一个浏览器窗口中的DOM顺序是:
    window->(navigator,screen,history,location,document)
5.得到表单中元素的名称和值:
    document.getElementById("表单中元素的ID号").name(或value)
6.一个小写转大写的JS:
    document.getElementById("output").value=document.getElementById("input").value.toUpperCase();
7.JS中的值类型:
    String,Number,Boolean,Null,Object,Function
8.JS中的字符型转换成数值型:
    parseInt(),parseFloat()
9.JS中的数字转换成字符型:
    ("" 变量)
10.JS中的取字符串长度是:
    (length)
11.JS中的字符与字符相连接使用 号.
12.JS中的比较操作符有:
    ==等于,!=不等于,>,>=,<.<=
13.JS中声明变量使用:
    var来进行声明
14.JS中的判断语句结构:
    if(condition){}else{}
15.JS中的循环结构:
    for([initial expression];[condition];[upadte expression]) {inside loop}
16.循环中止的命令是:
    break
17.JS中的函数定义:
    function functionName([parameter],...){statement[s]}
18.当文件中出现多个form表单时.可以用document.forms[0],document.forms[1]来代替.
19.窗口:
    打开窗口window.open(), 关闭一个窗口:window.close(), 窗口本身:self
20.状态栏的设置:
    window.status="字符";
21.弹出提示信息:
    window.alert("字符");
22.弹出确认框:
    window.confirm();
23.弹出输入提示框:
    window.prompt();
24.指定当前显示链接的位置:
    window.location.href="URL"
25.取出窗体中的所有表单的数量:
    document.forms.length
26.关闭文档的输出流:
    document.close();
27.字符串追加连接符: =
28.创建一个文档元素:
    document.createElement(),document.createTextNode()
29.得到元素的方法:
    document.getElementById()
30.设置表单中所有文本型的成员的值为空:
var form = window.document.forms[0]
for (var i = 0; i<form.elements.length;i ){
if (form.elements.type == "text"){
form.elements.value = "";
}
}
31.复选按钮在JS中判断是否选中:
    document.forms[0].checkThis.checked
        (checked属性代表为是否选中返回TRUE或FALSE)
32.单选按钮组(单选按钮的名称必须相同):
取单选按钮组的长度document.forms[0].groupName.length
33.单选按钮组判断是否被选中也是用checked.
34.下拉列表框的值:
    document.forms[0].selectName.options[n].value 
        (n有时用下拉列表框名称加上.selectedIndex来确定被选中的值)
35.字符串的定义:
    var myString = new String("This is lightsword");
36.字符串转成大写:
    string.toUpperCase(); 字符串转成小写:string.toLowerCase();
37.返回字符串2在字符串1中出现的位置:
    String1.indexOf("String2")!=-1则说明没找到.
38.取字符串中指定位置的一个字符:
    StringA.charAt(9);
39.取出字符串中指定起点和终点的子字符串:
    stringA.substring(2,6);
40.数学函数:
    Math.PI(返回圆周率),Math.SQRT2(返回开方),Math.max(value1,value2)返回两个数中的
最在值,Math.pow(value1,10)返回value1的十次方,Math.round(value1)四舍五入函数,
Math.floor(Math.random()*(n 1))返回随机数
41.定义日期型变量:
    var today = new Date();
42.日期函数列表:
    dateObj.getTime()得到时间,dateObj.getYear()得到年份,dateObj.getFullYear()得到四位的年份,
    dateObj.getMonth()得到月份,dateObj.getDate()得到日,dateObj.getDay()得到日期几,
    dateObj.getHours()得到小时,dateObj.getMinutes()得到分,dateObj.getSeconds()得到秒,
    dateObj.setTime(value)设置时间,dateObj.setYear(val)设置年,
    dateObj.setMonth(val)设置月,dateObj.setDate(val)设置日,
    dateObj.setDay(val)设置星期几,dateObj.setHours设置小时,dateObj.setMinutes(val)设置分,
    dateObj.setSeconds(val)设置秒 [注意:此日期时间从0开始计]
43.FRAME的表示方式: 
    [window.]frames[n].ObjFuncVarName,frames["frameName"].ObjFuncVarName,frameName.ObjFuncVarName
44.parent代表父亲对象,top代表最顶端对象
45.打开子窗口的父窗口为:opener
46.表示当前所属的位置:this
47.当在超链接中调用JS函数时用:(javascript :)来开头后面加函数名
48.在老的浏览器中不执行此JS:<!-- //-->
49.引用一个文件式的JS:<script type="text/javascript" src="aaa.js"></script>
50.指定在不支持脚本的浏览器显示的HTML:<noscript></noscript>
51.当超链和onCLICK事件都有时,则老版本的浏览器转向a.html,否则转向b.html.
    例:<a href="a.html" onclick="location.href='b.html';return false">dfsadf</a>
52.JS的内建对象有:
    Array,Boolean,Date,Error,EvalError,
Function,Math,Number,Object,RangeError,ReferenceError,
RegExp,String,SyntaxError,TypeError,URIError
53.JS中的换行:\n
54.窗口全屏大小:
    <script>function fullScreen(){ this.moveTo(0,0);this.outerWidth=screen.availWidth;
this.outerHeight=screen.availHeight;}window.maximize=fullScreen;</script>
55.JS中的all代表其下层的全部元素
56.JS中的焦点顺序:document.getElementByid("表单元素").tabIndex = 1
57.innerHTML的值是表单元素的值:
    如<p id="para">"how are <em>you</em>"</p>,则innerHTML的值就是:how are <em>you</em>
58.innerTEXT的值和上面的一样,只不过不会把<em>这种标记显示出来.
59.contentEditable可设置元素是否可被修改,isContentEditable返回是否可修改的状态.
60.isDisabled判断是否为禁止状态.disabled设置禁止状态
61.length取得长度,返回整型数值
62.addBehavior()是一种JS调用的外部函数文件其扩展名为.htc
63.window.focus()使当前的窗口在所有窗口之前.
64.blur()指失去焦点.与FOCUS()相反.
65.select()指元素为选中状态.
66.防止用户对文本框中输入文本:
    onfocus="this.blur()"
67.取出该元素在页面中出现的数量:
    document.all.tags("div(或其它HTML标记符)").length
68.JS中分为两种窗体输出:模态和非模态.
    window.showModaldialog(),window.showModeless()
69.状态栏文字的设置:
    window.status='文字',默认的状态栏文字设置:window.defaultStatus = '文字.';
70.添加到收藏夹:
    external.AddFavorite("http://meil.cnblogs.com";,"jaskdlf");
71.JS中遇到脚本错误时不做任何操作:
    window.onerror = doNothing; 指定错误句柄的语法为:window.onerror = handleError;
72.JS中指定当前打开窗口的父窗口:
    window.opener,支持opener.opener...的多重继续.
73.JS中的self指的是当前的窗口
74.JS中状态栏显示内容:window.status="内容"
75.JS中的top指的是框架集中最顶层的框架
76.JS中关闭当前的窗口:window.close();
77.JS中提出是否确认的框:if(confirm("Are you sure?")){alert("ok");}else{alert("Not Ok");}
78.JS中的窗口重定向:window.navigate("http://meil.cnblogs.com";);
79.JS中的打印:window.print()
80.JS中的提示输入框:window.prompt("message","defaultReply");
81.JS中的窗口滚动条:window.scroll(x,y)
82.JS中的窗口滚动到位置:window.scrollby
83.JS中设置时间间隔:setInterval("expr",msecDelay)或setInterval(funcRef,msecDelay)或setTimeout
84.JS中的模态显示在IE4 行,在NN中不行:showModalDialog("URL"[,arguments][,features]);
85.JS中的退出之前使用的句柄:
    function verifyClose(){event.returnValue="we really like you and hope you will stay longer.";}} window.=verifyClose;
86.当窗体第一次调用时使用的文件句柄:onload()
87.当窗体关闭时调用的文件句柄:onunload()
88.window.location的属性:
    protocol(http:),hostname(www.example.com),port(80),host(www.example.com:80),
    pathname("/a/a.html"),hash("#giantGizmo",指跳转到相应的锚记),href(全部的信息)
89.window.location.reload()刷新当前页面.
90.window.history.back()返回上一页,window.history.forward()返回下一页,
window.history.go(返回第几页,也可以使用访问过的URL)
91.document.write()不换行的输出,document.writeln()换行输出
92.document.body.noWrap=true;防止链接文字折行.
93.变量名.charAt(第几位),取该变量的第几位的字符.
94."abc".charCodeAt(第几个),返回第几个字符的ASCii码值.
95.字符串连接:string.concat(string2),或用 =进行连接
96.变量.indexOf("字符",起始位置),返回第一个出现的位置(从0开始计算)
97.string.lastIndexOf(searchString[,startIndex])最后一次出现的位置.
98.string.match(regExpression),判断字符是否匹配.
99.string.replace(regExpression,replaceString)替换现有字符串.
100.string.split(分隔符)返回一个数组存储值.
101.string.substr(start[,length])取从第几位到指定长度的字符串.
102.string.toLowerCase()使字符串全部变为小写.
103.string.toUpperCase()使全部字符变为大写.
104.parseInt(string[,radix(代表进制)])强制转换成整型.
105.parseFloat(string[,radix])强制转换成浮点型.
106.isNaN(变量):测试是否为数值型.
107.定义常量的关键字:const,定义变量的关键字:var  

Ajax技术体系简要说明

       JavaScript、CSS(层叠样式表)、DOM(文档对象模型)、XMLHttpRequest是构成Ajax技术体系的四个技术基石,其中前三者合在一起以前称为DHTML。

        JavaScript是一种弱类型、解释型的、通用的脚本语言,在Ajax技术体系中,它将各个部分粘合在一起。JavaScript定义应用业务逻辑、操作DOM改变和刷新用户界面、重绘或重新组织用户数据、处理用户交互。

        CSS为Web页面元素提供了一种可重用的可视化样式的定义方法来定义应用的外观。样式表提供了集中定义各种视觉样式的方法并方便地设置到页面元素上。样式表可以定义样式元素、定义元素相互之间的布局以及简单的用户交互功能以实现视觉效果。HTML定义了文档的结构,定义了元素之间的包含关系,而不是外观,但它也定义了文档中可以应用样式的位置。通过定义CSS样式来定义用户界面的样式。

        DOM组织网页视图,以一组可以使用JavaScript操作的可编程对象展现出Web页面的结构。通过使用脚本修改DOM在运行时改变用户界面,或重绘页面的某个部分。Web页面的DOM是树状结构,JavaScript引擎通过全局变量document公开当前web页面的根节点,这个变量是所有DOM操作的起点。DOM文档与HTML表单的关系是双向的,修改DOM将会改变HTML标记。

        使用XMLHttpRequest以异步方式与服务器通信。它以后台方式获取数据,使得发生异步调用的业务流畅。数据格式通常是XML。IFrame是另外一种异步请求方式,本身作为文档布局的一部分,表现为DOM树的一个元素。样式可设置为不可见,使得以后台方式获取数据成为可能。

        CSS和DOM互为补充,为用户界面提供了清晰的编程视图,同时保持了结构和视觉样式的分离。Ajax是以这四种技术为基础的新的交互模型。
3月17日

利用Rational XDE中模式的能力来促进软件的重用

软件的重用一直以来都是软件开发追求的重要目标之一。软件的重用可以缩短软件开放周期,提高软件质量。可重用的软件组件、设计、代码是软件开发企业最重要的资产。但是软件的重用受到很多因素的影响,比如软件设计的质量,项目的交付时间,以及软件开发过程各阶段工作产品的管理及规范都在某种程度上制约了软件的重用。软件的重用可以分为多个层次:代码级重用,组件级重用,设计的重用,软件架构的重用以及解决方案的重用。对于开发人员来说更加关心代码级重用,组件级重用,设计的重用和软件架构的重用。Rational XDE提供了通过支持模型和代码模板来达到软件重用目的的机制,可以实现各个层次的软件重用。本文是将向大家介绍如何在XDE 中应用已经创建好的模式来促进软件的重用。

Rational XDE 模式基础

使用模式的好处

模式是在某一特定环境下,对一个特定问题的一个解决方案。使用模式可以给我们带来短期或长期的利益。但是在使用模式的过程中一定要注意,并不是在你的软件开发中使用了模式,就表示你的软件设计就是合理的。在你决定选择哪一种模式的时候一定要对目标模式和你的开发问题以及问题的环境有深刻理解。同时在利用模式时,不要生搬硬套,在找不到最合适的模式时,你可以考虑在已有的模式的基础上进行扩展或修改实现自己的模式。下面我们先来看一下利用模式的好处:

1. 模式可以被很好的共享
模式是一种解决方案,通过对模式的规范化和文档化,它可以在项目、公司甚至是公司之间进行共享。这个共享的范围取决于模式的创建者创建模式的意图。当前互联网上有很多已存在的模式可以被我们使用,最著名的莫过于"四人帮"(GoF)模式。Rational XDE提供了对"四人帮"模式的完全支持,包括对某些指定编程语言的实现。

2. 模式通过已经定义好的解决方案来解决问题
模式包含在一定环境下解决特定问题的专家经验和方法。模式的用户依靠良好的模式文档来选择和应用模式。用户需要知道模式能够解决什么样的问题,并且需要了解模式是如何解决问题和应用模式的过程逻辑。因此好的模式应该包括好的模式文档。

3. 模式可以被广泛的应用
模式可以在软件开发的各个阶段被使用。你可以创建一个解决单一问题的模式或者针对某一用例应用的模式。一个模式也可以使用其他的模式或者模式系统来解决复杂的问题。模式的设计类型可以包括结构化的、行为化的和条件化的解决方案,因此,模式的应用范围是非常广阔的和灵活的。

4. 模式可以很好的提升软件的重用性
软件的重用包括系统的创建、修补和软件组件的维护和。创建和使用模式可以促进软件的重用,模式一旦被创建便可以被多次的使用。使用模式可以通过避免重新设计来节省开发的成本,重用可以不断的提高软件的质量和可靠性。




回页首


Rational XDE中有关模式的概念

在学习使用Rational XDE来使用模式之前我们需要对Rational XDE中涉及到的模式的概念有所了解,这样在学习使用模式的过程中,大家会有更清晰的思路。

Rational XDE对模式的支持

Rational XDE对模式的支持体现在几个方面:模式的创建(定制模式)、模式的应用(使用模式)、对已有模式的支持和RAS模式支持。

  1. 模式的创建:在Rational XDE中,我们可以创建属于自己的模式,模式中可以包含模式的用UML表示的模式设计模型以及可以参数化的模板参数,还可以包含支持代码生成的代码模板。在Rational XDE 中提供了专门的工具和视图帮助模式的开发人员完成模式的创建工作。在创建模式时,模式开发人员可以为模式添加完善的文档,以指导模式的使用者选择和应用模式,同时Rational XDE 提供了应用模式向导的机制来指导模式用户对模式的使用。模式开发人员可以定制特定模式的使用向导,通过提示对话框一步一步的指导模式的使用。

     

  2. 模式的应用: 如果你只是模式的使用者,你可以利用Rational XDE非常方便的应用已有的模式,结合Rational XDE的代码和模型同步的特性可以大大的提高软件开发的效率和提高软件的质量和可靠性。

     

  3. 对已有模式的支持:在Rational XDE中包含了对业界最著名的模式的支持,例如"四人帮"模式、J2EE核心模式等。在RDN(Rational 开发者网络)上,有一个专门为交换模式资产的区域,我们可以从这个区域免费的下载可用的模式。

     

  4. RAS(可重用资产规范)支持:在XDE中模式可以按照RAS的标准来组织和归档,RAS是对软件开发过程中可重用资产进行组织的业界标准。模式以RAS标准组织意味着模式可以更好的被软件组织重用。

模式模板(pattern template)

模式模板是XDE中模式的核心部分,几乎所有的模式元素都定义在模式模板当中,其中包括模式的设计模型和参数。我们可以通过Model Explore来浏览和编辑它。模式模板用资产<<Asset>>原型来表示,如图1所示。从图1中我们可以看到名为RASPackage1的模式模板,其中包含模式的设计模型以及模型中类的定义。
图1: 模式模板

模板参数(template parameter)

模式的设计人员必须为模式模板设置模板参数,哪怕模式模板本身不需要参数,这个模板参数也是必须的。你可以为模板参数设定缺省的值,或者在模式的应用时为模板参数赋值。

根上下文(Root Context)

根上下文是模式的一个属性,用它来指明模式模板的一个模式内容被应用的范围,这个范围可以是模式模板内容体的整体,也可以是模式模板内容体中的一个包或者一个类。通过这个设置我们可以实现相同的模型的不同部分可以被不同的模式使用。

绑定和绑定点(binding and binding location)

绑定是模式中的参数被赋予具体的参数值的过程,这个参数值可以是用户指定的一个模型元素,也可以是用缺省值自动创建的元素。当一个模式被应用之后,在指定的绑定点中就有一个绑定对象被创建,它被用来维护这个模式的模板参数和具体的参数值之间的绑定关系。你可以直接在绑定对象中修改被绑定的参数值。在缺省的情况下,绑定点和扩展点是同一位置。

扩展点(expansion location)

扩展点是在使用模式时,模式实现文件存放的地方。你必须要为模式的应用设置它。




回页首


模式的应用

如果你只想在你的应用开发中使用模式,这个部分的内容对你来说是最重要的。我们将从模式使用者的角度来详细的说明在Rational XDE中如何应用已存在的模式。我们将对这个过程中的每一个步骤进行详细的讲述。

步骤1:选择模式、学习模式使用方法

在使用模式之前,我们必须根据实际的需要来选择适合你的软件开发的模式。如果你对模式还不是很了解,你首先需要学习模式的基本知识和概念,《设计模式》一书是学习模式的不错选择。我们这里假定你对模式已经有了一定的了解,现在我们选择"四人帮"模式中的 Facade模式作为我们学习模式应用的例子。如果你对Facade模式并不了解,没关系,在这里我们会对Facade模式的使用环境、解决的问题和使用方法做全面的介绍。在Rational XDE中,支持很多经典的模式,"四人帮"模式就是其中的一些。你可以通过XDE工具菜单中的Patterns菜单项的子菜单项Organize Favorites来设置可用的模式。
图2:组织模式对话框

如图2所示,你可以添加你需要的模式到XDE中,这样你就可以在你的应用开发中使用其他人开发的模式。但要注意的是在XDE中,模式是按照RAS资产的形式被组织的,模式被存放在RAS的资产库中,资产库的文件形式是ras为扩展明的,比如你可以在XDE的按章目录下的\addins\Patterns\content\GoF\Java\v2.5目录下找到名为GoF.ras的文件,这个文件中存放了"四人帮"的模式。也就是说其他人创建的你希望使用的模式也必须符合RAS标准才可以在XDE中使用。你可以访问 Rational 开发者网络(RDN)中的 模式交换区域,,这里有很多已经被开发的模式可以用来加速你的软件开发过程。

现在我们来了解一下Facade模式的内容。我们来看一下Facade模式的文档,为了查看模式的文档我们首先需要在模式浏览器(Pattern Explore)中打开模式,可以通过菜单Tool > Patterns > Open Favorites Libray > GoF Pattern Libray for Java V2.5来打开整个"四人帮"模式库,这时你将在模式浏览器中看到"四人帮"中的所有模式,如图3。
图3: 模式浏览器

用鼠标选中Facade模式,然后在窗口菜单中选择显示视图 > Pattern Documentation,你将会看到模式文档视图,如图4。
图4: 模式文档视图

模式的文档为你提供了模式的应用环境、能够解决的问题以及在XDE中应用模式的方法。下面我们来看一下模式文档中的各个部分。

Short Description: 简要的对模式进行描述。

Version: 模式的版本

Last Modified Date:模式的修改时间

上面的部分是模式的基本信息,下面是模式文档的主题部分。

Participants:参与者代表了模式模板的参数,它描述了这个模式中的每一个模式模板参数的在模式中的作用、数量关系、类型、参数值的来源、缺省值和代码模板的使用。

Facade模式中有三个参与者: Facade、SubsystemInterface和operation。

Facade参与者知道哪一个子系统负责处理用户的请求,并将请求转发给适当的子系统对象。它的类型是Class,它的参数值的来源可以是用户提供的已存在的类,也可以有XDE为你新创建一个类。这个参与者被设定了缺省值Facade,这意味着如果你不为它设定参数值,它将使用Facade作为参数值使用。

SubsystemInterface参与者实现了子系统的功能,它处理被Facade转发过来的用户请求。它的类型是Class,参数值的来源是用户提供已存在的处理类。用户需要在应用Facade模式之前构建好这个子系统类。

Operation参与者是子系统处理用户请求的操作或者可以说是函数。它的类型是操作(operation),参数值的来由可以是用户提供或者来自于集合。

下面我们通过模式的类图和时序图来了解模式中参与者之间的关系。
图5:Facade模式的类图

在这个类图中我们可以看到参与者Facade和SubsystemInterface之间的关系。请注意在这个图中你可以发现有<%=Facade%>的表达式,这里Facade代表了模式模板的一个参数,在应用模式时通过为这个参数赋值可得到相应的类名,比如你可以将FacadeTest赋给它,这样产成的Facade类的名字就是FacadeTest,而其他引用了Facade参数的地方的值也是FacadeTest。当你应用了这个模式后,这个类图也会出现在你的模型中,与这个图不同的是参数部分已经被赋值了。
图6:Facade模式的时序图

图6是Facade的时序图,它描述了模式中各个对象的交互关系。在应用了这个模式后,这个时序图也会在你的模型中出现,与这个图不同的是参数部分已经被赋值了。

Classification部分描述了作为RAS资产模式的信息。

Author :模式的作者,可用来对模式进行检索

Packager:模式的包装者

Keyword :用于检索的关键词

Problem Solved :模式解决的问题

Benefit :使用这个模式的好处

Usage部分描述了应用这个模式的步骤和活动

现在我们已经对Facade模式中的参与者以及他们之间的关系和模式能够解决的问题有了一定的了解,接下来让我们开发使用这个模式。

步骤2:应用模式

如果你对前面讲的XDE中模式的概念以及Facade模式的各个部分都已经理解了,应用模式的过程就非常的简单,我们可以把它看作是一个给模式模板的参数赋值的过程。

首先我们需要创建一个Java建模项目,在这个项目中应用Facade模式。通过以下步骤来创建Java 建模项目:

文件 > 新建 > 项目 弹出新建项目对话框见图7
图7: 创建Java建模项目

在新建项目对话框的右边的浏览栏中选择Modeling,然后在新建项目对话框的右边的浏览栏中选择Java Modeling Project。

点击下一步,在项目名的文本框中输入FacadeTest。点击完成。XDE将为你创建Java建模项目,如图8。
图8:Java 建模项目

在Model Explore视图中,你可以看到刚创建好的项目Java Code Model,在XDE的右边是我们刚才打开的模式浏览器(Pattern Explore),一会我们将在这里开始应用Facade模式。现在我们的任务是创建一个代表子系统的类,这是Facade模式的SubsystemInterface参与者的要求。我们简单的创建一个名为SubSystem的类。步骤如下:

在模型浏览器(Model Explorer)鼠标右键点击Java Code Model,选择 Add UML > Class,命名为SubSystem。

然后为类SubSystem添加一个操作名为test()。这个操作将成为Facade 模式operation模式模板参数的值。步骤如下:

鼠标右键点击类SubsystemInterface,选择 Add UML > Operation,命名为test。

接下来开始应用模式Facade,步骤如下:

在模式浏览器(Pattern Exlpore)中鼠标右键点击Facade模式,选择 Apply this pattern。应用模式向导样式选择器对话框弹出,如图9
图9: 应用模式

选择Apply Pattern Dialog,应用Facade模式对话框弹出如图10。
图10:应用Facade模式对话框

这个对话框分为几个部分,最上面是模式描述部分,它简要的说明了Facade模式的用途。接下来的部分是模式模板参数信息部分,这是我们应用模式的核心部分,在这里我们需要为模式模板的参数赋值。在Facade模式中我们需要为四个参数进行赋值。

Facade参数:类型为Class因此我们需要为他设定一个类,在Facade参数的值域中我们可以看到已经有 了一个Facade的值,这是Facade模式的缺省值,如果你不希望用这个缺省值,可以通过鼠标双击值域弹出如图11的对话框。
图11:Facade的选择参数值对话框

你可以重新设定Facade参数的值,这里我们用缺省的值Facade。

接下来为SubSystemClass参数赋值,这个参数的类型为Class,我们要为它指定一个类,这个参数没有缺省值,因此我们必须为它分配一个。双击SubSystemClass参数的值域,弹出SubSystemClass参数的选择参数值对话框如图12
图12: SubSystemClass的选择参数值对话框

在对话框的左边浏览栏中选择我们之前创建好的SubSystem类,点击Select按钮,这样我们就为SubSystemClass设定了值。SubSystemClass将有SubSystem类来代替。

接下来为参数operation赋值,operation的参数类型为操作,因此我们要为它设定一个操作值。如图13
图13: operation的选择参数值对话框

在对话框的上方可以看到两个选项:User和Collection. 选择User意味着需要我们设定一个操作作为参数值,Collection表示可以选择多个操作的集合作为参数值。这里我们选择User选项,并在对话框的左边的浏览兰中找到之前我们创建好的SubSystem类的test() 操作作为参数值。

接下来为SubSystem参数赋值,它的类型为包, 并且有缺省的值SubSystem,这个参数的作用是将生成模式中的元素是存放的包。我们使用缺省值SubSystem,在生成模式元素时,你将会看到一个名为SubSystem的包被生成,在这个包之下是模式的模型元素。

我们已经为Facade模式的四个参数赋了值,接下来的事情是设定扩展点和绑定点。前面我们已经介绍过了扩展点和绑定点的概念,扩展点是生成模型的模型元素的存放地点,绑定点是指绑定对象的存放地点,

这里我们都选择Java Code Model包。这样我们就已经为Facade模式设定好了所有的参数值,如图14
图14:为Facade模式的参数赋值

下面点击Apply按钮完成模式的应用,XDE将根据我们设定的参数值为我们产生模式的模型元素。我们已经成功的完成了应用Facade模式的步骤,下面我们来看看应用模式为我们生成了哪些模型元素。首先我们来看一下模型浏览器中的内容,见图15
图15:应用模式Facade生成的模型元素

首先我们可以看到在Java Code Model下有一个叫做Subsystem的包,这是根据Facade模式的Subsystem参数值创建的。在这个包下可以看到两个类的模型Facade和SubSystem,他们的名字也是根据前面我们设定的参数值制定的。与包Subsystem平行有一个名为 Facade Participants的类图如图15
图16:应用 Facade模式生成的类图

和在模式Facade中的类图相比可以发现,他们的区别只在于Facade模式模板的参数被我们所设定的参数代替了。

与Facade Participants的类图平行的还有一个名为AccessSubystem的协作的实例,见图16
图17

在模型浏览器中可以看到AccessSubystem协作实例中包含了几个对象(aClient、aFacade和aSybsystemClass),还有一个交互实例,交互实例描述了系统中某些对象间的交互过程,典型的使用时序图来表示。双击时序图AccessSubsystem你可以看到Facade模式产生的时序图,见图17
图18:Facade模式生成的时序图

在图中你可以发现与Facade模式中的时序图的区别就在于模式模板的参数被我们赋的值代替了。

到此为止我们已经完整的经历了一次应用模式的过程。在XDE中应用模式可以为你创建模式实现的框架,在生成的框架的基础上进一步的细化来完成模式的实现。

Ajax.NET与Atlas的比较

简介:
Ajax.NET是一款免费的面向.Net的Ajax Library
Atlas是微软提供给开发者的Ajax开发包
两者都可以让ASP.Net具备Ajax功能
近日,利用空闲时间把这两个东西做了不完全的比较
1、代码量
由于两者通过不同途径实现Ajax,所以代码的量也是不相同的,下面我用VB.Net为例写了段读写Session的例子。
[Ajax.NET]
前台:
    <form id="form1" runat="server">
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" /><br />
                <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
                <asp:Button ID="Button2" runat="server" Text="Button" />
    </form>

后台:
   <Ajax.AjaxMethod(HttpSessionStateRequirement.ReadWrite)> Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Session("Uesr") = TextBox1.Text
    End Sub
   <Ajax.AjaxMethod(HttpSessionStateRequirement.Read)> Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        TextBox2.Text = Session("Uesr").ToString
    End Sub
[Atlas]
前台:
    <form id="form1" runat="server">
        <atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True" />
        <atlas:UpdatePanel ID="UpdatePanel" runat="server">
            <ContentTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" /><br />
                <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
                <asp:Button ID="Button2" runat="server" Text="Button" />
            </ContentTemplate>
        </atlas:UpdatePanel>
    </form>
后台:
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Session("Uesr") = TextBox1.Text
    End Sub
    Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        TextBox2.Text = Session("Uesr").ToString
    End Sub
由上面的代码可以看出Ajax.NET是通过在后台方法声明前加上<Ajax.AjaxMethod>把当前方法变成Ajax方法,而Atlas是通过前台把需要用到Ajax的表单加上<atlas:UpdatePanel>标签来完成的。
2、兼容性
Ajax.NET可以在任何.Net版本下运行,要用时需把相关的DLL附加引用
Atlas更偏向于.Net 2.0,甚至提供了Visual Studio 2005模板的安装
3、效率
同时在ASP.Net 2.0的环境下使用两者发现Atlas的执行效率比Ajax.NET略高
4、总结
综合上面的对比,Ajax.NET与Atlas各有特色,但对于大规模的ASP.Net程序的Ajax改造,个人觉得使用Atlas要来得简单。如果你是使用ASP.Net 2.0要用到Ajax的话,个人推荐你用Atlas。

面向.NET开发人员的Ajax 技术平台策略

      在这里我将试图考察一下目前.NET平台的下的Ajax框架,我也试图从中总结出来一种方法,使得你可以在众多基于.NET平台的Ajax框架和工具包中找到你所合适的一种,同时也希望你在考察、预研和使用这些流行的这些Ajax-NET 的框架时,做得理性和有的放矢。

      我想,文章的方法会给目前使用Ajax的.NET用户带来帮助,从而提高你在.NET平台下使用Ajax的体验。为什么这么说,因为最近我的一个客户(应该是一些客户)的研发主管对我说,我们对Atlas 非常兴趣,想了解更多一些相关的内容和如何开始看待Atlas,因为下个月会来一个Atlas的专家和我们交流。。。。因为我知道这个主管手上掌握着一个Ajax架构的业务应用,目前在考虑从.NET v1.1迁移到.NET v2.0,Atlas能在怎样的程度上帮忙他或他的Team?我没有说太多,因为心里我有些吃惊,目前的他们的架构应用Atlas 可能并不是一个明智的选择,当然这个担心基于我目前对Atlas的理解。

      我列举和讨论的Ajax-NET的框架和工具包括Atlas(Jan CTP), Anthem.NET, MagicAjax.NET , Ajax.NET Professional wwHoverPanel Control,这基本都是我关注的.NET平台的下的Ajax 的一些框架和实现。 基本上也都是我的这篇文章中列举的,另外一个原因是因为他们基本上都是开源的,这个非常重要,因为没有源代码,我们将不知道究竟发生了什么。另外我无意于使之成为像Daniel Zeiss作的这个比较报告

      首先,开门见山的说明我的观点,这是前些天Ajax书评中忽略过的话题和论点,今天就在这里补上。


      对于开源或现有的Ajax-NET技术或框架的选用必须针对你目前应用的架构来选取和考虑,如果你目前的架构是"似Ajax"的,那么你在选择现在所有流行的Ajax-NET的技术的时候都必须非常小心;而如果你目前的应用是使用传统的ASP.NET的应用架构(或准备用ASP.NET v2.0开始创建新的应用),那么目前流行的Ajax-NET的框架和技术都是普遍适合的,关键你要在合适的时机选择合适的某个框架或实现。

    在我的眼中,目前流行的Ajax-NET的框架或实现都是Add-in (Plug-in)的模式的,也就是说这些框架对于所有后一种即使用传统的ASP.NET的应用架构(或准备用ASP.NET v2.0开始创建新的应用)是Awared的也就是非常有利和方便的。但对于"似Ajax"的架构来说,情况有所不同,需要你从另外的角度来衡量,有选择的使用。
 
那什么是"似Ajax" 的架构呢,这就是说,你的应用程序是在Ajax概念提出之前就创建的。从客户端和服务器端的交互分析来说,你的客户端有大量的java-script 代码接受XML数据,进行对象的序列化,然后使用java-script配合其它的HTML技术展现这些对象和数据,也可能你还有一堆HTC或其它的java-script的HTML表现层控件。你的服务器端是一个Facade(或者是Adapter,Observer)模式的(Handler)控制器,接收客户端java-script的XML请求数据后,然后解析XML,然后调用相应的某个服务或业务组件,再将结果以XML的形式返回给客户端java-script ,客户端的java-script接收之后,再进行处理和显示,因为可以使用HTML的DOM 和CSS,所有页面的展现是动态的。
这样客户端是<Ajax in Action>中描述的Script-centric architecture 或Data-centric interactions 的方式。而且这种方式和Jesse James Garrett列举的Ajax 是最类似的,只不过那时你或我不知道这个可以叫Ajax,只不过是现在的人误解了Ajax,Ajax成了一种技术,一种特性,而首先不是一种某种架构下Web 应用了。

而且目前流行的Ajax-NET的框架基本上都没有实现双向序列化,因为实现一个TextBox的自动完成客户端只用接收数据就行了,根本不用传回数据/对象到服务器端,同样做一个Ajax的状态进度条也不用,但这些都是Ajax啊,我们衡量的标准是异步的、页面没有刷新。

很抱歉,我用了这么字才解释完我的观点。最后可以这么说,如果你的应用已经是Ajax架构的,那么你需要仔细选择使用目前的Ajax-NET框架,确保它也提供双向序列化功能,兼容你原来的应用和架构。如果你的应用不是Ajax架构的,那么你可以依据一些条件来选择Ajax-NET框架

然后我们回到文章的开始,来看一些流行的Ajax-NET框架


1. MagicAjax.NET

这是目前框架中版本号最小的一个Ajax-NET实现,许多人很喜欢它,甚至一见如故,但真的看过它的代码之后,我有些担忧。
MagicAjax.NET基于这样一种策略,即__doPostBack 会提及整个的ASP.NET页面,这样会导致页面刷新,所以MagicAjax.NET使用AJAXCbo.DoPostCallBack 做局部的提交,而每个Ajax
Panel 中的内容则对应客户端即时的HTML内容,因为在MagicAjax.NET中,客户端只用执行eval(responseText) 服务器端Rendered返回的HTML就可以了(很被动)。

由于DoPostCallBack 会提交ViewState 以及AjaxPanelx$RBS_Store,几乎是用XMLHttpRequest 模拟一个正常的提交,所以服务器端可以创建页面的实例也可以根据ViewState 恢复所有的控件状态,同样AjaxPanel 以及AjaxControl 也都会实例化,然后接收客户端传来的_EventTarget, _EventArgument 走正常的ASP.NET控件的处理过程,等控件Rendered之后,最终的HTML输出被传回客户端,然后被客户端的eval 显示出来。

整个过程非常巧妙,这几乎是ASP.NET __doPostBack 的"Hook ASP.NET"版和加强版本。
而HttpModel 主要是为了解决Session和交叉提交,进行客户端java-script的整理和注入,当然也是这里接收客户端的请求,在Application_EndRequest中返回结果。剩下的代码都是处理控件在VS Web Design中的设计时支持。AjaxCallObject.js 和WebParts.js 每次都要传到客户端。

MagicAjax.NET 的一些不足和想法:
1。 __doPostBack 的加强版,适合于ASP.NET的高级用户使用
2。由于和ASP.NET的页面处理机制依赖非常密切,控件的默认动作发生变化则可能不工作,比如第三方的某个自定义控件;
3。依赖ViewState ,如果是加密的ViewState,则可能工作不正常,我没有试,在代码中好像没有看见__VIEWSTATEENCRYPTED
4。是对ASP.NET 全部页面提交的优化,实现有限的Ajax功能,可扩展性不大

如果是基于ASP.NET 提供的控件和开发,那么MagicAjax.NET 是非常有效的,很好的解决了Session和跨页面状态的问题。而且客户端的操作和工作基本可以忽略,MagicAjax.NET设计贴近最近的ASP.NET的版本,目前不提供调用客户端直接调用页面的方法。但随着其发展,优势可能渐少,因为Atlas 最新的版本提供类似的UpdatePanel 控件。

经典必看文章-Magic AJAX: Applying AJAX to your existing Web Pages -Argiris Kirtzidis
http://www.codeproject.com/Ajax/magicajax.asp#xx1313380xx


2. Anthem.NET

目前是1.0版本,其设计理念是通过另外一个思路,遵循这样的理念--既然ASP.NET的各个标准控件没有实现提交功能,那么我可以产生一个提交的接口,然后继承原来的标准控件,然后再实现这个接口,这样每个控件都可以向服务器端单独进行提交。

每个控件的发生过程类似MagicAjax.NET,Anthem.NET提供了各个控件java-script端的提交函数-这等于也截取了__doPostBack,之后Anthem.NET 还提供了完善的客户端的事件比如PostCallBack 和PreCallBack 这样的客户端事件,之后也将使用XMLHttpRequest 模拟一个传统的页面提交请求到服务器端,服务器端生成页面实例,这个过程和MagicAjax.NET一样,最后是将Rendered的HTML在控件的Render() 事件传回到客户端,客户端控件的innerHTML被赋值,动态更新

和MagicAjax.NET不同的是,Anthem.NET没有容器的概念,因为每个控件都增加了提交接口,所以可以单独的提交,所以单位是以一个控件为单位进行一次提交,Anthem.NET的花费更小些(但服务器端是类似的,因为整个ASP.NET页面的Pipeline都会进行)。

此外,Anthem.NET 还有另外的功能,就是可以通过客户端调用页面中的方法并获得结果/数据,这种情况下,你将调用Anthem_InvokePageMethod 方法,而不是Anthem.NET提供的默认各个控件的提交方法。这样java-script的回调处理函数中的result.value 将可以获得调用的服务端的某个方法(该方法以[Anthem.Method]为标记)的执行结果,因为java-scriptPost的数据中有Page/MasterPage/Control 了,那么服务器端很容易通过这个标识获得方法的地址,应用反射寻找[Anthem.Method]标记,然后调用,将结果返回到客户端。

Anthem.NET支持返回对象,DataSet,DataTable和 WriteDataRow(WriteDataSet,WriteDataTable,WriteDataRow,WriteObject),返回的是符合是JSON规范的字符串,这样客户端的java-script就可以使用这些对象了。不同于MagicAjax.NET,Anthem.NET 没有使用HTTP Model,所以结果是在页面的PreRender() 事件中处理和返回请求的结果。

2.1 Ajax.NET Professional
我没有看过Ajax.NET Professional 的源代码,但从例子中看得其支持调用页面的某个方法,以及返回对象,DataSet,DataTable的数据,我认为Ajax.NET Professional 的实现和Anthem.NET 原理是一样的,虽然Ajax.NET Professional 使用了HTTP Model,这个只是和Anthem.NET 一样,最终处理结果的返回处理上稍有不同不同。比较起来,Ajax.NET Professional 没有重新继承所有常用的ASP.NET控件实现部分提交的功能,所以可能Ajax.NET Professional 比较强项的是调用页面上的某个方法,并在客户端获得结果的数据,这个已经够实现大部分的Ajax的功能了。

从这个层面上看,我认为Ajax.NET Professional 是相对笨重和复杂了。Anthem.NET不使用HTTP Model,提供控件基本的局部提交,也提供数据层面的客户端方法调用。Ajax.NET Professional 的源代码似乎总是不想共享 [redface] ,这也是我不喜欢它的另外一个原因。
无论如何,大家都没有提供两路的数据交换,即客户端可以获得服务器端的方法并获得结果和数据,但是目前都支持将这些对象/数据修改之后返回给服务器端。

Anthem.NET 的一些不足和想法:
1. Anthem.NET 也是一种"Hook ASP.NET"原理,旨在弥补ASP.NET的整页面的提交和PostBack,并且在客户端的数据访问和交互上做了加强。
2. Anthem.NET需要重新将ASP.NET提供的控件进行继承和包装,所以使用和功能的兼容性上非常敏感。
3. 也许微软下个版本的ASP.NET的标准控件可以借鉴Anthem.NET的做法,给各个控件增加这个远程回调的接口。
4. 目前版本的功能已经非常强大和略有些复杂了,而且部署比较方便,无需设置HTTP Model。

经典必看文章-Introduction to Anthem.NET
http://www.codeproject.com/useritems/AnthemNET.asp#xxxx


3. wwHoverPanel AJAX Control for ASP.NET

wwHoverPanel AJAX Control for ASP.NET 这也是一个ASP.NET的控件,但是提供了客户端回调(高级回调)、客户端调用页面方法,以及双向两路的序列化功能。
wwHoverPanel 吸取了MagicAjax.NET 和 Anthem.NET的优点,同时又结合了ASP.NET的客户端回调功能,是一个轻量级的Ajax组件。

看待wwHoverPanel 最大的两个特性中的一个是用很简单的方式实现了一个HoverPanel Behavior,这个实现比目前Atalas的Behavior 要简单,作者Rick Strahl 也强调这个主要是结合他具体的应用,比如这里提供了一个小的HTML板,可以显示获得的结果信息。

wwHoverPanel 也提供一个局部回调的方法,但是这点的实现上和MagicAjax.NET 以及 Anthem.NET完全不同,它是使用一个StartCallback的java-script来组合查询字符串提交并且使用XMLHTTP发请求到服务器的某个页面(由ServerUrl 属性指定),之后这个页面将结果以Response.Write()的原生HTML内容返回。这个和ASP.NET的回调方法非常类似,而且还支持将请求发到本页之外的ASP.NET并获得结果,所以它增强了原来ASP.NET的客户端回调的方法,即支持其它页面的回调。可以说,这是一种基于URL的客户端回调。

wwHoverPanel 提供的第二个功能是,客户端可以调用服务器端中的某个页面的方法(这些方法以[CallbackMethod]进行标识),这种情况下,你要设置EventHandlerMode="CallPageMethod" ,然后使用wwHoverPanel.服务器方法名(参数,参数,...,回调处理函数)的方式进行调用。这个其实使用的是一个java-script的CallMethod 方法,调用服务器端的请求。java-script 的HandleCallback 则用来处理返回的结果,逻辑相对简单,尽管控件的innerHTML 也被赋值,但这个主要是为了维护作为客户端回调结果显示的小的HTML板的内容,否则就是调用页面中的方法了,那么结果就直接给客户端的回调方法了。

特色三,就是我说的双路的序列化功能了,其实这个场景我们也非常需要,比如我们用客户端回调或XMLHTTP请求获得了一个定单对象,那么客户端修改之后,我还想把它作为一个客户端调用的输入参数,返回到服务器端。这时候两路双向的序列化就需要了,因为这次服务器需要将java-script的函数传了的数据序列化成.NET的类。这也就是JSON的双向序列化了(主要代码在JSONSerializer.cs ),这也是我挺喜欢的一个功能,因为我对这个功能关注很久,但是目前流行的Ajax-NET的框架都不支持这个功能。
目前在wwHoverPanel 的场景中,我认为这是一种轻量级的实现,对于多层嵌套多组引用的对象图类型或是大规模容量访问压力下,客户端和服务器端都还需要优化,所以如果其作为Ajax架构,客户端和服务器端通信和传递数据的通讯层上,显然是有些单薄了。

wwHoverPanel 的一些不足和想法:
1. 该控件是目前我见过.NET平台下,惟一同时支持客户端回调和页面方法调用的Ajax 控件,同时又支持两路双向的序列化。
2. 相对来说,wwHoverPanel是设计最简单的一个,而且是基于控件不依赖HTTP Model和ASP.NET Page Pipeline,也不依赖ViewState
3. 该控件能够让你在Ajax特性实现的技术层面上,能够在客户回调和客户端调用页面方法两者中取得平衡。
4. 目前的客户端回调支持其它页面的回调,但是其结果输出需要输出原始的HTML,这个影响应用的分层和设计。
5. JSON的双向序列化是一个不错的方案,但高性能的场景下,应该考虑实现更高效的序列化框架

经典必看文章-wwHoverPanel AJAX Control for ASP.NET posted
http://west-wind.com/weblog/posts/4408.aspx



4. Atlas

这个产品,我就不列举具体的功能了,而主要说一下我对其的看法和持有的态度。因为在我的Ajax书评中提到过问题。
Atlas 是一个个性鲜明的产品,其优点是明显的,缺点也是明显的,但首先你必须认识到它还是一个比较复杂,拥有较高学习曲线的解决方案。对于其复杂性,老实说目前,大多数人还缺乏真实的感受。

最近的一个个版本-Jan CTP,我们看到了一些特性,其强大之处在于:

1.客户端(java-script)的数据绑定、校验带来便利。
2. 新的Update Panels不仅拥有了MagicAjax.NET 的特性,而且功能更强,是目前Atlas中异步回调的主要控件。
3.内置了一些具体Ajax特性的控件,比如AutoCompleteExtender ,DragOverlayExtender
4. 提供了一些使用的控件比如,ScriptManager, Triggers ,TimerControl
5. 主要用途着重在提供一个客户端控件和服务器端控件的特性集成的方案和容易使用的开发效率上。

但缺点也是明显的,比如:
1. 客户端的Behaviors还很弱,模板(Templates)和UI增强(UI Enhancements)功能还没有看到。
2. 所谓的客户端Atlas控件(“Atlas” Client Controls)和服务器端的Atlas控件(“Atlas” Server Controls) 还没有一个明确的规范,所以现在你基本上还不能创建自定义的Atlas控件(无论客户端还是服务器端的)。
3. 目前还只支持调用Web Services的服务,对于ASP.NET的内置的服务以及WCF的服务支持也没有看见,也不支持页面或控件内的方法调用
4. 功能上还不稳定,一些功能仅是在特定条件下的特性实现,还不能满足部署生产环境的要求。我认为,如果Atlas发布Go-Live License,那么可以考虑Atlas的放入到正式的项目或应用中。

我并不建议,你现在就将它应用在一个老的ASP.NET 项目中,或是老项目迁移到ASP.NET v2.0时优先考虑它;更多时候,如果你是创建一个新的ASP.NET应用,而又跨越了其学习曲线的情况下,可以考虑使用它。目前的情况下,对于Atlas,我建议,你应该保持足够的关注和实践学习,但是要抑制住将其应用到项目中的兴趣;因为Ajax,你现在可以开始关注和学习它,但是你不能因为要实现Ajax一个特性,而立即选择Atlas,那么是可能有风险的。

注: Atals 的Microsoft.Web.Script.Serialization 命名空间中有java-scriptObjectDeserializer和java-scriptObjectSerializer两个对象,第一,我不确定其是否也是JSON 序列化,而且我也不确定目前是否支持两路双向的序列化;第二,目前的版本,我还不能进行自定义或扩展,同时也很难对于其性能做任何的结论。

经典必看文章- Atlas 快速学习参考
http://atlas.asp.net/quickstart/default.aspx



基于Ajax 架构的Web应用框架
之前我提到过"似Ajax" 的架构,现在我要说的Ajax框架也就是指专门针对这种Ajax架构而提供的框架。目前,我还没有听说过特别好的这个领域的流行框架。但我知道我的身边,.NET领域,J2EE领域或PHP平台上都有这样的框架和应用,我认为,正是因为有很多这样应用,所以Ajax才会像某个模式一样,被撰有一个专门的名词。不过我感觉Ajax 渐渐变成了Ajax feature的代名词,变成了XMLHTTP的代名词,成了异步通讯,不刷新页面的技术表示法。直到我看过Ajax in Action这本书,我才把Ajax和系统的架构、设计模式,分布式对象的序列化和我之前的项目和经历联系在一切。

我修改了一些Jesse的图,来说明我认为的基于Ajax的架构是什么样的。

ͼƬСŴ


这也就是我上面说的“似Ajax”架构,首先它是一个Web应用;它的表现层用DHTML+CSS + HTC控件+ java-script ,服务器端用.NET或任何的服务器端技术,中间以XML方式序列化和反序列化进行传递数据。

简单的说,客户端需要将请求的数据封装成一个XML数据通过HTTP传递给服务器端,服务器端处理这个请求,并将结果也以XML的形式返回到客户端,客户端再处理这些请求,然后使用HTML+CSS进行展示。其实如果不是Web客户端(浏览器)的问题,这是最简单的架构,但关键问题在于上面我们说的java-script端的对象封装成一个XML,以及到服务端解析XML变成服务器端对象,然后再将结果封装成XML,传回给客户端(java-script),客户端也解析XML数据,然后变成java-script 中的对象的这个序列化和反序列化的问题。另外一个问题就是表现层的展现问题,怎么展现,用什么控件?

所以,一个Ajax架构的Web应用程序,必须解决下面的问题:
1. 双向两路的序列化问题
2. 表现层展现的问题
3. 传输时客户端和服务器端的数据安全问题
4. 性能问题
5. 国际化支持

最好玩的双向两路的序列化问题,最早接触的是JSON ,它的问题在于扩展性,数据类型的支持和性能,但是平台无关性比较好,什么浏览器都可以,因为它不需要用msxml2.DOMDocumen分析XML,本质上就是用字符串描述对象;之后多平台的应用的迁移经历中(比如CORBAR,J2EE的后台应用),开始接触到XML-RPC ICEHessian,Web Services等等。其中XML-RPC有java-script 的支持库,Web Services也有java-script的支持库,也就是你可以使用java-script访问或者获得XML-RPC/Web Services的对象,但是如果你将其作为一个主要的通讯协议,那么就会遇到另外一些问题,比如性能、国际化的问题,又会困扰你,XML-RPC和Web Services的一个主要问题都是性能,因为他们传输的XML大小都太大了,但显然用这些实现一个Ajax的特性,那是完全没有问题了。

比如,Atlas目前不也是使用一个java-script库调用Web Services吗?,所以,你也可以这么做,同样你也可以用XML-RPC.NET 很快就可以实现一个Service,然后使用Scotandrew的XML-RPC java-script 库就可以在java-script中发一个XML-RPC 消息请求这个服务,然后异步的获得这个结果,然后展现它。所以从技术的实现上讲,Ajax的特性非常容易实现,但从架构上来看。你需要思考更多的因素。当然直到最后,我们才发现,在项目中,最完美的方案是你自己写一个双向两路的序列化引擎供你的java-script客户端使用。

这就说到了第二个问题,界面表现的问题,这个问题也是一个大的问题。这个问题一直会永远存在,Ajax之前没有人会太注意这些,但今天不同了,我想未来还会有很大的一个飞跃, Yahoo! 不是最近也开源了他的Yahoo! Web UI库,Atlas 也表示要提供更多的前端UI控件。无论如何,这个问题是,你的团队或组织是否有一套经过项目或客户检验的前端java-script的库。无论是自己用java-script写的也好,是自己写的一套HTC的控件库也好,总之这些是Ajax 架构中非常重要的一环。

Atlas 带来了另外一个思考问题,就是服务器端控件可能可以通过某种方式和java-script的控件很好的集成在一起,以前我们用HTC解决了重用、性能、Behaviors、甚至模板功能。但是新的特性还是有比如数据的绑定、缓存和校验、甚至是数据编码和压缩、加密和解密,java-script UI前端还是有许多可以做的,而且如何无缝的集成两者,这个有非常大的意义。

接着安全、性能、国际化等等,架构中的问题需要你依次考虑和解决,如果这么看Ajax,我认为,目前的Ajax框架还有很长很长一段路要走,同样真正完美支持Ajax架构的还需要继续努力。这些也是我在这篇专栏文章中的观点。

把这些合在一起,那么Ajax架构的开发包或框架,就应该是包含了上述几个问题(两路双向的序列化、java-script UI 表现库、安全、国际化和性能等等)解决方案的一个平台实现。

同样也许你会说,不就是Ajax吗? 我干嘛要搞这么复杂,一定要搞到架构这个层面。
我认为,
第一,从架构的层面看Ajax,然后再应用相关的技术,比你直接使用某个Ajax框架然后再理解Ajax,你会从这个过程中收获更多。
第二,对于一个开发团队/组织来说,真正Ajax架构的产品,可以带来效益和具体的生产力。比如,我身边就有拥有这样的优势的团队,他们拥有一套统一的由java-script+HTML+CSS+HTC的前端表现层,而后台的业务系统有两个平台,一个.NET平台和J2EE平台;同样我身边的也有这样的团队,他们拥有一套统一的由java-script+DHTML+CSS+HTC+VML+ASP.NET的前端表现层,但他们的后台业务层分别来自.NET平台、J2EE平台和Unix平台,我不能说Ajax架构的应用似乎就是统一Web 表现层。因为从今天看到他们的明天,也许会是, 一个ASP.NET V2+Atlas 的统一表现层,一个统一CAB+Smart Client 的统一表现层,也可以是一个WPF 3D的统一表现层,也可以是一个Xgl 桌面的统一层。。。。
第三,从这架构的层面上,你也能够非常容易理解SOA或ESB概念,和SOA相比,Ajax架构的区别在于,Ajax有足够的松散耦合,但它依然以应用的数据为中心,更多的是一个面向Messages的架构,而且对于流行的WS-*协议的支持非常有限。

但是假如,今天你或你的团队已经有了一个Ajax 架构的应用,那么你是不是应该要小心选择现有的Ajax框架,因为这些Ajax的特性,相对于目前的架构来说,是多么小,但又可能会产生很大危害的一个因素。也许这样的团队并不多,也许也很多,但是只有我们从更高更深的层次来思考,那么我们就能做出正确的选择,并且从新的Ajax技术和研究中获得好处。



结论
当我们回到文章的起点,我希望这样能够说明的我观点,即Ajax-NET的框架或实现分为两类,一类是基于Ajax应用程序架构的,一类是基于Ajax特性的,目前几乎大部分的Ajax-NET的框架或实现都是基于Ajax特性,以Add-in 方式提供的代码或框架。

Ajax-NET的实现/框架选取上的建议:
  • ASP.NET控件形式已经成为连接服务器和客户端Ajax通信的主要形式和选择。
  • 客户端调用服务器端页面中的方法是Ajax的重要手段,使得客户端可以更加灵活的获得服务器端的数据。
  • MagicAjax.NET,Anthem.NET用了"Hook ASP.NET"和Add-In的技术手段,使用上受到的影响比较多,这两个框架中,最简单的应用,第一选择MagicAjax.NET,但总是优先使用Anthem.NET
  • 如果是自己写的服务器端控件,那么应该先掌握Anthem.NET的技术,然后使自己的控件拥有Ajax的特性
  • MagicAjax.NET, Anthem.NET和wwHoverPanel 对于国际化的支持都有待加强
  • 在Atlas没有正式发布之前,在ASP.NET的应用中优先在自己的项目中使用类似wwHoverPanel的技术,即尽可能的使用客户端回调功能,在特别需要的地方使用其方法调用的功能,充分发挥Ajax的特性,而不要因为Ajax而特意选择某个Ajax的框架
  • Atlas的强项在于服务器端和客户端控件特性的集成、客户端的数据绑定、校验、内置的多个客户端Ajax 特性UI或组件,与ASP.NET的Profile, Membership ,Role 服务的集成,与Web Services和WCF 服务的集成,以及良好的国际化/开发工具支持的。因为它是一个完整的解决方案,所以最大的弱点是不能很容易地被老的Ajax架构的应用使用。另外该产品目前还在不断开发中,距离部署到生产环境中的要求还有差距。
  • 轻量级的双向序列化可以考虑JSON格式,安全问题可以在传递的对象中增加字段,然后在服务器端进行校验。
  • 对于原来已经有一套序列化框架的组织来说,其主要的目标是尽快将这个框架迁移/升级到ASP.NET V2,而不是优先考虑实现某个Ajax的特性
  • Ajax 要求有足够的力量关注前端的UI展现或开发,所以对Ajax实现/框架的选择,最先要考察其客户端的实现以及提供的Web UI
看完这篇文章,我希望,2006年我们再谈起Ajax的时候,
  • 作为技术人员,我不用谈论什么Web 2.0,我一样可以清楚的表达Ajax的概念
  • 如果你是一个架构师,Ajax 不再是什么异步的XMLHTTP调用,不再是不刷新页面,它可以帮忙你Review应用程序的架构。
  • 对于你的团队或老板来说,Ajax可以是你统一界面表现层的一个策略,同样也可能让你有了一个创建一套部门或公司级能够重用的UI类库的机会。
  • 同样对于java-script的开发人员来说,Ajax让你们还需要了解一些业务,并证明前台的Web开发人员一样很昂贵,后台开发也可以是技术含量不高的
  • 对于SOA的爱好者来说,Ajax架构让你能够站在面向消息的架构和系统上来看面向服务;一般我们说,对内你首先要有一套面向消息的架构,然后对外你就很容易延伸成一个面向服务面向Internet的分布式架构。
  • 最后,不要讨论Ajax的消亡,因为Ajax对于程序员来说,是一种力量均衡的策略,在Ajax中,Web前端的开发人员被重新重视,成为一支重要的力量。
后记
写这些文字的某几个段落,让我有些痛苦,因为我本来没想些这么多。所以你不要太在意我对各个框架的评价和描述,这些都是技术的层面的东西,其实我写这篇文字,主要是想突出Ajax的架构观,以及设计模式和Web应用架构重构的考虑,续而你也能够用类似横切面的角度,用Ajax来看你目前的应用和架构,从而更深的了解分布式对象的序列化、性能、安全以及Ajax 和ASP.NET服务器端控件的融合。最后欢迎大家斧正。

在ASP.NET中实现AJAX

Asynchronous java-script and XML(AJAX)最近掀起的高潮,要完全归功于Google在Google SuggestGoogle Maps中的使用。对ASP.NET而言,AJAX不需要回传就能进行服务器端处理,从而使客户机(浏览器)具有丰富的服务器端能力。换句话说,它为异步指派和处理请求与服务器响应提供了一个框架。AJAX利用了一些不是很新颖的已有技术,但是对这些技术(加到一起就是AJAX)的爱好最近突然升温。
请尝试Michael Schwarz的AJAX .NET包装器,通过它ASP.NET开发人员可以快速方便的部署很容易利用AJAX功能的页面。需要注意的是,这个包装器处于初期开发阶段,因此还没有完全成熟。
然而,AJAX这样的技术很可能破坏分层体系结构(N-Tier)。我的看法是,AJAX增加了表示逻辑层(甚至更糟,业务层)渗透到表示层的可能性。像我这样严肃的架构师对这种想法可能畏步不前。我感到AJAX的使用即便稍微越过了层次边界,这种代价也是值得深思的。当然,这要视具体的项目和环境而定。
起步
它是如何工作的——概述
AJAX依靠代理(broker)指派和处理往返服务器的请求。对此,.NET包装器依靠客户端XmlHttpRequest对象。多数浏览器都支持XmlHttpRequest对象,这就是选择它的原因。因为包装器的目的是隐藏XmlHttpRequest的实现,我们就不再详细讨论它了。
包装器本身通过将.NET函数标记为AJAX方法来工作。标记之后,AJAX就创建对应的java-script函数,这些函数(和任何java-script函数一样)作为代理可以在客户端使用XmlHttpRequest调用。这些代理再映射回服务器端函数。
复杂吗?并不复杂。我们来看一个例子。假设有一个.NET函数:
ublic int Add(int firstNumber, int secondNumber)
{
return firstNumber + secondNumber;
}
AJAX .NET包装器将自动创建名为“Add”、带有两个参数的java-script函数。使用java-script(在客户机上)调用该函数时,请求将传递给服务器并把结果返回给客户机。
 
初始设置
我们首先介绍“安装”项目中使用的.dll的步骤。如果您很清楚如何添加.dll文件引用,可以跳过这一节。
首先,如果还没有的话,请下载最新的AJAX版本。解压下载的文件并把ajax.dll放到项目的引用文件夹中。在Visual Studio.NET中有机Solution Explorer的“References(引用)”节点并选择Add Reference(添加引用)。在打开的对话框中,单击Browse(浏览)并找到ref/ajax.dll文件。依次单击Open(打开)和Ok(确认)。这样就可以用AJAX .NET包装器编程了。
建立HttpHandler
为了保证正常工作,第一步是在web.config中设置包装器的HttpHandler。不需要详细解释HttpHandlers是什么及其如何工作,只要知道它们用于处理ASP.NET请求就足够了。比如,所有*.aspx页面请求都由System.Web.UI.PageHandlerFactory类处理。类似的,我们让所有对ajax/*.ashx的请求由Ajax.PageHandlerFactory处理:
<configuration>
  <system.web>
    <httpHandlers>
      <add verb="POST,GET" path="ajax/*.ashx"
          type="Ajax.PageHandlerFactory, Ajax" />
    </httpHandlers> 
    ...
  <system.web>
</configuration>
简言之,上面的代码告诉ASP.NET,和指定路径(ajax/*.ashx)匹配的任何请求都由Ajax.PageHandlerFactory而不是默认处理程序工厂来处理。不需要创建ajax子目录,使用这个神秘的目录只是为了让其他HttpHandlers能够在自己建立的子目录中使用.ashx扩展。
 
建立页面
现在我们可以开始编码了。创建一个新页面或者打开已有的页面,在file后的代码中,为Page_Load事件添加以下代码:
public class Index : System.Web.UI.Page{
  private void Page_Load(object sender, EventArgs e){
      Ajax.Utility.RegisterTypeForAjax(typeof(Index));     
      //...   
  }
  //... 
}
调用RegisterTypeForAjax将在页面上引发后面的java-script(或者在页面中手工加入以下两行代码):
<script language="java-script" src="ajax/common.ashx"></script>
<script language="java-script"
src="ajax/Namespace.PageClass,AssemblyName.ashx"></script>
其中最后一行的含义是:
下面是AjaxPlay项目中sample.aspx页面的结果例子:
<%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
<html>
<head>
  <script language="java-script" src="ajax/common.ashx"></script>
  <script language="java-script"
          src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>
</head>
  <body>   
    <form id="Form1" method="post" runat="server">
      ...
    </form>   
  </body>
</html>
可以在浏览器中手工导航到src路径(查看源代码,复制粘贴路径)检查是否一切正常。如果两个路径都输出一些(似乎)毫无意义的文本,就万事大吉了。如果什么也没输出或者出现ASP.NET错误,则表明有些地方出现问题。
即便不知道HttpHandlers如何工作,上面的例子也很容易理解。通过web.config,我们已经保证所有对ajax/*.ashx的请求都由自定义的处理程序处理。显然,这里的两个脚本标签将由自定义的处理程序处理。
 
创建服务器端函数
现在来创建可从客户端调用中异步访问的服务器端函数。因为目前还不支持所有的返回类型(不用担心,将在目前的基础上开发新的版本),我们继续使用简单的ServerSideAdd函数吧。在file后的代码中,向页面添加下列代码:
[Ajax.AjaxMethod()]
public int ServerSideAdd(int firstNumber, int secondNumber)
{
  return firstNumber + secondNumber;
}
要注意,这些函数具有Ajax.AjaxMethod属性集。该属性告诉包装器这些方法创建java-script代理,以便在客户端调用。
 
客户端调用
最后一步是用java-script调用该函数。AJAX包装器负责创建带有两个参数的java-script函数Sample.ServerSideAdd。对这种最简单的函数,只需要调用该方法并传递两个数字:
<%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
<html>
<head>
  <script language="java-script" src="ajax/common.ashx"></script>
  <script language="java-script"
          src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>
</head>
  <body>   
    <form id="Form1" method="post" runat="server">
      <script language="java-script">
        var response = Sample.ServerSideAdd(100,99);
        alert(response.value);
      </script>
    </form>   
  </body>
</html>
当然,我们不希望仅仅用这种强大的能力来警告用户。这就是所有客户端代理(如java-script Sample.ServerSideAd函数)还接受其他特性的原因。这种特性就是为了处理响应而调用的回调函数:
Sample.ServerSideAdd(100,99, ServerSideAdd_CallBack);

function ServerSideAdd_CallBack(response){
 if (response.error != null){
  alert(response.error);
  return;
 }
 alert(response.value);
}
从上述代码中可以看到我们指定了另外一个参数。ServerSideAdd_CallBack(同样参见上述代码)是用于处理服务器响应的客户端函数。这个回调函数接收一个响应对象,该对象公开了三个主要性质
  • Value——服务器端函数实际返回的值(无论是字符串、自定义对象还是数据集)。
  • Error——错误消息,如果有的话。
  • Request——xml http请求的原始响应。
  • Context——上下文对象。
首先我们检查error只看看是否出现了错误。通过在服务器端函数中抛出异常,可以很容易处理error特性。在这个简化的例子中,然后用这个值警告用户。Request特性可用于获得更多信息(参见下一节)。
 
处理类型
 
返回复杂类型
Ajax包装器不仅能处理ServerSideAdd函数所返回的整数。它目前还支持integers、strings、double、booleans、DateTime、DataSets和DataTables,以及自定义类和数组等基本类型。其他所有类型都返回它们的ToString值。
返回的DataSets和真正的.NET DataSet差不多。假设一个服务器端函数返回DataSet,我们可以通过下面的代%
posted @ 2007-03-12 11:47  南京酷得软件-陈朕  阅读(403)  评论(0编辑  收藏  举报
南京酷得软件-陈朕