Computação na Internet 2005/2006 Laboratório 8 – JSP’s, EL, JSTL Introdução JSP significa Java Server Page e representa uma forma de gerar conteúdo dinâmico numa página web. Em termos sintácticos, são documentos constituídos por tags xhtml normalíssimo,mas onde é possível, de forma mais ou menos explícita, embutir código Java. As páginas JSP utilizam tags XML e scriptlets Java por forma a encapsular a lógica que gera o conteúdo da página. Quaisquer tags de formatação, são directamente enviadas para a página de resultado. Por forma a que este objectivo seja atingido, quando uma jsp é solicitada ao servidor aplicacional pela primeira vez, este começa por invocar um compilador de JSPs, que não faz nada mais nada menos do que interpretar todas as tags e scriptlets nela contida, por forma a gerar uma servlet cujo comportamento seja aquele que foi especificado via XML na JSP em causa. Em pedidos posteriores, esta compilação já estará efectuada, sendo que não há necessidade de o compilador de JSPs entrar em funcionamento novamente. A servlet já gerada atenderá o pedido e apresentará a resposta pretendida. No entanto, se tiver havido alguma alteração na JSP original, é suposto que esta seja compilada novamente no próximo pedido que seja feito. É neste sentido que as JSPs representam uma extensão à tecnologia de Servlets. Na prática, uma JSP é uma Servlet, mas simplesmente nós não temos de implementar os métodos da Servlet, especificamos o que esta tem de fazer via XML e quando a página for compilada, os métodos representativos de todo o ciclo de vida da servlet correspondente são implementados automaticamente. Resumindo, são uma linguagem de server-side scripting, tal como o php ou asp. A diferença ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 1/18 Computação na Internet 2005/2006 reside no facto de não serem interpretadas (como php ou asp), mas sim compiladas. O primeiro pedido a uma JSP pode ser mais lento em termos de execução pelo facto de esta ter de ser compilada, mas posteriormente já não há necessidade de re-interpretar todo o código nelas escrito, pelo que todo o processo de execução assiste a uma melhoria significativa no desempenho. Como Criar uma JSP Tipicamente, uma servlet só permite ao programador embeber código html dentro do Java, o que dificulta todo o processo de design. Usando JSPs consegue-se uma separação muito mais eficiente entre a camada de apresentação e o modelo de processamento. Agora passamos a funcionar num modo oposto, dentro das tags é embutida a lógica também sob a forma de tag ou de expressões. A forma mais simples de criar documentos JSP, é • Mudar a extensão de um ficheiro HTML para .jsp • Colocar o documento num servidor que suporte JSP (no vosso caso, tomcat) • Ao fazer isto, a página será transformada numa servlet, sendo que a sua compilação é feita no primeiro acesso. (Podem, aliás, consultar a directoria work do tomcat onde, entre outras coisas se mantém a cache relativa à vossa aplicação. Podem procurar o ficheiro.java e o ficheiro.class correspondentes à implementação e compilação da jsp em causa. É uma forma de identificar e compreender melhor o que é que o tomcar faz afinal com as páginas jsp que desenvolvemos.) • Nos acessos subsequentes, o pedido é redirecionada a servlet que foi gerada a partir da página Ao transformar um ficheiro html numa JSP, podemos lá inserir blocos de código (scriptlets): • <% ... %> • e expressões <%= ... %> que são os elementos mais frequentes ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 2/18 Computação na Internet 2005/2006 Exemplo: <p>Texto repetido: <% for (int i = 0; i < 10; i++) { %> <p>Esta é a linha <%=i %> <% }%> Exemplo de uma JSP: Neste exemplo podemos identificar a utilização de: • Directivas JSP • Beans • Scriptlets Java • Expressões • Acções ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 3/18 Computação na Internet 2005/2006 Sintaxe dos elementos JSP Os elementos que podemos usar para especificar uma JSP são embutidos no código xhtml, como já foi referido, mas no entanto são interpretados no servidor e jamais chegam ao browser. O resultado apresentado é sempre xhtml puro. A sua sintaxe geral é a seguinte: • directivas: o <%@ ... %> Podem ser do tipo: page: para definir atributos relacionados com a página include: para incluir outros ficheiros (html ou jsp) na página taglib: para declarar a utilização de bibliotecas de marcas (tags) personalizadas utilizadas na página Exemplo: <%@page import="java.net.*, java.io.*" session="false" errorPage="/erro.jsp" %> <%@include file="navbar.jsp" %> • declarações: <%! ... %> : Uma declaração equivale à declaração de <%= ... %> : Uma expressão, quando é processada, uma variável. • expressões: retorna um valor que é inserido na página de resultado em substituição da expressão original. Equivale a fazer um out.println do valor de uma variável, por exemplo. • scriptlets: <% ... %>: Uma scriptlet é um bloco de código Java que será executado sempre que a JSP em que se encontra é processada. • comentários: <%-- ... --%> • acções: <jsp:acção ... /> • Marcas Personalizadas: <prefixo:elemento ... /> ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 4/18 Computação na Internet 2005/2006 A directiva page pode ter os seguintes atributos: • info="Texto informativo" default: nenhum • language="java" (default) • contentType="text/html; charset=ISO-8859-1" (default) • extends="acme.FonteJsp" • import="java.io.*, java.net.*" • session="true" (default) • buffer="8kb" (default) • autoFlush="true" (default) • isThreadSafe="true" (default) • errorPage="/erros/404.jsp" default: nenhum • isErrorPage= "false" (default) default: nenhum default: java.lang Exemplo: <%@page autoFlush="true" buffer="16kb" contentType="text/html" errorPage="myErrorPage.jsp" extends="org.apache.jasper.runtime.HttpJspBase" import="java.sql.*" info="This page has a set of page directive attributes" language="java" pageEncoding="UTF-8" session="false" %> <HTML> <HEAD><TITLE>Exemplo da directive page</TITLE></HEAD> <BODY> <P>A página JSP usada para gerar este conteúdo tem definidos valores para todos os atributos da directive page. </P> </BODY> </HTML> ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 5/18 Computação na Internet 2005/2006 A directiva include pode exemplificar-se da seguinte forma: <HTML> <HEAD><TITLE>Exemplo da directiva include</TITLE></HEAD> <BODY> <%@ include file =”exemplo2.html” %> <!-- incluir nesta página o conteúdo de outra cujo nome é exemplo2.html --> <P> Este texto aparece após o conteúdo do ficheiro exemplo2.html </P> </BODY> </HTML> Exemplos de declarações: <%! public final static String[] meses = {"jan", "fev", "mar", "abr", "mai", "jun"}; // declaração do array “meses” %> <%! public static String getMes() { /* Declaração do método getMes() na Servlet que vai ser gerada por esta JSP */ Calendar cal = new GregorianCalendar(); return meses[cal.get(Calendar.MONTH)]; } %> Exemplo de uma JSP que usa declarações e expressões: <%! String name = "Mark"; String date = "8th April, 2002"; %> <HTML> <HEAD><TITLE>Exemplo da directiva include</TITLE></HEAD> <BODY> <P> Esta página foi modificada pela última vez em <%= date %> por <%= name %>. </P> </BODY> </HTML> Exemplo de uma JSP que usa scriptlets: <%! ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 6/18 Computação na Internet 2005/2006 String[] names = {"Ruth", "Matilda", "Millicent", "Micah"}; %> <HTML> <HEAD><TITLE>Chapter 2 - Embedding Code</TITLE></HEAD> <BODY> <H1>List of people</H1> <TABLE BORDER="1"> <TH>Name</TH> <% for (int i=0; i<names.length; i++) { %> <TR><TD> <%= names[i]%> </TD></TR> <% } %> </TABLE> </BODY> </HTML> No que diz respeito a comentários no código, os comentários xhtml não servem para comentar JSP: <!-- Texto ignorado pelo browser mas não pelo servidor. Tags são processados --> Comentários JSP: podem ser usados para comentar blocos JSP <%-- Texto, código Java, <HTML> ou tags <%JSP%> ignorados pelo servidor --%> Pode-se também usar comentários Java quando dentro de scriptlets, expressões ou declarações: <% código JSP ... /* texto ou comandos Java ignorados pelo servidor */ ... mais código %> As acções, numa JSP, proporcionam acesso a tarefas a serem realizadas, nomeadamente: • incluir conteúdos de outros recursos • redireccionar os pedidos para outros recursos • interagir com JavaBeans ou outros objectos Java Há um conjunto de acções standard que podem ser executadas: ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 7/18 Computação na Internet 2005/2006 Acção <jsp:include> <jsp:forward> <jsp:plugin> <jsp:param> <jsp:useBean> <jsp:setProperty> <jsp:getProperty> Descrição Inclui Dinamicamente outro recurso num JSP. Quando a JSP é executadam o recurso referenciado é incluido e processado. Se o recurso é alterado entre pedidos as alterações são incluidas na proxima chamada da página Redireciona o processamento para outro JSP, servlet ou página estática. Esta acção termina com a execução da página JSP corrente. Permite gerar uma página HTML que contenha as construções apropriadas (dependentes do browser) para que se faça o download do plug-in Java e a subsequente execução da applet especificada A tag <jsp:plugin> é substituída pela tag <object> ou pela tag <embed>, dependendo do browser do cliente Usado em conjunto com as acções include, forward and plugin. Permite definir duplos do tipo (nome; valor) que podem ser lidos quando a acção é executada Associa uma instância de um JavaBean, definido com um determinada abragencia e icom um id. Modifica o valor de uma propriedade da instancia do JavaBean. Possui um funcionalidade especial a qual permite modifcar o atributo pelo uso de um parametro lido num pedido, desde que seja utilizado o mesmo identificador. Obtem e converta uma propriedade numa String de modo a ser possível incluir na resposta. Objectos Implícitos Os objectos implícitos são variáveis locais previamente inicializadas. Exceptuando o objecto session e exception, que dependem de uma directiva page para serem activados/desactivados, os objectos implícitos estão disponíveis numa JSP através de qualquer bloco de scriptlet. Essencialmente, são os seguintes: • Objectos da servlet a. page b. config • Entrada e saída a. request b. response c. out ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 8/18 Computação na Internet 2005/2006 • Objectos contextuais a. session b. application c. pageContext • Controle de excepções a. Exception Estes objectos são representados pelas seguintes APIs: Objeto Classe ou Interface page javax.servlet.jsp.HttpJspPage Descrição Instância de servlet da config javax.servlet.ServletConfig Dados de configuração do página servlet request javax.servlet.http.HttpServletReq Dados de solicitação, uest incluindo parâmetros response javax.servlet.http.HttpServletRes Dados da resposta out javax.servlet.jsp.JspWriter ponse Fluxo de saída para o conteúdo da página session javax.servlet.http.HttpSession Dados de sessão específicos application javax.servlet.ServletContext Dados partilhados por todas do utilizador as páginas de aplicação pageContex javax.servlet.jsp.PageContext t Dados de contexto para exception Erros não capturados ou javax.lang.Throwable execução da página excepções No fundo, estamos a falar dos mesmos objectos aos quais já tínhamos acesso numa Servlet, sendo que a API onde estão definidos é exactamente a mesma, tal como são os mesmos os métodos e atributos que os constituem. A diferença reside na forma como são utilizados. Exemplo de obtenção dos valores de parâmetros na JSP: <% String nome = request.getParameter("nome"); String idStr = request.getParameter("id"); int id = Integer.parseInt(idStr); ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 9/18 Computação na Internet 2005/2006 %> <p>Bom dia <%=nome %>! (cod: <%=id %> Modelo MVC MVC significa Model View Controller e, essencialmente, consiste numa estratégia para separar dados ou lógica da aplicação (model) da interface do utilizador (view) e do fluxo da aplicação (controller). Pode ser representado da forma seguinte: User View Model Controller O que se pretende, na implementação das vossas JSPs é que recorram ao modelo MVC, com uma estratégia centrada num único controlador que atende todos os pedidos, e os encaminha para os devidos recursos que efectuam o processamento adequado para o efeito. Vão seguir o modelo seguinte (JSP modelo2): ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 10/18 Computação na Internet 2005/2006 MVC Funcionamento Servlet processa os parâmetros e controla a execução da aplicação Beans são responsáveis pelo modelo de negócio JSP gere a saída enviada para o Browser Benefícios Especialização dos componentes Servlets: Controle da aplicação Beans: Modelo do negócio e envia objectos e/ou Beans para uma vista. JSP: simplificação do código Em termos tecnológicos, vão recorrer, para implementar as vossas aplicações segundo este modelo, a elementos como: • EL (Expression Language) • Beans (para o modelo aplicacional) • JSTL (bibliotecas de tags que escondem lógica de processamento e vêm em substituição de scriptlets Java por forma a que uma JSP seja constituída apenas ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 11/18 Computação na Internet 2005/2006 por tags e seja assim mais fácil não só de compreeder, mas também de desenvolver) Expression Language A expression language oferece uma sintaxe para definir expressões que pode ser utilizada em texto estático ou como valor de qualquer atributo de uma marca que aceite uma expressão. Como usar uma expressão EL num atributo: Associado a uma só expressão: <some:tag value="${expr}"/> A expressão é avaliada e o resultado é convertido para o tipo esperado como valor do atributo. Intercalar texto com várias expressões text: <some:tag value="some${expr}${expr}text${expr}"/> As expressões são avaliadas da esquerda para a direita. Cada expressão é convertida para uma string e ligada com o texto. A string final é convertida no tipo esperado para o atributo. Somente texto: <some:tag value="sometext"/> A string é convertida no tipo esperado para o atributo.. Exemplo: ${produto} equivale a: <%= pageContext.findAttribute(“produto") %> que por sua vez equivale a: <jsp:useBean id=“produto“ type="somePackage.SomeClass“scope="..."> <%= produto %> Aplicação a uma servlet e ao seu resultado: public class ScopedVars extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 12/18 Computação na Internet 2005/2006 request.setAttribute("attribute1", "First Value"); HttpSession session = request.getSession(); session.setAttribute("attribute2", "Second Value"); ServletContext application = getServletContext(); application.setAttribute("attribute3", new java.util.Date()); request.setAttribute("repeated", "Request"); session.setAttribute("repeated", "Session"); application.setAttribute("repeated", "ServletContext"); RequestDispatcher dispatcher = request.getRequestDispatcher("/el/scopedvars.jsp"); dispatcher.forward(request, response); } } JSP a processar: <!DOCTYPE …> … <TABLE BORDER=5 ALIGN="CENTER"> <TR><TH CLASS="TITLE"> Accessing Scoped Variables </TABLE> <P> <UL> <LI><B>attribute1:</B> ${attribute1} <LI><B>attribute2:</B> ${attribute2} <LI><B>attribute3:</B> ${attribute3} <LI><B>Source of "repeated" attribute:</B> ${repeated} </UL> </BODY></HTML> Em EL, os objectos implícitos que estão disponíveis na JSP surgem agora através de expressões com recurso a: param: Mapeia o nome de um parametro de pedido com seu valor paramValues: Mapeia o nome de um parametro de pedido com um array de valores header: Mapeia o nome de um cabeçalho com o seu valor headerValues: Mapeia o nome de um cabeçalho com um array de valores ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 13/18 Computação na Internet 2005/2006 cookie: Mapeia o nome de um cookie com o objecto initParam: Mapeia o parametro de inicalização do contexto com o seu valor pageScope: Mapeia uma variavel de página com os seus valores requestScope: Mapeia uma variavel de pedido com os seus valores sessionScope: Mapeia uma variavel de sessão com os seus valores applicationScope: Mapeia uma variavel de aplicação com os seus valores Exemplos: ${param.foo} => booyah ${param["foo"]} => booyah \${param["foo"]} => ${param["foo"]} ${header["host"]} => localhost:8080 ${header["accept"]} => */* ${header["user-agent"]} => Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/124 (KHTML, like Gecko) Safari/125 Em termos de operadores, em EL não deixam de estar disponíveis os mesmos e com as mesmas precedências que se utilizam em Java. Exemplos: Expressão EL ${1 > (4/2)} ${4.0 >= 3} ${100.0 == 100} ${(10*10) ne 100} ${'a' < 'b'} ${'hip' gt 'hit'} ${4 > 3} ${1.2E4 + 1.4} ${3 div 4} ${10 mod 4} ${!empty param.Add} ${pageContext.request.contextPath} ${sessionScope.cart.numberOfItems} ${param['mycom.productId']} Resultado false true true false true false true 12001.4 0.75 2 True if the request parameter named Add is null or an empty string The context path The value of the numberOfItems property of the sessionscoped attribute named cart The value of the request parameter named mycom.productId ${header["host"]} ${departments[deptName]} ${requestScope['javax.servlet. forward.servlet_path']} The host The value of the entry named deptName in the departments map The value of the request-scoped attribute named javax.servlet. forward.servlet_path ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 14/18 Computação na Internet 2005/2006 Exemplo de aplicação numa JSP: <html> <head> <title>Expression Language Examples</title> <% pageContext.setAttribute("pageColor", "yellow"); %> </head> <body bgcolor=“ ${pageScope.pageColor} "> <h1>Welcome to the ${param.department} Department</h1> Here are some basic comparisons:<p> Is 1 less than 2? ${1<2} <br> Does 5 equal 5? ${5==5} <br> Is 6 greater than 7? ${6 gt 7} <br> <p>Now for some math:<br> 6 + 7 = ${6+7} <br> 8 x 9 = ${8*9} <br> <hr>You appear to be using the following browser: ${header["user-agent"]} </body> </html> Beans Um Bean, no contexto de uma JSP, consiste essencialmente num objecto Java normalíssimo, que apresenta um conjunto de atributos e métodos get e set para cada um deles. Inclui-se na página com recurso à directiva useBean. As directivas set e getProperty permitem alterar e obter os valores do objecto. Em alternativa, podemos usar a EL para aceder às propriedades de um objecto. Os JavaBeans são utilizados essencialmente para recolher dados dos forms, passar esses dados aos elementos do modelo de negócio que os vão processar. São também usados na produção dos resultados a apresentar ao cliente no sentido de que os módulos aplicacionais, uma vez terminado o processamento, preenchem os devidos beans com informação que depois é retirada dos mesmos para ser vista na página de resultado. Exemplo de um bean que representa uma pessoa: public class Person { private String name; private String password; public String getName(){ return name;} public void setName(String s){name = s;} public String getPassword(){return password;} public void setPassword(String s){password = s;} } ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 15/18 Computação na Internet 2005/2006 Exemplo que combina numa JSP a utilização de um Bean Java com a EL: <html> <head> <title>Expression Language Accessing Objects</title> <%-- create a single Person object --%> <jsp:useBean id="man" class="Person"> <jsp:setProperty name="man" property="name" value="Nick"/> <jsp:setProperty name="man" property="password" value="pass"/> </jsp:useBean> The person is called ${man.name}. The password is ${man.password}. </body> </html> JSTL JSTL significa JSP Standard Tag Library e consiste essencialmente, num conjunto de tags, que oferecem controle sobre o processamento das páginas sem aumento de complexidade. Permitem substituir os scriptlets e assim estimular a separação entre apresentação e lógica, resultando num investimento significativo no sentido de conseguir seguir o modelo MVC. Como usar: 1. Fazer o download da última versão do site da Sun 2. Copiar os JARs das bibliotecas desejadas para o directório WEB-INF/lib/ da sua aplicação Web e os arquivos TLD para o directório WEB-INF/ 3. Declarar cada taglib e associá-la com seu TLD no deployment descriptor web.xml. 4. Incluir em cada página que usa as marcas: <%@ taglib uri="uri_da_taglib“ prefix="prefixo" %> 5. Usar as marcas da biblioteca com o prefixo definido no passo anterior <prefixo:nomeTag atributo="..."> ... </prefixo:nomeTag> ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 16/18 Computação na Internet 2005/2006 Existem quatro bibliotecas de Marcas JSTL: Core library: tags para condicionais, iterações, urls, ...: <%@taglib uri="http://java.sun.com/jstl/ea/core" prefix="c" /> Exemplo: <c:if test="..." ... >...</c:if> XML library: tags para processamento XML: <%@taglib uri="http://java.sun.com/jstl/ea/xml" prefix="x" /> Exemplo: <x:parse>...</x:parse> Internationalization library: <%@ taglib uri="http://java.sun.com/jstl/ea/fmt" prefix="fmt" /> Exemplo: <fmt:message key="..." /> SQL library: <%@ taglib uri="http://java.sun.com/jstl/ea/sql" prefix="sql" /> Exemplo: <sql:update>...</sql:update> Ao longo deste trabalho, tal como no projecto, vamo-nos focar essencialmente na Core Library. Exemplo de uma JSP que processa tags JSTL (com utilização de um JavaBean): <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <jsp:useBean id="person" scope="session" class="com.conygre.jspdevhandbook.chapter5.Person" /> <jsp:setProperty name="person" property="*" /> <html> <head><title>Chapter 5 - Display details</title></head> <body> <h1>Your details (or, the details you entered!)</h1> <table> <tr> <td>First name</td> <td><c:out value="${person.firstName}" /></td> </tr> <tr> <td>Last name</td> ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 17/18 Computação na Internet 2005/2006 <td><c:out value="${person.lastName}" /></td> </tr> <tr> <td>Age</td> <td><c:out value="${person.age}" /> </td></tr> </table> </body> </html> Trabalho de Laboratório: O que se pretende neste trabalho de laboratório é que, da mesma forma que já transformaram a geração da vossa página xhtml simples por forma a ser efectuada por uma servlet, o façam agora através de uma JSP. 1. Definir o cabeçalho e o rodapé da página em ficheiros separados que devem ser incluídos na página principal de forma declarativa, com recurso ao ficheiro web.xml. 2. Transformar o vosso código da página original para passar a ser gerado por uma JSP 3. Criar um conjunto de objectos java a serem utilizados na página como beans que são usados para recolher os dados submetidos e para mostrar, nas páginas seguintes, os resultados do processamento 4. Numa primeira fase, o processamento dos dados na vossa página poderá ser efectuado com recurso a scriptlets Java. 5. Na fase seguinte: a. Passar a implementar as mesmas JSPs com recurso à expression language por forma a evitar a utilização de scriptlets e seguir o modelo MVC b. A página de resultado, igual à que anteriormente geravam para mostrar os dados preenchidos no form pelo utilizador, deve agora ser alterada por forma a que seja uma JSP e que recorra às taglibs JSTL disponíveis para processar uma lista de valores e apresentar o mesmo resultado que apresentavam antes. Devem igualmente recorrer à EL. ©2005 ESTSetúbal – Susana Cabaço - Computação na Internet 2005/2006 Página 18/18