我有一个变量${path}
,其中包含字符串“a.b.c”,我想将其评估为对象${object}的属性:
如果我尝试${object[path]}
,它会抛出“未找到属性”
我会写成:
${object.a.b.c}
我可以根据“.”进行拆分。并执行 for 循环 object = object[split[i]]
但是我觉得很丑。
我想要类似的东西:
eval("object."${path})
这可能吗?
最佳答案
您可以使用 bean 或函数作为中介来创建和评估 ValueExpression:
package hoteval;
import javax.el.*;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
import javax.servlet.jsp.*;
@ApplicationScoped
@Named
public class Expr {
public Object eval(PageContext pageContext, String expression) {
ExpressionFactory factory = JspFactory.getDefaultFactory()
.getJspApplicationContext(pageContext.getServletContext())
.getExpressionFactory();
ELContext elCtxt = pageContext.getELContext();
ValueExpression ve = factory
.createValueExpression(elCtxt, expression, Object.class);
return ve.getValue(elCtxt);
}
}
调用语法如下所示:
${expr.eval(pageContext, "${bean.prop}")}
针对 Glassfish 4.0 编写/测试。
<小时/>上面的代码只是一个例子。要提供 ${expr.eval(pageContext, object, path)}
形式的表达式,其中 path 是 a.b.c
,可以将其重写为:
public Object eval(PageContext pageContext, Object o, String path) {
expression = "${_tmpRootObject."+expression+"}";
pageContext.setAttribute("_tmpRootObject", o);
//etc.
评估代码同样可以成为采用 ex:eval(...
形式的函数。
关于使用 ELResolver 的评论。
- 您可以将ElResolver添加到 JspApplicationContext (见上文)在 ServletContextListener .
- 它将在大多数其他解析器之前被调用 - see order .
- 但是现在您在 getValue(ELContext, Object, Object) 中遇到了一些问题。
- 对于
${object[path]}
你会得到 path 解析到的任何值,并且需要区分它和其他属性(bean 属性/映射值/等)。 ) - 只要检查基本类型不是 Map,查找包含
.
的字符串实例就足够了。 - 您可能必须拆分字符串并使用反射来查找属性。
- 我认为不支持嵌套计算(在ELResolver中解析ValueExpression),但我可能是错的。
- 对于
关于Java EL 评估 bean 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21909439/