Skip to content

8. A biblioteca de tags JSTL

8.0.1. Introdução

Considere a vista [erreurs.jsp], que apresenta uma lista de erros:

Image

Existem várias formas de escrever uma página deste tipo. Aqui, estamos apenas interessados na parte que exibe os erros. Uma solução é utilizar código Java, tal como foi feito:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page import="java.util.ArrayList" %>
 
<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
 
<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
        <%
          for(int i=0;i<erreurs.size();i++){
            out.println("<li>" + (String) erreurs.get(i) + "</li>\n");
        }//for
      %>
    </ul>
    <br>
    <form name="frmPersonne" method="post">
      <input type="hidden" name="action" value="retourFormulaire">
    </form>
    <a href="javascript:document.frmPersonne.submit();">
      <%= lienRetourFormulaire %>
    </a>
  </body>
</html>
 

A página JSP recupera a lista de erros da solicitação (linha 8) e exibe-a utilizando um loop Java (linhas 19–23). A página mistura código HTML e Java, o que pode ser problemático se a página precisar de ser mantida por um web designer que, geralmente, não compreende o código Java. Para evitar esta mistura, utilizam-se bibliotecas de tags para introduzir novas funcionalidades nas páginas JSP. Com a biblioteca de tags JSTL (Java Standard Tag Library), a visualização anterior passa a ser a seguinte:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
 
<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
            <c:forEach var="erreur" items="${erreurs}">
                <li>${erreur}</li>
            </c:forEach>
    </ul>
    <br>
    <form name="frmPersonne" method="post">
      <input type="hidden" name="action" value="retourFormulaire">
    </form>
    <a href="javascript:document.frmPersonne.submit();">
      ${lienRetourFormulaire}
    </a>
  </body>
</html>

A tag (linha 4)

<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>

indica a utilização de uma biblioteca de tags definida no ficheiro [/WEB-INF/c.tld]. Estas tags serão utilizadas no código da página, precedidas pela letra c (prefix="c"). Pode utilizar qualquer prefixo à sua escolha. Aqui, c significa [core]. Os prefixos permitem-lhe utilizar bibliotecas de tags que possam ter os mesmos nomes para determinadas tags. A utilização de um prefixo resolve qualquer ambiguidade. A nova página já não tem código Java nos dois locais onde anteriormente o tinha:

  • recuperação do modelo da página [errors, returnFormLink] (secção removida)
  • exibição da lista de erros (linhas 13–15)

O ciclo de exibição de erros foi substituído pelo seguinte código:


            <c:forEach var="erreur" items="${erreurs}">
                <li>${erreur}</li>
            </c:forEach>
  • A tag <forEach> é utilizada para definir um ciclo
  • A notação ${variável} é utilizada para apresentar o valor de uma variável

A tag <forEach> tem dois atributos aqui:

  • items="${errors}" especifica a coleção de objetos a ser iterada. Aqui, a coleção é o objeto errors. Onde é que isto se encontra? A página JSP procura um atributo chamado "errors" sucessivamente e na seguinte ordem:
    • o objeto [request], que representa o pedido enviado pelo controlador: request.getAttribute("errors")
    • o objeto [session], que representa a sessão do cliente: session.getAttribute("errors")
    • o objeto [application], que representa o contexto da aplicação web: application.getAttribute("errors")

A coleção designada pelo atributo **items** pode assumir várias formas: matriz, ArrayList*, objeto que implemente a interface List*, etc.

  • var="error" é utilizado para nomear o elemento atual da coleção que está a ser processada. O ciclo <forEach> será executado sucessivamente para cada elemento da coleção items. Dentro do ciclo, o elemento da coleção que está a ser processado será, portanto, referido aqui como error.

A sintaxe ${error} insere o valor da variável error no texto. Esta variável não é necessariamente uma string. O JSTL utiliza o método error.toString() para inserir o valor da variável error. Em vez da sintaxe ${error}, também pode utilizar a tag <c:out value="${error}"/>.

Voltando ao nosso exemplo de exibição de erros:

  • o controlador colocará uma ArrayList de mensagens de erro — ou seja, uma ArrayList de objetos String — na solicitação enviada à página JSP: request.setAttribute("errors", errors), onde errors é a ArrayList;
  • devido ao atributo items="${errors}", a página JSP irá procurar um atributo chamado errors, sucessivamente na solicitação, na sessão e na aplicação. Encontrá-lo-á na solicitação: request.getAttribute("errors") irá devolver o ArrayList colocado na solicitação pelo controlador;
  • A variável error do atributo var="error" irá, portanto, referir-se ao elemento atual da ArrayList, que é um objeto String. O método error.toString() irá inserir o valor desta String — neste caso, uma mensagem de erro — na saída HTML da página.

Os objetos na coleção processada pela tag <forEach> podem ser mais complexos do que simples strings. Tomemos o exemplo de uma página JSP que exibe uma lista de artigos:

1
2
3
4
5
6
7
            <c:forEach var="article" items="${listarticles}">
                <tr>
                    <td><c:out value="${article.nom}"/></td>
                    <td><c:out value="${article.prix}"/></td>
                    <td><a href="<c:url value="?action=infos&id=${article.id}"/>">Infos</a></td>
                </tr>
     </c:forEach>

onde [listarticles] é uma ArrayList de objetos do tipo [Article], que assumimos ser um JavaBean com os campos [id, name, price, currentStock, minimumStock], cada um destes campos tendo os seus próprios métodos get e set. O objeto [listarticles] foi colocado na solicitação pelo controlador. A página JSP anterior recupera-o a partir do atributo items da tag forEach. O objeto artigo atual (var="article") refere-se, portanto, a um objeto do tipo [Article]. Considere a tag na linha 3:

<c:out value="${article.nom}"/>

O que significa ${article.nom}? Na verdade, várias coisas, dependendo da natureza do objeto artigo. Para obter o valor de article.nom, a página JSP tentará duas coisas:

  1. article.getNom() - repare na grafia getNom para recuperar o campo name (padrão JavaBean)
  2. article.get("name")

O objeto [article] pode, portanto, ser um bean com um campo "name" ou um dicionário com uma chave "name".

Não há limites para a profundidade do objeto que está a ser processado. Assim, a tag

<c:out value="${individu.enfants[1].nom}"/>

permite-lhe processar um objeto [individu] do seguinte tipo:

class Individu{
    private String nom;
    private String prénom;
    private Individu[] enfants;
    // méthodes de la norme Javabean
    public String getNom(){ return nom;}
    public String getPrénom(){ return prénom;}
    public Individu getEnfants(int i){ return enfants[i];}
}

Para obter o valor de ${person.children[1].lastName}, a página JSP tentará vários métodos, incluindo este, que será bem-sucedido:

person.getChildren(1).getLastName() onde person se refere a um objeto do tipo Person.

8.0.2. Instalação e exploração da biblioteca JSTL

As explicações fornecidas acima serão suficientes para a aplicação em que estamos interessados, mas a biblioteca de tags JSTL oferece outras tags além das apresentadas. Para explorá-las, pode executar um tutorial incluído no pacote da biblioteca.

Iremos utilizar a implementação JSTL 1.1 do projeto [Jakarta Taglibs] disponível no URL [http://jakarta.apache.org/taglibs/] (maio de 2006):

O ficheiro ZIP descarregado contém o seguinte:

Image

Os dois ficheiros com a extensão .war são arquivos de aplicações web:

  • standard-doc: documentação sobre as tags JSTL
  • standard-examples: exemplos de utilização das tags

Iremos implementar esta aplicação no Tomcat. Iniciamos o Tomcat utilizando a opção apropriada no menu [Iniciar], depois introduzimos o URL [http://localhost:8080] e seguimos a ligação [Tomcat Manager]:

Image

É-nos então apresentada uma página de autenticação. Iniciamos sessão como manager/manager ou admin/admin, conforme mostrado na secção 2.3.3.

Image

É-nos apresentada uma página que lista as aplicações atualmente implementadas no Tomcat:

Image

Podemos adicionar uma nova aplicação utilizando os formulários na parte inferior da página:

Image

Utilizamos o botão [Browse] para selecionar um ficheiro .war para implementar.

Image

A captura de ecrã não o mostra, mas selecionámos o ficheiro [standard-examples.war] da distribuição JSTL descarregada. O botão [Deploy] guarda e implementa esta aplicação no Tomcat.

Image

A aplicação [/standard-examples] foi implementada com sucesso. Vamos iniciá-la:

Image

Recomenda-se aos leitores que sigam os vários links fornecidos nesta página quando procurarem exemplos de como utilizar as tags JSTL.

A aplicação [standard-doc] pode ser implementada da mesma forma a partir do ficheiro [standard-doc.war]. Esta aplicação fornece acesso a informações bastante técnicas sobre a biblioteca JSTL. É de menor interesse para principiantes.

8.0.3. Utilização do JSTL numa aplicação Web

Nos exemplos fornecidos com a biblioteca JSTL 1.2, as páginas JSP começam com a seguinte tag:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Já nos deparámos com esta tag na Secção 8.1.1 e fornecemos uma breve explicação:

  • [uri]: URI (Uniform Resource Identifier) onde se encontram as definições das tags utilizadas na página. Este URI será utilizado pelo servidor web quando a página JSP for traduzida em código Java para se tornar um servlet. É também utilizado por ferramentas de desenvolvimento de páginas web para verificar a sintaxe correta das tags utilizadas na página ou para fornecer sugestões de autocompletar. Quando começa a digitar uma tag, uma ferramenta familiarizada com a biblioteca pode sugerir ao utilizador possíveis atributos para essa tag.
  • [prefix]: prefixo que identifica estas tags na página

O URI [http://java.sun.com/jsp/jstl/core] não pode ser utilizado se não estiver ligado à Internet pública. Neste caso, pode colocar o ficheiro de definição de tags localmente. Vários desses ficheiros são fornecidos com a distribuição do JSTL 1.2 na pasta [tld] (Tag Language Definition):

Image

O JSTL é, na verdade, uma coleção de bibliotecas de tags. Utilizaremos apenas a biblioteca [c.tld], conhecida como a biblioteca «core». Colocaremos o ficheiro [c.tld] mencionado acima na pasta [WEB-INF] das nossas aplicações:

Image

e incluiremos a seguinte tag nas nossas páginas JSP para declarar a utilização da biblioteca «core»:

<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>

Embora a utilização de bibliotecas de tags nos permita evitar colocar código Java nas páginas JSP, estas tags são, naturalmente, traduzidas para código Java quando a página JSP é compilada num servlet Java. Utilizam classes definidas em dois ficheiros JAR [jstl.jar, standard.jar] que se encontram na pasta [lib] da distribuição JSTL:

Image

Estes dois ficheiros JAR são colocados na pasta [WEB-INF/lib] das nossas aplicações:

Image

Agora temos os conhecimentos básicos para abordar a próxima versão da nossa aplicação de exemplo.