计算c:forEach循环中所有数字的总和

时间:2020-03-06 14:26:34  来源:igfitidea点击:

我有一个像这样的Java Bean:

class Person {
  int age;
  String name;
}

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

生成表行的代码如下所示:

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

但是,我正在努力寻找一种方法来计算将在最后一行中显示的年龄总计,而无需借助scriptlet代码,有什么建议吗?

解决方案

这有点hacky,但是在控制器代码中,我们可以创建一个虚拟的Person对象,其中包含总数!

我们如何检索对象? HTML使我们可以设置<TFOOT>元素,该元素将位于我们拥有的任何数据的底部,因此,我们可以仅将总计与Person对象分开设置,并按原样在页面上输出,而无需在JSP页面上进行任何计算。

签出显示标签。 http://displaytag.sourceforge.net/11/tut_basic.html

我们要累加所有年龄吗?

我们可以在控制器中进行计算,而仅在jsp中显示结果。

我们可以编写一个自定义标签来进行计算。

我们可以像这样使用jstl在jsp中进行计算。

<c:set var="ageTotal" value="
class MySum {
public double sum(List list) {...}
}
" /> <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}

ScArcher2具有最简单的解决方案。如果我们想要尽可能紧凑的东西,可以创建一个带有" sum"功能的标签库。就像是:

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

在TLD中:

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

${f:sum(personList)}

在JSP中,我们将具有以下内容:

<c:set var="ageTotal" value="
<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()}
" /> <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解决方案

正如上面的ScArcher2所述,一个非常简单的解决方案是直接在JSP中实现它,如下所示:

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

该解决方案的问题在于,JSP可能会令人困惑,以至于我们可能还引入了scriplet。如果我们希望每个人都可以阅读该页面的基本逻辑,这是一个不错的选择。

纯EL解决方案

如果我们已经在使用EL 3.0(Java EE 7 / Servlet 3.1),请使用对流和lambda的新支持:

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

JSP EL函数

在不向JSP中引入脚本代码的情况下输出总计的另一种方法是使用EL函数。 EL函数使我们可以在公共类中调用公共静态方法。例如,如果我们想遍历集合并求和值,则可以在公共类(可能称为PersonUtils)中定义一个称为sum(List people)的公共静态方法。在tld文件中,我们将放置以下声明:

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;
   }
}

在JSP中,我们应该编写:

<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>

JSP EL函数有一些好处。它们使我们可以使用现有的Java方法,而无需编写特定的UI(自定义标签库)代码。它们也很紧凑,不会混淆非编程人员。

自定义标签

另一个选择是滚动我们自己的自定义标签。此选项将涉及最多的设置,但会为我们提供我认为我们基本上需要的内容,绝对没有scriptlet。可以在http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701中找到使用简单自定义标签的不错的教程。

涉及的步骤包括将TagSupport子类化:

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

在tld文件中定义标签:

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

在JSP的顶部声明taglib:

##代码##

并使用标签:

##代码##

显示标签

正如前面的zmf所提到的,尽管我们需要包括适当的库,但是我们也可以使用display标记:

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