Curso Java e JSTL: Tags para facilitar o desenvolvimento JSP
O mundo java para web vive de JSPs. Não há muito como fugir delas, afinal, é a forma que temos para representar a camada visual das nossas aplicações.
O problema é que JSPs tendem a ser complicadas, afinal, ela contém código HTML, CSS, Javascript (que tendem a ser bem extensos), além de código Java que lida com lógica de apresentação (mostrar ou não mostrar uma tabela, uma informação, por exemplo).
Tópicos:
- Taglib core do JSTL
- FOR EACH - Criando loops
- IF - Tomando decisões
- URL - Montando as URL's
- FMT - Formatando datas e números
- FTM - Exibindo mensagens internacionalizáveis
- IMPORT - Reutilizando páginas
Taglib core do JSTL
Muitas JSPs fazem uso do que chamamos de Scriptlets. Scriptlets são código Java, espalhados dentro da JSP. Veja, por exemplo, a JSP abaixo.
A ideia da JSTL é justamente facilitar a vida do programador na hora de escrever JSPs. A JSTL é hoje um padrão entre os desenvolvedores Java, e é muito utilizada. Existem diferentes "pacotes" na JSTL. Nesse momento, estamos estudando o pacote "core". Precisamos importá-lo na JSP:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
FOR EACH - Criando loops
eja o que temos nesse loop: uma lista chamada produtoList
, que foi mandada para a JSP pela aplicação; o loop então passeia pela lista e cria a variável p
, que contém cada um dos produtos. O loop, por sua vez, gera um monte de tr
, preenchendo a tabela.
<c:forEach var="p" items="${produtoList}">
<tr id="produto${p.id}">
<td>${p.nome}</td>
<td>${p.preco}</td>
<td>${p.descricao}</td>
<td>${p.dataInicioVenda.time}</td>
</tr>
</c:forEach>
Veja só como nosso código final ficou muito mais fácil de ser entendido. É fácil de ver onde a tag "forEach" começa e termina; imprimir os valores do produto também ficou muito mais enxuto com o uso da EL.
Outro detalhe importante a reparar é o ${produtoList}
. Veja que usamos a notação com o caractere cifrão. Chamamos isso de EL (Expression Language). É assim que lidamos com as variáveis. Ali estamos dizendo que os ítens vem dessa variável.
IF - Tomando decisões
De maneira análoga à tag c:forEach
, temos a tag c:if
. Ela recebe o mesmo parâmetro que um if convencional: a condição do if. Veja no código abaixo, onde usamos o c:if
e passamos a condição para ele, usando novamente a EL:
<c:if test="${p.usado}">
<td>Sim</td>
</c:if>
<c:if test="${not p.usado}">
<td>Não</td>
</c:if>
A EL é extremamente poderosa. Podemos fazer diferentes tipos de comparação nela. No código acima, fizemos apenas
${p.usado}
. Na próxima, fizemos ${not p.usado}
, ou seja, onot
vai negar a condição. Podemos fazer comparações usando ==, >, <, e etc.
E o c:if
faz o resto do trabalho. Se a expressão for verdadeira, ele vai mostrar o que estiver dentro do bloco.
Mas de olhar o código acima dá pra ver um problema: não existe um "else" na JSTL! A solução é fazermos igual fizemos acima: colocando um novo if, com a condição contrária. Para alguns, isso faz com que o código da JSP fique mais complicado do que deveria.
Uma alternativa ao if, é a tag c:choose
. Essa tag parece-se muito com um switch da linguagem Java. Com ela, podemos ter várias condições, e por fim, um "default". Veja no código abaixo como o choose funciona:
<c:choose>
<c:when test="${p.usado}">
<td>Sim</td>
</c:when>
<c:otherwise>
<td>Não</td>
</c:otherwise>
</c:choose>
Veja que a tag "choose" é composta por diversas tags "when". Por fim, se nenhuma condição for satisfeita, então a tag "otherwise" é processada.
URL - Montando as URL's
Outro grande problema do mundo de desenvolvimento web é gerar URLs. URLs são sempre relativas ao lugar atual que elas estão. Por exemplo, se a URL atual do site for www.meusite.com.br/produto/lista
, e tivermos um link que aponta para novo
, essa URL é relativa ao caminho atual, e ao clicar no link, a nova URL será www.meusite.com.br/produto/novo
.
Para resolver esse problema, o correto é sempre gerarmos URLs completas para nossa aplicação. Mas isso também pode ser difícil, já que no mundo Java é bem comum o "contexto" mudar. Contexto é como chamamos o "começo da URL", que diz ao Tomcat qual projeto deve rodar; no nosso caso, é "produtos". Se colocarmos na URL, por exemplo, "/produtos/produto/novo", ela funcionaria. O problema é que se "produtos" mudar, precisaremos mudar em todos os lugares.
Por esse motivo, a melhor maneira para se gerar uma URL é por meio da JSTL. Ela saberá sempre como montar a URL certa! Veja o HTML que temos, que gera a URL para a página de novo produto:
<c:url value="/produto/formulario" var="urlAdicionar" />
<a href="${urlAdicionar}">Adicionar um produto</a>
Repare que a URL que montamos começa com uma "/", e é relativo a raiz do projeto. Se você olhar o HTML gerado, verá que a URL será "/produtos/produto/formulario", pois a JSTL percebeu que existe um "context root" e automaticamente o colocou na URL!
Use sempre c:url para gerar seus links. Ele é extremamente útil quando esses links estão em componentes reutilizáveis. Aí, dependendo da página que você coloca o componente, a URL é diferente. Com a JSTL, isso deixa de ser um problema.
FMT - Formatando datas e números
É comum querermos exibir a data em formato amigável, mais fácil de ser lido, por exemplo, dia/mês/ano.
A JSTL possui um outro pacote, focado nesse tipo de formatação. Esse é o pacote "fmt". Ele contém uma taglib chamada "formatDate", que faz isso para nós. Ela recebe o padrão que deve formatar a data (por exemplo, dd/MM/yyyy que representa dia/mês/ano) e a data a ser exibida.
Veja o código abaixo:
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<td><fmt:formatDate pattern="dd/MM/yyyy" value="${p.dataInicioVenda.time}" /></td>
Repare que fizemos ${p.dataInicioVenda.time}
. Precisamos passar o time
, porque o formatDate
recebe um objeto do tipo Date
, e nossa data está representada como um Calendar.
Outra coisa que podemos formatar são números. Exibimos ali o preço do produto. Podemos usar a taglib "formatNumber" para formatar o número:
<fmt:formatNumber value="${p.preco}" type="currency"/>
Caso não funcione pode ser porque seu servidor está em uma máquina em outra língua, para resolver basta:
<fmt:setLocale value="pt-BR" />
<fmt:formatNumber value="${p.preco}" minFractionDigits="2" type="currency" />
Ambas as funções podem receber diversos parâmetros e diferentes maneiras de formatar datas e números. Consultar a documentação oficial é importante e ajuda bastante.
Com a nova EL, podemos invocar métodos dos objetos que estamos manipulando. Uma boa utilidade para isso é, por exemplo, fazer uso dos métodos de formatação da String. Troque a linha que imprime o nome do produto, pela seguinte:
<td>${p.nome.toUpperCase()}</td>
Veja que aqui, colocamos "()", pois estamos invocando um método que não segue o padrão "getX()".
FTM - Exibindo mensagens internacionalizáveis
Uma outra tarefa que é bastante simplificada pela JSTL é a internacionalização. Com ela, conseguimos colocar as mensagens das várias línguas em um arquivo, e ela é responsável por trocar a língua de acordo com o usuário que acessa o site.
Para isso, precisamos fazer algumas coisas. A primeira delas é definir o nome desse arquivo dentro do web.xml. Veja o trecho de configuração abaixo:
<context-param>
<param-name>
javax.servlet.jsp.jstl.fmt.localizationContext
</param-name>
<param-value>messages</param-value>
</context-param>
O parâmetro param-value
contém o nome do arquivo que terá as frases em várias línguas. Esse arquivo deve ter a extensão .properties
e deve ficar disponível no classpath
. Para isso, salvaremos o messages.properties
dentro da pasta src
.
Vamos colocar o conteúdo desse arquivo:
mensagem.bemvindo=Bem vindo ao curso de JSTL
mensagem.novoProduto=Adicionar um novo produto
Repare que esse arquivo é composto de chave e valor. E é por meio da chave que capturaremos a mensagem que queremos exibir.
Se quisermos exibir a mensagem de bem vindo, faremos:
<fmt:message key="mensagem.bemvindo" />
O link, por exemplo, podemos alterar para:
<c:url value="/produto/formulario" var="linkProduto" />
<a href="${linkProduto}"><fmt:message key="mensagem.novoProduto" /></a>
Se quisermos que nosso site responda para inglês, precisamos ter um arquivo chamado messages_en.properties
, com o mesmo conteúdo do original em português. O "en" indica que é o arquivo em inglês; se colocássemos "de", seria em alemão, e assim por diante. Por exemplo:
mensagem.bemvindo=Welcome to the JSTL course!
mensagem.novoProduto=Add a new product
Se você mudar a língua do seu browser e atualizar a página, repare que as mensagens virão em inglês! Veja só como a JSTL faz a parte de internacionalização ser simples!
IMPORT - Reutilizando páginas
Com a JSTL, podemos também reutilizar páginas já existentes. Um bom exemplo de uso são o cabeçalho e o rodapé das páginas. Elas geralmente são iguais entre todas as páginas.
Para isso, vamos criar o arquivo "rodape.jsp", na pasta /WEB-INF/jsp/_comum
. Nele, colocaremos o seguinte conteúdo:
<hr/>
Cursos Online Alura
Agora, para utilizarmos ela na listagem, basta fazermos uso da tag import
. Veja o código abaixo:
... pagina ...
<c:import url="../_comum/rodape.jsp" />
</body>
</html>
Veja que passamos a URL da JSP, em relação a JSP que estamos. Ou seja, voltamos um nível, e aí acessamos a pasta "_comum".
Um detalhe importante é que variáveis declaradas em uma página não são visíveis na outra, pois elas são processadas de forma separada pelo servlet container (Tomcat).