asp.net2.0+xml实现多语言开发!

mikel阅读(872)

我们来看如何使用xml来实现吧!
1。我们需要编写一个ResourceManager.cs来读取xml文件内容
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
//对xml读写操作
using System.Xml;
//缓存
using System.Web.Caching;
//
using System.Collections;
///

/// ResourceManager 的摘要说明
///

public class ResourceManager
{
public ResourceManager() { }
public static string GetString(string name, string userLanguages)
{
//通过指定属性名返回包含此属性名相关信息的hash表
Hashtable source = LoadSource(userLanguages);
//如果hash表不等于null就将其值返回
if (source != null)
{
return source[name].ToString();
}
//否则空
return “”;
}
//获取语言语句字典
public static Hashtable LoadSource(string userLanguages)
{
//获取xml文件存放的物理路径
string pathFile = System.Web.HttpContext.Current.Server.MapPath(HttpContext.Current.Request.ApplicationPath + “/Languages/”+userLanguages+”/Resources.xml”);
//创建一个xmldatadocument对象
System.Xml.XmlDataDocument lagXml = new XmlDataDocument();
//加载其要操作的xml文件
lagXml.Load(pathFile);
//声明一个hash表
Hashtable supportedLanguages;
//创建hash表
supportedLanguages = new Hashtable();
//获取xml文件中root节点下的所有子节点
foreach (XmlNode xn in lagXml.SelectSingleNode(“root”).ChildNodes)
{
//如果不是注释就将子节点属性值和节点文本以键/值对形式存放到hash表里
if (xn.NodeType != XmlNodeType.Comment)
{
supportedLanguages.Add(xn.Attributes[“name”].Value,xn.InnerText);
}
}
//返回hash表
return supportedLanguages;
}
}
2。肯定还需要xml文件。
我们在项目根目录下创建一个Languages文件夹,然后在下面建子文件夹:例如中文就是zh-CN,英文就是en-US.
然后在这些子文件夹下创建相同名称的xml文件Resources.xml
当然名字是随便取的!不过注意代码里要改动!
xml文件里的具体格式如下:


Account number:
Password:
Confirmation
Publishes

3。讲到这里我来说下实现原理,前台有两个按钮 一个在点击后使页面显示中文,一个则显示英文
那么我们需要先拖出这么两个button控件!
然后分别在他们的click事件里写上:
string langauge = “zh-CN”;//这三句话是写在了中文按钮的事件下,英文下同样是这三句话,但要记得将zh-CN改成en-US
Session[“Language”] = langauge;
ShowText(langauge);
4。大家肯定看到了ShowText干什么的!他就是来指定翻译那些东东的! 这个方法还需要在每个页面都放到page_load下面!因为我们需要在
页面一加载时就翻译!
void ShowText(string userLanguage)
{
localizeAccount.Text = ResourceManager.GetString(“Account”, userLanguage);
}
例如这个是将localizeAccount控件的文本按指定要求翻译成指定文本!
这里大家也该明白我们必须将需要翻译的东东都放到控件里,然后后台调用其text属性来改变他的显示语言!
关于这一点,有几点需要注意,就是datalist这类绑定控件里的header,item里的控件如何取出来翻译!
foreach(DataListItem item in DataList控件id.Controls)
{
if(item.ItemType==ListItemType.Header)
{
(Localize) a = item.FindControl(“id”) as Localize;
a.Text = …;
}
}
这样就可以取出header部分的控件了,但是不知道为什么这样取item里的控件会有问题!
所以取item里的大家这样取
foreach(DataListItem item in DataList控件id.Items)
{
(Localize) a = item.FindControl(“id”) as Localize;
a.Text = …;
}
5。创建Global.asax文件
void Session_Start(object sender, EventArgs e)
{
// 在新会话启动时运行的代码
Session[“Language”] = “zh-CN”;
}
void Session_End(object sender, EventArgs e)
{
// 在会话结束时运行的代码。
// 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
// InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer
// 或 SQLServer,则不会引发该事件。
Session.Clear();
}
———————总结—————————–
那么我们来把上面乱七八糟步骤整理一下,
首先Global.asax会在一开始默认一中语言显示,这里是中文!
然后当有用户点击英文按钮的时候,会改变session存贮的值,
然后页面根据session值加载ShowText()方法,
而这一方法会通过调用ResourceManager.cs文件里的方法到指定xml文件中读取数据!
这样一个多语言就实现了!也没也过什么文章,随便写写,只希望能帮助到大家,而且我的
说不定是很差的实现方法,就当给大家提供个思路吧,有错的地方还请指教!
最后提两点,如果需要下拉框,需要在Languages文件夹下建一个xml专门存贮下拉框内容:例如:
一—————————————–






然后在ResourceManger.cs文件里加上一个方法:
//获取语言目录数据,返回一个数据视图
public static DataView GetSupportedLanguages()
{
string cacheKey = “Languages”;
if(HttpContext.Current.Cache[cacheKey]==null)
{
string PathFile=System.Web.HttpContext.Current.Server.MapPath(HttpContext.Current.Request.ApplicationPath+”/Languages/languages.xml”);
DataSet objDataSet=new DataSet();
objDataSet.ReadXml(PathFile);
//下面两句自己也不是很理解,还望高人指点,呵呵!~
CacheDependency dp = new CacheDependency(PathFile);
HttpContext.Current.Cache.Insert(cacheKey,objDataSet.Tables[0].DefaultView,dp,DateTime.MaxValue, TimeSpan.Zero);
}
return (DataView)HttpContext.Current.Cache[cacheKey];
}
后台这样为下拉菜单绑定数据
drp_language.DataSource = MultLanuage.ResourceManager.GetSupportedLanguages();
drp_language.DataTextField = “name”;
drp_language.DataValueField = “key”;
drp_language.DataBind();
二—————————————
如果项目中有用到母版+导航制作的框架,那就很郁闷!
我是想到了通过配置配置文件,根据session加载不同语言的sitemap文件
不知道大家有没有更好的推荐一下!
thank you~!!!!!!!!!
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1744933

asp制作多国语言网站

mikel阅读(820)

现在越来越多的公司为了打开过外市场,都会在自己网站上做上相应的英文,日文,韩文,西班牙文…等一些网页。而一个企业网做一个英文版,在深圳这个地方已经成为一种时尚。
而很多人做英文版都是是用GB2312,这套制就算是繁体操作系统上也可能看到乱码现象。这显然是一个错误,只是可以应付客户而已。制作多国语言最好用utf-8。
而asp制作多国语言网站,也会给大家带来一些问题。现在把自己制作过程中的经验分享出来。
打开新建一个ASP页面,相信玩ASP的朋友都会留意到,许多下载的源码里,页面最上方一般都有一句:
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>
前面的language应该不用多说了,vbscript就是ASP默认的脚本语言,其实完全可以不用写,写了好像还会影响页面执行效率,在这里我们先不讨论这个问题. 后面的codepage就是关键了,目的就是告诉浏览器,此页面是何种编码,936代表是简体中文,而950代表繁体中文,65001就是我们今天说的 UTF-8编码了.我们将936改成65001,整句如下:
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
再加上输出几个中文字看看能不能正确显示吧.
<% Response.Write "第一次测试UTF-8页面" %>
OK,直接点击”保存”,执行这个页面看看,如果不出意外,大家可能看到显示出的是 “一尾UTF-8页” 这几个字,中文有乱码的现象,什么原因呢?
OK, 请大家再点击最上面的 “文件” 菜单,选择”另存为”,最下面一行有个编码,默认应该是ANSI的,请大家点下拉框,选择UTF-8,再点保存,再执行试试看,如果不出意外,乱得更厉害了,呵呵,晕了吧.别急,想想原因,因为我们做的页面是HTML返回的,以前我们写HTML时,看到body前面,也就是head里都有一句meta,应该是这样的:

也就是指定页面以gb2312编码返回结果,一定要写在有返回结果输出的前面.大家都知道gb2312是简体中文吧,我们今天说的是UTF-8编码,我们就将gb2312改成UTF-8吧,全部代码如下:
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>

<% Response.Write "第一次测试UTF-8页面" %>
再看,这次正常了。
得出结论:采用UTF-8编码,除了要将文件另存为UTF-8格式之外,还需要同时指定codepage及charset.
但有了这些还不够,在制作过程中还会出现一些乱码的问题。为了。保证asp叶面一定不会出现乱码的代码应该是这样的:
<%@ CODEPAGE=65001 %>
<% Response.CodePage=65001%>
<% Response.Charset="UTF-8" %>
建议:可以建立公共文件code.asp,或则直接写到习惯的conn.asp中。

面向Web的数据挖掘

mikel阅读(624)

