评点Flex结合J2EE的开发与架构

摘要:最近晚上抽出点时间写了这篇文章,关于 Flex 开发方面的语言和架构,介绍了大家都熟悉的分层结构,着重介绍视图层(flex 实现),服务控制层和领域模型层,并按照严格分层,高解耦合性并结合 Flex 技术实验了一个用户管理小模块,案例不是目的,重要的是介绍开发思想。本文第一部分介绍 Flex 相关技术以及 ActionStript3.0 语言。第二部分介绍开发实例的开发过程,代码可以下载,亮点在接口工程。由于本人 flex 经验不足,在以后的工作中会不断补充。

 

1 Flex 介绍

FLEX,是Rich Internet Applications时代的牛×产物Rich Internet Applications,翻译成中文为富因特网应用程序。传统网络程序的开发是基于页面的、服务器端数据传递的模式,把网络程序的表示层建立于HTML 页面之上,而HTML是适合于文本的,传统的基于页面的系统已经渐渐不能满足网络浏览者的更高的、全方位的体验要求了,这就是被Macromedia公司 称之为的“体验问题”,而富因特网应用程序的出现也就是为了解决这个问题。

Flex最重要的两个技术要数AS和MXML, MXML 和 HTML 一样是标记语言,它描述了反映内容与功能的用户界面。与 HTML 不同的是,MXML 可对表示层逻辑与用户界面和服务器端数据绑定提供声明抽象。MXML 可将表示与业务逻辑的问题彻底分开,以实现最大程度地提高开发人员的生产率及应用程序的重复使用率。MXML 的开发基础是在迭代过程上,这与其他类型的 Web 应用程序文件如 HTML、JSP、ASP是相同的。开发 MXML 应用程序就象打开一个文件编辑器一样简单,只要输入一些标签、保存文件,然后在 Web 浏览器上打开文件 URL 即可。

MXML 文件同时也是普通的 XML 文件,所以可以选择多种开发环境。可以在简单文件编辑器、专用 XML 编辑器或是支持文件编辑的集成开发环境 (IDE) 中进行开发。由于 MXML 符合 W3C XML 方案的定义,您也可以使用结构化编辑,如代码着色和代码提示。

MXML和HTML间最大区别:前者定义的应用是编译的SWF文件,执行于FlashPlayer客户端中。后者是基于页面技术的应用。因此前者能 提供更丰富的、动态的UI。MXML不支持Flash的某些特性,例如:时间轴。但是可以利用Flash设计组件并应用在Flex中。MXML应用可以是 一个MXML文件,也可以是多个MXML组成,MXML支持MXML文件形式的自定义组件、ActionScript文件形式的自定义组件以及在 Flash中建立的自定义组件。

FLEX试图通过提供一个程序员们已经熟知的工作流和编程模型,让程序员比从前更快更简单地开发动画及RIA应用。在多层式开发模型中,FLEX应用属于表现层。FLEX的语言和文件结构也试图把应用程序的逻辑从设计中分离出来

总之,flex 是未来界面开发的一个好方向,据我了解很多公司都要求员工要学习 flex 技术,可见 flex 受欢迎的程度。

 

2 ActionStript3.0 特性介绍

ActionScript 是针对 Adobe Flash Player 运行时环境的编程语言,它在 Flash 内容和应用程序中实现了交互性、数据处理以及其它许多功能,ActionScript 是由 Flash Player 中的 ActionScript 虚拟机 (AVM) 来执行的。ActionScript代码通常被编译器编译成“字节码格式” ,有点类似 java 的处理和运行机制。变过 C#,Java和javascript程序的朋友,肯定能在 ActionScript 中找到这些语言的影子。

2.1 内置命名空间和自定义命名空间

四个内置修饰符:

 1public :对所有代码可见
2
3private: 只对类内部可见
4
5internal :只对定义所在的同一包内可见
6
7protected :对同一包以及不同包的子类可见
8

自定义命名空间:使用关键字namespace定义命名空间,声明属性和方法时,应用命名空间。

AS 代码: 

1Namespace testSpace="org.blogjava.jm/ testSpace ";
2
3testSpace myfunction2():void{}
4
5 调用使用 use 关键字打开命名空间
6
7use mySpace2;
8
9myfunction2();

2.2 Local 变量特点

与java不同的是,在as3中,变量没有块级作用域(即两人大括号中间),如果在一个块内声明了一个变量,比如一个for循环内声明了一个变量,它在该代码所在整个函数内都是可访问的。

1function myFunction():void{
2
3 for(var i:int=0;i<5:i++){
4
5 var last:int = i;
6
7 }
8
9 trace(last);
10
11}
12

last 在 for 中定义但可以在 for 块外面访问到,个人觉得这样设计欠妥,尽管很方便。

2.3 Dynamic 类

Object 类本身就是动态类,当然也可以用 dynamic 关键字来声明一个类,所谓动态就是在运行时可以对类追加属性和方法。 

