2008-09-19 179 views
16

我有一个Java bean是这样的:计算总和:forEach循环

class Person { 
    int age; 
    String name; 
} 

我想遍历这些豆类在JSP的集合,呈现在每个人HTML表格行,并且在表格的最后一行中,我想显示所有年龄段的总数。

生成表中的行会看起来像这样的代码:

<c:forEach var="person" items="${personList}"> 
    <tr><td>${person.name}<td><td>${person.age}</td></tr> 
</c:forEach> 

不过,我在努力寻找一种方法来计算总的年龄将在最后一行所示,而不诉诸来以scriptlet代码,有什么建议吗?

+0

您是将所有年龄加起来并显示在最后一行吗? – ScArcher2 2008-09-19 15:45:08

回答

36

注:我试图合并的答案,使一个全面的清单。我在适当的地方提到了可以在哪里提供贷款的名称。

有许多方法来解决这个问题,以及与每个相关联的优点/缺点:

纯JSP解

如ScArcher2如上所述,很容易和简单的解决方案的问题是直接在JSP实现它像这样:

<c:set var="ageTotal" value="${0}" /> 
<c:forEach var="person" items="${personList}"> 
    <c:set var="ageTotal" value="${ageTotal + person.age}" /> 
    <tr><td>${person.name}<td><td>${person.age}</td></tr> 
</c:forEach> 
${ageTotal} 

这种解决方案的问题是,JSP变得扑朔迷离的地步,你可能也有我引入的脚本。如果您预计每个看到该页面的人都能够遵循目前的基本逻辑,那么这是一个不错的选择。

纯EL解决方案

如果你已经在EL 3.0(Java EE的7/Servlet的3.1),使用streams and lambdas新的支持:

<c:forEach var="person" items="${personList}"> 
    <tr><td>${person.name}<td><td>${person.age}</td></tr> 
</c:forEach> 
${personList.stream().map(person -> person.age).sum()} 

JSP EL功能

另一种在不将脚本代码引入JSP的情况下输出总和的方法是使用EL函数。 EL函数允许您在公共类中调用公共静态方法。例如,如果您想迭代您的集合并对这些值求和,则可以在公共类中定义一个名为sum(List people)的公共静态方法,也许称为PersonUtils。在您的TLD文件,你会放置以下声明:

<function> 
    <name>sum</name> 
    <function-class>com.example.PersonUtils</function-class> 
    <function-signature>int sum(java.util.List people)</function-signature> 
</function> 

在你的JSP你可以这样写:

<%@ taglib prefix="f" uri="/your-tld-uri"%> 
... 
<c:out value="${f:sum(personList)}"/> 

JSP EL功能有几个好处。它们允许您使用现有的Java方法,而无需编写特定的UI(自定义标签库)。它们也非常紧凑,不会混淆非编程导向的人员。

自定义标记

另一个选择是推出自己的自定义标签。这个选项将涉及最多的设置,但会给你我想你实际上寻找的东西,绝对没有scriptlet。使用简单的自定义标签的一个很好的教程可以在http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

涉及的步骤可以找到包括子类TagSupport类:

public PersonSumTag extends TagSupport { 

    private List personList; 

    public List getPersonList(){ 
     return personList; 
    } 

    public void setPersonList(List personList){ 
     this.personList = personList; 
    } 

    public int doStartTag() throws JspException { 
     try { 
     int sum = 0; 
     for(Iterator it = personList.iterator(); it.hasNext()){ 
      Person p = (Person)it.next(); 
      sum+=p.getAge(); 
     } 
     pageContext.getOut().print(""+sum); 
     } catch (Exception ex) { 
     throw new JspTagException("SimpleTag: " + 
      ex.getMessage()); 
     } 
     return SKIP_BODY; 
    } 
    public int doEndTag() { 
     return EVAL_PAGE; 
    } 
} 

定义标签的TLD文件:

<tag> 
    <name>personSum</name> 
    <tag-class>example.PersonSumTag</tag-class> 
    <body-content>empty</body-content> 
    ... 
    <attribute> 
     <name>personList</name> 
     <required>true</required> 
     <rtexprvalue>true</rtexprvalue> 
     <type>java.util.List</type> 
    </attribute> 
    ... 
</tag> 

上声明的taglib JSP顶端:

<%@ taglib uri="/you-taglib-uri" prefix="p" %> 

并使用标签:

<c:forEach var="person" items="${personList}"> 
    <tr><td>${person.name}<td><td>${person.age}</td></tr> 
</c:forEach> 
<p:personSum personList="${personList}"/> 

显示标签

由于ZMF前面提到的,你也可以使用显示标签,虽然你将需要包括相应的库:

http://displaytag.sourceforge.net/11/tut_basic.html

0

这有点不好意思,但是在你的控制器代码中,你可以创建一个虚拟Person对象,其中包含总数!

你如何检索你的对象?通过使用HTML,您可以设置一个<TFOOT>元素,该元素将位于您拥有的任何数据的底部,因此您可以从Person对象中单独设置总数,并在页面上将其原样输出,而无需在JSP页面上进行任何计算。

3

您是否试图将所有年龄加起来?

你可以在你的控制器中计算它,只显示结果在jsp中。

您可以编写自定义标签来进行计算。

你可以用jstl在jsp中计算它。

<c:set var="ageTotal" value="${0}" /> 
<c:forEach var="person" items="${personList}"> 
    <c:set var="ageTotal" value="${ageTotal + person.age}" /> 
    <tr><td>${person.name}<td><td>${person.age}</td></tr> 
</c:forEach> 
${ageTotal} 
1

ScArcher2是最简单的solution。如果你想要尽可能紧凑的东西,你可以创建一个带有“和”功能的标签库。喜欢的东西:

class MySum { 
public double sum(List list) {...} 
} 

在你的TLD:

<function> 
<name>sum</name> 
<function-class>my.MySum</function-class> 
<function-signature>double sum(List)</function-signature> 
</function> 

在你的JSP,你会碰到这样的:

<%@ taglib uri="/myfunc" prefix="f" %> 

${f:sum(personList)} 
+0

不通用 - 无法指定哪些属性或函数结果sum()用于计算。要么你已经走了很长的路要做一个单一目的的操作员,或者你必须走得更远,并通过反思使其变得多才多艺。 – 2013-03-30 05:47:40

+0

简短而正确的答案:在Controller中计算摘要,而不是在JSP中。 – 2013-03-30 05:48:01

0

你可以遍历按以下方式使用JSTL进行收集

<c:forEach items="${numList}" var="item"> 
     ${item} 
</c:forEach> 

如果它是一个地图,你可以在以下

<c:forEach items="${numMap}" var="entry"> 
    ${entry.key},${entry.value}<br/> 
</c:forEach> 
0

计算合计/或其他控制器做总结 - 而不是在JSP - 真的是强烈优选的。

使用Java代码&的MVC方法,例如Spring MVC框架,而不是试图在JSP或JSTL中做太多;在这些语言中进行重要的计算是很慢的,并且使您的JSP页面更加不清晰。

例子:

class PersonList_Controller implements Controller { 
    ... 
    protected void renderModel (List<Person> items, Map model) { 
     int totalAge = 0; 
     for (Person person : items) { 
      totalAge += person.getAge(); 
     } 
     model.put("items", items); 
     model.put("totalAge", totalAge); 
    } 
} 

设计决策英明 - 任何地方总要求,可以想见,下个月扩展到需要的平均值,中位数,标准偏差。

JSTL计算&总结几乎没有在一起,只是得到一个总。你真的想在JSTL中满足任何进一步的总结要求吗?我相信答案是否定的 - 因此,正确的设计决策是在控制器中进行计算,因为同等/更简单以及绝对更合理的要求是可扩展的。