事件無疑是AJAX應(yīng)用中最重要的部分,EXT將事件分為了兩種:自定義事件與瀏覽器事件。
自定義事件
按字面意思就是用戶自己定義的事件,這個事件通常與組件相關(guān)。并且需要用戶根據(jù)組件的狀態(tài)自己觸發(fā)。相關(guān)的類Ext.util.Observable 、Ext.util.Event(Observable.js)。Ext.util.Observable是所有組件(component)的父類,它使得所有的組件都可以任意的添加自定義事件,它的events屬性對事件進(jìn)行維護(hù),這些事件實(shí)際都是Ext.util.Event對象,Ext.util.Event對象里的listeners屬性對與該事件相關(guān)的處理器進(jìn)行維護(hù)。Observable給所有的子類提供了一個統(tǒng)一的接口來發(fā)布事件以及管理事件,這一特性對于組件來說是至關(guān)重要的。
瀏覽器事件
即傳統(tǒng)意義上的鼠標(biāo)單擊、移動等等事件,這些事件是由瀏覽器根據(jù)用戶的動作自己觸發(fā)的,與頁面元素緊密關(guān)聯(lián)。相關(guān)的類Ext.Element 、Ext.EventManager、Ext.EventObject、Ext.lib.Event 。Element包含了常見的DOM方法和屬性,提供一個快捷的、統(tǒng)一的、跨瀏覽器的接口,內(nèi)置了常用的DOM節(jié)點(diǎn)的動作,并且是跨瀏覽器的定位的位置、大小、動畫、拖放等等。對事件的處理,Element實(shí)際將這一處理委托給了EventManager,由EventManager對頁面所有的瀏覽器事件進(jìn)行管理,例如增加事件處理器、移除事件處理器等等,另外EventManager還定義了幾個很重要的方法:onDocumentReady、onWindowResize、onTextResize。其中onDocumentReady尤為重要,通常在頁面需要通過它來啟動我們的AJAX程序,它會在頁面document渲染完畢而圖片等還未下載時調(diào)用我們的啟動函數(shù)。至于EventObject,它則是對原始的瀏覽器事件進(jìn)行了封裝,提供給事件處理器一個統(tǒng)一一致的事件接口。Ext.lib.Event呢?EventManager的很多功能其實(shí)是調(diào)用它完成的,它的listeners、unloadListeners維護(hù)著所有的事件處理器。
posted @
2008-01-17 15:17 ronghao 閱讀(3359) |
評論 (0) |
編輯 收藏
正在翻譯《Enterprise AJAX》,附錄里介紹到OPENAJAX HUB,google相應(yīng)的中文資料很少,所以就把譯文貼出來:)
OpenAjax Hub(“Hub”)主要用來處理Web應(yīng)用開發(fā)者需要在同一個應(yīng)用中同時使用多個AJAX運(yùn)行庫的情況。它提供標(biāo)準(zhǔn)的JavaScript,當(dāng)被包含在AJAX驅(qū)動的Web應(yīng)用里時,它使得多個AJAX工具包能夠在同一個頁面里一起協(xié)同工作。
AJAX應(yīng)用開發(fā)者在開發(fā)中的需求往往存在著巨大的差異,這導(dǎo)致了如今市場上存在超過200個各種各樣的AJAX產(chǎn)品,同時這些產(chǎn)品的架構(gòu)和特性也存在巨大的差異。對一些開發(fā)者來說,他們認(rèn)為開發(fā)中最重要的因素是找到一個能提供與后端服務(wù)器強(qiáng)大集成能力的AJAX工具包。
而對其他一些開發(fā)者來說,最重要的因素則是能否應(yīng)用特殊的客戶端組件(例如,富數(shù)據(jù)網(wǎng)格組件或交互式的圖表組件)。結(jié)果,AJAX生態(tài)系統(tǒng)發(fā)展到現(xiàn)在,開發(fā)者在大部分時間里都能找到滿足他們每個特殊需求的AJAX工具包,但是也存在問題,他們往往必須在同一個Web應(yīng)用里混合和匹配使用多個AJAX工具包才能滿足所有的需求。
Hub應(yīng)用的一個重要場合是門戶和內(nèi)容糅合,這里,應(yīng)用開發(fā)者創(chuàng)建一個頁面,頁面里松散組裝預(yù)先包裝好的應(yīng)用組件。Hub實(shí)際上是保證這些AJAX驅(qū)動的應(yīng)用組件能夠使用多個不同的AJAX工具包創(chuàng)建。
主要特性:Hub 的發(fā)布/訂閱管理器
Hub的主要特性是它的發(fā)布/訂閱管理器(“pub/sub管理器”)。 pub/sub管理器允許內(nèi)容糅合的一個部分能夠傳播其他應(yīng)用組件所訂閱的事件。例如,假設(shè)存在一個日歷組件,該組件允許用戶能夠選取一個特定的日期。內(nèi)容糅合里可能存在多個UI組件,這些組件都需要根據(jù)新選擇的日歷日期而更新它們的視覺外觀。在這種情況下,日歷組件將發(fā)布一個“新日歷日期”的事件,而其他可視化組件將訂閱這個事件。因此,pub/sub管理器的通用消息的優(yōu)點(diǎn)是給由不同AJAX工具包所構(gòu)建的組件之間提供了一個關(guān)鍵的集成機(jī)制。
Hub的pub/sub管理器提供各種各樣的先進(jìn)特性,例如對事件名稱通配符的強(qiáng)大支持,在下面的例子里并沒有展示這個特性。
范例
讓我們假設(shè)現(xiàn)在有這樣一個商務(wù)智能應(yīng)用,該應(yīng)用使用下面的AJAX運(yùn)行庫:
■ UTILS.js, 對瀏覽器的JavaScript環(huán)境提供非常有用的擴(kuò)展,例如XMLHttpRequest的APIs。
■ CALENDAR.js,提供一個日歷組件
■ CHARTS.js, 提供一個圖表組件
■
DATAGRID.js,提供一個交互式的數(shù)據(jù)網(wǎng)格組件
該應(yīng)用有一個唯一的日歷組件,用戶可以以圖表組件的形式(例如,每日情形、每周情形、每月情形和每年情形的柱狀圖)和數(shù)據(jù)網(wǎng)格組件的形式(例如,地方數(shù)據(jù)與全國數(shù)據(jù),兩種數(shù)據(jù)都以用戶選擇的感興趣的列展示)選擇其中的一些數(shù)據(jù)視圖當(dāng)一個新的日期在日歷組件里被選擇時,各個用戶指定的可視化組件(例如,圖表和/或數(shù)據(jù)網(wǎng)格組件)都需要被更新。
實(shí)現(xiàn)該應(yīng)用的一個方法是在加載其他AJAX庫之前加載OpenAjax Hub的JavaScript。例如:
<html>
<head>

