2008-09-19 7 views
16

J'ai un bean Java comme ceci:somme totale de tous les nombres dans c: boucle forEach

class Person { 
    int age; 
    String name; 
} 

J'aimerais itérer sur une collection de ces haricots dans une page JSP, montrant chaque personne dans un Ligne du tableau HTML, et dans la dernière rangée du tableau, je voudrais montrer le total de tous les âges.

Le code pour générer les lignes de la table ressemblera à quelque chose comme ceci:

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

Cependant, je me bats pour trouver un moyen de calculer le total d'âge qui sera affiché dans la dernière rangée sans avoir recours au code de scriptlet, des suggestions?

+0

Additionnez-vous tous les âges et affichez cela dans la dernière rangée? – ScArcher2

Répondre

36

Note: J'ai essayé la combinaison des réponses à faire une liste complète. J'ai mentionné les noms, le cas échéant, pour donner du crédit là où il est dû.

Il y a plusieurs façons de résoudre ce problème, avec avantages/inconvénients associés à chaque:

pure JSP Solution

Comme ScArcher2 mentionné ci-dessus, une solution très facile et simple au problème est de mettre en œuvre directement dans la JSP comme si:

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

le problème avec cette solution est que la JSP devient déroutant au point où vous pourriez aussi bien avoir i scriplets ntroduits. Si vous prévoyez que tout le monde regarde la page sera en mesure de suivre la logique rudimentaire présente, c'est un bon choix.

solution pure EL

Si vous êtes déjà sur EL 3.0 (Java EE 7/Servlet 3.1), utiliser un nouveau support pour streams and 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()} 

JSP EL Fonctions

Une autre façon de générer le total sans introduire de code scriplet dans votre JSP consiste à utiliser une fonction EL. Les fonctions EL vous permettent d'appeler une méthode statique publique dans une classe publique. Par exemple, si vous souhaitez parcourir votre collection et additionner les valeurs, vous pouvez définir une méthode statique publique appelée sum (List people) dans une classe publique, peut-être appelée PersonUtils. Dans votre fichier tld vous placeriez la déclaration suivante:

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

Au sein de votre JSP vous écrivez:

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

Fonctions JSP EL ont quelques avantages. Ils vous permettent d'utiliser des méthodes Java existantes sans avoir besoin de coder pour une interface utilisateur spécifique (bibliothèques de balises personnalisées). Ils sont également compacts et ne vont pas confondre une personne non orientée vers la programmation.

personnalisé Tag

Une autre option est de faire rouler votre propre étiquette personnalisée. Cette option impliquera le plus de configuration mais vous donnera ce que je pense que vous cherchez, absolument pas de scriptlets.Un tutoriel agréable pour l'utilisation des balises simples personnalisés peuvent être trouvés à http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

Les étapes comprennent subclassing 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; 
    } 
} 

Définir la balise dans un fichier 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> 

Déclarez la taglib sur le dessus de votre JSP:

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

et d'utiliser le tag:

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

Affichage Tag

Comme ZMF mentionné plus haut, vous pouvez également utiliser l'étiquette d'affichage, bien que vous devrez inclure les bibliothèques appropriées:

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

+0

Calcul des totaux dans le contrôleur - pas dans la JSP - est vraiment fortement préférable. Utilisez un framework MVC, par exemple Spring, au lieu d'essayer d'en faire trop dans JSP ou JSTL. –

0

C'est un peu hacky, mais dans votre code de contrôleur, vous pouvez simplement créer un objet Person fictif avec le total dedans!

Comment récupérez-vous vos objets? HTML vous permet de définir un élément <TFOOT> qui sera placé au bas de toutes les données que vous avez, donc vous pouvez simplement définir le total séparément des objets Person et le sortir tel quel sur la page sans aucun calcul sur la page JSP.

3

Essayez-vous d'additionner tous les âges?

Vous pouvez le calculer dans votre contrôleur et afficher uniquement le résultat dans le jsp.

Vous pouvez écrire une étiquette personnalisée pour faire le calcul.

Vous pouvez le calculer dans le fichier jsp en utilisant jstl comme ceci.

<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 a la plus simple solution. Si vous voulez quelque chose d'aussi compact que possible, vous pouvez créer une bibliothèque de balises avec une fonction "somme". Quelque chose comme:

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

Dans votre TLD:

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

Dans votre JSP, vous auriez quelque chose comme:

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

${f:sum(personList)} 
+0

Non polyvalent - ce que la propriété ou le résultat de la fonction somme() est destiné à calculer, ne peut pas être spécifié. Soit vous avez fait le long chemin pour faire un opérateur à usage unique, ou vous devez aller plus loin et devenir hacky avec la réflexion pour le rendre polyvalent. –

+0

Réponse courte et correcte: calculez le résumé dans le contrôleur, pas dans JSP. –

0

vous pouvez itérer sur une collection en utilisant JSTL selon

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

si elle est une carte que vous pouvez faire sur les points suivants

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

Calcul de totaux/ou d'autres résumés dans le contrôleur - pas dans la JSP - est vraiment fortement préférable.

Utilisez le code Java & une approche MVC, par exemple Spring MVC, au lieu d'essayer d'en faire trop dans JSP ou JSTL; faire des calculs significatifs dans ces langues est faible, et rend vos pages JSP beaucoup moins claires.

Exemple:

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

décision sage Design - où un total est nécessaire, le mois prochain pourrait éventuellement être étendu à exiger une moyenne, une médiane, un écart-type.

Les calculs JSTL & ne tiennent pas ensemble, juste pour obtenir un total. Allez-vous vraiment vouloir répondre à d'autres exigences de résumé dans JSTL? Je crois que la réponse est NON - et que, par conséquent, la décision de conception correcte est de calculer dans le contrôleur des exigences également plus simples et certainement plus plausibles.

Questions connexes