1dynamic class Protean{}
2
3 var myProtean:Protean = new Protean();
4
5myProtean.name = "jack.wang";
6
7myProtean.password = 3;
8
9trace(myProtean. name , myProtean. password );
10
2.4 定义函数的两种方式:函数语句和函数表达式

 1 //函数语句声明
2
3Function fun1():void{}
4
5 //函数表达式声明
6
7var fun2:Function = function():void{}
8
9函数表达式声明的函数是不能够被垃圾回收的,必须显示的调用 delete 命令。
10
11var t:Test = new Test(); //t是动态类Test的一个实例
12
13t.funt = function(){};//把一个函数声明为t的一个属性
14
15delete t.funt; //删除刚才新增的函数,我们刚才声明的函数也被回收了
16

 2.5 在as3中也有arguments对象,功能基本上和javascript中的一样。

arguments 对象是一个数组,其中包括传递给函数的所有参数,arguments.length 属性报告传递给函数的参数数量,(避免将 "arguments" 字符串作为参数名,因为它将遮蔽 arguments 对象)

 1 function traceArgArray(x:int):void
2
3{
4
5 for (var i:uint = 0; i < arguments.length; i++)
6
7 {
8
9 trace(arguments[i]);
10
11 }
12
13}
14
15traceArgArray(1, 2, 3);
16
17// 输出:
18
19// 1
20
21// 2
22
23// 3
24

当然也可以用类似 java 的形式 

function traceArgArray(x: int, args) 

2.6 在as3中允许定义同名的静态属性和实例属性
1class StaticTest
2
3{
4
5 static var message:String = "static variable";
6
7 var message:String = "instance variable";
8
9}
10
11// 在脚本中
12
13var myST:StaticTest = new StaticTest();
14
15trace(StaticTest.message); // 输出:静态变量
16
17trace(myST.message); // 输出:实例变量
18

2.7 在as中有一个叫做set和get存取器的东西,类似JavaBean,但又有所不同。 

class GetSe
t{

private var privateProperty:String;

public function get publicAccess():String

{

return privateProperty;

}

public function set publicAccess(setValue:String):void

{
privateProperty = setValue;
}
}  

3 案例介绍

案例是超级简单的,开发Web 应用的,不管你是基于 J2EE,.net 平台还是其他的 PHP 等等都很熟悉分层架构,其中五层是最熟悉不过的了,一般分为表示层,控制层,服务层,模型层和数据层,有的公司干脆就把服务层和模型层合并起来和控制层合 并在一起,基于分层的开发可以横向也可以纵向,由于引入 flex 技术,因为并不是所有人都懂得 flex 开发方式,尽管他和传统的 Swing, SWT,GWT开发很相近 ,不过这样需求分析时可以构建可演进的原型系统,界面也很 RIA。

人们常提面向接口编程于是经常看到 IUser user=new User();这样的代码,似乎就是在用接口,但是 new 的动作还是有依赖,于是人们用一些设计模式比如 Factory, Proxy,反射等等模式,后来又有了更好的依赖注入,似乎很完美了,可人们又陷进了过度设计,其实接口应用比直接用原类要多耗费几个机械指令 User user=new User(),而且在一个内聚的组件中尽量用对象直接连接,该分开的时候我们去用接口分,接口的目的是为了抽象,抽象的目的是为了解耦。

本开发为了把模型层和服务层完全分开,引入接口工程,也就是单独开发一个工程来设计接口,这个工程有设计师开发。

用户接口: 

package org.blogjava.model;

/** *//**

*@authorJack

*

*/

publicinterface IUser {

long getId();

void setId(long id);

void setUserName(String name);

String getUserName();

void setPassword(String password);

String getPassword();

void setEmail(String email);

String getEmail();

void setAddress(String address);

String getAddress();

}


工厂接口: 

package org.blogjava.dao;

import java.util.List;

import org.blogjava.model.IUser;

import org.blogjava.util.InstanceUtils;

import org.blogjava.util.PropertiesUtils;

/** *//**

*@authorJack

*

*/

publicinterface DAOFactory {

publicfinal String IMPL_NAME = PropertiesUtils.getParam(

"/DaoFactoryImpl.properties", "DAOFactoryImpl");

publicfinal DAOFactory factory = (DAOFactory) InstanceUtils

.newInstance(IMPL_NAME);

boolean checkUserValid(String userName, String password);

IUser getUserById(String id);

IUser createUser(IUser user);

boolean deleteUserById(String id);

boolean updateUser(IUser user);

List<IUser> getAllUsers();

}
这两个类在单独的工程里开发,以便于模型和服务层同步开发。

在服务层不能对外暴露 IUser 接口,而他也要接受数据,这里用的是 UserVO 对象来封装数据,服务层不操作模型层的任何实现类,这样这两层之间完全解耦。 

package org.blogjava.vo;

/** *//**

*@authorJack

*

*/

publicclass UserVO {

publiclongid;

public String userName;

public String password;

public String email;

public String address;

public UserVO() {

}

}

Flex 开发和 HTML开发有很大的不同,客户端和服务端交互的不是 HTML 而是 XML,所以在服务器 端的 Servlet 就应该输出 XML 流到客户端

判断登录: 