<script type=”text/javascript” src=”OpenAjax.js”/>
<script type=”text/javascript” src=”UTILS.js”/>
<script type=”text/javascript” src=”CALENDAR.js”/>
<script type=”text/javascript” src=”CHARTS.js”/>
<script type=”text/javascript” src=”DATAGRID.js”/>

</head>

一些AJAX運(yùn)行庫包含OpenAjax Hub,將Hub作為它們標(biāo)準(zhǔn)發(fā)布的一部分,在這種情況下,只要特定的AJAX運(yùn)行期的JavaScript(譯注:這里特定的JavaScript指的就是包含OpenAjax Hub的AJAX運(yùn)行庫的代碼)在其他兼容OpenAjax的運(yùn)行庫之前被加載,那么則沒有必要為OpenAjax.js使用一個單獨(dú)的<script>元素。
要使應(yīng)用工作,開發(fā)者需要注冊一個回調(diào)函數(shù),當(dāng)用戶在日歷組件里選擇一個新的日期時調(diào)用該函數(shù)。這個回調(diào)函數(shù)接著使用OpenAjax Hub的publish()函數(shù)傳播這個新日期事件:
<script type=”text/javascript”>

function MyCalendarCallback(
) {
OpenAjax.hub.publish(“myapp.newdate”, newdate);
}

