2

有没有办法以编程方式在 java 代码中注册自定义 taglib 引用?
我正在使用 JSF 1.2_09,丰富的面孔 3.3.3,jsf-facelets 1.1.14。

具体来说:

在这段代码中,jsf 表达式语言用于为我们做一些工作,比如在一个字段中连接 2 个结果或类似的东西..

FacesContext ctx = FacesContext.getCurrentInstance();
Application app = ctx.getApplication();
ExpressionFactory ef = app.getExpressionFactory();
ELContext elContext = ctx.getELContext();
ValueExpression valueExpression = new OverrideValueExpression(singleResult.getClass(), singleResult);
elContext.getVariableMapper().setVariable("row", valueExpression);

for (int i = 0; i < jsfDisplayValue.size(); i++){
    Object value = ef.createValueExpression(elContext, jsfDisplayValue.get(i), Object.class).getValue(ctx.getELContext());
//Do something with value...
}

例如,元素 ofjsfDisplayValue可以是:
“#{row.name} #{row.surname}”、“#{row.age}”、"#{tagfoo:fooFunction(row.age)}"...
当表达式包含函数(如高亮显示)时会出现问题tagfoo:fooFunction

堆栈跟踪:

javax.el.ELException: Function 'tagfoo:fooFunction' not found
    at org.apache.el.lang.ExpressionBuilder.visit(ExpressionBuilder.java:198)
    at org.apache.el.parser.SimpleNode.accept(SimpleNode.java:147)
    at org.apache.el.lang.ExpressionBuilder.prepare(ExpressionBuilder.java:155)
    at org.apache.el.lang.ExpressionBuilder.build(ExpressionBuilder.java:173)
    at org.apache.el.lang.ExpressionBuilder.createValueExpression(ExpressionBuilder.java:217)
    at org.apache.el.ExpressionFactoryImpl.createValueExpression(ExpressionFactoryImpl.java:67)

tagfooELContext 无法识别自定义函数,由于ELContext 未知,因此无法解析该函数​​。如何在 java 类中注册 taglib 引用,以便 ELContext 可以识别自定义函数?

在 JSF 页面上,我会这样做:

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:tagfoo="http://tagfoo.org/tags">  

PS
我的自定义函数在 jsf 页面上正常工作。

4

1 回答 1

2

对不起,我来晚了,但我今天偶然发现了同样的问题。

检查 ElContext 和 FunctionMapper 实例,我发现它们肯定是标准抽象类的自定义实现。

由于我想保持我的代码可移植性,我决定不参与为特定实现编写代码,并且由于抽象类只定义了读取合同并省略了写入方面,所​​以我只编写了一个自定义 FunctionMapper。这是有意义的代码:

public void register(String prefix, String function, Method method) {
    register.put(prefix + ":" + function, method);
}

@Override
public Method resolveFunction(String prefix, String localName) {
    if (register.containsKey(prefix + ":" + localName)) {
        return register.get(prefix + ":" + localName);
    }
    for (FunctionMapper it : delegates) {
        final Method current = it.resolveFunction(prefix, localName);
        if (current != null) {
            return current;
        }
    }
    return null;
}

通过包装标准 FunctionMapper,我可以轻松添加自己的函数并保持标准环境正常。在我的例子中,我也必须编写一个自定义的 ElContext 实现,它基本上克隆了默认的 ElContext 并只包装了 FunctionMapper。

我对结果很满意,希望这会有所帮助。

于 2013-07-21T16:38:08.877 回答