??xml version="1.0" encoding="utf-8" standalone="yes"?>
1.保你安装了Flex Data Service。这个对于单个CUP无限APP是免费的Q可以去Adobe下蝲。如果只是读取XML文g是不需要这个的Q连接数据库需要它了?br />
2.安装了Flex Builder或者有Flex SDK。我q里使用的是Flex BuilderQIDE是方便?^_^Q?br />
3.安装了SQLServer数据库?br />
4.安装了JRUN或者tomcat或其它的J2EE容器Q因为发布的时候我们的E序要运行在J2EEq_上?br />
5.安装了JDK?br />
W一步:创徏数据?br />
q里我们有一个公告表Q表名ؓBulletin。结构如下:
字段名称 字段cd 说明
ID 自动~号 自动~号
title Nvarchar(100) 题目
date datatime 日期
author Nvarchar(20) 作?br />
content ntext 内容
在数据库中创个表。保存之后进入下一步?br />
W二步:在JAVA中编写获取公告的代码
首先Q我们要创徏一个公告类来专门保存获取的公告信息Q代码如下?br />
NoticeInfo.java
package net.zhuoqun.connectDB;
import java.util.Date;
public class NoticeInfo {
private String title; // 标题
private String author; // 作?br />
private String content;// 内容
private Date dates; // 旉
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
……………… // 其它get ?set Ҏ?br />
}
创徏好这个之后我们要创徏一个数据查询类QDataServiceImpl.java来查询数据库Qƈ查询结果传l将要创建的FlexE序。由于我们不清楚有多条记录Q所以就借助一下JAVA中的ArrayListq个c,它位于java.util 包中。先创徏一个ArrayListQ?br />
ArrayList noticeList = new ArrayList();
查询数据库之后,每读取一条记录就d?noticeList?br />
while(rs.next()){
NoticeInfo temp = new NoticeInfo();
temp.setAuthor(rs.getString("author"));
temp.setContent(rs.getString("content"));
temp.setDates(rs.getDate("date"));
temp.setTitle(rs.getString("title"));
noticeList.add(temp);
}
查询完毕之后你就可以把这个noticeList传回去,你也可以传回M?NoticeInfo 数组Q?br />
NoticeInfo[] notices = new NoticeInfo[noticeList.size()];
for(int i=0;i<noticeList.size();i++){
notices = (NoticeInfo)noticeList.get(i);
}
return notices;
我这里用的是后一U方法。如果你直接把noticeList传回ȝ话,C一点,JAVA的ArrayListcd的对象到了Flex中会变成ArrayCollectioncd的?br />
现在JAVA部分的代码就写好了?br />
DataServiceImpl.java 的全部代码如下:
package net.zhuoqun.connectDB;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
public class DataServiceImpl {
private Connection conn = null;
private Statement stmt = null;
// 以下是数据库以及驱动信息
public final static String DRIVER = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
public final static String CONN_STR_PRE = "jdbc:microsoft:sqlserver://";
public final static String HOST_NAME = "localhost:1433;";
public final static String DATABASE_NAME = "DatabaseName=mydata";
public final static String USERNAME = "aaa";
public final static String PASSWORD = "aaa";
public DataServiceImpl(){
}
// 查询数据?br />
private ResultSet executeQuery(String sqlText){
try{
Class.forName(DRIVER);
}catch(ClassNotFoundException e){
e.printStackTrace();
}
try{
conn = DriverManager.getConnection(CONN_STR_PRE + HOST_NAME + DATABASE_NAME, USERNAME, PASSWORD);
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sqlText);
return rs;
}catch(SQLException e){
e.printStackTrace();
}
return null;
}
// 查询公告. q个是本E序的关键代?br />
public NoticeInfo[] getNotices(){
ArrayList noticeList = new ArrayList();
String sqlText = "select author,content,date,title from Bulletin";
ResultSet rs = executeQuery(sqlText);
try{
while(rs.next()){
NoticeInfo temp = new NoticeInfo();
temp.setAuthor(rs.getString("author"));
temp.setContent(rs.getString("content"));
temp.setDates(rs.getDate("date"));
temp.setTitle(rs.getString("title"));
noticeList.add(temp);
}
NoticeInfo[] notices = new NoticeInfo[noticeList.size()];
for(int i=0;i<noticeList.size();i++){
notices = (NoticeInfo)noticeList.get(i);
}
return notices;
}catch(SQLException e){
e.printStackTrace();
return null;
}
}
}
W三步: 配置Flex Data Service
1Q把刚才写的JAVA文g~译。打开FDS的安装文件夹Q将~译的文件拷贝到\jrun4\servers\default\flex\WEB-INF\classes 文g夹中Q进行下面的配置?br />
2.打开FDS的安装文件夹。进入jrun4\servers\default\flex\WEB-INF\flex 目录。里面是关于FlexData Service的配|文Ӟ我们q里只看RemoteObject如何配置Q其它配|信息请自己看帮助。现在我们打开里面的remoting-config.xml文g。向里面d如下信息Q作?lt;service>的子标签Q?br />
E序代码
<destination id="dataService">
<properties>
<source>net.zhuoqun.connectDB.DataServiceImpl</source>
</properties>
</destination>
当你讑֮?destination的时候,你就引用了了可以用来q接相应cȝ信息通道Qmessaging channelQ。它的id必须在文件中是独一无二的。source属性是指你~译的JAVAcdclasses文g夹中的\径。由于我的DataServiceImplcdclasses\net\zhuoqun\connectDB中,所以source的gؓnet.zhuoqun.connectDB.DataServiceImpl。记住,不要?class后缀?lt;properties>标签q可以有一?lt;scope>子标{,其作用我在这里就不说了,大家自己看相x档(关于FDS的配|其实有很多东西Q这些在帮助文档里都有,我这里不多说了,也说不过来,自己看吧Q?br />
现在我们已经配置好了后台?FDSQ做完了整个E序的大部分工作Q接下来是前台FlexE序调用的事情了?br />
W四步:创徏FlexE序
打开Flex BuilderQ新Z个工E?ConnectDB。菜单栏?File -> New -> Flex ProjectQ这时会弹出一个对话框Q选择 Flex Data ServiceQ创Z一个Flex工程?br />
W五步:通过 RemoteObject 讉K数据?br />
打开工程中生成的L?ConnectDB.mxmlQ声明一?RemoteObject Q?br />
E序代码
<mx:RemoteObjectid="getData" destination="dataService"result="proccessResult(event.result)"fault="Alert.show(event.fault.faultString,'Error')"/>
其中destination 的值是刚才我们在配|?FDS 的时候设定的 destination?result 表示在这个RemoteObject成功q回之后所要做的动作,q里我们调用一个方?proccessResult()来处理返回的数据Q它的参?event.result是从服务器D获得的数据Q数据是作ؓ一个对象传q来的?fault表示在这个RemoteObjecthp|时要做的处理Q这里我们会弹出一个显C错误信息的对话框。接下来我们要声明一个DataGrid控g来显C公告的标题和发布日期:
E序代码
<mxataGrid id="myDG">
<mx:columns>
<mxataGridColumn headerText="标题" dataField="title"/>
<mxataGridColumn headerText="发布日期" dataField="dates" labelFunction="formatDate"/>
</mx:columns>
</mx:DataGrid>
其中headerText是显C在上方的表_dataField表示要显C的数据域,Z么数据域是title和dates呢?因ؓ我们传回的是一个NoticeInfo 对象数组Q虽然它是作Z个对象传回来的,但是其中的数据结构ƈ没有变,那些数据域的名字也没有变Q所以我们可以根据NoticeInfo 中的变量讑֮dataField。labelFunction属性是用来格式化显C的Q因Z回来的是格林威治旉Q所以我们需要将其格式化然后昄出来。注意,q里只是昄两个数据域,q不代表其它的数据都没有了,它们仍然存在Q只是没有显C出来?br />
接下来,?<mx:Script> 标签中编写proccessResult()Ҏ和格式化日期?formatDateҎQ?br />
E序代码
private function proccessResult(result:Object):void
{
myDG.dataProvider = ArrayUtil.toArray(result);
}
private function formatDate(item:Object,column:DataGridColumn):String
{
return df.format(item.dates);
} // df 是一?DateFormatterQ在下面会给出。关于如何格式化DataGrid的显C?br />
// 以及DateFormatterq里׃讨论了,帮助里写得很清楚
q个函数只是单地获得的数据传给 myDG ?dataProvider。result的类型是ObjectQ因为数据是作ؓ一个对象传q来的。之所以调?ArrayUtil.toArray()q个ҎQ是因ؓq回的记录可能只有一条,而myDG ?dataProvider昄单个对象的时候可能会出错Q所以安全v见先其转换成数l?br />
最后,我们~写调用 RemoteObject 的方法,使其在程序启动时p用?br />
E序代码
private function initApp():void
{
getData.getNotices();
}
其中 getData 是RemoteObject的idQgetNotices()是DataServiceImpl.java中的Ҏ。在q里可以直接调用它。当Ӟ如果DataServiceImpl.java有其它方法,也可以通过q种方式直接调用。接下来讑֮lg创徏完毕时调?initApp()ҎQ在<mx:Application>中添加一个creationComplete属?
E序代码
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" fontSize="12" creationComplete="initApp()">
ConnectDB.mxml的全部代码:
E序代码
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" fontSize="12" creationComplete="initApp()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.utils.ArrayUtil;
private function initApp():void
{
getData.getNotices();
}
private function proccessResult(result:Object):void
{
myDG.dataProvider = ArrayUtil.toArray(result);
}
private function formatDate(item:Object,column:DataGridColumn):String
{
return df.format(item.dates);
}// df 是一?DateFormatterQ在下面会给出。关于如何格式化DataGrid的显C?br />
// 以及DateFormatterq里׃讨论了,帮助里写得很清楚
]]>
</mx:Script>
<mx:DateFormatter id="df" formatString="YYYY-MM-DD"/>
<mx:RemoteObject id="getData" destination="dataService"result="proccessResult(event.result)"fault="Alert.show(event.fault.faultString,'Error')"/>
<mx:DataGrid id="myDG">
<mx:columns>
<mx:DataGridColumn headerText="标题" dataField="title"/>
<mx:DataGridColumn headerText="发布日期" dataField="dates" labelFunction="formatDate"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
整个工程l于完成Q启动JRUNQ然后运行程序,查看E序l果
如果是其他数据库Q只需要改一下数据库驱动信息可以了
2.复制一个ArrayCollection
//dummy solution( well, it works )
var bar:ArrayCollection = new ArrayCollection();
for each ( var i:Object in ac ){
bar.addItem( i );
}
// fantastic ! //
var bar:ListCollectionView = new ListCollectionView( ListCollectionView( ac ).list );
3.打开一个新览器窗?
navigateToURL(new URLRequest('http://52friends.com'), '_blank');
4.h览?/strong>
navigateToURL(new URLRequest("javascript:location.reload();"),"_self")
5.关闭览?/strong>
navigateToURL(new URLRequest("javascript:window.close()"),"_self");
6.讄Alert H口的背景ؓ透明
Alert
{
modalTransparency:0.0;
modalTransparencyBlur:0;
}
7.取随机颜?/strong>
lbl.setStyle('color', 0xffffff*Math.random());
8.清除子串左侧I格
public function LTrim(s : String):String
{
var i : Number = 0;
while(s.charCodeAt(i) == 32 || s.charCodeAt(i) == 13 || s.charCodeAt(i) == 10 || s.charCodeAt(i) == 9)
{
i++;
}
return s.substring(i,s.length);
}
9.清除字串右侧I格
public function RTrim(s : String):String
{
var i : Number = s.length - 1;
while(s.charCodeAt(i) == 32 || s.charCodeAt(i) == 13 || s.charCodeAt(i) == 10 ||s.charCodeAt(i) == 9)
{
i--;
}
return s.substring(0,i+1);
}
10.清除字串左右的空?/strong>
public function Trim(s : String):String
{
return LTrim(RTrim(s));
}
11.获取数据cd
getQualifiedClassName(data)
12.生成随机字符?
private function GenerateCheckCode():String
{
//init
var ran:Number;
var number:Number;
var code:String;
var checkCode:String ="";
//get 4 radom
for(var i:int=0; i<4; i++)
{
ran=Math.random();
number =Math.round(ran*10000); //get result like 0.1234
if(number % 2 == 0)
code = String.fromCharCode(48+(number % 10)); //0's ASCII code is 48
else
code = String.fromCharCode(65+(number % 26)) ; // A's ASCII code is 65
checkCode += code;
}
return checkCode;
}
[Bindable]大概又是Flex用得最多的元数据了。刚开始用用确实好单,效率真是没的说。不q这几天用着却碰C些问题,我自己搜集了些资料,想着有必要在blog里ȝ一下吧?/p>
知道pq吧。今天不晓得Z么livedoc.adobe.comq么慢,没办法,拿不到权威的解释了。我按自己的理解随便解释一下:首先要明白元数据不是语法的一部分Q而是专门l编译器用的Q说白了是告诉编译器做某些事情,学过java之类的应该知道。那Bindable来讲Q它的作用是告诉flex~译器,l某些某些东西徏立绑定关p,flex~译器会在编译过E中lASQflex~译器就是把mxml~译成asQ再~译到swfQ也可能直接~译倒swfQ我q里假设有asq么个环节)加一点事件发生和处理之类的代码,由此l定的关pM建立了,如果我们用纯_as3代码来写也是可以实现的,是太太太麻烦?/p>
知道l箋跌。D个例子:l下面的public变量加上[Bindable]
[Bindable] public var name:String = "";
作ؓ一个public变量Q肯定既可以被赋|也能赋值给别的变量。绑定的作用是Q当name改变的时候(被赋gQ,可能通知其它被name影响Q赋值给它们Q的变量发生改变。这里的“可能”需要编译器来判断,q就是ؓ什么元数据是给~译器用的原因了。在mxml里用{}的语法的地方是l定的对象,比如label={xxx.name}Q当name变化Qlabel也跟着变化。这P我们只是很简单的改变了name的|׃有绑定,界面上的label也跟着自动变化了,爽吧?/p>
三个地方Q类, 变量, getter/setter。是不是public没有关系Qprivate的就只能l自家用呗。用在Class上就是简单的l所有的public属性(包括变量Qgetter/setterQ普通方法)加上[Bindable]Q可是一般的Ҏ不能用[Bindable]呀Q于是一般就能看到flexl了个warningQ直接无?)。变量嘛是上面讲的Q很单略掉?/p>
l于讲到关键地方了,因ؓgetter和setter很像ҎQ用h会有点不同。看看这个例子:
[Bindable] private var content:Array = new Array(); [Bindable] public function set _content(ct:String):void { content = ct.split(SEP); } [Bindable] public function get _wholeText():String { if(content.length == 0) { return ""; } else { var _w:String = ""; for(var i:int=0 ; i<content.length ; i++) { _w += content[i] + "\r\n"; } return _w; } }
原来的设xcontentl定_wholeTextQ可它是不工作的。ؓ什么?_wholeText太复杂了Q被~译器排除在“可能”之外Q编译器认ؓ没有l定关系Q如果只是简单的return contentQ倒是可以的。我q里搜到了一些比较权威的解释。来?a >http://www.rubenswieringa.com/blog/binding-read-only-accessors-in-flex扑ֈEly Greenfield讲的?/p>
Now keep in mind that there’s no way for the compiler to actually tell if the value of a property get function would be different if called, short of doing an extensive code flow analysis of the get function, identifying all the inputs that might be affecting the value of the get function (i.e., member fields, statics, globals that are used in the get function and in any methods, global functions, closures, etc) it might call, and setting up watchers on every one of those to trigger the binding when any of them change. That’s prohibitively difficult, and expensive to do. So the compiler doesn’t try.
Instead when you put [Bindable] on a get/set property, the compiler makes it bindable with a little creative rewriting that allows the framework to watch the get function, and dispatch a change event when the get function is triggered. This means that automatic bindable properties don’t work when the get function is computed from multiple values, or when you change its value by setting a backing field, rather than using the set function.
It _also_ means that if you have no set function, we can pretty much guarantee that there’s no way automatically bindable get properties will be triggered. a read only propeerty is, to the compiler, completely opaque…at the moment, it has no idea where that value is coming from, and hence will never be able to ‘automatically’ trigger the binding.
说白了就是ؓ了降低复杂度和提高效率,复杂情况的getter会被忽略。如何解冻I可以手动建立l定Q即[Bindable("eventName")]。把代码Ҏq样Q?/p>
[Bindable] private var content:Array = new Array(); [Bindable] public function set _content(ct:String):void { content = ct.split(SEP); this.dispatchEvent(new Event("_contectChanged")); } [Bindable("_contectChanged")] public function get _wholeText():String { if(content.length == 0) { return ""; } else { var _w:String = ""; for(var i:int=0 ; i<content.length ; i++) { _w += content[i] + "\r\n"; } return _w; } }
q样避免了~译器去自动识别。自己加上绑定关p,当_content被赋|发出_contentChanged事gQ通知所有被l定的getterҎ执行一遍。这也说明了Q绑定不q是事g游戏而已Qflex为用户隐藏了很多底层法?/p>