面向Web的数据挖掘
  Web上有海量的数据信息,怎样对这些数据进行复杂的应用成了现今数据库技术的研究热点。数据挖掘就是从大量的数据中发现隐含的规律性的内容,解决数据的应用质量问题。充分利用有用的数据,废弃虚伪无用的数据,是数据挖掘技术的最重要的应用。相对于Web的数据而言,传统的数据库中的数据结构性很强,即其中的数据为完全结构化的数据,而Web上的数据最大特点就是半结构化。所谓半结构化是相对于完全结构化的传统数据库的数据而言。显然,面向Web的数据挖掘比面向单个数据仓库的数据挖掘要复杂得多。
1.异构数据库环境
  从数据库研究的角度出发,Web网站上的信息也可以看作一个数据库,一个更大、更复杂的数据库。Web上的每一个站点就是一个数据源,每个数据源都是异构的,因而每一站点之间的信息和组织都不一样,这就构成了一个巨大的异构数据库环境。如果想要利用这些数据进行数据挖掘,首先,必须要研究站点之间异构数据的集成问题,只有将这些站点的数据都集成起来,提供给用户一个统一的视图,才有可能从巨大的数据资源中获取所需的东西。其次,还要解决Web上的数据查询问题,因为如果所需的数据不能很有效地得到,对这些数据进行分析、集成、处理就无从谈起。
2.半结构化的数据结构
  Web上的数据与传统的数据库中的数据不同,传统的数据库都有一定的数据模型,可以根据模型来具体描述特定的数据。而Web上的数据非常复杂,没有特定的模型描述,每一站点的数据都各自独立设计,并且数据本身具有自述性和动态可变性。因而, Web上的数据具有一定的结构性,但因自述层次的存在,从而是一种非完全结构化的数据,这也被称之为半结构化数据。半结构化是Web上数据的最大特点。
3.解决半结构化的数据源问题
  Web数据挖掘技术首要解决半结构化数据源模型和半结构化数据模型的查询与集成问题。解决Web上的异构数据的集成与查询问题,就必须要有一个模型来清晰地描述Web上的数据。针对Web上的数据半结构化的特点,寻找一个半结构化的数据模型是解决问题的关键所在。除了要定义一个半结构化数据模型外,还需要一种半结构化模型抽取技术,即自动地从现有数据中抽取半结构化模型的技术。面向 Web的数据挖掘必须以半结构化模型和半结构化数据模型抽取技术为前提。
XML与Web数据挖掘技术
  以XML 为基础的新一代WWW环境是直接面对Web数据的,不仅可以很好地兼容原有的Web应用,而且可以更好地实现Web中的信息共享与交换。XML可看作一种半结构化的数据模型,可以很容易地将XML的文档描述与关系数据库中的属性一对应起来,实施精确地查询与模型抽取。
1.XML的产生与发展
  XML(eXtensibleMarkupLanguage)是由万维网协会(W3C)设计,特别为Web应用服务的SGML (StandardGeneralMarkupLanguage)的一个重要分支。总的来说,XML是一种中介标示语言(Meta- markupLanguage),可提供描述结构化资料的格式,详细来说,XML是一种类似于HTML,被设计用来描述数据的语言。XML提供了一种独立的运行程序的方法来共享数据,它是用来自动描述信息的一种新的标准语言,它能使计算机通信把Internet的功能由信息传递扩大到人类其他多种多样的活动中去。XML由若干规则组成,这些规则可用于创建标记语言,并能用一种被称作分析程序的简明程序处理所有新创建的标记语言,正如HTML为第一个计算机用户阅读Internet文档提供一种显示方式一样,XML也创建了一种任何人都能读出和写入的世界语。XML解决了HTML不能解决的两个Web问题,即Internet发展速度快而接入速度慢的问题,以及可利用的信息多,但难以找到自己需要的那部分信息的问题。XML能增加结构和语义信息,可使计算机和服务器即时处理多种形式的信息。因此,运用XML的扩展功能不仅能从Web服务器下载大量的信息,还能大大减少网络业务量。
   XML中的标志(TAG)是没有预先定义的,使用者必须要自定义需要的标志,XML是能够进行自解释(SelfDescribing)的语言。XML使用 DTD(DocumentTypeDefinition文档类型定义)来显示这些数据,XSL (eXtensibleStyleSheetLanguage)是一种来描述这些文档如何显示的机制,它是XML的样式表描述语言。XSL的历史比 HTML用的CSS(层叠式样式表CascadingStyleSheets)还要悠久,XSL包括两部分:一个用来转换XML文档的方法;一个用来格式化XML文档的方法。XLL(eXtensibleLinkLanguage)是XML连接语言,它提供XML中的连接,与HTML中的类似,但功能更强大。使用XLL,可以多方向连接,且连接可以存在于对象层级,而不仅仅是页面层级。由于XML能够标记更多的信息,所以它就能使用户很轻松地找到他们需要的信息。利用XML,Web设计人员不仅能创建文字和图形,而且还能构建文档类型定义的多层次、相互依存的系统、数据树、元数据、超链接结构和样式表。
2.XML的主要特点
  正是XML的特点决定了其卓越的性能表现。XML作为一种标记语言,有许多特点:
  · 简单。XML经过精心设计,整个规范简单明了,它由若干规则组成,这些规则可用于创建标记语言,并能用一种常常称作分析程序的简明程序处理所有新创建的标记语言。XML能创建一种任何人都能读出和写入的世界语,这种创建世界语的功能叫做统一性功能。如XML创建的标记总是成对出现,以及依靠称作统一代码的新的编码标准。
  · 开放。XML是SGML在市场上有许多成熟的软件可用来帮助编写、管理等,开放式标准XML的基础是经过验证的标准技术,并针对网络做最佳化。众多业界顶尖公司,与W3C的工作群组并肩合作,协助确保交互作业性,支持各式系统和浏览器上的开发人员、作者和使用者,以及改进XML标准。XML解释器可以使用编程的方法来载入一个XML的文档,当这个文档被载入以后,用户就可以通过XML文件对象模型来获取和操纵整个文档的信息,加快了网络运行速度。
  · 高效且可扩充。支持复用文档片断,使用者可以发明和使用自己的标签,也可与他人共享,可延伸性大,在XML中,可以定义无限量的一组标注。XML提供了一个标示结构化资料的架构。一个XML组件可以宣告与其相关的资料为零售价、营业税、书名、数量或其它任何数据元素。随着世界范围内的许多机构逐渐采用 XML标准,将会有更多的相关功能出现:一旦锁定资料,便可以使用任何方式透过电缆线传递,并在浏览器中呈现,或者转交到其他应用程序做进一步的处理。 XML提供了一个独立的运用程序的方法来共享数据,使用DTD,不同的组中的人就能够使用共同的DTD来交换数据。你的应用程序可以使用这个标准的DTD 来验证你接受到的数据是否有效,你也可以使用一个DTD来验证你自己的数据。
  · 国际化。标准国际化,且支持世界上大多数文字。这源于依靠它的统一代码的新的编码标准,这种编码标准支持世界上所有以主要语言编写的混合文本。在HTML 中,就大多数字处理而言,一个文档一般是用一种特殊语言写成的,不管是英语,还是日语或阿拉伯语,如果用户的软件不能阅读特殊语言的字符,那么他就不能使用该文档。但是能阅读XML语言的软件就能顺利处理这些不同语言字符的任意组合。因此,XML不仅能在不同的计算机系统之间交换信息,而且能跨国界和超越不同文化疆界交换信息。
