OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言(Expression Language,簡稱為EL),通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。
第一次接觸OGNL是因為tapestry,tapestry使用ognl在頁面中綁定業務數據。。。
關于ognl的原理和一般使用規則,本文不作詳細描述,請自行參考http://www.ognl.org/
在工作流的實際開發中,常常會遇到這樣的情況,以經費申請流程為例,當申請金額<1000,流轉到科長審批環節034,當申請金額>1000,流轉到處長審批環節035。其ognl表達式可以這樣定義:ammount>1000?'035':'034'。其中ammount為該流程綁定業務模型JfsqModel.java的一個屬性。
現在我們的問題來了,在流程引擎中如何動態解析以上表達式的結果呢?這個時候,ognl的作用充分體現出來了,下面式我寫的一個ognl表達式解析類:
package cn.common;
import java.util.Map;
import ognl.DefaultMemberAccess;
import ognl.Ognl;
import ognl.OgnlException;
/**
* 解析ognl表達式工具類
*/
public class OgnlParser {
private Map context = null;
private Object target = null;
/**
* 默認構造函數,與當前class綁定
*/
public OgnlParser(){
context = Ognl.createDefaultContext(this);
target = this;
}
/**
* 構造函數,綁定目標class
* @param targetBean 綁定bean
*/
public OgnlParser(String className){
try {
target = Class.forName(className).newInstance();
context = Ognl.createDefaultContext(target);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 構造函數,綁定目標bean
* @param targetBean 綁定bean
*/
public OgnlParser(Object bean){
try {
target = bean;
context = Ognl.createDefaultContext(target);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param ognlExpression 標準的OGNL表達式
* @return
* @throws EecmisRuleException
*/
public Object getValue(String expression)throws EecmisRuleException{
DefaultMemberAccess aMemberAccess = new DefaultMemberAccess(true);
Ognl.setMemberAccess(context, aMemberAccess);
try {
return Ognl.getValue(expression,context,target);
} catch (OgnlException e) {
e.printStackTrace();
throw new EecmisRuleException("ognl表達式解析失敗:"+e.getMessage());
}
}
//TODO setValue
}
提供了三個構造函數建立context,即Ognl與特定bean的綁定. 然后調用public Object getValue(String expression)返回表達式的結果值,expression為標準的ognl表達式。
對上述實例來說,通過如下方式調用:
JfSqModel model = .....;
OgnlParser parser = new OgnlParser(model);
String nodeId =
(String)parser.getValue("ammount>1000?'035':'034'");
JfSqWF.switch(nodeId);