Рассчитать общую сумму всех чисел в цикле c: forEach - PullRequest
17 голосов
/ 19 сентября 2008

У меня есть такой Java-бин:

class Person {
  int age;
  String name;
}

Я бы хотел перебрать коллекцию этих bean-компонентов в JSP, показывая каждого человека в строке таблицы HTML, а в последней строке таблицы я хотел бы показать общее количество всех возрастов.

Код для генерации строк таблицы будет выглядеть примерно так:

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

Однако я изо всех сил пытаюсь найти способ подсчета общего возраста, который будет показан в последней строке , не прибегая к коду скриптлета , есть предложения?

Ответы [ 7 ]

38 голосов
/ 19 сентября 2008

Примечание: Я попытался объединить ответы, чтобы составить полный список. Я упомянул имена, где это уместно, чтобы дать кредит, где это причитается.

Есть много способов решить эту проблему, с плюсами / минусами, связанными с каждым:

Чистое решение 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), используйте новую поддержку потоков и лямбд :

<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 без необходимости кодирования для определенного пользовательского интерфейса (библиотеки пользовательских тегов). Они также компактны и не смущают не ориентированного на программирование человека.

Пользовательский тег

Еще один вариант - свернуть свой собственный тег. Эта опция будет включать в себя большую часть настроек, но даст вам то, что вы, по-моему, ищете, абсолютно без скриплетов. Хороший учебник по использованию простых пользовательских тегов можно найти по адресу 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, вы также можете использовать тег display, хотя вам нужно будет включить соответствующие библиотеки:

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

4 голосов
/ 19 сентября 2008

Вы пытаетесь сложить все возрасты?

Вы можете рассчитать его в вашем контроллере и отобразить результат только в jsp.

Вы можете написать собственный тег для выполнения расчетов.

Вы можете рассчитать его в jsp, используя jstl следующим образом.

<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}
3 голосов
/ 19 сентября 2008

Проверить отображение тега. http://displaytag.sourceforge.net/11/tut_basic.html

1 голос
/ 19 сентября 2008

ScArcher2 имеет самое простое решение . Если вы хотите что-то как можно более компактное, вы можете создать библиотеку тегов с функцией sum. Что-то вроде:

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

В вашем ДВУ:

<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 голосов
/ 30 марта 2013

Расчет итогов / или других сводок в контроллере, а не в JSP, действительно очень предпочтителен.

Используйте Java-код и подход MVC, например Spring MVC Framework, вместо того, чтобы пытаться сделать слишком много в 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? Я полагаю, что ответ НЕТ - и поэтому правильное проектное решение - рассчитать в Контроллере как одинаково / более простые и определенно более правдоподобные расширяемые требования.

0 голосов
/ 04 мая 2012

вы можете перебрать коллекцию с помощью JSTL в соответствии со следующим

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

если это карта, которую вы можете сделать на следующем

<c:forEach items="${numMap}" var="entry">
  ${entry.key},${entry.value}<br/>
</c:forEach>
0 голосов
/ 19 сентября 2008

Это немного странно, но в коде вашего контроллера вы можете просто создать фиктивный объект Person с общим количеством в нем!

Как вы получаете ваши объекты? HTML позволяет вам установить элемент , который будет находиться в нижней части любых ваших данных, поэтому вы можете просто установить итоговое значение отдельно от объектов Person и выводить его на страницу как есть, без каких-либо вычисления на странице JSP.

...