3.XML在Web数据挖掘中的应用
  XML已经成为正式的规范,开发人员能够用XML 的格式标记和交换数据。XML在三层架构上为数据处理提供了很好的方法。使用可升级的三层模型,XML可以从存在的数据中产生出来,使用XML结构化的数据可以从商业规范和表现形式中分离出来。数据的集成、发送、处理和显示是下面过程中的每一个步骤:
  促进XML应用的是那些用标准的HTML无法完成的Web应用。这些应用从大的方面讲可以被分成以下四类:需要Web客户端在两个或更多异质数据库之间进行通信的应用;试图将大部分处理负载从Web服务器转到Web客户端的应用;需要Web客户端将同样的数据以不同的浏览形式提供给不同的用户的应用;需要智能Web代理根据个人用户的需要裁减信息内容的应用。显而易见,这些应用和Web的数据挖掘技术有着重要的联系,基于Web的数据挖掘必须依靠它们来实现。
  XML给基于Web的应用软件赋予了强大的功能和灵活性,因此它给开发者和用户带来了许多好处。比如进行更有意义的搜索,并且Web数据可被XML唯一地标识。没有XML,搜索软件必须了解每个数据库是如何构建的,但这实际上是不可能的,因为每个数据库描述数据的格式几乎都是不同的。由于不同来源数据的集成问题的存在,现在搜索多样的不兼容的数据库实际上是不可能的。XML能够使不同来源的结构化的数据很容易地结合在一起。软件代理商可以在中间层的服务器上对从后端数据库和其它应用处来的数据进行集成。然后,数据就能被发送到客户或其他服务器做进一步的集合、处理和分发。XML的扩展性和灵活性允许它描述不同种类应用软件中的数据,从描述搜集的Web页到数据记录,从而通过多种应用得到数据。同时,由于基于XML的数据是自我描述的,数据不需要有内部描述就能被交换和处理。利用XML,用户可以方便地进行本地计算和处理,XML格式的数据发送给客户后,客户可以用应用软件解析数据并对数据进行编辑和处理。使用者可以用不同的方法处理数据,而不仅仅是显示它。XML文档对象模式(DOM)允许用脚本或其他编程语言处理数据,数据计算不需要回到服务器就能进行。XML可以被利用来分离使用者观看数据的界面,使用简单灵活开放的格式,可以给Web创建功能强大的应用软件,而原来这些软件只能建立在高端数据库上。另外,数据发到桌面后,能够用多种方式显示。
  XML还可以通过以简单开放扩展的方式描述结构化的数据,XML补充了 HTML,被广泛地用来描述使用者界面。HTML描述数据的外观,而XML描述数据本身。由于数据显示与内容分开,XML定义的数据允许指定不同的显示方式,使数据更合理地表现出来。本地的数据能够以客户配置、使用者选择或其他标准决定的方式动态地表现出来。CSS和XSL为数据的显示提供了公布的机制。通过XML,数据可以粒状地更新。每当一部分数据变化后,不需要重发整个结构化的数据。变化的元素必须从服务器发送给客户,变化的数据不需要刷新整个使用者的界面就能够显示出来。但在目前,只要一条数据变化了,整一页都必须重建。这严重限制了服务器的升级性能。XML也允许加进其他数据,比如预测的温度。加入的信息能够进入存在的页面,不需要浏览器重新发一个新的页面。XML应用于客户需要与不同的数据源进行交互时,数据可能来自不同的数据库,它们都有各自不同的复杂格式。但客户与这些数据库间只通过一种标准语言进行交互,那就是XML。由于XML的自定义性及可扩展性,它足以表达各种类型的数据。客户收到数据后可以进行处理,也可以在不同数据库间进行传递。总之,在这类应用中,XML解决了数据的统一接口问题。但是,与其他的数据传递标准不同的是, XML并没有定义数据文件中数据出现的具体规范,而是在数据中附加TAG来表达数据的逻辑结构和含义。这使XML成为一种程序能自动理解的规范。
  XML应用于将大量运算负荷分布在客户端,即客户可根据自己的需求选择和制作不同的应用程序以处理数据,而服务器只须发出同一个XML文件。如按传统的 “Client/Server”工作方式,客户向服务器发出不同的请求,服务器分别予以响应,这不仅加重服务器本身的负荷,而且网络管理者还须事先调查各种不同的用户需求以做出相应不同的程序,但假如用户的需求繁杂而多变,则仍然将所有业务逻辑集中在服务器端是不合适的,因为服务器端的编程人员可能来不及满足众多的应用需求,也来不及跟上需求的变化,双方都很被动。应用XML则将处理数据的主动权交给了客户,服务器所作的只是尽可能完善、准确地将数据封装进XML文件中,正是各取所需、各司其职。XML的自解释性使客户端在收到数据的同时也理解数据的逻辑结构与含义,从而使广泛、通用的分布式计算成为可能。
  XML还被应用于网络代理,以便对所取得的信息进行编辑、增减以适应个人用户的需要。有些客户取得数据并不是为了直接使用而是为了根据需要组织自己的数据库。比方说,教育部门要建立一个庞大的题库,考试时将题库中的题目取出若干组成试卷,再将试卷封装进XML文件,接下来在各个学校让其通过一个过滤器,滤掉所有的答案,再发送到各个考生面前,未经过滤的内容则可直接送到老师手中,当然考试过后还可以再传送一份答案汇编。此外, XML文件中还可以包含进诸如难度系数、往年错误率等其他相关信息,这样只需几个小程序,同一个XML文件便可变成多个文件传送到不同的用户手中。
结束语
  面向Web的数据挖掘是一项复杂的技术,由于Web数据挖掘比单个数据仓库的挖掘要复杂的多,因而面向Web的数据挖掘成了一个难以解决的问题。而 XML的出现为解决Web数据挖掘的难题带来了机会。由于XML能够使不同来源的结构化的数据很容易地结合在一起,因而使搜索多样的不兼容的数据库能够成为可能,从而为解决Web数据挖掘难题带来了希望。XML的扩展性和灵活性允许XML描述不同种类应用软件中的数据,从而能描述搜集的Web页中的数据记录。同时,由于基于XML的数据是自我描述的,数据不需要有内部描述就能被交换和处理。作为表示结构化数据的一个工业标准,XML为组织、软件开发者、 Web站点和终端使用者提供了许多有利条件。相信在以后,随着XML作为在Web上交换数据的一种标准方式的出现,面向Web的数据挖掘将会变得非常轻松。

多语言网站开发 不完全技术分析收录

mikel阅读(726)

转自:http://www.cnbruce.com/blog/showlog.asp?cat_id=27&log_id=691
语言是信息传播的主要障碍。
多语言网站,顾名思义就是能够以多种语言(而不是单种语言)为用户提供信息服务,让使用不同语言的用户都能够从同个网站获得内容相同的信息。
多语言网站实现方案
1,静态:就是为每种语言分别准备一套页面文件,要么通过文件后缀名来区分不同语言,要么通过子目录来区分不同语言。
例如对于首页文件index_en.htm提供英语界面,index_gb.htm提供简体中文界面,index_big.htm提供繁体中文界面,或者是 en/index.htm提供英语界面,gb/index.htm提供简体中文界面,big/index.htm提供繁体中文界面,一旦用户选择了需要的语言后,自动跳转到相应的页面,首页以下其他链接也是按照同样方式处理。从维护的角度来看,通过子目录比通过文件后缀名来区分不同语言版本显得要简单明了。
2,动态:站点内所有页面文件都是动态页面文件(PHP,ASP等)而不是静态页面文件,在需要输出语言文字的地方统一采用语言变量来表示,这些语言变量可以根据用户选择不同的语言赋予不同的值,从而能够实现在不同的语言环境下输出不同的文字。
例如:语言变量ln_name,当用户选择的语言是英语时赋值为“Name”,当用户选择的语言是简体中文时赋值为“姓名”,这样就可以适应不同语言时的输出。
采用静态方式的优点是页面直接输出到客户端,不需要在服务器上运行,占用服务器的资源比较少,系统能够支持的并发连接数较多,缺点是要为每种语言制作一套页面文件,很多内容即使是和语言无关的也要分不同语言来存储,因此占用的存储空间较多。
采用动态方式和静态方式的优缺点正好相反,它的优点是动态页面文件只有一套,不同语言的文字使用语言变量来存储,和语言无关的内容只存储一份,占用的存储空间较少,并且扩展新语言比较容易,缺点需要在服务器上运行,然后把结果输入到客户端,占用服务器的资源比较多,系统能够支持的并发连接数较少。
动态数据存贮涉及的一些技术问题
由于现在网站上动态应用日益增多,相当多的网站还会使用文件或者数据库来存储应用信息,因此如果文件或者数据库中存储的内容与语言相关时,还需要特别注意。对于存储在数据库中信息,可以采取以下几种方式支持多语言:
1,在数据库级别支持多语言:为每种语言建立独立的数据库,不同语言的用户操作不同的数据库。
2,在表级别支持多语言:为每种语言建立独立的表,不同语言的用户操作不同的表,但是它们在同一个数据库中。
3,在字段级别支持多语言:在同一个表中为每种语言建立独立的字段,不同语言的用户操作不同的字段,它们在同一个表中。
由于数据库中有大量的信息(如标志,编码,数字等)是用于内部处理使用的,与语言无关的,因此在数据库级别支持多语言会导致空间的极大浪费,在字段级别支持多语言最大的问题是一旦需要支持新的语言,由于需要修改表结构,维护起来非常麻烦,可扩展性不好。
相比之下,在表级别支持多语言比较好,因为并不是所有的表都需要支持多语言,对于与语言无关的表,不同语言的用户共用一套,那些和语言相关的表根据支持语言的种类来建立,不同语言的用户存取访问不同的表格。这样使得维护简单,节省了存储空间,即使是扩展起来也比较方便,只要把需要支持多语言的表,多建立一套即可。
还需要注意的问题是:有些表中某些字段是不同语言版本的表共享的(例如库存量),由于各种语言的表之间的相对独立性,使得数据共享有些困难。解决的方法有两个:
1,不同语言的表的共享字段同步:也就是说,只要修改了其中一个表的共享字段,其他语言表中该字段也作相应改变,实际上当不同语言的用户同时访问时处理还是比较麻烦的,并且扩充新语言时修改工作比较大。
2,增加一个新的表:把所有语言共享的字段(例如货物编号,产地编码等)全部放在这个表,支持多语言的表只存放与各种语言相关的字段。不同语言的用户在使用数据库时,需要操作两个数据表。
比较而言,第二种方法比较简单,并且效率比较高,维护也比较方便。
应用字符集的选择
一个定位于不同语言国家的企业网站势必需要提供多种语言版本的产品和销售信息来满足其世界各地使用不同语言的客户和合作伙伴,其中包括法语、德语、意大利语、葡萄牙语、西班牙语、阿拉伯语等等。但有一个问题却极易被网站设计者们所忽略。这就是网站的字符集设置问题。
一般我们使用的是简体中文(GB2312)字符集,而对多语言网站来说,中文字符集却可能会使你辛辛苦苦的努力功亏一篑。原因很简单:就是这个毫不起眼的小小字符集在作怪。
计算机应用领域中存在着几十种互不相同的字符集,而不同语言客户在浏览不同语言网页时,往往会因为相互间所使用字符集无法兼容而出现乱码情况。我们在浏览国外一些网站时,往往也会出现为了能正常地看到网站上的信息而不得不在各种字符集之间来回切换的情况。
试想一下:如果一个网站提供了中,英,法,德等多种语言版本的内容,内容全之又全,设计美仑美奂。我们在中文编码环境下浏览这些非中文版本的页面觉得非常完美,现在一个法国客户对你的产品发生了兴趣,当他进到法语版面一看—乱码多多,甚至可能整个版面都一塌里糊涂。你的网站再下大工夫又有什么意义呢?
所以对提供了多语言版本的网站来说,Unicode字符集应该是最理想的选择。它是一种双字节编码机制的字符集,不管是东方文字还是西方文字,在 Unicode中一律用两个字节来表示,因而至少可以定义65536个不同的字符,几乎可以涵盖世界上目前所有通用的语言的每一种字符。 所以在设计和开发多语言网站时,一定要注意先把非中文页面的字符集定义为“utf-8”格式。
这一步非常重要,原因在于若等页面做好之后再更改字符集设置,可说是一件非常非常吃力不讨好的工作,有时候甚至可能需要从头再来,重新输入网站的文字内容。
HTML中的META标签:

不写,根据浏览器默认字符集显示
charset=gb2312 简体中文
charset=big5 繁体中文
charset=EUC_KR 韩语
charset=Shift_JIS 或 EUC_JP 日语
charset= KOI8-R / Windows-1251 俄语
charset=iso-8859-1 西欧语系(荷兰语,英语,法语,德语,意大利语,挪威语,葡萄牙语,瑞士语.等十八种语言)http://www.microsoft.com/
charset=iso-8859-2 中欧语系
charset=iso-8859-5 斯拉夫语系(保加利亚语,Byelorussian语,马其顿语,俄语,塞尔维亚语,乌克兰语等)
charset=uft-8 unicode多语言
ASP与脚本引擎页码的概念
由于我们传统使用的内码像Big5,GB2312与unicode并不是一一对应,故两者之间的转换要靠codepage(页码)来实现
<%@ Language=VBScript CodePage=xxx%>
不写,根据服务器端解析引擎默认代码页自动解析并返回浏览器。
如果制作的网页脚本与WEB服务端的默认代码页不同,则必须指明代码页:
codepage=936 简体中文GBK
codepage=950 繁体中文BIG5
codepage=437 美国/加拿大英语
codepage=932 日文
codepage=949 韩文
codepage=866 俄文
codepage=65001 unicode UFT-8

ASP国际化多语言详细方案

mikel阅读(673)

1.ASP部分
a.建立语言包
1.在各个子系统建立”语言包”目录 ,
如BBS–> language –>Simplified
—>Traditional
—>English
2 为每个ASP,js,HTC 建立语言文件,如ACMBBStopic.asp.lang ,treeview.htc.lang ,
用来存放语言全局变量。
如目录LanguageEnglish ACMBBSShow.asp.lang
Public Const LangRollway=”reverse roll”
Public Const LangInvaildUser=”invaild user”
Public Const LangMailbox=”mail box”
Public Const LangSysSetup=”system setup”
Public Const LangACMBBS=”Acer BBS”
Public Const LangBulltn=”Acer bulltin”
Public Const LangPersnSetup=”personal setting”
Public Const LangPublicTools=”Public Tools”
如目录Language Simplified ACMBBSShow.asp.lang
Public Const LangRollway=”反向滚动”
Public Const LangInvaildUser=”非法用户”
Public Const LangMailbox=”邮件资料夹”
Public Const LangSysSetup=”系统设置”
Public Const LangACMBBS=”明碁网咖”
Public Const LangBulltn=”公告栏”
Public Const LangPersnSetup=”个人设定”
Public Const LangPublicTools=”群组工具”
语言全局变量命名规则;
必须是VBscript 变量定义方式 Public Const
变量名为 : “Lang” + Message Descption
b. 设定Global.asa
SUB Session_OnStart
Session.CODEPAGE=”1252″ '1252En '950繁体 '936简体
Session.Contents(“Language”)=”EngLish” 'EngLish 'Traditional 'Simplified
Session.Contents(“StrCharset”)=”big5″ 'iso-8859-1 'big5 'gb2312
End Sub
c. 引用语言包
1.建立 BBS–> language –>script 目录, IncludeLang.vbs
2.在各个asp,js,HTC头部

<% call IncludeLangFile("acmMainPageshow.asp.lang",Session.Contents("Language"))%>
3.使用思想
o 将 *.lang 等语言包用Function GetFileContents 读到变量中,
o 使用vbscript中EXECUTE方法在Server执行
IncludeLang.vbs 内容如下
'//'*********************************************************
'// ' Purpose: open include 文件
'// ' Inputs: strIncludeFile 路径
'// ' Returns: All Text
'//'*********************************************************
Function GetFileContents(strIncludeFile)
On Error Resume Next
Dim objFSO
Dim objText
Dim strPage
Set objFSO = Server.CreateObject(“Scripting.FileSystemObject”)
Set objText = objFSO.OpenTextFile(Server.MapPath(strIncludeFile))
GetFileContents= objText.ReadAll
objText.Close
Set objText = Nothing
Set objFSO = Nothing
IF Err Then
Response.Write “Error open this language package file<<" & strIncludeFile & ">>!”
Response.End
END IF
End Function
'//'*********************************************************
'// ' Purpose: 动态 include 文件
'// ' Inputs: strIncludeFile 路径,语言种类
'// ' Returns: 执行变量到全局变量
'//'*********************************************************
Function IncludeLangFile(StrFileName,Language)
On Error Resume Next
dim StrLangPackagePath
dim StrLanguagePath
StrLanguagePath=Language
StrLangPackagePath=”./Language/” & StrLanguagePath & “/” & StrFileName
Execute(GetFileContents(StrLangPackagePath))
IF Err Then
Response.Write “Error Include this language package file<<" & strIncludeFile & ">>! check the file's syntax”
Response.End
END IF
End Function
2.图片部分
为带有汉字图片建立 BBS–> language –>simplified–>Image
—>traditional–>Image
—>English –>Image
动态Include

3.COM部分
使用resource file 控制语言版本,由系统自动判断语言版本
注意: resource file 简体字码必须在简体机器输入,繁体字码必须在繁体机器输入
4.其他
多语言版本参考规则﹕
1.英文翻译长度尽量与汉语长度相当。
2.要符合各个版本的语言习惯。
3.英文版中Title ,text标签文本﹐按钮文本﹐select option 中英文单词 首字母大写,但
介词﹐连词 ,冠词 使用小写。
4. 英文版中缩写全部使用大写。
5. 英文版中check ,radio ,英文首字母大写.
6. 英文版中状态信息使用小写。

Kigg - Building a Digg Clone with ASP.NET MVC

mikel阅读(510)

http://dotnetslackers.com/articles/aspnet/KiggBuildingADiggCloneWithASPNETMVC1.aspx
http://weblogs.ASP.NET/scottgu/archive/2008/03/28/march-28th-links-asp-net-asp-net-ajax-asp-net-mvc-visual-studio-silverlight-net.aspx

Learning Cairngorm

mikel阅读(723)

