以编程方式注册taglib引用

时间:2013-04-25 12:10:27

标签: jsf el jsf-1.2 taglib

有没有办法以编程方式在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...
}

例如jsfDisplayValue的元素可以是:
“#{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)

ELContext无法识别自定义函数,并且无法解析该函数​​,因为ELContext不知道tagfoo。 如何在java类中注册taglib引用,以便ELContext可以识别自定义函数?

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

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

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

1 个答案:

答案 0 :(得分: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。

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