我有一个 JSP 需要打印一些文本,这些文本是通过获取循环迭代器并将其提供给另一个对象(Spring bean)产生的,例如:
<c:forEach var="myVar" items="${myVars}">
<c:out value="anotherObject.getFoo(myVar)"/>
</c:forEach>
显然上面的代码是无效的,因为 JSTL .
运算符只允许无参数调用。我可以看到以下问题的解决方案:
1) 小脚本
<c:forEach var="myVar" items="${myVars}">
<%
SomeType myVar = (SomeType) pageContext.getAttribute("myVar");
SomeOtherType anotherObject = (SomeOtherType) pageContext.getAttribute("anotherObject");
YetAnotherType result = anotherObject.getFoo(myVar);
pageContext.setAttribute("result", result);
%>
<c:out value="${result}"/>
</c:forEach>
这里明显的缺点是 JSP 代码污染和普遍的丑陋。
2) 编写一个标签来执行在 scriptlet 中执行的任何操作。过度工程的典型例子,糟糕!
3) 分解myVars
的集合并将每个myVar
替换为dynamic proxy ,其中的 InvocationHandler
将添加额外的无参数方法,以通过 anotherObject
进行所有 getFoo()
调用。所有这些都将在 Controller 中完成,因此 JSP 将保持干净并且 myVar
保持不变。但价格是多少?
我无法将 .getFoo()
方法添加到 myVar
中,因为它不适合放在那里并且会破坏关注点分离。
看起来在 JSP/EL 2.2 中可以传递参数,但我使用的是 Tomcat 6.0.29,它只捆绑了 EL 2.1 API。
问题:有人可以针对这种情况提出最简洁的方法吗?
最佳答案
一个简单的仅适用于 Java 的“trick-fix”,也适用于旧的 JSTL 版本,
并且不需要额外的 taglibs/config/dependencies/frameworks 等。
是“包装”你想从 JSTL 调用的函数
在从 Map
类扩展的类中,并覆盖其 get()
方法。
作为一个最小的例子,如果你想从 JSTL 调用 Math.sin()
函数,
你会定义一个类:
public class Sine extends HashMap<Double, Double> {
private static final long serialVersionUID = 1L; // Avoids compiler-warning
@Override
public Double get(Object arg) {
Double x = (Double) arg;
return Math.sin(x);
}
}
然后在您的 Action execute() 方法中,您执行:
...
request.setAttribute("sine", new Sine());
...
然后在jsp中你可以说:
${sine[0.75]}
计算值Math.sin(0.75)
JSTL 会将变量 sine 视为 Map
,但您可以从 get() 方法计算并返回任何您喜欢的内容。
我想如果你的函数有多个参数,它会变得更复杂一点, 但也应该有解决方法:)
关于java - 在 JSTL 循环中调用带参数的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6760575/