Posted At : February 16, 2007 12:17 PM | Posted By : Jeffry Houser
Related Categories: Flex,Professional
In my previous post I talked about some of my experiences while trying to learn Cairngorm. This post extends on those experiences, as I continue to read Steve Webster's series of articles on the framework.
Getting the Cairngorm Store to work
Part three of Steven's series finally starts to get some meat. He goes through the example of how to use the Model Locator pattern within the Cairngorm store application. The Cairngorm store is a modification of The Flex store. The Flex store was designed to showcase features of Flex. The Cairngorm Store is just The Flex Store rebuilt to demonstrate how to build apps using Cairngorm. This article was a bit lost on me without reviewing the code. I think it's time to download the Cairngorm 2.1 Store and see if I can get it running.
I downloaded the store zip file, create a new Flex Builder project and pointed it to that directory. 8 errors exist right off the bat. After a look at a few of the errors, it seems the store download doesn't contain the Cairngorm framework. So, I grab the framework and unzip it into the same directory. The framework tries to overwrite some of my eclipse property files. I declined that.
Seven errors went away, a new one came up, and one stayed constant. This is progress.
com.adobe.cairngorm.IServiceLocator.as throws an error on line 92. 1046: Type was not found or was not a compile tome constant: DataService. A function's return type is set to DataService. mx.data.DataService is properly imported in this component. I am not the only one with these errors. I discovered the solution on Flex Coders. You must add the cairngorm.swc file to the class path.
I tried that and had no more errors, the Cairngorm store is able to compile and run. Another hurdle down. Unfortunately, we aren't out of the woods yet.
So, where are my Products?
When loading the app, the products are not found. I figure there is a path error somewhere. How do I Debug this?
I started with the main.mxml. OnCreationComplete, a Cairngorm event is fired named “EVENT_GET_PRODUCTS”). I forget how, but I ended up in com/adobe/cairngorm/samples/control/shopcontroller.as. I think this defines what happens when events get fired. When the EVENT_GET_PRODUCTS is fired the GetPRoductsCommand is … Well, I dunno, but I opened that file next. The execute method triggers a getProducts method in ProductDelegate. ProductDelegate calls “GetRemoteObject” for productService.
(Note: In Flex Builder a control click will open the source code on the object if it is available. I used this a lot to try to figure out what was being called and where )
I'm guessing that at this point that my remoteObject is incorrect and the productService is somehow pointed at the wrong place. I had Services.mxml opened (but I'm not sure why) and I think I found the problem there. All services are defined here as RemoteObjects. The RemoteObjects specify a destination. The RemoteObject class will only work with Flex Data Services. The destination attribute points to an entry in the services-config.xml.
I don't have Flex Data Services installed. This store is in serious need of some documentation, or at least a readme file. I'm thinking I can replace the RemoteObject with some other form of data retrieval, but, then I realize I don't have data anywhere. There is some shipping and state information in XML documents, but no products.
What Next?
Now I start doing some digging into other directories. I discover that the Java code is included in the application. Poking through, I discovered that the Java Code is not accessing a database or external datasource. It's just manually populating the Value Objects and sending them back.
I bet the backend could be rewritten in ColdFusion. And that is my plan for part 3.
In the last part of this series, I spoke about how I was going to see if I could get the Cairngorm store working from ColdFusion instead of Java. I was successful. The exercise, unfortunately, did not move along my understanding of Cairngorm. However, it did teach me a lot about ColdFusion and Flex interrelate. There will come a day where I'm glad for this experience.
Turning Java Classes into ColdFusion Components
The first thing I did was to convert all the java classes into ColdFusion components. The java components are in “WEB-INF\com\adobe\cairngorm\samples\store\*”.
I decided, for simplicity, to create my CFCs in the root directory of the Cairngorm store app, instead of in a subdirectory structure. You do not have to do that to use ColdFusion with Flex.
The first class I migrated was CreditCardDelegate. This contains a single function, validateCreditCard. It doesn't look like an credit card validation is done in this method, it just picks a random number. Half the time it will be validated, and half the time it won't. It's not real world, but for proof of principle purposes it suffices. The java class used Math.random to pick the random number. I used ColdFusion's function RandRange.
The next file was the ProductDelegate. It seems to me that a delegate is akin to service objects used commonly by ColdFusion developers. The ProductDelegate has a single method, getproducts. It returns a list type, which is a bit problematic. The Java List is an interface, with other types mapping to it. In the Data Access Object, the Linked List class is used. ColdFusion doesn't have a parallel. At first I was going to use a query, but eventually decided upon using an Array of value objects. The Java version of ProductDelegate does not create an instance of the ProductDAO inside it. This is something I changed in the CFC, although I'm not sure if it was an improvement, but I don't want to go back and change it.
The Java version had an abstract class named DAO. I didn't bother to convert this.
ColdFusion and Java Differences
Next there is a ProductDAO.java file. This is the data access object layer. The Java version creates a LinkedList of product value objects. The ColdFusion version creates an Array of product value objects. In the Java code, it looked like an instance variable was created (products) and then never used again. This was a result of my inexperience with Java. In ColdFusion, there is no distinction between variable definition and variable assignment. The variable is defined as a private instance variable:
private List products = new LinkedList();
And then later reinitialized in a method:
products = new LinkedList();
I mistook the second for creating an function local variable of the same name as the instance variable. It's not doing that, though. It is just re-initting it. The DAO does not access a database, local storage, an XML file, or web service to get it's data. It's all hard coded into the component. You wouldn't want to do this in the real world, but for the proof-of-principle-ness of this app, it fine.
I took each Java code block, like this:
ProductVO product1 = new ProductVO();
product1.setId( 1 );
product1.setName( “USB Watch” );
product1.setDescription( “So, you need to tell the time of…” );
product1.setPrice( 129.99f );
product1.setImage( “assets/products/usbwatch.jpg” );
product1.setThumbnail( “assets/products/usbwatch_sm.jpg” );
products.add( product1 );
And turned it into CF code, like this:


product1.setId( 1 );
product1.setName( “USB Watch” );
product1.setDescription( “So, you need to tell the time of…” );
product1.setPrice( 129.99 );
product1.setImage( “assets/products/usbwatch.jpg” );
product1.setThumbnail( “assets/products/usbwatch_sm.jpg” );
ArrayAppend(products, product1 );

All the vars went at the top of the method, of course. Once the Value Object is created, we just call the set methods to populate it with data. I copied most of the code from Java to ColdFusion with few . I removed the 'f' at the end of price. This most likely it stood for 'float', AKA decimal numbers. The only change of the code block is in the last line. In Java, the code was being added to a link list. In ColdFusion I'm using ArrayAppend.
The Product Value Object
The product value object was simple to convert from a code standpoint. However, getting it to work with Flex was a bit tricker. Flex and ColdFusion are very finicky on how CFCs will be automatically converted to ActionScript objects. Before getting into ActionScript, first, I'll discuss the CF side of things.
There are six instance variables in the ProductVO component. An id, name, description, price, image, and thumbnail. I recreated all of them in ColdFusion. The Java code created the instance variables as private. With ColdFusion code, I had to put them in the this scope, and define the components using the cfproperty tag.
A bunch of get and set methods were in the Java version of the product value object. I wasn't sure how closely the CFC and AS files had to be related, so I converted them all from Java to CF.
The Java method had two methods, toString and equals that ColdFusion would not let me convert. You cannot create methods that have the same name as as reserved words in CF. toString and equals are the name of generic Java methods, and ColdFusion does not allow you to create methods that are similar to names of built in functions. Even though toString and equals are not built in functions, CF still throws the error. With no other alternative, I left those two methods out.
I tested my components with this code:

MyObject = CreateObject('component','productdelegate');


Once I got everything the CFCs working, I moved back to the Flex code.
Defining the Services
In theory, all you need to do at this point is to tell the remoteObject tags to point at the ColdFusion code, not the Java code. Open up com/adobe/cairngorm/samples/store/business/services.mxml. This is the file that defines the services your application uses. You'll see one remoteObject for the productService and one for the creditCardService.




We could create those destinations in ColdFusion's services-config.xml file, but I instead chose to use the default ColdFusion destination. Comment out the previous lines and replace them with these:




