jsp - Calcule la suma total de todos los números en c: para cada ciclo
foreach jstl (7)
Nota: Intenté combinar las 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 y desventajas asociadas con cada uno:
Solución Pure JSP
Como ScArcher2 mencionado anteriormente, una solución muy fácil y simple al problema es implementarlo directamente en el 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 en que también podría haber introducido scriplets. 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 Pure EL
Si ya tiene EL 3.0 (Java EE 7 / Servlet 3.1), use la nueva compatibilidad para transmisiones 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 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 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 su JSP usted escribiría:
<%@ taglib prefix="f" uri="/your-tld-uri"%>
...
<c:out value="${f:sum(personList)}"/>
Las funciones JSP EL tienen algunos beneficios. 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
Otra opción es rodar tu 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 buen tutorial para usar etiquetas personalizadas simples se puede encontrar 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}"/>
Mostrar etiqueta
Como zmf se mencionó anteriormente, también podría usar la etiqueta de visualización, aunque deberá incluir las bibliotecas apropiadas:
Tengo un Java Bean 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 tendrá el siguiente aspecto:
<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 forma de calcular el total de edad que se mostrará en la última fila sin recurrir al código scriptlet , ¿alguna sugerencia?
puede 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 que puede hacer en el siguiente
<c:forEach items="${numMap}" var="entry">
${entry.key},${entry.value}<br/>
</c:forEach>
¿Estás tratando de sumar todas las edades?
Puedes calcularlo en tu controlador y solo mostrar el resultado en 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}
Echa un vistazo a la etiqueta de visualización. http://displaytag.sourceforge.net/11/tut_basic.html
Es un poco raro, pero en tu código de controlador puedes crear un objeto Person simulado con el total en él.
¿Cómo recuperas tus 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 Person y enviarlo a la página tal como está sin ningún cálculo en la página JSP.
Calcular los totales u otros resúmenes en el controlador, no en el JSP, es realmente preferible.
Utilice el código Java y un enfoque MVC, por ejemplo, el marco Spring MVC, en lugar de tratar de hacer demasiado en JSP o JSTL; hacer cálculos significativos en estos idiomas 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);
}
}
Diseño por decisión: en cualquier lugar que se requiera un total, es posible que el siguiente mes se extienda para requerir un promedio, una mediana, una desviación estándar.
Los cálculos y el resumen de JSTL apenas se mantienen juntos, al 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.
ScArcher2 tiene la solución más simple. Si quiere algo tan compacto como sea posible, puede 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 su JSP, tendría algo como:
<%@ taglib uri="/myfunc" prefix="f" %>
${f:sum(personList)}