</script>
接著開發(fā)者需要開發(fā)這樣一些代碼:所有的圖表組件和數(shù)據(jù)網(wǎng)格組件都要訂閱這個新日期事件,并要提供一個回調(diào)函數(shù)。各個回調(diào)函數(shù)將相應(yīng)地更新特定的可視化組件:
<script type=”text/javascript”>

function NewDateCallback(eventname, publisherData,
subscriberData) {
更新特定的可視化組件
}
OpenAjax.hub.subscribe(“myapp.newdate”, NewDateCallback);

</script>
未來支持OpenAjax
Hub的工具包
OpenAjax聯(lián)盟正與工業(yè)界一起合作,達(dá)到對OpenAjax Hub的廣泛支持。一個特殊的AJAX工具包可以像下面這樣支持OpenAjax Hub:
■ AJAX工具包可以包含Hub(最好的方式)。Hub可以被小于3K的JavaScript實(shí)現(xiàn),所以一些AJAX工具包簡單地捆綁Hub,將它作為它們工具包的一個標(biāo)準(zhǔn)組件。
■ 如果Hub在運(yùn)行環(huán)境里可用則使用它。其他一些AJAX工具包可能決定在它們的發(fā)布中并不包含Hub,它們會檢查Hub是否早先已經(jīng)被加載了,如果已經(jīng)加載,它們則直接使用Hub的服務(wù)。
■第三方的開發(fā)者可以開發(fā)適配器。對大多數(shù)工具包來說,它們可能允許第三方的開發(fā)者編寫少量的JavaScript使得自己能夠支持Hub。
當(dāng)AJAX工具包包含內(nèi)置對Hub的支持時,應(yīng)用開發(fā)者的工作將更加容易,但是通過查找或編寫適配器的方式,Hub依然可以被那些并未實(shí)現(xiàn)支持Hub的工具包所使用。
posted @
2008-01-01 12:57 ronghao 閱讀(2468) |
評論 (4) |
編輯 收藏
其實(shí)本沒打算看這部電影來著,其實(shí)是等著德甲來著,然而,德甲還沒有開始,百無聊賴地那么一按,就看到了《火柴人》,其實(shí)如果不是尼古拉斯·凱奇我也早繼續(xù)換臺來著。
“一二三,開門”,習(xí)慣性隨著短促咳嗽而來的眨動的左眼,潔癖的讓人抓狂的種種,呵,真是個煩躁的男人。
故事開始,詐騙亦開始,中間向體育頻道換過好幾次頻道,溫吞的故事,毫無新意的詐騙過程,讓人沒有欲望。哪有什么所謂的大片好看,幾次爆炸,追車、美女,眼球已經(jīng)被牢牢抓住。情況在羅伊第一次去見他的女兒時發(fā)生變化,煩躁的羅伊不停地在車?yán)镂鵁煟澏兜膴A著煙卷的手,布滿煙霧的車廂,一根接著一根的煙卷,飄忽不定找不到落腳點(diǎn)的眼神,看到女兒要走下定決心的追趕,立刻沒有猶豫地喜歡上這個猶豫的男人。心想,這肯定是一部充滿溫情的電影了,一定就是了。因?yàn)榕畠海纳罴磳⒋騺y,充滿生氣?抑或是雜亂?不管那種,都得改變。
生活中存在著這樣或那樣的不安,所以我總是以最大的善意來揣度電影。劇情也在向我希望的方向發(fā)展。小女孩讓父親教她去行騙,第一次行騙成功。女孩拿著騙來的300美元開心地關(guān)上車門:我們成功了!父親和她慶祝后卻讓她把錢還回去:如果不這么做,我算得上是一個父親嗎?呵,溫暖。
隨后一次更大的詐騙開始,父親也決定完成這最后一次詐騙重新開始。情節(jié)發(fā)展再次讓我大跌眼鏡:這也太easy了吧,雖然被騙的胖男人沒有像他們想象的那樣在飛機(jī)中才發(fā)現(xiàn)錢被調(diào)了包,而是一路追趕出來,收費(fèi)站找零錢一節(jié)也確實(shí)讓心里小小激靈了一把,但整個過程非常順利,順利得讓我覺得索然無味。這應(yīng)該是一個多么充滿驚險和刺激的過程啊,槍戰(zhàn)、追逐、飛車、心里懸疑,可惜,沒有,沒有,還是沒有,什么都沒有。應(yīng)該是這樣一個激烈的過程,然后是美妙的結(jié)局:父親和女兒美滿的在一起,成功隱退,快樂的生活,然后是終場的字幕打起。應(yīng)該是這樣的呵!
女兒槍響的一剎那,我的心咯噔一下:完了,導(dǎo)演該如何結(jié)尾呢?我再也想像不到一種合乎邏輯而又符合我心理的結(jié)局。悲劇?感人的悲劇?父女情深的悲劇?無論是哪一種,我都不愿意看到。切到體育頻道:斯圖加特3比0領(lǐng)先拜仁。切回來,被捕、審訊、醫(yī)生、密碼、接頭地點(diǎn)…這一切都意味著父親在劫難逃。作為父親,能做到就這么多了;然而,作為電影,它顯然可以做到更好-一切在打開那扇門的一剎那霍然開朗,謎底像沙子那樣刺入人的雙眼,讓人心疼,原來一切都是假的,一切都是騙局,他們欺騙了羅伊,導(dǎo)演欺騙了我。心里空蕩蕩的再無著落,像無人的秋千,空在那里蕩漾,像突然的人去樓空,只剩滿心的空曠。半天回味回來:哦,這是電影,并且是好萊塢的電影呢。
一年后再見,女兒離開,轉(zhuǎn)身說:“I'll see you, dad”。是的,到此為止,over。
卻還是溫暖。我更愿相信最初故事的情節(jié)是這樣的:父親詐騙,女兒到來,最初的混亂,親情,融合,改變,生活一起。可是,可是,如何處理這位父親的過去,抹不去的過去,而這個過去最直接的代表莫過于他詐騙所得來的錢財了。捐掉?這不很搞嗎?自首?你以為是中國電影?于是導(dǎo)演以一場更大的騙局將這些錢將父親的過去輕松的抹去了。原來是這樣。原來是這樣呵!女兒還是女兒,父親還是父親。“I'll see you, dad”。是的,沒有復(fù)仇,沒有怨恨。
好久沒有看過如此溫暖的電影了。再補(bǔ)充一下:很喜歡羅伊的眼睛,非常喜歡,焦慮、關(guān)愛、猶豫、彷徨、絕望、溫情。
posted @
2007-11-11 22:58 ronghao 閱讀(1169) |
評論 (0) |
編輯 收藏
Solr 是一個可供企業(yè)使用的、基于 Lucene 的開箱即用的搜索服務(wù)器。對Lucene不熟?那么建議先看看下面兩篇文檔:
實(shí)戰(zhàn)Lucene,第 1 部分: 初識 Lucene:http://www.ibm.com/developerworks/cn/java/j-lo-lucene1/
用Lucene加速Web搜索應(yīng)用程序的開發(fā):http://www.ibm.com/developerworks/cn/web/wa-lucene2/
一、 solr介紹
solr是基于Lucene Java搜索庫的企業(yè)級全文搜索引擎,目前是apache的一個項(xiàng)目。它的官方網(wǎng)址在http://lucene.apache.org/solr/ 。solr需要運(yùn)行在一個servlet
容器里,例如tomcat5.5。solr在lucene的上層提供了一個基于HTTP/XML的Web Services,我們的應(yīng)用需要通過這個服務(wù)與solr進(jìn)行交互。
二、 solr安裝和配置
關(guān)于solr的安裝和配置,這里也有兩篇非常好的文檔,作者同時也是 Lucene Java 項(xiàng)目的提交人和發(fā)言人:
使用Apache Solr實(shí)現(xiàn)更加靈巧的搜索:http://www.ibm.com/developerworks/cn/java/j-solr1/index.html
http://www.ibm.com/developerworks/cn/java/j-solr2/index.html
下面主要說說需要注意的地方。
Solr的安裝非常簡單,下載solr的zip包后解壓縮將dist目錄下的war文件改名為solr.war直接復(fù)制到tomcat5.5的webapps目錄即可。注意一定要設(shè)置solr的主位置。有三種方法。我采用的是在tomcat里配置java:comp/env/solr/home的一個JNDI指向solr的主目錄(example目錄下),建立/tomcat55/conf/Catalina/localhost/solr.xml文件。
<Context docBase="D:/solr.war" debug="0" crossContext="true" >
<Environment name="solr/home" type="java.lang.String" value="D:/solr/solr" override="true" />
</Context>
觀察這個指定的solr主位置,里面存在兩個文件夾:conf和data。其中conf里存放了對solr而言最為重要的兩個配置文件schema.xml和solrconfig.xml。data則用于存放索引文件。
schema.xml主要包括types、fields和其他的一些缺省設(shè)置。
solrconfig.xml用來配置Solr的一些系統(tǒng)屬性,例如與索引和查詢處理有關(guān)的一些常見的配置選項(xiàng),以及緩存、擴(kuò)展等等。
上面的文檔對這兩個文件有比較詳細(xì)的說明,非常容易上手。注意到schema.xml里有一個
<uniqueKey>url</uniqueKey>
的配置,這里將url字段作為索引文檔的唯一標(biāo)識符,非常重要。
三、 加入中文分詞
對全文檢索而言,中文分詞非常的重要,這里采用了qieqie庖丁分詞(非常不錯:))。集成非常的容易,我下載的是2.0.4-alpha2版本,其中它支持最多切分和按最大切分。創(chuàng)建自己的一個中文TokenizerFactory繼承自solr的BaseTokenizerFactory。
/**
* Created by IntelliJ IDEA.
* User: ronghao
* Date: 2007-11-3
* Time: 14:40:59
* 中文切詞 對庖丁切詞的封裝
*/
public class ChineseTokenizerFactory extends BaseTokenizerFactory {
/**
* 最多切分 默認(rèn)模式
*/
public static final String MOST_WORDS_MODE = "most-words";
/**
* 按最大切分
*/
public static final String MAX_WORD_LENGTH_MODE = "max-word-length";
private String mode = null;
public void setMode(String mode) {
if (mode==null||MOST_WORDS_MODE.equalsIgnoreCase(mode)
|| "default".equalsIgnoreCase(mode)) {
this.mode=MOST_WORDS_MODE;
} else if (MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) {
this.mode=MAX_WORD_LENGTH_MODE;
}
else {
throw new IllegalArgumentException("不合法的分析器Mode參數(shù)設(shè)置:" + mode);
}
}
@Override
public void init(Map<String, String> args) {
super.init(args);
setMode(args.get("mode"));
}
public TokenStream create(Reader input) {
return new PaodingTokenizer(input, PaodingMaker.make(),
createTokenCollector());
}
private TokenCollector createTokenCollector() {
if( MOST_WORDS_MODE.equals(mode))
return new MostWordsTokenCollector();
if( MAX_WORD_LENGTH_MODE.equals(mode))
return new MaxWordLengthTokenCollector();
throw new Error("never happened");
}
}
在schema.xml的字段text配置里加入該分詞器。
<fieldtype name="text" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="com.ronghao.fulltextsearch.analyzer.ChineseTokenizerFactory" mode="most-words"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="com.ronghao.fulltextsearch.analyzer.ChineseTokenizerFactory" mode="most-words"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldtype>
</types>
完成后重啟tomcat,即可在http://localhost:8080/solr/admin/analysis.jsp
體驗(yàn)到庖丁的中文分詞。注意要將paoding-analysis.jar復(fù)制到solr的lib下,注意修改jar包里字典的home。
四、 與自己應(yīng)用進(jìn)行集成
Solr安裝完畢,現(xiàn)在可以將自己的應(yīng)用與solr集成。其實(shí)過程非常的簡單,應(yīng)用增加數(shù)據(jù)-->根據(jù)配置的字段構(gòu)建add的xml文檔-->post至solr/update。
應(yīng)用刪除數(shù)據(jù)à根據(jù)配置的索引文檔唯一標(biāo)識符構(gòu)建delete的xml文檔-->post至solr/update。
檢索數(shù)據(jù)à構(gòu)建查詢xml—>get至/solr/select/-->對solr返回的xml進(jìn)行處理-->頁面展現(xiàn)。
具體的xml格式可以在solr網(wǎng)站找到。另外就是solr支持高亮顯示,非常方便。
關(guān)于中文,solr內(nèi)核支持UTF-8編碼,所以在tomcat里的server.xml需要進(jìn)行配置
<Connector port="8080" maxHttpHeaderSize="8192" URIEncoding="UTF-8" …/>
另外,向solr Post請求的時候需要轉(zhuǎn)為utf-8編碼。對solr 返回的查詢結(jié)果也需要進(jìn)行一次utf-8的轉(zhuǎn)碼。檢索數(shù)據(jù)時對查詢的關(guān)鍵字也需要轉(zhuǎn)碼,然后用“+”連接。
String[] array = StringUtils.split(query, null, 0);
for (String str : array) {
result = result + URLEncoder.encode(str, "UTF-8") + "+";
}
posted @
2007-11-06 18:03 ronghao 閱讀(67362) |
評論 (14) |
編輯 收藏
也許是流程做多了的緣故,所以看起程序開發(fā)來一切都是流程或者說都包含流程。個人認(rèn)為大多數(shù)的企業(yè)應(yīng)用(不包括特殊應(yīng)用,例如文檔庫、信息資源庫、BBS等等)不過是對數(shù)據(jù)以一定的樣式展現(xiàn)(表單),以一定的邏輯對數(shù)據(jù)進(jìn)行操作(業(yè)務(wù)規(guī)則),以及把這些處理數(shù)據(jù)的過程以一定的流程進(jìn)行管理(流程)。上面三個方面分別對應(yīng)著表單、業(yè)務(wù)規(guī)則和流程。程序開發(fā)中則對應(yīng)于表單引擎、規(guī)則引擎和工作流引擎。而這些方面又可以統(tǒng)一到一個更大范疇的流程上來,所以這里有對流程驅(qū)動開發(fā)的設(shè)想。
先來看看具體的應(yīng)用場景。
單表增刪改查
這是最簡單的情形,也沒有流程,對這個情形不加討論。但是這里會提到表單引擎,VB里的數(shù)據(jù)控件非常的易用,沒有PO,沒有DAO,也沒有Service,直接與數(shù)據(jù)庫字段進(jìn)行綁定。我們的表單引擎也可以采用這種方式。
支持表單控件(輸入框、文本框、下拉框等)的拖拽,將整個表單與數(shù)據(jù)庫表綁定。

