Вычислить общую сумму всех чисел в цикле c: forEach

StackOverflow https://stackoverflow.com/questions/102964

Вопрос

У меня есть такой 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>

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

Это было полезно?

Решение

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

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

Чистое решение 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(Listpeople) в общедоступном классе, возможно, называемом 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

Другие советы

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

Вы можете вычислить его в своем контроллере и отобразить результат только в 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}

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top