Java 在JSTL循环中调用带参数的方法

Java 在JSTL循环中调用带参数的方法,java,jsp,jstl,Java,Jsp,Jstl,我有一个JSP,它需要打印一些文本,这些文本是通过使用循环迭代器并将其提供给另一个对象(SpringBean)生成的,类似于: <c:forEach var="myVar" items="${myVars}"> <c:out value="anotherObject.getFoo(myVar)"/> </c:forEach> 这里明显的缺点是JSP代码污染和普遍的丑陋 2) 编写一个标记,该标记执行Scriptlet中的任何操作。过度工程的典型例子,恶

我有一个JSP,它需要打印一些文本,这些文本是通过使用循环迭代器并将其提供给另一个对象(SpringBean)生成的,类似于:

<c:forEach var="myVar" items="${myVars}">
   <c:out value="anotherObject.getFoo(myVar)"/>
</c:forEach>
这里明显的缺点是JSP代码污染和普遍的丑陋

2) 编写一个标记,该标记执行Scriptlet中的任何操作。过度工程的典型例子,恶心

3) 分解一组
myVar
并用一个
InvocationHandler
替换每个
myVar
,其中的
InvocationHandler
将添加额外的无参数方法,通过
另一个对象进行所有
getFoo()
调用。所有这些都将在控制器中完成,因此JSP将保持干净,
myVar
保持不变。但代价是什么

我不能将
.getFoo()
方法添加到
myVar
中,因为它不适合那里,并且会破坏关注点的分离

在JSP/EL2.2中似乎可以传递参数,但我使用的是Tomcat6.0.29,它只绑定了EL2.1API


问题:有人能为这种情况推荐最干净的方法吗?

如果您不能遵守Scriptlet(您的备选方案1),我会为其创建一个自定义标记(您的备选方案2)或一个自定义EL函数。我不认为这是“过度工程”,而是将可用的工具用于其预期目的


不过,我不喜欢你的备选方案3。如果有什么区别的话,那就是过度工程化,而且它会使你的系统变得不必要的复杂,让其他人更难遵循。遵守您在其中工作的规范和标准的意图。不要因此而使事情变得更困难或更复杂。

以下是我最后的做法

我传递的不是
SomeType
实例的集合,而是映射。映射键是相同的
SomeType
s,值是特定于控制器的内部类的实例,我们称之为
SomeTypeSupplement

SomeTypeSupplement
添加了必要的无参数getter,并将所有内容连接在一起。JSP现在可以迭代映射条目,并且能够通过JSTL检索数据


这样我就避免了代理,避免了不必要的TLD,保持JSP整洁和合理的类型安全。

为什么不在后端Java代码中编写对象列表,然后使用JSP来显示它呢?

另一个选择是使用。它比jstl好得多。

一个简单的纯Java“技巧修复”,也适用于较旧的jstl版本, 并且不需要额外的taglib/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);
    }
}
然后在jsp中,您可以说:

  ${sine[0.75]}
计算数值
Math.sin(0.75)

JSTL将变量sine视为
映射
,但您可以通过get()方法计算并返回任何您喜欢的内容

我想如果你的函数有不止一个参数,它会变得更复杂,
但也应该有解决办法:)

想在Rop的最后一个(按时间)答案中添加一条评论,但缺少“声誉”,所以我有一个答案

我很快就对这样一个映射有了同样的想法,但我试图使它更普遍地可用,拥有一个“DynamicMap”,DynamicMapCalculator接口,并允许您将任何方法调用包装到这样一个映射中(无需每次都进行新的映射实现,只需使用匿名类实例化)

如果您感兴趣,这将是主题:


我对这里的观点很感兴趣:这是一件你可以毫无良心地做的事情吗?

如果为每个方法调用编写JSP标记不是过度工程,那么我不知道过度工程是什么。我不是说选项#3是好的/首选的,但选项#2也不是。好吧,如果您有很多实例需要显式调用JSP:s中的方法,那么我建议您改进MVC模式,努力创建一个只保存数据的更干净的模型层。然后将任何逻辑移入控制器层。myVar对象就是您所称的Model(在本例中仅保存数据的对象-持久性数据)的一个确切示例。然而,我需要可视化的数据来自完全不同的源(“
另一个对象”
”),需要这个模型类。您将逻辑移到控制器层的建议接近于我建议的选项#3,您说这是个坏主意。我指的是您关于动态代理以实现某些类似AOP的行为的想法,我仍然认为这过于复杂,随着时间的推移很难维护。我会重构您的支持代码(控制器),从“anotherObject”实例中提取所需信息,并将其存储为更干净的模型对象。我认为您还不了解我面临的问题<代码>${myVars}
已经引用了一个对象列表。请投票选择一个有创意的替代方案(以及我个人的首选方案),但我们不能总是选择如何提供视图。非常感谢。对于那些在model和view.addObject(“sine”,newsine())中是新手的人;等效于request.setAttribute的SpringMVC版本(“sine”,newsine());
...
request.setAttribute("sine", new Sine());
...
  ${sine[0.75]}