表單控件與數(shù)據(jù)庫字段的綁定。
單表業(yè)務(wù)+流程
比上面的情況稍微復(fù)雜一點(diǎn)點(diǎn),也就是要在業(yè)務(wù)里引入流程,其實(shí)這也是現(xiàn)在工作流引擎應(yīng)用最多的地方,比如說政府OA里的收文、發(fā)文。
這里只需要將表單與流程進(jìn)行綁定,表單引擎的處理方式不變,依然是直接與數(shù)據(jù)庫表進(jìn)行綁定。表單負(fù)責(zé)對數(shù)據(jù)庫里的業(yè)務(wù)數(shù)據(jù)進(jìn)行展現(xiàn),工作流則負(fù)責(zé)推動這些數(shù)據(jù)在業(yè)務(wù)意義上狀態(tài)的轉(zhuǎn)換,互不影響,并在需要的時候在自動節(jié)點(diǎn)上對這些數(shù)據(jù)進(jìn)行相應(yīng)的業(yè)務(wù)處理。

關(guān)于表單權(quán)限。這個也是表單與工作流進(jìn)行綁定時所必須考慮到的問題。其實(shí)只是需要在表單引擎里引入權(quán)限角色的概念,每個角色對應(yīng)于一種權(quán)限,這種權(quán)限具體說來就是表單里每個字段的可見、可編輯等等。然后在人工節(jié)點(diǎn)定義時指定表單權(quán)限角色即可。這樣也實(shí)現(xiàn)了流程與表單權(quán)限一定程度上的解耦。


