Pergunta

Eu tenho um bean Java como este:

class Person {
  int age;
  String name;
}

Eu gostaria de iterar sobre uma coleção de estes feijões em um JSP, mostrando cada pessoa em uma linha da tabela HTML, e na última linha da tabela Eu gostaria de mostrar o total de todas as idades.

O código para gerar as linhas da tabela será algo parecido com isto:

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

No entanto, eu estou lutando para encontrar uma maneira de calcular o total idade que será mostrado na linha final sem recorrer ao código scriptlet , alguma sugestão?

Foi útil?

Solução

Nota: Eu tentei combinando respostas para fazer uma lista abrangente. Eu mencionei nomes quando necessário para dar crédito onde é devido.

Existem muitas maneiras de resolver este problema, com vantagens / desvantagens associadas a cada:

Pure JSP Solução

Como ScArcher2 mencionado acima, uma solução muito fácil e simples para o problema é para implementá-lo diretamente na JSP assim:

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

O problema com esta solução é que o JSP torna-se confuso para o ponto onde você poderia muito bem ter Scriplets introduzidas. Se você antecipar que todo mundo olhando para a página será capaz de seguir a lógica rudimentar presente é uma boa escolha.

solução EL Pure

Se você já está no EL 3.0 (Java EE 7 / Servlet 3.1), usar o novo suporte para córregos e 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()}

Funções JSP EL

Outra forma de saída do total sem introduzir código scriplet em sua JSP é usar uma função EL. funções EL permitem que você chamar um método estático público de uma classe pública. Por exemplo, se você gostaria de interagir sobre sua coleção e somar os valores que você pode definir um método estático público chamado sum (Lista de pessoas) em uma classe pública, talvez chamados PersonUtils. Em seu arquivo TLD você colocaria a seguinte declaração:

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

Dentro de sua JSP você escreveria:

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

JSP EL Funções ter alguns benefícios. Eles permitem que você use métodos Java existentes sem a necessidade de código para uma interface específica (Custom Tag Libraries). Eles também são compactos e não irá confundir a programação não-pessoa orientada.

Tag personalizado

No entanto, outra opção é para rolar a sua própria etiqueta personalizada. Esta opção irá envolver o mais configuração, mas vai dar o que eu acho que você está esentially procurando, absolutly não scriptlets. Um tutorial bom para usar marcas personalizadas simples podem ser encontradas em http : //java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

As etapas envolvidas incluem subclasse 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 a marca em um arquivo 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 a taglib no topo de sua JSP:

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

e utilize a tag:

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

Exibição Tag

Como ZMF mencionado anteriormente, você também pode usar a tag de exibição, embora você terá que incluir as bibliotecas apropriadas:

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

Outras dicas

Você está tentando somar todas as idades?

Você poderia calculá-lo em seu controlador e só exibir o resultado no jsp.

Você pode escrever um tag personalizado para fazer o cálculo.

Você pode calcular-la no jsp utilizando JSTL assim.

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

ScArcher2 tem o mais simples solução . Se você queria algo mais compacto possível, você pode criar uma biblioteca de tag com uma função de "soma" nele. Algo como:

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

Em seu TLD:

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

Em seu JSP, você teria algo como:

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

${f:sum(personList)}

É um pouco hacky, mas em seu código controlador você poderia simplesmente criar um objeto Pessoa manequim com o total nele!

Como você recuperar seus objetos? HTML permite definir um elemento que vai sentar-se na parte inferior de todos os dados você, portanto você poderia apenas definir o total de separadamente da Pessoa objetos e sua saída será na página tal como está, sem qualquer computação na página JSP.

Você pode iterar sobre uma coleção usando JSTL de acordo com a seguinte

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

se é um mapa que você pode fazer no seguinte

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

Calculando Totais / ou em outros resumos no controlador - não no JSP -. É realmente fortemente preferível

Use o código de Java e uma abordagem MVC, por exemplo framework Spring MVC, em vez de tentar fazer muito em JSP ou JSTL; fazendo cálculo significativa nesses idiomas é fraco e lento, e faz suas páginas JSP muito menos claro.

Exemplo:

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

Design-decisão sábia -. Em qualquer lugar um total for necessário, pode conseguir próximo mês ser estendida para exigir uma média, a mediana, o desvio padrão

cálculos JSTL e sumarização são pouco segurando juntos, em apenas recebendo um total. Você realmente vai querer cumprir quaisquer outras exigências sumárias no JSTL? Creio que a resposta é NÃO -. E que, portanto, a decisão de design correto é calcular no Controller, como igualmente / mais simples e definitivamente mais plausível-requisitos extensível

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top