Javax.el,ELResolver:解析变量之间的依赖关系
iam正在构建一个小型应用程序来处理变量。 第一步是解决变量之间的简单依赖关系。 我无法使事情正常运行。 我可以解析非常简单的声明,比如a=10,但如果它变得稍微复杂一点,就会失败,比如: a=b;b=10。 我将代码缩减为以下几行:Javax.el,ELResolver:解析变量之间的依赖关系,java,variables,jboss,el,Java,Variables,Jboss,El,iam正在构建一个小型应用程序来处理变量。 第一步是解决变量之间的简单依赖关系。 我无法使事情正常运行。 我可以解析非常简单的声明,比如a=10,但如果它变得稍微复杂一点,就会失败,比如: a=b;b=10。 我将代码缩减为以下几行: import javax.el.BeanELResolver; import javax.el.ELContext; import javax.el.ELResolver; import javax.el.ExpressionFactory; import jav
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。
有没有什么a做错了,或者你知道我运行代码的方法吗
感谢您的建议我已经深入研究了EL实现,它对表达式创建和映射的顺序非常敏感 当创建时,它将解析表达式并使用绑定从此处解析的任何表达式。因此,当您设置a时,它将不会解析b,因为它尚未设置 结果,
#{b}
解析为null,然后强制为Float,结果为0.0
以下代码解析为值10.0:
请注意,这与从中解析变量时发生的情况不同
我使用了一个不同的实现(EL2.2;JavaEE6等价),但我希望JBoss实现中会有类似的行为。我找到了一个解决方案,它可以像我需要的那样工作。它不依赖于排序,并以任何复杂度解析变量:
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"));
}
}
公共类ElVariableResolver扩展了ELResolver{
[...]
受保护的最终HashMap变量smap=新HashMap();
公共ElVariableResolver(最终集合变量){
this.variables=新的HashSet(变量);
迭代器迭代器=变量。迭代器();
while(iterator.hasNext()){
变量v=迭代器.next();
this.variablesMap.put(v.getName(),v);
}
[...]
final FunctionMapperImpl functionMapper=新函数MapPerImpl();
this.expressionFactory=new ExpressionFactoryImpl();
this.elContext=createELContext(this,functionMapper);
}
专用静态ELContext createELContext(最终ELResolver解析器、最终FunctionMapper FunctionMapper){
返回新的ELContext(){
最终variableMapprimpl variableMapper=新的variableMapprimpl();
@凌驾
公共ELResolver getELResolver(){
返回解析器;
}
@凌驾
公共函数映射器getFunctionMapper(){
返回函数映射器;
}
@凌驾
公共VariableMapper getVariableMapper(){
返回变量映射器;
}
};
}
公共对象getVariableValue(最终变量){
字符串el;
最后的班级类型;
最终字符串值=variable.getValue();
开关(variable.getVariableType()){
案件编号:
el=value.trim();
类型=Float.class;
打破
[...]
最终字符串表达式=String.format(“${%s}”,el);
ValueExpression ve=expressionFactory.createValueExpression(this.elContext,表达式,类型);
对象结果=ve.getValue(this.elContext);
返回结果;
}
}
@凌驾
公共对象getValue(ELContext上下文、对象基、对象属性){
if((base==null)和&(property!=null)){
变量v=this.variablesMap.get(属性);
如果(v!=null){
返回此.getVariableValue(v);
}
}
返回“待办事项”;
}
}
公共类ElVariableResolverTest扩展了TestCase{
私有最终变量l=新变量(“l”,数字,“M”);
私有最终变量m=新变量(“m”,数字,“N”);
私有最终变量n=新变量(“n”,数字,“10”);
专用可变分解器;
公共资产评估(){
最终列表变量=数组.asList(l,m,n);
分解器=新的ElVariableResolver(变量);
assertEquals(新浮点(10),解析器.getVariableValue(“L”);
}
}
我注意到您只使用了一个。通常,您会创建一个,如中所示。您好,我已经阅读了您提到的示例,并在我的代码中尝试了类似的计算。如果我设置a=10和b=5,我可以创建一个类似${a+b}的表达式,它的结果是正确的:15。但是这个例子没有显示我如何链接变量a=b;b=10。即使有一个复合的解决方案,我仍然没有得到正确的结果。
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"));
}
}