其實(shí)還有一種更方便的方式,將表單直接與人工節(jié)點(diǎn)進(jìn)行綁定,每個人工節(jié)點(diǎn)對應(yīng)于不同的表單。
復(fù)雜一點(diǎn),多表關(guān)聯(lián)的情況
復(fù)雜一點(diǎn)的情況是業(yè)務(wù)往往是多表的關(guān)聯(lián)。這需要對表單引擎做出擴(kuò)展,讓它可以根據(jù)關(guān)聯(lián)字段對關(guān)聯(lián)表做出查詢,得到關(guān)聯(lián)表的設(shè)計結(jié)構(gòu),繼續(xù)映射。這讓我想起了ORM,這里很有FRM的意思在里面。其實(shí)對于常用的關(guān)聯(lián)查詢往往有通用的組件可用,例如根據(jù)userid渲染出用戶名,根據(jù)數(shù)據(jù)字典的id關(guān)聯(lián)渲染出相應(yīng)的值,oa里的正文、附件、印章等等。
流程跨越多個業(yè)務(wù)
流程需要跨越多個業(yè)務(wù),一個典型的流程如下:

會議審批會涉及到兩張業(yè)務(wù)表:會議室使用表,會議記錄表。在會議申請和領(lǐng)導(dǎo)審批節(jié)點(diǎn),最終用戶打開的都是會議申請的表單,對應(yīng)于會議記錄表,對該表進(jìn)行操作。但是流程運(yùn)行到會議室管理員安排會議室的節(jié)點(diǎn),該節(jié)點(diǎn)最終用戶不僅需要看到會議申請的表單同時還要看到會議室使用情況的表單,如果有空閑的會議室,用戶登記操作會議室使用表,然后通知申請者;如果沒有空閑的會議室,則不用登記直接通知申請者。這個過程中跨越了兩個業(yè)務(wù),分別是會議室管理和會議管理。表單在各個節(jié)點(diǎn)也是不同的。
這其實(shí)對工作流引擎提出了比較高的要求。例如如果流程已經(jīng)結(jié)束,會議得到批準(zhǔn),但申請者突然有事要改變會議時間怎么辦?回退。這里的回退無疑就需要有業(yè)務(wù)的補(bǔ)償,例如要刪除會議室的相關(guān)記錄。
應(yīng)用集成
一個流程不僅會跨越多個業(yè)務(wù),也會跨越多個系統(tǒng)。這里的應(yīng)用場景很多,重要的是要去其他系統(tǒng)抓取數(shù)據(jù)和操作數(shù)據(jù),僅僅靠數(shù)據(jù)庫表對表單的映射滿足不了需求。

