使用ExtJs开发MIS系统(1):基于ExtJs的MIS构架设计
2009-03-10 12:20
337 查看
1,引言
本系列文章的目标是讲述ExtJs开发MIS的一些设计思路和技巧,本文假定你已经了解ExtJs,熟悉ExtJs中的主要类且有较强的Js编程能力,缺乏的仅仅是应用的技巧。关于ExtJs的基本内容,请参阅ExtJs官
方网站、Google和园里的相关文章。文中中一些技巧和方法不限于ExtJs,在很多基于富客户端框架——例如SilverLight、Flex等的系
统设计中,都可以使用。
本系列主要包括以下内容:
基于ExtJs的MIS构架设计。
Js的动态加载。
使用数据库保存客户端状态。
轮询。
使用Action抽象客户端操作。
客户端MVC。
最后,如果还有精力的话,再写一些ExtJs性能方面的心得。
本文中的例子、代码等来源于真实的的项目,所以恕不能提供完整的代码下载,但会尽量详细的阐述设计思路,并给出关键的代码片段。
欢迎大家交流和指教。
2,客户端的“致富”之路
在SilverLight、Flex等富客户端框架出现以前,系统中通常由服务器负责Html、Css等的生成,也就是负责显示逻辑,客户端与服务器端的交互是按下图的样子:富客户端将显示逻辑从服务器端转移到客户端。这样服务器端仅仅负责业务逻辑的处理和运算,把处理的结果以纯数据的形式发送给客户端,然后客户端负责具体的显示和交互,这个过程可以通过下面这个图直观的看出来:
以下对图进行一些说明:
1,图中ExtJs即为客户端框架,当然也可以采用SilverLight等充当。
2,服务器给出的响应Response,也可以使用JSON等格式,Google就有自己的数据串行化格式:ProtocolBuffers。
3,服务器端关注的仅仅是业务逻辑,而不是数据的表现形式。所以服务器端的响应通常是和客户端无关的,客户端也可以采用WinForm、SilverLight甚至是其他服务等处理端。
4,
理论上讲,我们可以仅仅和ExtJs打交道,而不需要关心具体Html、Css、JavaScript等,然而实际上是不可能的,复杂操作的时候仍免不了
和DOM打交道,而ExtJs在这个时候也能开发提供很大便利。如果使用的SilverLight等其它的、基于浏览器端插件的框架,情况会好一些,但仍
然无法避免和DOM打交道。客户端框架任重而道远……
3,两个世界的对话
服务器和客户端通过Http协议进行交谈,对于一个典型的登录操作来说,客户端发送的Http请求如下(忽略Http头):POST/User.asmx/LoginHTTP/1.1
……
loginId=yuandong&password=mypassword
而服务器端给出的响应是:
HTTP/1.1200OK
……
<?xmlversion="1.0"encoding="utf-8"?>
<LoginResult>
<State>WrongPassword</State>
</LoginResult>
对于列表类型的数据,服务器给出类似以下的响应:
HTTP/1.1200OK
……
<?xmlversion="1.0"encoding="utf-8"?>
<Announcemnts>
<Announcement>
<Content>为方便专家使用……</Content>
<DateTime>2008/11/05</DateTime>
<ID>3</ID><State>Top</State>
<Title>关于新系统密码获取问题</Title>
<UserName>袁冬</UserName>
</Announcement>
<Announcement>
<Content>为适应三校区办公……</Content>
<DateTime>2008/10/16</DateTime>
<ID>1</ID><State>Top</State><Title>关于启用新版的说明</Title>
<UserName>用户A</UserName>
</Announcement>
</Announcemnts>
就像上一节提到的,以上请求和响应,完全是基于数据的,与显示方式无关。另一方面,以上类型的响应可以很容易的使用ExtJs的相关Reader类读取。当然使用JSON等方式传输数据也是可以的,ExtJs也提供了相关的读取类。
4,不是WebService的WebService
从服务器和客户端的通讯方式来看,只要服务器端能够在接收到请求后,给出符合格式的响应,就算OK。我们使用ASP.NetWebService的方式来组织服务器端代码,但不使用SOAP协议,所以叫“不是WebService的WebService”,呵呵。例如,用户相关的操作——包含同意用户协议、激活、登陆、退出登录等,我们组织为User.asmx,代码如下:
1:using……
18:
19:namespaceSrims.WebSite
20:{
21:///<summary>
22:///用户相关服务
23:///</summary>
24:[WebService(Namespace="http://srims.ouc.edu.cn/")]
25:[WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]
26:[ToolboxItem(false)]
27:[System.Web.Script.Services.ScriptService]
28:publicclassUserWebService:WebServiceBase
29:{
30:[WebMethod]
31:publicvoidAgreeLicence(stringloginID,stringpassword)
32:{
33:Database
34:.Experts
35:.Get(loginID,password)
36:.AgreeLicence(Database,UserIP);
37:}
38:
39:[WebMethod]
40:publicvoidActive(stringtoken)
41:{
42:Response.WriteXmlHead();
43:
44:Database
45:.Users
46:.Active(newGuid(token),UserIP)
47:.Show(Response);
48:}
49:
50:[WebMethod]
51:publicvoidLogin(stringloginID,stringpassword)
52:{
53:Response.WriteXmlHead();
54:Database
55:.Users
56:.Login(loginID,password,UserIP)
57:.Show(Response);
58:}
59:
60:[WebMethod]
61:publicvoidLogout()
62:{
63:GetUserLoginLog().Logout(Database);
64:}
65:
66:[WebMethod]
67:publicvoidGetExtClientState()
68:{
69:Response.AppendXmlHeader();
70:Response.Write(GetUser().ExtClientState);
71:}
72:
73:[WebMethod]
74:publicvoidSetExtClientState(stringkey,stringvalue)
75:{
76:GetUser().SetExtClientState(key,value,Database);
77:}
78:}
79:}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
根据以上代码,我们可以使用类似
样的链接方式来访问用户的登陆操作。之所以不使用SOAP协议,是因为要包装请求和响应的信息比较复杂,而且ExtJs本身对SOAP没有提供支持,需要
自行开发包装类,引入了不必要的复杂性,得不偿失。这里需要注意的是,如果想直接以POST和GET的方法调用WebService,需要对
web.config做一些设置,具体来说,就是system.web/webServices节点加入以下内容:
<protocols>
<addname="HttpGet"/>
<addname="HttpPost"/>
</protocols>
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
其实这里使用UrlRewrite更优雅一些,但是由于我们项目本身的一些限制,就不做修改了,有兴趣的朋友可以自己尝试。服务器端不是本文关注的交点,这里就不展开了,相关设计可以参考我的另一个系列文章:
5,客户端架构
客户端基本上使用Js编写,包含少量的Html代码,其它都是通过ExtJs生成。从结构上可以分为三层,最底层是ExtJs,然后是提供各种通用服务的CommonModules,最上面是提供专注于各个功能模块的FunctionModules。如下图:如图所示,CommonModules提供了Js动态加载、状态提供者、轮询、动作等通用功能,这些功能为上层的功能模块提供服务。
从文件夹的组织上也可以一些端倪。文件按照命名空间进行组织,直接位于JavaScript目录下的js适合具体项目无关的。Srims是
项目相关js的顶级命名空间,表示整个系统;用于Common
Modules的action.js、formLogin.js、load.js、login.js、main.js等,直接隶属于根命名空间,而
project,common等文件夹则是各个模块。以后的文章中着重讲解这些js。
整个系统中客户端仅有一个Html页面,也就是所谓的OAOP了。页面代码非常简单,仅仅是对Js、Css等文件的引用:
1:<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2:<htmlxmlns="http://www.w3.org/1999/xhtml">
3:<head>
4:<linkhref="/stylesheets/ext-all.css"rel="stylesheet"type="text/css"/>
5:<linkhref="/stylesheets/srims.css"rel="stylesheet"type="text/css"/>
6:<title>中国海洋大学XXXX管理系统</title>
7:</head>
8:<body>
9:<divid="DivWrapper">
10:<divid="DivLoading"style="text-align:center">
11:正在加载
12:<br/>
13:<imgalt="正在加载"src="images/index_loading.gif"/>
14:</div>
15:<divid="DivCopyRight">
16:SrimsV0.5中国海洋大学并行与分布式计算实验室Copyright©2008
<ahref='#'title="采用SSL加密的安全连接模式">安全模式</a>
17:</div>
18:<divid="DivBrowserRecommand">
19:推荐使用谷歌(Google)浏览器操作本系统(<ahref='http://www.google.com/chrome'
title="点击安装谷歌(Google)浏览器">点击安装</a>)
20:</div>
21:</div>
22:<scriptsrc="/javascript/ext-base.js"type="text/javascript">
23:</script>
24:<scriptsrc="/javascript/ext-all.js"type="text/javascript">
25:</script>
26:<scriptsrc="/javascript/menu/EditableItem.js"type="text/javascript">
27:</script>
28:<scriptsrc="/javascript/menu/RangeMenu.js"type="text/javascript">
29:</script>
30:<scriptsrc="/javascript/grid/GridFilters.js"type="text/javascript">
31:</script>
32:<scriptsrc="/javascript/grid/filter/Filter.js"type="text/javascript">
33:</script>
34:<scriptsrc="/javascript/grid/filter/StringFilter.js"type="text/javascript">
35:</script>
36:<scriptsrc="/javascript/grid/filter/DateFilter.js"type="text/javascript">
37:</script>
38:<scriptsrc="/javascript/grid/filter/ListFilter.js"type="text/javascript">
39:</script>
40:<scriptsrc="/javascript/grid/filter/NumericFilter.js"type="text/javascript">
41:</script>
42:<scriptsrc="/javascript/grid/filter/BooleanFilter.js"type="text/javascript">
43:</script>
44:<scriptsrc="/javascript/bool.js"type="text/javascript">
45:</script>
46:<scriptsrc="/javascript/format.js"type="text/javascript">
47:</script>
48:<scriptsrc="/javascript/cookies.js"type="text/javascript">
49:</script>
50:<scriptsrc="/javascript/srims.js"type="text/javascript">
51:</script>
52:<scriptsrc="/javascript/srims/login.js"type="text/javascript">
53:</script>
54:<scriptsrc="/javascript/srims/load.js"type="text/javascript">
55:</script>
56:<scripttype="text/javascript"language="javascript">
57:Ext.onReady(function(){
63:Ext.BLANK_IMAGE_URL='/images/s.gif';
64:
65:Ext.QuickTips.init();
66:Srims.tryLogin();
67:});
68:</script>
69:</body>
70:</html>
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
该页面在载入基本的Js后,会调用Srims.tryLogin()方法(65行),该方法会根据当前用户状态试图登录系统,然后更具登陆结果加载不同的Js,也就是下一篇文章将要叙述的内容:Js的动态加载。
相关文章推荐
- 使用ExtJs开发MIS系统(1):基于ExtJs的MIS构架设计
- 使用ExtJs开发MIS系统(6):客户端MVC
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
- 使用ExtJs开发MIS系统(系列文章)
- 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET平台开发指南 - 对象设计器使用帮助
- 使用ExtJs开发MIS系统(2):Js的动态加载
- 使用ExtJs开发MIS系统(5):使用Action抽象客户端操作
- 使用模型驱动开发和基于模式的工程来设计 SOA之第 4 部分
- 使用ExtJs开发MIS系统(4):轮询
- 使用ExtJs开发MIS系统(7):ExtJs性能浅析
- 使用ExtJs开发MIS系统(3):使用数据库保存客户端状态
- 基于Extjs的web表单设计器 第七节——取数公式设计之取数公式的使用
- 《Flask Web开发——基于Python的Web应用开发实践》代码使用方法
- 实战使用Axure设计App,使用WebStorm开发(5) – 实现页面功能
- 【视频教程】如何使用云图进行基于LBS开发
- 基于模型设计的FPGA开发与实现:滤波器设计与实现(三)Matlab中滤波器的HDL代码生成
- 移动网络应用开发中,使用 HTTP 协议比起使用 socket 实现基于 TCP 的自定义协议有哪些优势?
- Linux平台下基于C++语言使用gSOAP开发Web Service服务端和客户端程序
- 翻译:使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 4 - 验证
- 使用OpenCl在Android相机的预览功能中做基于CV的应用开发