有没有办法以编程方式在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页面上正常工作。
答案 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。
我对结果非常满意,希望这会有所帮助。