對工作流引擎做出改進(jìn),與前面相比,需要由引擎來完成對其他系統(tǒng)服務(wù)的調(diào)用。這里一個很重要的載體就是XML。首先要定義交換數(shù)據(jù)所用的XML scheme,然后將這個XML scheme再與表單引擎做出映射。實(shí)際執(zhí)行時,工作流的自動節(jié)點(diǎn)會在人工節(jié)點(diǎn)前調(diào)用其他系統(tǒng)的服務(wù),按照XML scheme將數(shù)據(jù)轉(zhuǎn)換為符合定義的XML,在緊接著的人工節(jié)點(diǎn)送給表單引擎,表單引擎渲染。修改數(shù)據(jù)也是同樣的過程,表單引擎將處理后的數(shù)據(jù)以XML返回,工作流再次做出轉(zhuǎn)換,調(diào)用服務(wù)的修改功能。
上面五種都是比較常見的應(yīng)用場景,理想的情況下,開發(fā)方式應(yīng)該是這樣的:畫出應(yīng)用流程à定義流程表單à表單與數(shù)據(jù)庫進(jìn)行映射à對流程進(jìn)行業(yè)務(wù)仿真à完成開發(fā)。問題是這樣的:你的表單引擎是否足夠強(qiáng)大?表單與后臺是直接用SQL進(jìn)行交互的,也就是Transaction Script模式,沒有業(yè)務(wù)對象,對于復(fù)雜業(yè)務(wù)邏輯如何處理?如何使用規(guī)則引擎來解決業(yè)務(wù)邏輯的問題?權(quán)限如何以一種AOP的方式對數(shù)據(jù)操作進(jìn)行橫切?
呵呵,純屬個人YY。
posted @
2007-11-02 10:07 ronghao 閱讀(1643) |
評論 (5) |
編輯 收藏