You'll have to modify the source attribute to with the path to your remote objects. I was hoping that after this, I'd be good to go. Unfortunately that was not the case. It would work with only this change. I was wrong. First, I forgot to add the services-config.xml to my compiler settings. In Flex Builder, bring up properties on your project, select Flex Compiler, and add this compiler argument:
-services C:\CFusionMX7\wwwroot\WEB-INF\flex\services-config.xml
Everything still wasn't working kosher. Next, open up the ActionScript value object (com/adobe/cairngorm/samples/vo/ProductVO.as). Find this line:
[RemoteClass(alias=”com.adobe.cairngorm.samples.store.vo.ProductVO”)]
And change it to point to your CFC:
[RemoteClass(alias=”htdocs.Experiments.CairngormStore.ProductVO”)]
If you built your CFC object in the same place as the Java object, you may not need to change this line.
I tested the code and it still wasn't working. Ben Forta has a great post about gotchas when doing this. make sure that the instance variables are identical in the AS file and ColdFusion file. They must also be in identical order. Check! Use full paths to the CFCs. Check! Specify RemoteClass in the AS file. Check! What's left? The answer is case sensitivity.
You want to be very careful about the case sensitivity in your paths. My CF code worked fine without case sensitivity, but Flex was being problematic. Once I addressed the case sensitive issue, I was able to get a proof of principle template working.
But within the context of the cairgorm store, Something was still wrong. I opened up the com/adobe/cairngorm/samples/store/command/GetProductsCommand.as file. I believe the framework must look for this file when invoking the GetProductsEvent.EVENT_GET_PRODUCTS event, since I could not find it explicitly called anywhere. If the fault event is getting called, you'll see the message “Products could not be retrieved” when loading the file. This means something is wrong with your remoteObject configuration.
However, if you get no errors, but nothing is happening then something else must be wrong. or if you see other error messages, something else must be wrong. During the course of my development I experienced both situations. First I added a quick Alert to the result function to be sure that the results are being returned properly:
Alert.show( “Products retrieved!” );
That helped me verify that the result method was indeed firing. There was one line of ActionScript in the result method that I didn't understand:
var products : ICollectionView = ICollectionView( event.result );
This line creates a product variable of ICollectionView, and calls the ICollectionView constructor with the 'event.result' as an argument. Unfortunately, ICollectionView is an interface and does not appear to have a constructor. This line was throwing errors.
After some digging I found that an ArrayCollection inherits the ICollectionView methods through the ListCollectionView class. All code written against the ICollectionView interface should also work against an ArrayCollection. I replaced the ICollectionView line above with these two:
var products : ArrayCollection = new ArrayCollection ();
products.source = event.result as Array;
And bingo, everything started working.
Getting it set up
I'm not sure how much of this code I'm allowed to distribute, but my code changes, along with the Cairngorm Store and Cairngorm framework are attached to this post.
This is what you have to do to get it working:
1. Download the file and unzip it to a web accessible directory. Create a Flex builder project pointed at that directory.
2. Add bin/Cairngorm.swc to your Library path.
3. Make sure that Services compiler argument is pointed to the services-config.xml for Flex.
4. Open up services.mxml and change the attributes to point to the CFCs. Watch your case sensitivity
5. Open up ProductVO.as and make sure that the RemoteClass directive properly points to the location of ProductVO. Watch your case sensitivity here too.
6. Build and run your project.
Where to Next
I did notice that I couldn't complete an order in this system because the credit card validation was failing. But, it looks like CC Validation is implemented as a crap-shoot. I either didn't try enough times or have a bug in the CreditCardDelegate CFC.
I'm wondering how the value objects that Cairngorm uses will work with ColdFusion Queries, or if it's better to run a query in CF, populate an array of Value Objects, and return that array. I'll have to do tests with this in the future.
To date, I have an understanding of some parts of Cairngorm, but I do not understand how it all comes together. It's time for me to go back to reading through Steven's articles, so the next article of this series will lean back towards them.
I can't believe it has almost 8 months since my last installment in the Learning Cairngorm series. Life got in the way, and I have a lot of experience with Cairngorm now compared to when I wrote the first three parts. In the last part, I spoke a bit about getting the Cairngorm Store to work with ColdFusion. In this part, I'm going to switch back to Steve Webster's collection of Cairngorm articles and talk a bit more about some of the additional design patterns related to Cairngorm. I'll summarize Part 4 of Steven's Article and intersperse it with some of my own experience.
User Gestures have Changed
Applications have grown in complexity these days and there are many different ways that the user will need to interact with your application. Every opportunity that a user has to interact with your applications is a gesture. In the traditional HTML interface world, each gesture requires the loading of a new page. AJAX has changed this somewhat, and Flex has changed it a lot. Sorting a data grid or filtering a group of data can all be done without a round trip to the server? This is part of what leads to a rich experience for the user. A benefit of Cairngorm is that all gestures, whether or not a round trip to the server is needed, can be treated exactly the same. No matter what is going on, we have a standard set approach, and can use that to more easily Debug potential problems.
Events, Commands, Controllers, oh my
First, we create a CairngormEvent class for each user gesture. The event class extends a CairngormEvent. It will contain a static variable with the name of the event. It can also contain instance variables, if those are needed to complete the event actions. This might be a sample CairngormEvent class:
package com.tempApp.event{
import flash.events.Event;
import com.adobe.cairngorm.control.CairngormEvent;
public class MyCustomEvent extends CairngormEvent{
public static var EVENT_ACTION : String = “actionname”
[Instance data here]
public function MyCustomEvent ([Instance data as arguments]){
[Set Instance Data Here]
super(EVENT_ACTION);
}
/**
* Override the inherited clone() method, but don't return any state.
*/
override public function clone() : Event{
return new MyCustomEvent ( );
}
}
}
This is a simple sample event class, but very powerful. The event class ties into a command class is the one that does the work. A command is a pattern which always has a single point of entry: an execute method. By creating a generic execute method on every command, the Cairngorm framework can generically run any command in response to an event. This might be a sample command class:
package com.tempApp.command{
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.commands.ICommand;
import com.tempApp.event. MyCustomEvent
public class MyCustomCommand implements ICommand{
public function execute(event:CairngormEvent):void{
var e : MyCustomEvent = event as MyCustomEvent;
[Do stuff here]
}
}
}
When Cairngorm “sees” the Event, how does it know to relate it to a command class? A third class, a front controller, ties the two together:
package com.tempApp.control{
import com.adobe.cairngorm.control.FrontController;
import com.tempApp.event.*;
import com.tempApp.command.*;
public class AssemblerController extends FrontController{
public function AssemblerController(){
initialiseCommands();
}
public function initialiseCommands() : void{
addCommand(MyCustomEvent. EVENT_ACTION, MyCustomCommand );
}
}
}
I had one of those “hallway conversations” with some folks at 360Flex and a few people claim that a front controller has no place in a Cairngorm and is just overkill. I haven't had time to think about that, or look into alternatives to the approach, but I thought it'd be something worth throwing out there for those listening. If you have thoughts on this, comment and tell me why a controller has no place in Cairngorm.
Tying them all together
We have three elements at play, here:
* Start with an event (AKA User Gesture).
* The Event goes to a controller and figures out what command to execute.
* Execute the Command
There are two missing bookends to our list list. First, what exactly does “Start with an event mean”? How do we tell the Cairngorm Framework or Flex that an event has taken place? Cairngorm has a special event dispatcher that tells the framework something happened that it needs to respond to. A sample line of code would be something like this:
import com.adobe.cairngorm.control.CairngormEventDispatcher;
import com.tempApp.event.MyCustomEvent;
CairngormEventDispatcher.getInstance().dispatchEvent( new MyCustomEvent ([optional arguments]) );
That is our first bookend. We dispatch our custom event, which looks at the controller, and executes the command. Holding up the stack, the command will then update the ModelLocator, which through the miracle of data binding will update relevant areas of the application. Our updated path list is like this:
* Dispatch a custom event (AKA User Gesture).
* The Event goes to a controller and figures out what command to execute.
* Execute the Command
* Command updates Model data, which updates the user views
Conclusions
This took a look at the architecture of a Cairngorm system events. We did not deal with retrieving data from a remote source, though. I'll look into that in the next part of the series. Now that I'm in a routine of blogging twice a week (Tuesday and Thursday morning) the next part of the series should come much quicker than this one.
Note: The alias link to this post is now working. I had to refresh the blog cache for the date to update. Not sure how this will affect aggregators
In the fifth part of this series on Cairngorm, I'm going to talk about how Cairngorm handles remote data calls. This, once again, is following along with the fifth part of Steven Webster's Adobe Center Articles.
A Recap
In the last article I wrote in this series I spoke about how Cairngorm handles user gestures. A user gesture is anything that the user will do to interact with your application. This is the general procedure:
* Dispatch a custom event (AKA User Gesture).
* The Event goes to a controller and figures out what command to execute.
* Execute the Command
* Command updates Model data, which updates the user views
We are missing is getting live data, probably from a database, using some intermediary software like ColdFusion (my choice) or PHP. (Or Java or Ruby, or .NET, or whatever).
3 Types of Services, one Location
There are three ways to get data from within Flex. You can use an HTTPService, a WebService, or a RemoteObject. Based on their names, it is probably pretty obvious what each tag does (Right?). My preferred method is RemoteObject because it ties into ColdFusion so nicely, but I've also done some work with HTTPService for integrating with remote systems beyond my control. Cairngorm uses a ServiceLocator to help you find services. This is, conceptually, not much different than a Model Locator. It is a singleton class that allows you to store your services in a central location, and access them anywhere from the application. This would be a sample ServiceLocator:





I have three (fake) services, one of each type. If you've used any of these tags before, you'll notice that I left out the 'result' and 'fault' events. Result and Fault methods are known as responder methods. They get called when the remote service sends data back to Flex. Cairngorm puts the responder methods in the Command, and calls the Service using a Delegate.
Delegates
A Delegate is a class that does nothing but call the service. Here is a simple example:
package com.tempApp.fooDelegate{
public class MyCustomDelegate{
private var responder : IResponder;
private var service : Object;
public function MyCustomDelegate ( responder : IResponder )
{
this.service = ServiceLocator.getInstance().getRemoteObject( ” sampleRemoteObject ” );
this.responder = responder;
}
}
public function getFoo ([foo arguments]):void{
var call : Object = service.getFoo([foo arguments]);
call.addResponder(responder);
}
}
Cairngorm keeps the delegates and the services file in a business folder. I guess this ties into “Business Logic”. Really this is just a layer to reach the backend business logic, though. I don't do a lot of work in the delegates. They just make calls. To me it makes sense to do data parsing in the responder, and as such in the command. ( Although this approach has been contested ). We can modify our command, Part 4, to handle make the delegate call.
package com.tempApp.command{
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.commands.ICommand;
import com.tempApp.event. MyCustomEvent
import com.tempApp.business. MyCustomDelegate
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
public class MyCustomCommand implements ICommand
, IResponder{
public function execute(event:CairngormEvent):void{
var e : MyCustomEvent = event as MyCustomEvent;
var delegate : MyCustomDelegate = new MyCustomDelegate ( this );
delegate.getFoo([instance variables from event]);
}
public function result( event : ResultEvent) : void
{
[do stuff with results]
}
public function fault( event : FaultEvent ) : void
{
[Do error processing]
}
}
}
The first change is that the code implements an IResponder interface in addition to the ICommand. The second change is that the execute method actually creates an instance of the delegate (passing in the instance of this object), and calls a method on the delegate. This modified class also includes a result event and a fault event. These are the responder methods called by the service when results are returned. Most likely the result event will be performing some actions on the ModelLocator, which will change some other aspect of the app via data binding.
A recap of Today
So, our updated process is this:
* Dispatch a custom event (AKA User Gesture).
* The Event goes to a controller and figures out what command to execute.
* Execute the Command
* Command creates instance of Delegate.
* Delegate gets Service Object from Service Locator
* Delegate calls the Service Object Method
* Remote Service does stuff and sends data back to the respond methods in the Command
* Command updates Model data, which updates the user views
A few final thoughts
I've spoken to some people who claim that Cairngorm must use a one-to-one ratio with Events, Commands, and Delegates. However, I do not implement code in such a manner. It seems to add an extra layer of complexity. I often have one delegate per service, and that delegate is used by many commands. Since the delegate does not do anything but call the remote service, it's a really small file. I can easily deal with multiple remote method calls in the same file.
It's a bit late, so if this is weird, it's because I'm proof-reading while tired.
On Friday (Tomorrow when you read this), I plan to start releasing the collection of articles from my CF101 column over at sys-con. They should be easy lunch time reading.
There was a presentation a while ago talking about the different frameworks in Flex. The presenters speak ill of Cairngorm's use of Singletons (It's about 20 minutes in, but I strongly recommend watching the whole thing if you haven't seen it yet). I thought it would be a worthy discussion to discuss the complaints with Singletons, how they relate to Cairngorm, and how I deal with this when building Cairngorm applications.
What is a Singleton
Singleton is a design pattern. It is a class that is only instantiated once. Only a single instance of the singleton object will exist. The most common use of singleton that I've seen is as a location for global data. Sometimes Singletons are used in frameworks as a single point of entry into the framework APIs.
In the ColdFusion world, the application or session scope might be considered a singleton. In Cairngorm, the ModelLocator is a singleton. Using the Cairngorm paradigm, most components refer to the ModelLocator for global application data, figuring out what the state of the application is. I really like the way that the Cairngorm ModelLocator can be used in conjunction with ViewStacks and binding to display screens to the user.
Problems with Singletons
So, a Singleton is a class that is a global data store. Why is this bad? In no particular order:
* In most Cairngorm applications I've seen, all components are referencing the ModelLocator. That means these components are not portable to other projects because they are specifically tied to the application. You are creating dependencies and there is no loose coupling.
* If the components you're building are not stand alone, then it becomes complicated, if not impossible, to perform unit tests on the component. This can lead to more time in development.
* Flex, or more appropriately, ActionScript 3, does not have private constructors. As such workarounds are used to prevent multiple instances of the class from being created. In the grand scheme of thing, this is a minor issue.
* Unless you write code to “Destroy” / get rid of the stuff you are storing in the ModelLocator, it will hang out there for as long as your application is in use. In some cases this is fine. In others it can be wasteful. Loading and storing too much data could lead to memory issues.
How can I code avoid singleton problems in Cairngorm?
So, how can you write Cairngorm applications in such a way that they avoid the problems associated with singletons? Well, in reality, you can't. but, you can try to organize your application to minimize the use of the ModelLocator; which is what I Try to do:
* Top Level Application: The Top level application is my main.mxml file; the one with the Application (or WindowedApplication in AIR) root. I think it's a pretty safe bet that this will be tightly coupled with the application, and reuse on this will be rare. I'm completely fine with that. As such, it's perfectly fine for my main.mxml to reference the ModelLocator. The Main.mxml often contains a ViewStack of the Application screens, but not much else.
* Second Tier Components: The second tier components are the main screen containers. I'll generally have one of these components for each 'viewstack' index in the main application. I figure it is okay if these are tied tightly to the application, and therefore they can access the ModelLocator.
* Everything Else: The second tier components will be made up of plenty of other components (Most likely using composition). Any level below the second tier, I try to make as loosely coupled as possible. Instead to referencing global data in the ModelLocator, I'll exchange data using parameters and events. In an ideal world, I'd only have 3 layers of components, but realistically these can trickle down much further just 3 layers.
I've found that implementing this use of the ModelLocator has given me a good balance of using “Global Variables” with loosely coupled components.
I wasn't ever planning on adding another entry into my Cairngorm series, but this has been stewing in my idea pool for a while, and tonight I felt inspired. While you're reading this, don't forget about the upcoming DotComIt focus group. Flex Developer's of all levels are welcome to attend.

How do you learn Cairngorm? (Part 1)

mikel阅读(703)

Posted At : February 15, 2007 11:59 PM | Posted By : Jeffry Houser
Related Categories: Flex,Professional
I am trying to learn Cairngorm and am finding the resources severely lacking. I thought I'd document my experiences trying to learn Cairngorm with hopes someone will be able to tread the pass more easily than I.
Where do you go.
First off, where do you go to start reading about Cairngorm? Well, you can start at the Adobe Labs page on the framework. That will most likely lead you to Steven Webster's 6 part series on developing Cairngorm apps. Let's start with that series of articles.
Part 1 talks about frameworks in general, and gives a history of Cairngorm. It is a nice introduction and an easy read, but was unfortunately lacking any implementation details. It's not a complete waste of time if you're unfamiliar with frameworks.
Value Objects.
The second article starts to get a little meatier. How do you maintain state in a Rich Internet Application built with Flex? In a web app, you are trying to force state on a stateless system by using URL variables or cookies. With Flex, you are not dealing with a stateless client. The flash player can deal with state.
Steven comes up with an interesting way to describe state in an RIA. The state is the model (of Model View Controller). When you're accessing a shopping cart, or user object you shouldn't be accessing them stored on a web server somewhere. You should access this data stored as part of the client.
The next part of the article talks about the Value Object. A Value Object is a design pattern, where the object represents a single entity. That entity may be a product, a person, a company, an address, or anything you need. Steven says that these objects are now called Data Transfer Objects. Conceptually, they sound exactly like what most CF Developers call a Bean. You can check out this Blog entry for more info on Value Objects, Coldfusion, and Flex.
With Cairngorm you can use Value Objects to help easily keep the state on your server in sync with the state on your client. I can understand that, although the article doesn't go into enough code detail for me to understand how to implement this.
Model Locator.
The second part of the article ends off by explaining the model locator pattern. This is a brand new pattern designed strictly for Flex RIA apps. Steven explains that model locators don't apply to traditional web development or Java Development.
One powerful feature of Flex is data binding. When data changes, so does the display that uses the data. I got to admit it's pretty powerful. When developing Flex with lots of components and relationships between the components, you have a problem of how to find the component that needs the data. You could start at the top level application and work down to the data, like this:
mx.core.Application.application.storeView.textualList.productGrid
That will get the productGrid values from the textualList component which is in the storeView component. It can get to be pretty tedious. I can honestly say I've never used this approach in a Flex app, and I'm not sorry about it.
An alternate method is that you could pass lots of parameters in and out of your component. In the example above, the productList value would be a property in textualList, which would then be a property in storeView. You do a lot of coding to specify the properties and components. It seems like a waste of time since many components will do nothing other define the property and pass it's value up or down. Unfortunately, this is a mistake I've made.
The model locator design pattern addresses the problem of how to access disparate data buried within different components that don't have an easy link between them. It is a single component that components use to access data. For all data and binding there is a single entry point across your application. This does address the two problems above.
The model locator component of Cairngorm is implemented as a Singleton. A Singleton is a design pattern, where only a single instance of the object is created for your application.
Summary So, after reading the first two parts of this article, I can tell you that Cairngorm uses Value Objects and a Model Locator. I like both of those ideas, although do not yet understand how I put this knowledge into practice when building a Flex application. I will continue to write more as I learn more.

企业级Ajax与SOA结合 =用户驱动的IT

mikel阅读(982)

