我不太了解变量如何在javax.el中工作:

// Implemented by the EL implementation:
ExpressionFactory factory = ExpressionFactory.newInstance();

// Implemented by the user:
ELContext context = ...;

Object result = factory.createValueExpression(context1, "${foo.bar}", Object.class).getValue1(context);

为什么需要两次传递上下文。是否可以传递两个不同的上下文?哪个用于什么目的?预期的结果是什么?
ValueExpression expr = factory.createValueExpression(context1, "${foo.bar}", Object.class).getValue(context2);

ExpressionFactory#createValueExpression / JSR-245的Javadoc解释说:
The FunctionMapper and VariableMapper stored in the ELContext are used to resolve
functions and variables found in the expression. They can be null, in which case
functions or variables are not supported for this expression. The object returned
must invoke the same functions and access the same variable mappings regardless
of whether the mappings in the provided FunctionMapper and VariableMapper
instances change between calling ExpressionFactory.createValueExpression()
and any method on ValueExpression.

此外,“JSR-245 2.0.7 EL变量”说明:
An EL variable does not directly refer to a model object that can then be resolved
by an ELResolver. Instead, it refers to an EL expression. The evaluation of that
EL expression gives the EL variable its value.

[...]

[...] in this [...] example:
<c:forEach var=“item” items=“#{model.list}”>
    <h:inputText value=“#{item.name}”/>
 </c:forEach>

创建“#{item.name}”表达式时,“item”变量被映射(在VariableMapper中)到某个ValueExpression实例,并且该表达式绑定到该ValueExpression实例。该ValueExpression如何创建以及如何绑定到“model.list”的不同元素?应该如何实施?有可能
一次创建ValueExpression并将其在每次迭代中重复使用:
 <!-- Same as above but using immediate evaluation -->
 <c:forEach var=“item” items=“${model.list}”>
    <h:inputText value=“${item.name}”/>
 </c:forEach>

ValueExpression e1 = factory.createExpression(context,"#{model.list}");
variableMapper.setVariable("item", ??);
ValueExpression e2 = factory.createExpression(context,"#{item.name}");
for(Object item : (Collection<?>) e1.getValue(context)) {
   ??
}

还是有必要为迭代创建新的ValueExpression:
ValueExpression e1 = factory.createExpression(context,"#{model.list}");
for(Object item : (Collection<?>) e1.getValue(context)) {
   variableMapper.setVariable("item", factory.createValueExpression(item,Object.class));
   ValueExpression e2 = factory.createExpression(context,"#{item.name}");
   Object name = e2.getValue(context);
   ...
}

最佳答案

为什么需要两次传递上下文。是否可以通过两个
不同的环境?哪个用于什么目的?
variableMapperfunctionMapper仅在解析时使用(factory.createMethod(...)),而elResolver在评估期间使用(expr.getValue(...))。使用不同的上下文来解析和评估表达式很好。

创建“#{item.name}”表达式时,“item”变量为
映射(在VariableMapper中)到某些ValueExpression实例,并且
表达式绑定到此ValueExpression实例。这怎么样
创建的ValueExpression及其如何绑定到其中的不同元素
“model.list”?应该如何实施?

首先:忘记“变量”。如Javadoc中所述,它们的值是在解析时提供的表达式。将EL变量视为常量或宏。您无法重新定义它们,它们被“烧掉”到表达式中。

您需要的是EL的解决属性的机制。在下面的工作示例中,我使用的是JUEL中的ELContext实现,只是为了使事情变得简单,并着重于relevan EL的用法:

import java.util.Arrays;
import java.util.List;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;

import de.odysseus.el.util.SimpleContext;

public class Sof9404739 {
  /**
   * Sample item
   */
  public static class MyItem {
    String name;
    public MyItem(String name) {
      this.name = name;
    }
    public String getName() {
      return name;
    }
    public void setName(String name) {
      this.name = name;
    }
  }

  /**
   * Sample model
   */
  public static class MyModel {
    List<MyModel> list;
    public List<?> getList() {
      return list;
    }
    public void setList(List<MyModel> list) {
      this.list = list;
    }
  }

  /**
   * EL expression factory
   */
  static ExpressionFactory factory = ExpressionFactory.newInstance();

  public static void main(String[] args) {
    /**
     * Simple EL context implementation from JUEL
     */
    ELContext context = new SimpleContext();

    /**
     * Define the two expressions
     */
    ValueExpression listExpr =
      factory.createValueExpression(context, "#{model.list}", List.class);
    ValueExpression nameExpr =
      factory.createValueExpression(context, "#{item.name}", String.class);

    /**
     * This looks like a variable, but it isn't - it's a "root property"
     */
    context.getELResolver().setValue(context, null, "model", new MyModel());

    /**
     * Just for fun, initialize model's list property via EL, too
     */
    context.getELResolver().setValue(context, "model", "list",
        Arrays.asList(new MyItem("alice"), new MyItem("bob")));

    /**
     * Evaluate expressions like c:forEach
     */
    for (Object item : (List<?>) listExpr.getValue(context)) {
      /**
       * For each item, define the "item" (root) property
       */
      context.getELResolver().setValue(context, null, "item", item);
      System.out.println(nameExpr.getValue(context)); // "alice", "bob"
    }
  }
}

关于java - javax.el API中的变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9404739/

10-12 04:54