摘要: 最近上一個項目想在Eclipse RCP中使用Spring,在網上Google了一下發現這方面的資料比較少,知道Spring自己有個Spring-OSGI的項目,可以在 Spring中配置OSGI服務。可是,我只是想在RCP中引入Spring來管理Java Bean,不想去研究那個東西。于是,看看有沒有什么簡單的方法來解決這個問題。
閱讀全文
摘要: The Law of Demeter和 Principle of Least Knowledge將的都是一回事,是說一個軟件實體要盡可能的只與和它最近的實體進行通訊。通常被表述為:talk only to your immediate friends ( 只和離你最近的朋友進行交互)。
閱讀全文
摘要: Rule 結構是最重要的結構。 Rule 使用了形如“ IF ” something “ THEN ” action (當然,我們的關鍵字是“ when ”和“ then ”)的形式。
一個規則在一個 package 中必須要有唯一的名字。如果一個名字中含有空格,那就需要將名字放在雙引號中(最好總是使用雙引號)。
Attribute 是可選的(最好是每行只有一個 Attribute )。
規則的 LHS 跟在“ when ”關鍵字的后面(最好是另起一行),同樣 RHS 要跟在“ then ”關鍵字后面(最好也另起一行)。規則以關鍵字“ end ”結束。規則不能嵌套。
閱讀全文
摘要: Drools 3 采用了原生的規則語言,那是一種非 XML 文本格式。在符號方面,這種格式是非常輕量的,并且通過“ expanders ”支持符合你問題域的 Domain Specific Language ( DSL )。這一章把焦點放在了 Drools 原生的規則格式。如果你想從技術上了解規則語言的機制,可以參考“ drl.g ”源文件,這是用 Antlr3 語法來描述規則語言。如果你使用 Rule Workbench ,內容助手將會為你完成大量的規則結構,例如輸入“ ru ”,然后按 ctrl + space ,會為你建立規則結構。
閱讀全文
下載地址:
http://labs.jboss.com/portal/index.html?ctrl:id=page.default.downloads&project=jbossrules
下載文件說明:
JBoss Rules 3.0.1 Binaries (includes
javadocs)
(?13MB
)―
僅僅包含
JBoss Rules
的四個核心類庫:
l????????
drools-core.jar
-
核心引擎,運行時組件。包含了
RETE
引擎和
LEAPS
引擎;
l????????
drools-compiler.jar
-
規則文件的編譯組件,構建可執行的
RuleBase
;
l????????
drools-jsr94.jar
-
提供了
JSR-94
的兼容實現,本質上是
drools-
compiler
組件的包裹層。注意:由于
JSR94
規約的限制,不是所有的特點都可以通過此接口暴露。
l????????
drools-decisiontables.jar
-
決策表的“編譯”組件(使用了
drools- compiler
組件)。支持
excel
和
CSV
輸入格式。
JBoss Rules 3.0.1 Binaries with
dependencies (includes javadocs)
( 23 MB
)-
包含了
JBoss Rules
的核心類庫和它們的
dependencies
:
l????????
antlr-2.7.6.jar
l????????
antlr-3.0ea8.jar
l????????
colt-1.2.0.jar
l????????
commons-collections-3.1.jar
l????????
commons-io-1.1.jar
l????????
commons-jci-core-1.0-406301.jar
l????????
commons-jci-eclipse-3.2.0.666.jar
l????????
commons-jci-janino-2.4.3.jar
l????????
commons-lang-2.1.jar
l????????
commons-logging-api-1.0.4.jar
l????????
concurrent-1.3.4.jar
l????????
core-3.2.0.666.jar
l????????
janino-2.4.3.jar
l????????
jsr94-1.1.jar
l????????
jung-1.7.2.jar
l????????
junit-3.8.1.jar
l????????
poi-2.5.1-final-20040804.jar
l????????
stringtemplate-2.3b6.jar
l????????
xercesImpl-2.6.2.jar
l????????
xml-apis-1.0.b2.jar
l????????
xpp3-1.1.3.4.0.jar
l????????
xstream-1.1.3.jar
如果你運行在
Java 1.5
環境下,有一些類庫,例如
XML libraries
,可以不需要。需要注意的類庫有:
“
JCI
”-這是
Apache Java Compiler Interface ,
提供了運行時編譯能力??梢酝ㄟ^
PackageBuilderConfiguration
實例來設定采用
eclipse
或
janino
編譯器,默認是
eclipse
;
“
POI
”-提供了解析
Excel
文件的能力;
“
antlr
”-提供了解析規則語言的能力。
JBoss Rules IDE 3.0.1
(
13 MB
)-
這是
JBoss Rules
的
Eclipse
插件,只支持
Eclipse 3.2
或以上版本。它提供了運行
JBoss Rules
的所有
dependencies
。你可以創建一個
Rule Project
,它能夠為你編寫規則文件提供自動完成的功能,并且它為你提供了
Agenda view
,
WorkingMemory view
,
Global Data view
,使你可以通過
eclipse
視圖很清楚的看到
Agenda
,
WorkingMemory
和
Global Data
的情況。
你還可以通過
update
site
來自動安裝這個插件
,URL
是:
http://anonsvn.labs.jboss.com/labs/jbossrules/updates/drools-ide-update/
?
摘要: WorkingMemory 是運行時規則引擎的主要類。它保持了所有被 asserted 進 WorkingMemory 的數據的引用,直到取消( retracted )。 WorkingMemory 是有狀態對象。它們的生命周期可長可短。如果從一個短生命周期的角度來同一個引擎進行交互,意味著你可以使用 RuleBase 對象來為每個 session 產生一個新的 WorkingMemory ,然后在結束 session 后 discard 這個 WorkingMemory (產生一個 WorkingMemory 是一個廉價的操作)。另一種形式,就是在一個相當長的時間中(例如一個 conversation ),保持一個 WorkingMemory ,并且對于新的 facts 保持持續的更新。當你希望 dispose 一個 WorkingMemory 的時候,最好的實踐就是調用 dispose() 方法,此時 RuleBase 中對它的引用將會被移除(盡管這是一個弱引用)。不管怎樣最后它將會被當成垃圾收集掉。術語
閱讀全文
摘要: Drools 分為兩個主要部分:構建( Authoring )和運行時( Runtime )。
構建的過程涉及到 .drl 或 .xml 規則文件的創建,它們被讀入一個解析器,使用 ANTLR 3 語法進行解析。解析器對語法進行正確性的檢查,然后產生一種中間結構“ descr ”, descr 用 AST 來描述規則。 AST 然后被傳到 PackageBuilder ,由 PackagBuilder 來產生 Packaged 對象。 PackageBuilder 還承擔著一些代碼產生和編譯的工作,這些對于產生 Package 對象都時必需的。 Package 對象是一個可以配置的,可序列化的,由一個或多個規則組成的對象。
閱讀全文
摘要: 在JBoss Rules 學習(一):什么是Rule中,我們介紹了JBoss Rules中對Rule的表示,其中提到了JBoss Rule中主要采用的RETE算法來進行規則匹配。下面將詳細的介紹一下RETE算法在JBoss Rule中的實現,最后隨便提一下JBoss Rules中也可以使用的另一種規則匹配算法Leaps。
閱讀全文
摘要: 學習JBoss Rules有幾天了,因為這方面的中文資料較少,所以這幾天都在看官網上的manual。這是一份不錯的教程,我把我看的一些重要的東西翻譯整理了一下,希望可以對想學習JBoss Rules的同學們提供一點幫助。
在開始這份教程之前,我先簡要介紹一下JBoss Rules:
JBoss Rules 的前身是Codehaus的一個開源項目叫Drools。最近被納入JBoss門下,更名為JBoss Rules,成為了JBoss應用服務器的規則引擎。
Drools是為Java量身定制的基于Charles Forgy的RETE算法的規則引擎的實現。具有了OO接口的RETE,使得商業規則有了更自然的表達。
既然JBoss Rules是一個商業規則引擎,那我們就要先知道到底什么是Rules,即規則。在JBoss Rules中,規則是如何被表示的
閱讀全文
?? (Jarkata 的 Commons Logging 包現在已經被用在幾乎所有的開源項目之中,它可以使你開發的系統工作在不同的日志框架下,包括Sun的logging框架和Apache Log4j。現在Commons Logging + Apache Log4j 的身影是隨處可見,Commons Logging 的易用與Log4j的強大功能形成了絕配。)
問題:
??? ? 你正在寫一個可重用的代碼庫,而你不知道你的代碼在哪里并且是如何工作的。你需要一個抽象的日志接口來寫入日志信息,因為你不能確定Log4j或者是JDK 1.4 logging的存在性。
解決:
??????? 通過Jakarta Commons Logging 的Log 接口來記錄信息,然后依靠Commons Logging自身來決定在運行時使用哪種具體的日志框架。下面的代碼使用了Log接口來記錄trace,debug,info,warning,error和fatal信息:
?1?import?org.apache.commons.logging.LogFactory;
?2?import?org.apache.commons.logging.Log
?3?
?4?Log?log?=?LogFactory.getLog(?"com.discursive.jccook.SomeApp"?);?
?5?
?6?if(?log.isTraceEnabled(?)?)?{
?7?????log.trace(?"This?is?a?trace?message"?);
?8?}
?9?
10?if(?log.isDebugEnabled(?)?)?{
11?????log.debug(?"This?is?a?debug?message"?);
12?}
13?
14?log.info(?"This?is?an?informational?message"?);
15?
16?log.warn(?"This?is?a?warning"?);
17?
18?log.error(?"This?is?an?error"?);
19?
20?log.fatal(?"This?is?fatal"?);
????? LogFactory.getInstance() 返回一個Log接口的具體實現,這個實現與底層具體的日志框架相對應。例如,如果你的系統是使用Apache Log4j ,一個Log4JLogger將被返回,對應于Log4J category
com.discursive.jccook.SomeApp 。
討論:
??????? 一個可重用代碼庫的開發者不能預知其代碼庫將在何時何地被用到,而現在有很多的日志框架可以使用,所以當開發可重用代碼庫的時候,使用Commons Logging 是非常明智的,例如Jakarta Commons 組件。當調用LogFactory.getInstance()方法的時候,Commons Logging 將通過系統屬性和classpath中的類庫來決定和管理適當的日志框架。對于一個小型可重用組件的開發者來說,進行日志記錄只需要調用Log接口。而配置底層日志框架的負擔,就轉移到使用其組件庫的開發者身上。
參考:
??????? 7.11節詳細的說明了Commons Logging在運行時確定適當日志框架的算法。
????
問題:
??????? 你需要使用HTTP POST 方法來向一個servlet傳遞參數。
討論:
??????? 創建一個 PostMethod 對象,然后調用 setParameter() 或 addParameter() 方法設置參數。 PostMethod 對象將會傳送一個 Content-Type 頭為 application/x-www-form-urlencoded 的請求,并且參數將在請求body中被傳送。在下列的例子中演示了用 PostMethod 對象傳遞參數的用法:
import?org.apache.commons.httpclient.HttpClient;
import?org.apache.commons.httpclient.HttpException;
import?org.apache.commons.httpclient.NameValuePair;
import?org.apache.commons.httpclient.methods.PostMethod;
HttpClient?client?=?new?HttpClient(?);
//?Create?POST?method
String?url?=?"http://www.discursive.com/cgi-bin/jccook/param_list.cgi";
PostMethod?method?=?new?PostMethod(?url?);
//?Set?parameters?on?POST????
method.setParameter(?"test1",?"Hello?World"?);
method.addParameter(?"test2",?"This?is?a?Form?Submission"?);
method.addParameter(?"Blah",?"Whoop"?);
method.addParameter(?new?NameValuePair(?"Blah",?"Whoop2"?)?);
//?Execute?and?print?response
client.executeMethod(?method?);
String?response?=?method.getResponseBodyAsString(?);
System.out.println(?response?);
method.releaseConnection(?);
??????
param_list.cgi CGI腳本會對所以接收到的參數進行回顯,從下面的輸出中,你可以看到傳遞給CGI腳本的三個參數:
These?are?the?parameters?I?received:
test1:
??Hello?World
test2:
??This?is?a?Form?Submission
Blah:
??Whoop
??Whoop2
?????? 有幾種方法來在一個PostMethod對象中設置參數。最直接的方法就是調用setParameter()方法,并傳遞兩個字符串給它:參數的名稱和參數值。setParameter()方法將會替代任何已經存在的同名參數。但是,如果一個同名的參數已經存在一個PostMethod對象中,addParameter()將會加入另一個同名參數值;addParameter()方法同樣接受兩個String:參數名和參數值。另一種方法,這兩個方法同樣接受一個包裝了參數名和參數值的NameValuePair對象。在前面的例子中,通過addParameter()方法,用參數名Blah傳遞了兩個值,第一次用兩個String作為參數,第二次用一個NameValuePair對象作為參數。
問題:
??????? 你需要在一個URL中傳送查詢參數。
解答:
??????? 使用一個HttpMethod實例的setQueryString()方法來設置查詢字符串。使用URIUtil類對包含在URL中的文本進行編碼。下面的例子在查詢字符串中放入了兩個參數:
?1?import?org.apache.commons.httpclient.HttpClient;
?2?import?org.apache.commons.httpclient.HttpException;
?3?import?org.apache.commons.httpclient.HttpMethod;
?4?import?org.apache.commons.httpclient.NameValuePair;
?5?import?org.apache.commons.httpclient.methods.GetMethod;
?6?import?org.apache.commons.httpclient.util.URIUtil;
?7?
?8?HttpClient?client?=?new?HttpClient(?);
?9?
10?String?url?=?"http://www.discursive.com/cgi-bin/jccook/param_list.cgi";
11?
12?HttpMethod?method?=?new?GetMethod(?url?);
13?
14?// 用setQueryString()來設置查詢字符串
15?method.setQueryString(URIUtil.encodeQuery("test1=O?Reilly&blah=Whoop"));
16?System.out.println(?"With?Query?String:?"?+?method.getURI(?)?);
17?
18?client.executeMethod(?method?);
19?
20?System.out.println(?"Response:\n?"?+?method.getResponseBodyAsString(?)?);
21?method.releaseConnection(?);
??????
param_list.cgi? CGI腳本只是簡單的回顯接收到的所以參數,在下面的輸出中,你可以看到URIUtil如何對第一個參數進行編碼:
?????? With?Query?String:?http://www.discursive.com/cgi-bin/jccook/param_list.cgi?test1=O%20Reilly&blah=Whoop
Response:
?These?are?the?parameters?I?received:
test1:
??O?Reilly
blah:
??Whoop
????? 提示:你不必在setQueryString()方法中加入?號,當HttpClient實例執行executeMethod()方法時,它會被自動加入。
討論:
????? ?? 在前面的例子中,HttpMethod的setQueryString()方法是一次性將整個查詢字符串加進去,但是還有另外一種選擇:通過一個NameValuePair對象的數組來設置查詢字符串。當一個NameValuePair[]傳入setQueryString()方法中時,HttpMethod實例會從數組中取出每一個NameValuePair對象,然后創建一系列用&號分割的參數。這種方法使程序代碼更加干凈,因為你不必連接字符串來傳遞多個參數。下面的例子用NameValuePair對象,與前一個例子設置了同樣的參數:
?1?// 用NameValuePair對象設置查詢參數
?2?HttpMethod?method?=?new?GetMethod(?url?);
?3?NameValuePair?pair?=?new?NameValuePair(?"test1",?URIUtil.encodeQuery(?"O?Reilly"?)?);
?4NameValuePair?pair2?=?new?NameValuePair(?"blah",?URIUtil.encodeQuery(?"Whoop"?)?);
?5NameValuePair[]?pairs?=?new?NameValuePair[]?{?pair,?pair2?};
?6method.setQueryString(?pairs?);
?7System.out.println(?"With?NameValuePairs:?"?+?method.getURI(?)?);
?8client.executeMethod(?method?);
?9 System.out.println(?"Response:\n?"?+?method.getResponseBodyAsString(?)?);
?10method.releaseConnection(?);
??????? 根據RFC1738,URL只能夠包含字母和數字字符:[0-9,a-z,A-Z]和一些特殊字符。如果你需要在參數中傳送一些URL所不允許的字符,你就需要對你的字符串進行編碼,以符合RFC1738的規定。URIUtil類有一個方法encodeQuery()能夠對前面例子中的"O Reilly"進行編碼。下面的代碼展示了用URIUtil類來對包含在URL中的字符串進行編碼:
1?String?encoded1?=?URIUtil.encodeQuery(?"<test>=O'Connell"?);
2?String?encoded2?=?URIUtil.encodeQuery(?"one:two=thr?ee#"?);
3?
4?String?decoded?=?URIUtil.decode(?"Hello%20World%3F"?);
5?
6?System.out.println(?"Encoded:?"?+?encoded1?);
7?System.out.println(?"Encoded:?"?+?encoded2?);
8?System.out.println(?"Decoded:?"?+?decoded?);
??????? 這個簡單的例子用URIUtil類對兩個字符串進行了編碼,并對一個經過編碼的字符串進行解碼。下面的輸出展示了每個轉換的結果:
Encoded:?%3ctest%e3=O'Connell
Encoded:?one%3atwo=thr%20ee#23
Decoded:?Hello?World?
????????
參考:
??????? 在這個例子中,URLUtil對傳入的查詢字符串的內容進行了編碼。最近,HttpClient小組將一些URL編碼和解碼的邏輯代碼移入了Jakarta Commons Codec項目中,對應的類名為URLCodec。需要URLCodec更多的信息,請參考
Jakarta Commons Codec項目主頁(http://jakarta.apache.org/codec)。
???????? RFC1738討論了URL中的合法字符,并規定了對其他字符進行編碼的過程。RFC1738能夠在http:// www.zvon.org/tmRFC/RFC2616/Output/index.html中找到。
問題:
??????? 你需要通過HTTP GET方法來獲取信息。
解答:
??????? 創建一個HttpClient實例,并調用以GetMethod對象為參數的executeMethod方法。然后,響應的內容就可以通過一個InputStream,byte[],或者是String來獲得。下面的例子將獲得
http://www.discursive.com /jccook/的內容,并且以一個String來獲得響應。
??????? ?1?import?org.apache.commons.httpclient.HttpClient;
?2?import?org.apache.commons.httpclient.HttpException;
?3?import?org.apache.commons.httpclient.HttpMethod;
?4?import?org.apache.commons.httpclient.methods.GetMethod;
?5?
?6?HttpClient?client?=?new?HttpClient(?);
?7?String?url?=?"http://www.discursive.com/jccook/";
?8?HttpMethod?method?=?new?GetMethod(?url?);
?9?
10?try?{
11?????client.executeMethod(?method?);
12?
13?????if(?method.getStatusCode(?)?==?HttpStatus.SC_OK?)?{
14?????????String?response?=?method.getResponseBodyAsString(?);
15?????????System.out.println(?response?);
16?????}
17?}?catch(?HttpException?he?)?{
18?????System.out.println(?"HTTP?Problem:?"?+?he.getMessage(?)?);
19?}?catch(?IOException?ioe?)?{
20?????System.out.println(?"IO?Exeception:?"?+?ioe.getMessage(?)?);
21?}?finally?{
22?????method.releaseConnection(?);
23?????method.recycle(?);
24?}
???? 這段代碼用HTTP GET方法獲得了
http://www.discursive.com/jccook/的內容。如果響應的狀態碼是HttpStatus.SC_OK(即200),下列響應將被輸出到控制臺:
<html>
?<head>
??<title>JCCook?Example</title>
?</head>
?<body>
??<h1>Hello?World!</h1>
?</body>
</html>
討論:
??????? 注意這段代碼中對異常的處理。執行一個簡單的HTTP GET需要捕捉兩個異常:HttpException和IOException。如果是發生HTTP協議錯誤時,將拋出HttpException異常;如果是發生有關網絡的錯誤時,將拋出IOException異常。這一章后面的例子將會忽略對異常的處理。你應該要知道每一次調用executeMethod()都要用適當的try/catch塊包裹。
??????? GetMethod類是HttpMethod接口的一種實現。HttpMethod會被HttpClient所調用。HttpMethod實現類的生命周期是很簡單的:一個HttpMethod實例被創建,然后被HttpClient調用;一旦響應被檢測到以后,HttpMethod釋放連接并被回收使用。當HttpMethod調用了recycle()方法,相當于發送了一個信號給系統表示這個HttpMethod實例可以再被使用。releaseConnection()方法指示HttpClient釋放掉與這個HttpMethod相關聯的連接。無論在使用HttpMethod實例的過程中發生了什么,都要調用releaseConnection()來釋放網絡資源。
??????? 一旦HttpClient的executeMethod方法被調用,你可以通過HttpMethod的getStatusCode()方法來獲得響應的狀態碼。這個方法返回一個int,對應于HttpStatus類的public static final 變量。HttpStatus類還包括下面一些常量:SC_OK(200),SC_NOT_FOUND(404),SC_INTERNAL_SERVER_ERROR(500),SC_MOVED_TEMPORARILY (302),SC_UNAUTHORIZED(401)等等。請參照HttpStatus的Javadoc來獲得所有的HTTP狀態列表。當服務器返回一個錯誤的HTTP狀態是,通常還會返回一小段信息。這一小段信息可以通過HttpMethod類的getStatusText()方法獲得。
?
參考:
?????? 可以從RFC2616(http://www.zvon.org/tmRFC/RFC2616/Output/index.html)獲得HTTP GET方法的官方定義;
?????? 要獲得HTTP 狀態碼的完整列表,請參見 HttpStatus Javadoc? (http://jakarta.apache.org/commons/ httpclient/apidocs/index.html)。