一直以来,SOA和Ajax对于整个IT业务而言意味着巨大的回报,同时,将这两种先进技术结合带了一种全新的基于Web的应用—也就是所谓的“丰富的企业级应用(Rich Enterprise Applications)”或REAs。
  REA不仅仅能够将Ajax与SOA的技术优势淋漓尽致的展现出来,更是在这个基础上提供一个先进的平台,通过授权最终用户以互动和整合的方式,有效提高产品生产效率,而这一应用方式是前所未有的。
  Ajax技术提供了一种基于浏览器的丰富互联网应用(Rich Internet Applications,RIA),它描述了一种运行在流览器中的全新 “桌面程序”互动式丰富应用。RIA应用不仅仅只是Ajax技术,同时还包括Flex,Flash,Java甚至微软的XAML等其他技术。就现有的企业应用看来,在技术标准以及采用率方面,Ajax将持续性的成为企业RIA应用技术的关键选择。正是因为如此,我们在本文中对RIA应用的相关讨论绝大部分都会是集中在Ajax。
  SOA,在相对于RIA应用而言,并不是作为一套技术,而是更多的强调一种架构风格,或是说基于松藕合原则,通过统一标准的“服务”而不是硬性关联的将应用软件连接到一起的架构体系。虽然很多时候我们在谈论服务和SOA都是处在同一背景之下,但其实这两者是不尽相同的。我们在这篇关于REA应用的讨论中就SOA服务更多的是强调其松藕合的特征,而对于一个SOA服务所使用的技术内容并未有所涉及。SOA服务可以是一个RSS源,一个数据库展现的XML到HTTP接口,甚至可以是一个第三方搜索引擎所提供的正式SOAP接口。
  Ajax + SOA = REA (丰富企业级应用)
  有效结合Ajax技术和SOA并进一步实现的丰富企业级应用产品能够直接赋能于最终用户,让其掌握强大的功能。之所以能出现这种情况的原因在于,REA应用会更多的与潜在的重要用户保持关联,增强用户内部的合理性,这也会对处于当前IT环境中的用户群体相当大的压力,从而促成了其实现。
  正因如此,REA应用对于未来的企业架构规划与设计将会产生非常重大的影响。其实,REA应用的影响在某些企业中已经是可以发现的,尤其是对于一些作为早期SOA实施的较大型企业而言,类似这样的应用已经在开始发挥作用。
  早期实施企业针对于“应用对应用整合”这一需求已经完成了一个或者两个甚至更多的SOA相关项目内容,只是他们还没有完全将这些新近完成的数据资产直接授权于他们的最终业务用户。正如我们都知道的,对于多数行业来说,收入方面的决定权大多掌握在这批最终用户手中。而所有关于最终用户以及 Ajax所能对SOA的支持在以往SOA应用项目中并未曾顾及到,那就是:为用户提供“最后一步”的业务功能。
REA所带来的企业级效益
  在当前的发展状况之下,已经有许多世界级REA应用的成功案例可供分享,结合这些示例能够有助于解释REA应用在企业架构规划和设计中的用途,效益以及所带来的重大影响。目前我们能看到的最为成熟的一次REA应用执行是Defense intelligence分析机构部门所采用的基于Ajax的“webtop”项目。每一个分析师从一个空白的webtop开始,创建一套以SOA服务为基础的信息资源以供使用。
  服务可以是由一些计划、预计的事件组成,如一些档案数据库中或是第三方新闻服务所提供或反应出来的即成事实和统计。许多可供使用的服务是从现有的整合数据资源中提炼出来可以直接为面向服务架构体系所使用的SOA型服务。其他的服务则是来自一些并非完全正式资源的“虚拟化”服务,这些资源可以是数据库,可以是EJB应用,可以是由两个或多个小粒度资源混合而成的“混合型服务(service mashups)”,这些混合型服务对于分析师而言比那些小粒度的单独资源更加有用。
  一旦服务被选定,将会以各种不同的方式进行个性化。例如,可以应用过滤器,改变或格式化显示区域……甚至是一些你所期望的Web2.0级别的应用,具体的数据记录或是项目也可以通过共享的社会化形态让其他用户在一个社区范围内使用。例如,分析师可以在webtop建立一个有期效的数据项,并将其显示给其他的分析师。很多服务还允许数据更新的同时可对原始资源进行更新,同时会通过webtop即时反应到其上各数据的同步显示。
  REA应用的快速实施
  前文所说到的这个示例是否也在另一个角度展现了REA应用所能提供的快速实施示例?首先我们得清楚,用户是处在一个驾驶人员的位置,他们手中握着这个异常强大的“交通工具”的方向盘。这种用户可授权性的REA应用对于各个行业中的雇员都是同样可行的,例如医疗病例卡管理人员,销售代表,呼叫中心工作人员,信贷分析师或是索赔理算人员。
  其次,在这个REA应用的示例中(几乎所有的REA应用都是如此),Ajax和SOA是紧密联系在一起的。很难确定究竟是SOA的原因引入了 Ajax还是说Ajax更多的让SOA深入到了企业的架构计划当中。或许这也取决于企业自身的优势以及对于实施时间曲线安排,通过Ajax和SOA展开具体的应用。可以确定的一点,将这两种技术有效的结合起来会是比任意一种技术单独使用产生更大的效用。
  还有非常重要的一点,千万不要错误的认为REA应用只是针对门户方面。反之,应该将REA应用作为一种没有传统门户服务的门户去考虑。当前的门户已经是作为企业信息的一个单一切入点,它们已经变成了一个太多太多信息所屯集的一个地方。REA应用作为门户形式的展现在另一方面的作用在于不仅仅让用户能够找到他们愿意去查找的信息,更能够将一些不相干的信息数据混合到一起并给予用户个性化的观点认识——这就是REA应用所带来的全新的以用户自身意识为驱动的整合应用。当用户共享这些特定的微小整合时,在本质上则是造就了整合效应的“长尾”发展。
  REA应用如何填补IT业务中用户驱动这一空缺
  但是正如你可能已经意识到的,在目前典型的企业架构中本来是存在着一些组件可以用来支持REA应用的,而这些组件却在传统应用中失去踪影。适当的服务粒度在整个企业架构应用中仍是一门艺术形式。将数据推向基于流览器的应用并非普遍,而“虚拟化”服务和“混合式服务”更是前所未闻。
  所有这些沟通都需要在符合底层服务所确定的可用服务政策的前提下安全实现,这也是对于各层次分布的用户群而言一种优雅的度量准则。
  我们千万不能忽视,当前大部分的企业并没有拥有一个属于自己的企业级Ajax开发团队,他们更多的只是在等待SOA项目能够在生产中发挥效用。他们需要一些支持可视化开发的工具,一些调试工具,一些从IDE所得的“表和按纽”的窗口式开发的代码重用工具。IDE还得是帮助他们创造一些轻量级代码以及能够在流览器中优化执行的。
  还有一些较小但同样重要的问题,如何解决门户网站的浏览器兼容问题,多语言支持问题,网页内易读性指引问题以及共存策略问题,等等。
  如上种种则是为什么Ajax和SOA会联手打造驱动性IT业务,当然你也可以如同本文中所称的那样称他们为REA应用对于未来企业架构规划和设计可能产生巨大影响的原因。从IT业务中REA应用型功能的最终用户需求可以明确的看到,新一代的企业架构将会无可避免的以用户驱动为前提。在未来的数年内,大部分的业务应用将作为REA应用的基础存在,IT部门 则是有责任为这方面需求安排计划。

程序设计介绍小结

mikel阅读(736)

前面简单的介绍了程序设计的相关知识,程序设计也就是用程序语言表达你自己的思维,所以重要的不是语言,而是你的思维,这个是现在程序设计教学中最大的误区,本书中将以语言和思维并重的方式来介绍Java语言,并培养你的逻辑思维。
程序设计的道路不是一帆风顺的,其中布满艰辛,所以如果你打算学习程序设计,那么要做好长期吃苦的准备,俗话说:“板凳要做十年冷”,要有这样的耐心和恒心才能把程序设计学会、学好。
当然如果基础不好,那么还想学习程序设计课程的话,将需要付出比一般人更多的努力才可以基本赶上一般人的水平,用句不恰当的话“出来混迟早要还的“,前面欠下的基础知识现在就是还的时候了。
关于工作,也简单的说一下,软件开发行业需要各种层次的人才,其实水平只要达到可以独立工作,也就能找到一份工作,但是要想找到一个不错的工作,而且以后还有良好的发展,需要的就是扎实的基础以及长期的努力。
后续讲解语言部分打算分成以下几大块来进行说明:
1、 计算机基础
计算机软件的基本概念、进制的相关知识、计算机内部的数据表达方式等。
2、 Java语言的简介。
注:我也不能免俗。
3、 Java开发环境的安装和配置。
介绍JDK、Eclipse的安装、配置以及使用。
4、 Java相关语法和程序逻辑。
以通俗的语言来介绍语法,深刻理解语法的作用和用途。
可能还会进行一些变更,本人保留最终的解释权,呵呵。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2252691