2014-02-26 34 views
1

iam構建一個小型應用程序來處理變量。 第一步是解決變量之間的簡單依賴關係。 我無法讓事情正常運行。 我可以解析非常簡單的聲明,如a = 10,但如果它稍微複雜一些,它總是失敗: a = b; B = 10。 我降低我的代碼下面幾行:Javax.el,ELResolver:解決變量之間的依賴關係

import javax.el.BeanELResolver; 
import javax.el.ELContext; 
import javax.el.ELResolver; 
import javax.el.ExpressionFactory; 
import javax.el.FunctionMapper; 
import javax.el.ValueExpression; 
import javax.el.VariableMapper; 

import org.jboss.el.ExpressionFactoryImpl; 
import org.jboss.el.lang.VariableMapperImpl; 


public void testEvalutation() throws Exception{ 

ExpressionFactory factory = new ExpressionFactoryImpl();  
ELContext context = new ELContext() { 
    final ELResolver elResolver = new BeanELResolver(); 
    final VariableMapper variableMapper = new VariableMapperImpl(); 
    public ELResolver getELResolver() { return elResolver; } 
    public FunctionMapper getFunctionMapper() { return null; } 
    public VariableMapper getVariableMapper() { return variableMapper; } 
}; 
ValueExpression a = factory.createValueExpression(context, "#{b}", Float.class); 
ValueExpression b = factory.createValueExpression(context, "#{c}", Float.class); 
ValueExpression c = factory.createValueExpression(context, "#{10}", Float.class); 

context.getVariableMapper().setVariable("a",a); 
context.getVariableMapper().setVariable("b",b); 
context.getVariableMapper().setVariable("c",c); 

ValueExpression expression = context.getVariableMapper().resolveVariable("a"); 
assertEquals(10f,expression.getValue(context)); 

}

結果爲 'a' 爲0.0。 是否有任何錯誤或你知道一種方式我可以讓我的代碼運行?

謝謝你的任何建議

+0

我注意到您只使用一個[BeanELResolver(http://docs.oracle.com/javaee/7/api/javax/el/ BeanELResolver.html)。通常,您可以創建一個[CompositeELResolver](http://docs.oracle.com/javaee/7/api/javax/el/CompositeELResolver.html),如[本博客文章]中所示(http://illegalargumentexception.blogspot。 co.uk/2008/04/java-using-el-outside-j2ee.html)。 – McDowell

+0

嗨,我已閱讀你提到的例子,並在我的代碼中嘗試了類似的評估。如果我設置a = 10和b = 5,我可以創建一個像$ {a + b}這樣的表達式,其結果是正確的結果:15.但是這個例子並不顯示如何鏈接到變量a = b; B = 10。即使使用CompositeELResolver,我仍然沒有得到正確的結果。 – user3355449

回答

0

我有一個挖成EL的實現,它是表達創作和映射的順序是敏感的。

ExpressionFactory創建ValueExpression時,它解析表達式並使用VariableMapper綁定從那裏解析的所有表達式。因此,當您設置a它不會解析b,因爲它尚未設置。

結果,#{b}解析爲,然後將其強制爲浮法0.0的結果。

下面的代碼解析爲價值10.0

ValueExpression c = factory.createValueExpression(context, "#{10}", Float.class); 
context.getVariableMapper().setVariable("c", c); 
ValueExpression b = factory.createValueExpression(context, "#{c}", Float.class); 
context.getVariableMapper().setVariable("b", b); 
ValueExpression a = factory.createValueExpression(context, "#{b}", Float.class); 
context.getVariableMapper().setVariable("a", a); 

ValueExpression expression = context.getVariableMapper().resolveVariable("a"); 
System.out.println(expression.getValue(context)); 

注意,這是從一個ELResolver解析變量時,會發生什麼不同。

我使用了不同的實現(EL 2.2; Java EE 6 equiv),但我期望在JBoss實現中有類似的行爲。

0

我發現了一個解決方案,可以像我需要的那樣工作。它不依賴於排序,並在任何複雜解決了變量:

public class ElVariableResolver extends ELResolver { 
[...] 
protected final HashMap<String, Variable> variablesMap = new HashMap<String, Variable>(); 

public ElVariableResolver(final Collection<Variable> variables) { 
    this.variables = new HashSet<Variable>(variables); 
    Iterator<Variable> iterator = variables.iterator(); 
    while (iterator.hasNext()) { 
     Variable v = iterator.next(); 
     this.variablesMap.put(v.getName(), v); 
    } 
    [...] 
    final FunctionMapperImpl functionMapper = new FunctionMapperImpl(); 
    this.expressionFactory = new ExpressionFactoryImpl(); 
    this.elContext = createELContext(this, functionMapper); 
    } 

private static ELContext createELContext(final ELResolver resolver, final FunctionMapper functionMapper) { 
    return new ELContext() { 
     final VariableMapperImpl variableMapper = new VariableMapperImpl(); 
     @Override 
     public ELResolver getELResolver() { 
     return resolver; 
     } 
     @Override 
     public FunctionMapper getFunctionMapper() { 
     return functionMapper; 
     } 
     @Override 
     public VariableMapper getVariableMapper() { 
     return variableMapper; 
     } 
    }; 
    } 

    public Object getVariableValue(final Variable variable) { 
    String el; 
    final Class<?> type; 
    final String value = variable.getValue(); 
    switch (variable.getVariableType()) { 
     case NUMBER: 
     el = value.trim(); 
     type = Float.class; 
     break; 
     [...] 
     final String expression = String.format("${%s}", el); 
     ValueExpression ve = expressionFactory.createValueExpression(this.elContext, expression, type); 
     Object result = ve.getValue(this.elContext); 
     return result; 
    } 
    } 

    @Override 
    public Object getValue(ELContext context, Object base, Object property) { 
    if ((base == null) && (property != null)) { 
     Variable v = this.variablesMap.get(property); 
     if (v != null) { 
     return this.getVariableValue(v); 
     } 
    } 
    return "TODO"; 
    } 
} 

public class ElVariableResolverTest extends TestCase{ 

    private final Variable l = new Variable("L",NUMBER,"M"); 
    private final Variable m = new Variable("M",NUMBER,"N"); 
    private final Variable n = new Variable("N",NUMBER,"10"); 
    private ElVariableResolver resolver; 

    public void testEvaluation() { 
    final List<Variable> variables = Arrays.asList(l,m,n); 
    resolver = new ElVariableResolver(variables); 
    assertEquals(new Float(10),resolver.getVariableValue("L")); 
    } 
}