Javax.el,ELResolver:解决变量之间的依赖关系

时间:2014-02-26 11:00:29

标签: java variables jboss el

构建一个小应用程序来处理变量。 第一步是解决变量之间的简单依赖关系。 我无法让事情正常运行。 我可以解决非常简单的声明,如a = 10,但如果它变得更复杂,它总是会失败,如: A = B; B = 10。 我将代码缩减为以下几行:

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。 是否有任何错误,或者您是否知道我可以运行代码的方式?

感谢您提出任何建议

2 个答案:

答案 0 :(得分:0)

我已经深入研究了EL实现,它对表达式创建和映射的排序很敏感。

ExpressionFactory创建ValueExpression时,它会解析表达式并使用VariableMapper绑定从那里解析的任何表达式。因此,当您设置 a 时,它将无法解析 b ,因为它尚未设置。

结果,#{b}解析为 null ,然后将其强制转换为 Float ,结果为 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实现中有类似的行为。

答案 1 :(得分: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"));
  } 
} 
相关问题