public ActionForward execute(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response) {

String userName = request.getParameter("userName");

String password = request.getParameter("password");

String sucess = "<?xml version=""1.0"" encoding=""utf-8""?><result><msg>sucess</msg></result>";

String unsucess = "<?xml version=""1.0"" encoding=""utf-8""?><result><msg>unsucess</msg></result>";

response.setContentType("text/xml");

try {

if (userName == null || "".equals(userName)) {

response.getOutputStream().write(unsucess.getBytes());

returnnull;

}

if (password == null || "".equals(password)) {

response.getOutputStream().write(unsucess.getBytes());

returnnull;

}

IUserService service = new IUserServiceImpl();

if (service.isUserValid(userName, password)) {

response.getOutputStream().write(sucess.getBytes());

} else {

response.getOutputStream().write(unsucess.getBytes());

}

} catch (IOException e) {

e.printStackTrace();

}

returnnull;

}


得到所有的用户: 

public ActionForward execute(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response) {

IUserService service = new IUserServiceImpl();

List<UserVO> users = service.getAllUsers();

try {

StringBuffer returnStr = new StringBuffer(

"<?xml version=""1.0"" encoding=""utf-8""?>");

returnStr.append("<users>");

for (UserVO user : users) {

returnStr.append("<user>");

returnStr.append("<id>" + user.id + "</id>");

returnStr.append("<userName>" + user.userName + "</userName>");

returnStr.append("<password>" + user.password + "</password>");

returnStr.append("<email>" + user.email + "</email>");

returnStr.append("<address>" + user.address + "</address>");

returnStr.append("</user>");

}

returnStr.append("</users>");

response.getOutputStream().write(returnStr.toString().getBytes());

System.out.println(returnStr.toString());

} catch (IOException e) {

e.printStackTrace();

}

returnnull;

}


最后 Flex 也是一个单独的工程,通过 HTTPService 和 Web 服务器 端交互数据
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundGradientAlphas="[0.72, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]">

<mx:HTTPService
showBusyCursor="true"
id="loginSrv"
result="doResult();"
method="GET"
url="http://localhost:8080/UserManager/checkUser.do">
<mx:request>
<userName>
{txtname.text}
</userName>
<password>
{txtpwd.text}
</password>
</mx:request>
</mx:HTTPService>
<mx:HTTPService
showBusyCursor="true"
id="loadUsers"
method="GET" result="users = event.result.users.user"
url="http://localhost:8080/UserManager/loadAllUsers.do">
</mx:HTTPService>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
import mx.collections.ArrayCollection;

[Bindable]
var users:ArrayCollection=new ArrayCollection();
internal function doResult():void
{
var returnValue:String=loginSrv.lastResult.result.msg;
if(returnValue=="sucess")
{
login.visible=false;
loadUsers.send();
userList.visible=true;
}
else
{
Alert.show("登录失败","提示信息",Alert.OK,this,null,null,Alert.YES);
}
}
private function index_sortCompareFunc(itemA:Object, itemB:Object):int {
// Make sure itemA has an "index" property.
if (!itemA.hasOwnProperty("id")) {
itemA.index = null;
}
// Make sure itemB has an "index" property.
if (!itemB.hasOwnProperty("id")) {
itemB.index = null;
}
// Perform a numeric sort.
return ObjectUtil.numericCompare(itemA.index, itemB.index);
}
]]>
</mx:Script>
<mx:Panel id="login" x="285.5" y="127" width="341" height="238" layout="absolute" fontFamily="Arial" fontSize="13" color="#3C280B" borderStyle="none" borderColor="#CC0B0B" cornerRadius="10" alpha="0.64">
<mx:TextInput id="txtname" x="101" y="34" width="172" displayAsPassword="true" editable="true" enabled="true"/>
<mx:Button x="92" y="130" label="登录" labelPlacement="top" enabled="true" click="loginSrv.send();"/>
<mx:Button x="183" y="130" label="取消"/>
<mx:TextInput id="txtpwd" x="101" y="75" width="172" displayAsPassword="true" editable="true" enabled="true"/>
<mx:Label x="44" y="36" text="帐号:" width="49" height="20" enabled="true"/>
<mx:Label x="44" y="77" text="密码:" width="49" height="20" enabled="true"/>
</mx:Panel>
<mx:Panel id="userList" x="181.5" y="98" width="576" height="311" layout="absolute" visible="false">
<mx:DataGrid x="0" y="0" width="556" height="271" sortableColumns="true" dataProvider="{users}" editable="true" enabled="true">
<mx:columns>
<mx:DataGridColumn headerText="编号" dataField="id" />
<mx:DataGridColumn headerText="姓名" dataField="userName" />
<mx:DataGridColumn headerText="密码" dataField="password"/>
<mx:DataGridColumn headerText="邮件" dataField="email"/>
<mx:DataGridColumn headerText="地址" dataField="address"/>
</mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:Application>


4 小结

在写这篇文章的时候已经是深夜了,可能有很多地方表述有问题,也可能有的思想没有表述清楚,欢迎大家讨论,就先写到这里,有时间我会继续补上一些内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值