Pregunta

Tengo un bean Java como este:

class Person {
  int age;
  String name;
}

Me gustaría iterar sobre una colección de estos beans en un JSP, mostrando a cada persona en una fila de la tabla HTML, y en la última fila de la tabla me gustaría mostrar el total de todas las edades.

El código para generar las filas de la tabla se verá así:

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

Sin embargo, estoy luchando por encontrar una manera de calcular la edad total que se mostrará en la última fila. sin recurrir al código scriptlet, ¿alguna sugerencia?

¿Fue útil?

Solución

Nota: Intenté combinar respuestas para hacer una lista completa.Mencioné nombres cuando correspondía para dar el crédito que correspondía.

Hay muchas formas de resolver este problema, con los pros y los contras asociados a cada una:

Solución JSP pura

Como ScArcher2 mencionó anteriormente, una solución muy fácil y sencilla al problema es implementarlo directamente en JSP de la siguiente manera:

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

El problema con esta solución es que el JSP se vuelve confuso hasta el punto de que bien podría haber introducido scriptlets.Si prevé que todos los que vean la página podrán seguir la lógica rudimentaria presente, es una buena elección.

Solución EL pura

Si ya está en EL 3.0 (Java EE 7 / Servlet 3.1), use el nuevo soporte para corrientes y 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()}

Funciones JSP EL

Otra forma de generar el total sin introducir código script en su JSP es utilizar una función EL.Las funciones EL le permiten llamar a un método estático público en una clase pública.Por ejemplo, si desea iterar sobre su colección y sumar los valores, puede definir un método estático público llamado suma(List people) en una clase pública, quizás llamada PersonUtils.En su archivo tld colocaría la siguiente declaración:

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

Dentro de tu JSP escribirías:

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

Las funciones JSP EL tienen algunos beneficios.Le permiten utilizar métodos Java existentes sin la necesidad de codificar en una interfaz de usuario específica (bibliotecas de etiquetas personalizadas).También son compactos y no confundirán a una persona que no esté orientada a la programación.

Etiqueta personalizada

Otra opción más es enrollar su propia etiqueta personalizada.Esta opción implicará la mayor parte de la configuración, pero le brindará lo que creo que esencialmente está buscando, absolutamente nada de scriptlets.Puede encontrar un buen tutorial para usar etiquetas personalizadas simples en http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

Los pasos involucrados incluyen la subclasificación de 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;
   }
}

Defina la etiqueta en un archivo 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>

Declare el taglib en la parte superior de su JSP:

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

y usa la etiqueta:

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

Etiqueta de visualización

Como zmf mencionó anteriormente, también puedes usar la etiqueta de visualización, aunque necesitarás incluir las bibliotecas apropiadas:

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

Otros consejos

¿Estás intentando sumar todas las edades?

Podrías calcularlo en tu controlador y solo mostrar el resultado en el jsp.

Puede escribir una etiqueta personalizada para hacer el cálculo.

Puedes calcularlo en jsp usando jstl como este.

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

Consulte la etiqueta de visualización. http://displaytag.sourceforge.net/11/tut_basic.html

ScArcher2 tiene el más simple solución.Si quisiera algo lo más compacto posible, podría crear una biblioteca de etiquetas con una función de "suma".Algo como:

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

En tu TLD:

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

En tu JSP, tendrías algo como:

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

${f:sum(personList)}

Es un poco complicado, pero en el código de tu controlador podrías simplemente crear un objeto Persona ficticio con el total.

¿Cómo estás recuperando tus objetos?HTML le permite establecer un <PIE> elemento que se ubicará en la parte inferior de cualquier dato que tenga, por lo tanto, puede establecer el total por separado de los objetos Persona y mostrarlo en la página tal como está sin ningún cálculo en la página JSP.

puedes iterar sobre una colección usando JSTL de acuerdo con lo siguiente

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

Si es un mapa, puedes hacerlo en lo siguiente.

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

Realmente es preferible calcular los totales u otros resúmenes en el controlador, no en el JSP.

Utilice código Java y un enfoque MVC, por ejemplo, el marco Spring MVC, en lugar de intentar hacer demasiado en JSP o JSTL;Hacer cálculos importantes en estos lenguajes es débil y lento, y hace que sus páginas JSP sean mucho menos claras.

Ejemplo:

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

En cuanto al diseño, en cualquier lugar donde se requiera un total, es posible que el próximo mes se extienda para requerir un promedio, una mediana y una desviación estándar.

Los cálculos y resúmenes de JSTL apenas se mantienen juntos, al obtener solo un total.¿Realmente querrá cumplir con más requisitos de resumen en JSTL?Creo que la respuesta es NO y que, por lo tanto, la decisión de diseño correcta es calcular en el Controlador los requisitos igualmente/más simples y definitivamente más plausibles y extensibles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top