2008-09-19 42 views
16

Tengo un bean Java como esto:Calcular la suma total de todos los números en c: forEach bucle

class Person { 
    int age; 
    String name; 
} 

me gustaría iterar sobre una colección de estos granos en una JSP, mostrando 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á algo como esto:

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

Sin embargo, estoy luchando para encontrar una manera de calcular el total de la edad que se muestra en la última fila sin recurrir al código scriptlet, alguna sugerencia?

+0

¿Está sumando todas las edades y exhibiendo eso en la última fila? – ScArcher2

Respuesta

36

Nota: Probé la combinación de respuestas para hacer una lista completa Mencioné nombres donde correspondía para dar crédito donde es debido.

Hay muchas maneras de resolver este problema, con ventajas/desventajas asociadas con cada uno:

Solución JSP puro

Como ScArcher2 se mencionó anteriormente, una solución muy fácil y sencilla al problema es para implementar directamente en el JSP como así:

<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 de esta solución es que el JSP se vuelve confuso hasta el punto en que también podría tener i scriplets presentados. Si anticipa que todos los que miran la página podrán seguir el rudimentario presente de la lógica, es una buena elección.

solución EL puro

Si ya estás en EL 3.0 (Java EE 7/servlet 3.1), utilizar un nuevo soporte para streams and lambdas: Funciones

<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

Otra forma de generar el total sin introducir código scriplet en su JSP es usar una función EL. Las funciones EL le permiten llamar a un método público estático en una clase pública. Por ejemplo, si desea iterar sobre su colección y sumar los valores, podría definir un método público estático denominado sum (List people) en una clase pública, quizás llamada PersonUtils. En el archivo TLD que le coloque 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 su JSP que iba a escribir:

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

Funciones JSP El presentan algunas ventajas. Le permiten usar métodos Java existentes sin la necesidad de codificar a una IU específica (Bibliotecas de etiquetas personalizadas). También son compactos y no confundirán a una persona no orientada a la programación.

etiqueta personalizada

Sin embargo, otra opción es la de rodar su propia etiqueta personalizada. Esta opción implicará la mayor cantidad de configuración, pero le dará lo que creo que está buscando esencialmente, absolutamente ningún scriptlets.Un tutorial agradable para el uso de etiquetas personalizadas simples se puede encontrar en http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

Los pasos a seguir incluyen subclases 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; 
    } 
} 

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

declarar la taglib en la parte superior de su JSP:

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

y utilice la etiqueta:

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

visualización de la etiqueta

Como ZMF se mencionó anteriormente, también se puede utilizar la etiqueta de presentación, aunque tendrá que incluir las bibliotecas apropiadas:

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

+0

Calcular los totales en el controlador, no en el JSP, es realmente preferible. Utilice un marco MVC, por ejemplo, Spring, en lugar de intentar hacer demasiado en JSP o JSTL. –

0

Es un poco raro, pero en el código de tu controlador puedes crear un objeto Person simulado con el total en él.

¿Cómo estás Recuperación de los objetos? HTML le permite establecer un elemento <TFOOT> 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.

3

¿Estás tratando de sumar todas las edades?

Puede calcularlo en su controlador y solo mostrar el resultado en el jsp.

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

se puede calcular en el JSP con 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} 
1

ScArcher2 tiene el más simple solution. Si quiere algo tan compacto como sea posible, puede crear una biblioteca de etiquetas con una función de "suma". Algo así como:

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

En su TLD:

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

En su JSP, tendría algo así como:

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

${f:sum(personList)} 
+0

No es versátil: qué propiedad o función-resultado suma() debe calcular, no se puede especificar. O ha recorrido un largo camino para hacer un operador de un solo propósito, o tiene que ir más allá y hacerse hacky con la reflexión para hacerlo versátil. –

+0

Respuesta breve y correcta: calcule el resumen en el Controlador, no en el JSP. –

0

se puede repetir sobre una colección usando JSTL según lo siguiente

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

si se trata de un mapa que puede hacer en los totales siguientes

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

Cálculo/u otros resúmenes en el controlador - no en el JSP - es realmente mucho más preferible.

Utilice el código Java & un enfoque MVC, p. Ej. Spring MVC framework, en lugar de intentar hacer demasiado en JSP o JSTL; haciendo cálculos significativos en estos idiomas es débil & 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); 
    } 
} 

Diseño decisión en cuanto - en cualquier lugar se requiere un total, podría concebiblemente próximo mes se extenderá a requerir una media, una mediana, una desviación estándar.

cálculos JSTL & resumen apenas se mantienen juntos, en apenas obtener un total. ¿Realmente va a querer cumplir con los requisitos de resumen adicionales 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, como requisitos igualmente/más simples y definitivamente más plausibles: extensibles.

Cuestiones relacionadas