Introducción aos Servlets e JSP

De Wiki do Ciclo ASIR do IES de Rodeira

Índice

Introducción

A tecnoloxía Java abrangue dende a programación de aplicacións tradicionais ata o desenvolvemento de aplicacións web tanto con execución no cliente (applets) como no servidor (Servlets, JSP (Java Server Pages), EJB (Enterprise JavaBeans)).

Os applets permiten a descarga dun servidor web dunha aplicación Java e a súa execución incrustada dentro dun navegador web que teña instalado un entorno de execución (JRE - Java Runtime Environment) cunha serie de limitacións de seguridade, en particular:

  • Un applet non poderá acceder o sistema de ficheiros local.
  • Un applet non poderá establecer unha comunicación de rede cunha dirección distinta da que proven o applet.

Estas limitacións de seguridade (e outras) únicamente poden deshabilitarse mediante unha autorización expresa do usuario a través do uso de applets certificados mediante sinatura dixital. Os Servlets e JSP son a parte de programación no lado do servidor de Java.

Os Servlets e JSP son clases Java que producen saída HTML que se envía o cliente web, e que poden recibir como entrada os datos suministrados ó servidor por parte dos clientes. A principal (e prácticamente única) diferencia entre un servlet e unha páxina JSP é que mentras que os servlets son clases Java xa compiladas, os JSP son ficheiros que poden incluír parte de Java e parte de HTML. O servidor transformará esa páxina JSP nunha clase compilada similar a un servlet.

Para realizar programación no lado no servidor con Java é necesario dispor dun servidor que soporte a execución de Java, o coñecido como Servidor de Aplicacións Java. Existen moitos e moi coñecidos servidores de aplicacións Java. Nós imos a traballar coa implementación da fundación Apache Tomcat.

O Servidor Tomcat

Introducción a Tomcat

(thumbnail)
Estructura dun Tomcat

Tomcat é a implementación dun servidor de Servlets e JSP feita pola fundación Apache. Se acolle a unha licencia libre (Apache License) e é un dos servidores de servlets e JSP máis utilizados. A continuación explicaremos alguns térmos de tomcat:

  • Server: Cando falamos do Server, nos estaremos a referir ó servidor tomcat completo.
  • Connector: Un Connector manexa a comunicación co cliente. Exemplos de Connector son Coyote que se encarga de dar servicio web, e jk3, que implementa o protocolo AJP utilizado para conectar o tomcat cun servidor web como Apache.
  • Engine: Un Engine representa o procesamento das peticións para un Service específico. Coma un Service pode ter varios Connectors, encárgase de procesar as peticións de todos eles e de enviarlles de volta a resposta. Un Engine pode ter un ou varios Host, cada un representando un host virtual. Dentro de un Service ten que existir un e só un Engine.
  • Service: Representa a combinación de un ou máis Connectors que comparten un Engine para procesar peticións. Un Server pode ter un ou máis Services.
  • Host: Un Host é unha asociación de un nome de host (web.iesrodeira.com) co servidor tomcat, é o encargado de manexar todas as peticións para un host virtual particular. Un Engine pode ter varios Host, e o Host pode soportar varios alias.
  • Context: Un Context representa unha aplicación web, é o encargado de procesar as peticións para unha aplicación web. Un Host pode ter moitos Context, cada un cun nome único.
  • Realm: Un Realm representa unha base de datos que conten usuarios, passwords e 'roles' a desempeñar por parte deses usuarios, que se utilizará para manexar a seguridade das aplicacións web. Se pode especificar un Realm dentro dun Engine, dun Host ou de un Context. Tomcat proporciona as clases JDBCRealm (Acceso á base de datos relacional mendiante o Java DataBase Connectivity), DataSourceRealm (Acceso a base de datos relacional JDBC mediante o Java Native Database Interface ) , JNDIRealm (Acceso mediante un driver JNDI a un directorio LDAP) , MemoryRealm (acceso a un ficheiro en formato Xml.
  • Valve: Unha Valve representa unha compoñente que pasa a formar parte do procesamento da petición a un Engine, Host ou Context. Algunhas suministradas con tomcat son: AccessLogValve para xerar logs, RemoteAddrValve para analizar a dirección IP do cliente, RemoteHostValve para analizar o nome do host do cliente, SingleSignOn que permite a un cliente autenticarse unha única vez para acceder a todas as aplicacións web do host virtual, FormAutenticator que permite o procesamento de formularios de autenticación, e que teñen por defecto todos os Context que usen estes formularios.
  • Loader: O Loader é o encargado de cargar todas as clases dunha aplicación web. Todos os Context deben ter un Loader, si non se especifica se creará un por defecto.
  • Manager: A misión do Manager é o manexo das sesións HTTP. Si non se especifica un Manager se creará un por defecto.
  • Resources: Os Resources representan recursos estáticos dende onde se cargarán as clases da aplicación web. Esto permite que a aplicación web poda estar situada nun ficheiro WAR ou nunha base de datos JDBC. Si non suministramos ningun Resources o sistema nos falicitará un que se encarga de coller as clases do sistema de ficheiros.
  • GlobalNamingResources: Sirve para definir recursos JNDI (Java Native Database Interface) globales para o Server.

Instalación de Tomcat

NOTA
A descripción da instalación é válida para unha Debian Etch, pero as diferencias con outras distribucións son mínimas

Comenzaremos por instalar os paquetes de tomcat e de administración:

 apt-get install tomcat5.5
 apt-get install tomcat5.5-admin

A continuación habilitamos as aplicacións de administración (manager e admin) creando un usuario cos roles necesarios no ficheiro /var/lib/tomcat5.5/conf/tomcat-users.xml. Este ficheiro e o utilizado polo Realm por defecto de tomcat.

En Debian etch existe un problema na instalación destas aplicacións, xa que non configura correctamente os permisos de acceso á clase Struts que se necesitan para a súa execución. Polo tanto debemos engadir:

 grant codeBase "file:/usr/share/struts1.2/struts.jar" {
    permission java.security.AllPermission;
 };

no ficheiro /etc/tomcat5.5/policy.d/50user.policy. ou en /etc/tomcat5.5/policy.d/01system.policy

Chegados a este punto debería ser posible carga-la páxina índice de tomcat en http://localhost:8180 e acceder tanto a documentación como as aplicacións de administración do tomcat (admin) e de manexo de aplicacións web (manager).

Configuración de Tomcat

O máis sinxelo é realizar as tarefas de administración do tomcat mediante a aplicación admin accesible dende a páxina de instalación. Os ficheiros de configuración máis importantes de tomcat atópanse en Debian Etch en /etc/tomcat5.5:

  • server.xml: Configuración do Servidor. Aquí podemos definir por exemplo hosts virtuais. A configuración real está en /var/lib/tomcat5.5/conf/server.xml, e é máis simple utilizar a aplicación 'admin' para manipular este ficheiro.
  • web.xml: Valores por defecto para todas as aplicacións web. Cada aplicación web pode sobreescribir estes valores situando o seu propio arquivo web.xml na súa carpeta WEB-INF.
  • policy.d/01system.policy: Permisos de seguridade para o tomcat.
  • policy.d/02debian.policy: Permisos de seguridade para os jar incluídos nos paquetes Debian relacionados con java.
  • policy.d/03catalina.policy: Permisos de seguridade para o Service Catalina, que é o Service por defecto de tomcat.
  • policy.d/04webapps.policy: Permisos para todas as aplicacións web.
  • policy.d/50user.policy: Permisos específicos que queira poñer o usuario.

Nos permisos se indica a qué se ten acceso e mediante grant codeBase.

O Tomcat trae por defecto configurado un Service chamado Catalina, que ten como Host por defecto localhost.

Desenvolvemento de Aplicacións

Unha vez instalado o tomcat, será posible desenvolver aplicacións que utilicen Java para tratar a información e producir HTML de saída sempre que dispoñamos dun entorno de desenvolvemento Java (Java Development Kit). O JDK de Sun necesario é un J2EE (Java 2 Enterprise Environment), non o J2SE (Java 2 Standard Edition).

A base das aplicacións web baseadas en Java son as páxinas JSP, os Servlets, os Beans e os Enterprise Java Beans.

Servlets

Os servlets son obxectos Java que residen no servidor e que son invocados polos clientes web (navegadores) para realizar algun tipo de procesamento. Os servlets teñen un ámbito de existencia de aplicación web, é dicir, existe unha soa instancia de cada obxecto para cada aplicación web. Esto quere dicir que os atributos do servlets son comúns a todos os clientes que estén utilizando a aplicacion, de xeito que si temos por exemplo unha variable nclients, o valor desa variable é comun e mantense para todos os clientes mentras non se reinicie a aplicación.

O servidor de aplicacións (tomcat no noso caso) invocará ó método service do servlet pasándolle como argumentos os obxectos que representan a petición (ServletRequest) e a resposta (ServletResponse). O método service é o encargado de realizar o procesamento da información suministrada polo cliente e de suministrar a saída html de resposta.

Para crear un Servlet normalmente se extende a clase HttpServlet que nos proporciona un método service que recibe como argumentos un obxecto petición HttpServletRequest e un obxecto resposta HttpServletResponse.

As páxinas JSP pola súa banda, xeneran tamén un Servlet, pero da clase HttpJspPage e cun método chamado __jspService en lugar de service.

As clases servlet que deseñemos para a nosa aplicación deben residir no directorio WEB-INF/classes da aplicación Web, respetando a xerarquía indicada polo package ó que pertence.

JSP

(thumbnail)
Transformación dun JSP

As páxinas JSP son páxinas que normalmente mezclan no mesmo documento HTML e Java. O servidor de aplicacións convertirá a páxina JSP a un Servlet encargado de facer o procesamento indicado e de producir o HTML resultado dun xeito automático. Existen diversos marcadores que se empregan nas páxinas JSP para indicar en qué posición do Servlet xerado se colocará o código escrito:

  • <%@ ... %>: Esto tradúcese a unha directiva Java que vai situada fora da clase. O uso máis común é facer imports para o Jsp.
  • <%! ... %>: Tradúcese como código Java da clase. Se emprega para crear novos atributos e métodos da clase.
  • <% ... %>: Código Java pertencente a __jspService. É o código principal do Jsp, tamén recibe o nome de scriptlet.
  • <%= ... %>: Avaliación de expresións. Tradúcese a un out.write() dentro de __jspService, é dicir, produce unha saída na páxina web que corresponde coa avaliación da expresión indicada.

As páxinas JSP colocanse normalmente no directorio principal da aplicación web.

Java Beans

Os Java Beans son a base da tecnoloxía de compoñentes baseadas en Java. Un Bean non é máis que unha clase ordinaria que proporciona métodos que permiten obter o valor e poñer un valor nos atributos dun obxecto. Estes métodos teñen que seguir unha convención de nomeamento, de xeito que a partir do nome do método se deduce tamén o nome do atributo. Unha clase Java para ser considerada como un Bean únicamente debe cumplir os seguintes puntos:

  • Os atributos comezan por minúscula.
  • Para cada atributo é necesario crear un método chamado setAtributo, sendo Atributo o nome do atributo (que como recordamos está todo en minúscula). Este método ten que encargarse de poñer un valor no atributo atributo.
  • Tamén é necesario crear un método chamado getAtributo por cada atributo, este método se encargará de facilitar o valor do atributo atributo.

Seguindo esta convención de nomes e mediante os mecanismos de introspección de Java, será posible facer que entornos Java recoñezan e saiban utilizar dun xeito automático os obxectos Bean, por exemplo para colocar elementos gráficos nunha paleta e facilitarnos automáticamente un formulario para determiñar as súas características.

Dentro da programación JSP unha das principais utilidades que veremos dos Beans é o procesamento de formularios.

JSP Tags

Un Tag JSP pode encapsular unha accion predefinida que se pode invocar dende dentro dunha páxina HTML. JSP ten 6 accións predefinidas, pero poden crearse moitas máis persoalizadas:

  • jsp:include
  • jsp:useBean
  • jsp:setProperty
  • jsp:getProperty
  • jsp:forward
  • jsp:plugin

Tags Persoalizados: Uso dos Tag

Para declarar que unha páxina JSP utiliza Tags persoalizados se usa a seguinte directiva ó principio da páxina:

   <%@ taglib uri="/meutag" prefix="meutag" %>

O atributo uri debe identificar de xeito único á librería de Tag e pode ser relativa ou absoluta. Si é relativa debe asinarse a unha dirección absoluta no elemento taglib no arquivo web.xml da aplicación. O atributo prefix indica o prefixo para utilizar os Tag proporcionados pola librería.

Para utilizar os Tags utilízase a sintaxe típica de XML:

 <meutag:Saudo>        
      corpo_do_tag
 </meutag:Saudo>

O corpo do Tag pode conter outros Tag, HTML ou scripting. Tamén pode utilizar obxectos creados polo propio tag. Si o Tag non ten corpo se expresaría:

 <meutag:DiHola/>

Os Tag tamén poden ter atributos:

 <meutag:Sauda texto="di Hola"/>

Tags Persoalizados: Creación da librería de Tag

Para crear unha librería de Tag precisaremos:

  • Desenvolver un manexador do Tag e as clases necesarias para levar a cabo as funcións da librería de Tag.
  • Declara-lo novo Tag nun descriptor de librería de etiquetas.

O manexador do Tag é un obxecto invocado polo servidor de aplicacións para avaliar un Tag no momento de procesar unha páxina. Un manexador de Tag precisa implementar os interfaces Tag ou BodyTag segundo o Tag teña corpo ou non. Máis sinxelo é estender as clases existentes TagSupport ou BodyTagSupport.

Os métodos importantes a escribir son os seguintes:

  • Si o Tag ten atributos precisamos os métodos setXXX e getXXX para eses atributos
  • Si o Tag vai ter un corpo co que necesitamos interactuar, os métodos doInitBody e doAfterBody
  • En todos os casos doStartTag, doEndTag, e release

O procesamento dun Tag por parte do servidor de aplicacións segue a seguinte estructura:

ATag t = new ATag();
t.setPageContext(...);
t.setParent(...);
t.setAttribute1(value1);
t.setAttribute2(value2);
t.doStartTag();
t.doEndTag();
t.release();

O descriptor da librería de etiquetas (TLD), é un ficheiro XML coa seguinte estructura:

<taglib>
 
    <tlibversion> - Versión da librería
 
    <jspversion> - Versión de JSP que necesita a librería 
 
    <shortname> - Un nome simple, pode usarse logo como prefixo dos tag
 
    <uri> - A URI que identifique á librería de xeito único
 
    <info> - Información sobre a librería
 
    <tag> 
       <name>Nome_do_Tag</name>
       <tagclass>Arquivo .class que implementa o tag</tagclass>
       ...
    </tag> 
 
    ... 
 
</taglib>

Enterprise Java Beans

Os Enterprise Java Beans (EJB) son beans que facilitan a construcción de aplicacións empregando compoñentes Java que se poden invocar remotamente facilitando un entorno de obxectos distribuídos. Deste xeito sería posible EJB en distintas máquinas que poden ser invocados dende outras para compoñer unha aplicación. Dende a especificación 2.1 de EJB existe soporte tamén para Servizos Web (Web Services) Os EJB necesitan de un servidor de aplicacións apropiado. Un dos máis coñecidos e JBoss, que é un servidor de EJB que ademáis incorpora Tomcat para servir Servlets e JSP.

Estructura dunha Aplicación Web con Java

Unha aplicación web consiste nunha xerarquía de directorios e ficheiros seguindo unhas regras concretas. Esta xerarquía pode estar directamente no sistema de ficheiros o almacenada nun ficheiro comprimido chamado WAR (Web Application ARchive).

  • O directorio raíz: Na xerarquía da aplicación é tamén o documento raíz da aplicación, aquí situaránse os documentos HTML e JSP que normalmente se ocupan da interface de usuario da aplicación e os ficheiros relacionados (CSS, JavaScript .js, ... etc). Poden tamén situarse subdirectorios si se considera oportuno.
  • WEB-INF/web.xml : Web Application Deployment Descriptor. É un documento XML que describe diversas características da aplicación como os Servlets que utiliza, parámetros de inicialización e restriccións de seguridade. Co Tomcat se suministra un arquivo web.xml que pode servir de plantilla para elaborar o que nós precisemos para a aplicación.
  • WEB-INF/classes: Conten os ficheiros .class de Java que precisa a nosa aplicación, incluíndo clases que sexan Servlets e clases que non o sexan. As clases deben estar almacenadas nunha estructura de directorios que reflexe o package ó que pertencen e non poden estar empaquetadas en ficheiros JAR.
  • WEB-INF/lib: Conten ficheiros JAR cos ficheiros .class e os recursos asociados que precise a nosa aplicación. Por exemplo, librerías de outras persoas ou drivers JDBC.

Instalación de Aplicacións

O Tomcat ven configurado por defecto cun único Service (Catalina) que ten un so Host (normalmente chamado localhost) que colle como raíz das súas aplicacións /usr/share/tomcat5.5/webapps. Existen varios xeitos de facer unha aplicación web visible para o tomcat:

  • Si dentro do raíz do Host situamos unha nova carpeta coa nosa aplicación ou un ficheiro WAR que conteña a aplicación, o Tomcat a detectará e servirá a nosa aplicación utilizando para o Context un nome igual que o da carpeta da aplicación.
  • Creando un arquivo XML de descripción de contexto e poñendo ese arquivo en /usr/share/tomcat5.5/conf/Catalina/localhost, supoñendo que Catalina é o nome do Service e localhost o nome do Host. Este arquivo pode chamarse como queiramos e contén a definición do contexto para a nosa aplicación, entre outras cousas o directorio onde está situada. Vexamos un exemplo:

<sourc lang='xml'>

 <Context path="/manager" docBase="/usr/share/tomcat5.5/server/webapps/manager"
          debug="0" privileged="true">
    <ResourceLink name="users" global="UserDatabase"
                  type="org.apache.catalina.UserDatabase"/>
 </Context>

</source>

  • Creando un novo Host no servidor (por exemplo, utilizando a aplicación de administración suministrada co Tomcat). Este Host pode tomar a súa raíz de documentos onde se indique e ahí poderemos situar a nosa aplicación ou un conxunto delas utilizando os métodos indicados anteriormente.

Enlace Apache/Tomcat

O servidor http máis extendido do mundo é o servidor Servidor HTTP Apache, de xeito que si queremos ofrecer un servizo web o máis probable é que teñamos un en funcionamento. Si ademáis das páxinas web servidas polo Apache queremos servir tamén páxinas baseadas en Java, precisaremos un servidor de aplicacións Java como Tomcat. Deste xeito teremos un servidor á escoita nun porto (no 80 normalmente) e o outro servidor noutro (por exemplo o 8080) e os clientes terían que especificar o porto na URL para acceder o servidor desexado. Esta aproximación ademáis de incómoda para os clientes é pouco efectiva, xa que o servidor Tomcat ten o seu mellor desempeño executando Servlets, non servindo as páxinas estáticas que poidan formar parte da nosa aplicación.

Conectando o servidor Apache co Tomcat podemos conseguir:

  • Os clientes se conectan utilizando so unha URL, sen preocuparse do porto.
  • Se pode configurar a conexión de xeito que o Tomcat so sirva as páxinas relacionadas con Java.
  • Se poden mezclar na aplicación páxinas dinámicas que utilicen linguaxes que o Apache poida procesar (PHP. Perl, ... ), ademáis das páxinas relacionadas con Java que executará o Tomcat.

Configuración no Apache

Para enlazar o Tomcat co apache é necesario un módulo chamado en Debian libapache-mod-jk ou libapache2-mod-jk segundo estemos a utilizar Apache 1.3 ou Apache 2.0:

 apt-get install libapache2-mod-jk

Este módulo é o encargado de conectarse co Tomcat mediante o protocolo AJP. O Tomcat debe ter configurado un Connector deste tipo.

Para establecer as conexións e realizar as peticións utilízanse os worker. Un worker é o proceso encargado de trasladar as peticións o Tomcat e de recoller a súa resposta a través dos Connector AJP que estean configurados no Service. Por defecto, o Service Catalina de Tomcat proporciona un Connector AJP no porto 8009.

As características dos workers que vai a utilizar apache configúranse no ficheiro workers.properties que no caso de Debian atópase en /etc/libapache2-mod-jk.É posible configurar o número de workers que se consideren necesarios e facer que se conecten a Connectors de Tomcat tanto locais como remotos.

Para activar o módulo de conexión debemos incluir no ficheiro de configuración de Apache (/etc/apache2/apache2.conf en Apache 2.0 ou /etc/apache/httpd.conf en Apache 1.3) o seguinte:

 JkWorkersFile /etc/libapache2-mod-jk/workers.properties
 JkLogFile /var/log/apache2/mod_jk.log
 JkLogLevel info

Logo bastará con indicar que arquivos van ir redirixidos ó Tomcat mediante o comando JkMount.

Por exemplo:

 JkMount /* ajp13_worker

Faría que as peticións a calquera documento do directorio raíz do servidor virtual do Apache donde se incluíu a directiva se redirixiran ó Context raíz do Host por defecto de Tomcat utilizando o worker definido en workers.properties co nome ajp13_worker.

 JkMount /aplicacionweb/* ajp13_work

Sería similar o anterior, pero redixiría as peticións á carpeta /aplicacionweb/ no servidor virtual do Apache ó Context aplicacionweb de Tomcat.

 JkMount /*.jsp ajp13_worker
 JkMount /servlet/* ajp13_worker
 JkMount /otherworker/*.jsp ajp13_worker_remote

Estas directivas farían que as peticións a calquera arquivo .jsp no raíz do host virtual de Apache foran redirixidas o Context raíz do Tomcat, que calquera petición á carpeta /servlet do host virtual de Apache se redirixa o Context servlet do Tomcat e que as peticións os arquivos .jsp na carpeta otherworker se redirixan o Context otherworker de Tomcat.

Utilízanse dous workers configurados en workers.properties, (ajp13_worker e ajp13_worker_remote) que poden estar conectando con servidores Tomcat distintos. Cando únicamente se redirixen os arquivos .jsp, os demáis son servidos mediante Apache e poden ser documentos dinámicos en calquera linguaxe soportada (PHP, Perl ...).

Configuración no Tomcat

O único requisito no Tomcat para que se poda enlazar co Apache é que proporcione un Connector co protocolo AJP. O que si resulta práctico é poder utilizar un dominio para acceder a unha aplicación web a través do Apache sen necesidade de especificar o Context.

A solución consiste en definir en Tomcat un Host virtual co mesmo nome que o utilizado en Apache. Deste xeito as peticións ó documento raíz no apache mapearanse o documento raíz do Host virtual de Tomcat.

Para crear un Host virtual o máis sinxelo é utilizar a aplicación de administración suministrada co Tomcat no paquete tomcat5.5-admin.

Configuración dun sitio web virtual JSP a través do apache

Para configurar un sitio web, o primeiro que necesitamos é que un DNS resolva o noso dominio. Unha vez feito esto, creamos a carpeta onde se vai a hospedar a aplicación.

A continuación, debemos dar de alta un VirtualHost no apache apuntando á carpeta de aplicación (o apache xa debe ter configurado o mod_jk coas directivas

  JkWorkersFile /etc/libapache2-mod-jk/workers.properties
  JkLogFile /var/log/apache2/mod_jk.log
  JkLogLevel info

en /etc/apache/httpd.conf ou /etc/apache2/httpd.conf. Por exemplo:

  <VirtualHost *:80>
    ServerName  www.radiorodeira.com  
    DocumentRoot /home/xavi/radiorodeira/
    JkMount /contexto/* ajp13_worker
  </VirtualHost>

No VirtualHost debemos indicar que páxinas lle imos pasar ó tomcat mediante o parámetro JkMount. O resto de páxinas as servirá apache (podendo levar php, perl ou calqueira linguaxe de servidor soportada polo apache).

En tomcat os nomes de contexto teñen que ser únicos en cada Host. Si queremos que tanto o apache como o tomcat utilicen o mesmo contexto no servidor virtual (para poder acceder como http://www.radiorodeira.com tanto a páxinas html mediante Apache como .jsp mediante tomcat) necesitaremos crear ademáis un host virtual no tomcat co mesmo nome que o host creado no apache.

Para crear o host virtual en tomcat5.5 é necesario editar o ficheiro server.xml (en Debian Lenny e Squeeze situado en /etc/tomcat55) e engadirlle un novo host:

  <Host
     appBase="/home/xavi/radiorodeira_contexts"
     name="www.radiorodeira.com">
  </Host>

Despois de facer esto e reiniciado o tomcat, debería aparecer unha carpeta en /etc/tomcat5.5/Catalina representando o novo host. Nesta carpeta é onde copiamos ou creamos o enlace ós novos contextos para este host.

E posible que esta carpeta non apareza de xeito automático, nese caso, é necesario creala a man e reiniciar tomcat.

Acceso a Base de Datos

Utilizando un Pool de Conexións

Acceso sen Pool de Conexións

Utilizando Java Standard Tag Library (JSTL)

Frameworks Java: Struts

Exemplo 1

O seguinte exemplo facilita un formulario que solicita a precisión de cálculo para o número e, e facilita o resultado utilizando a sucesión de Mac Laurin.

Código

index.html

  • Versión con procesamento mediante JSP ou Beans
<html>
<form method="POST" action="numeroe.jsp">
  Precision: <input type="text" name="precision" value="0"/>
  <br><br>
  <input type="submit" value="Calcular"/>
</form>
</html>
  • Versión con procesamento mediante Servlet
<html>
<form method="POST" action="calculo">
  Precision: <input type="text" name="precision" value="0"/>
  <br><br>
  <input type="submit" value="Calcular"/>
</form>
</html>

Procesamento do Formulario con un Java Bean

A maior ventaxa do uso de Beans no procesamento de formularios é que o código dos Beans son clases completamente autónomas do HTML e reutilizables donde sexan necesarias.

Este é o JSP (numeroe.jsp) que visualiza o resultado:

<jsp:useBean id="e" class="com.xavi.beane" scope="session"/>
<jsp:setProperty name="e" property="*"/>
<html>
O número 'e' calculado cunha precisión de <%= e.getPrecision() %> é 
<%= e.calcula_e() %>
</html>

O código do Bean, que deberá ir situado en WEB-INF/classes/com/xavi é o seguinte:

package com.xavi;
 
public class beane {
  private int precision;
 
  public void setPrecision(int pr) {
     precision=pr;
  }
 
  public int getPrecision() {
     return precision;
  }
 
  public long factorial(int num)
  {
     long res=1;
 
     while(num>0)
     {
       res=res*num;
       num--;
     }
     return res;
  }
 
  public double calcula_e()
  {
    double nume=1;
 
    while (precision>=1)
    {
      nume=nume+1.0/(double)factorial(precision);
      precision=precision-1;
    }
    return nume;
  }
}

De especial importancia é que os atributos do Bean coincidan co nome das variables enviadas no formulario.

Procesamento do Formulario cun Servlet

package com.xavi;
 
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class numeroe extends HttpServlet {
  long factorial(int num)
  {
    long res=1;
 
    while(num>0)
    {
       res=res*num;
       num--;
    }
    return res;
  }
 
  double calcula_e(int pr)
  {
    double nume=1;
    while (pr>=1)
    {
      nume=nume+1.0/(double)factorial(pr);
      pr=pr-1;
    }
    return nume;
  }
 
  protected void doPost(HttpServletRequest req,HttpServletResponse res)
                 throws ServletException, IOException {
     PrintWriter out=res.getWriter();
     int precision=Integer.parseInt(req.getParameter("precision"));
 
     res.setContentType("text/html");
     out.write("<html>");
     out.write("<h1>Cálculo do número 'e' mediante un Servlet</h1>");
     out.write("O número 'e' calculado cunha precisión de "+precision+
     " vale "+calcula_e(precision));
     out.write("</html>");
  }
}

Esta clase é necesario compilala a man engadíndolle o classpath as clases Servlet, que están normalmente implementadas no servidor de aplicacións. No caso concreto do Tomcat 5.5:

 javac -classpath "/usr/share/tomcat5.5/common/lib/servlet-api.jar" numeroe.java

O ficheiro .class resultante debe colocarse no directorio WEB-INF/classes/com/xavi do Context da aplicación, xa que a clase pertence o package com.xavi.

Tamén é necesario indicar no ficheiro WEB-INF/web.xml que a aplicación fará uso deste Servlet, como se accederá a él, os parámetros de inicialización,... No noso caso engadimos:

   <servlet>
     <servlet-name>nume_servlet</servlet-name>
     <servlet-class>com.xavi.numeroe</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>nume_servlet</servlet-name>
      <url-pattern>/calculo</url-pattern>
   </servlet-mapping>

Por último, cada vez que modifiquemos un Servlet será necesario reinicia-lo Tomcat.

Procesamento do Formulario cun JSP

numeroe.jsp

<%!
long factorial(int num)
{
   long res=1;
 
   while(num>0)
   {
        res=res*num;
        num--;
   }
   return res;
}
 
double numeroe(int pr)
{
  double nume=1;
  while (pr>=1)
  {
    nume=nume+1.0/(double)factorial(pr);
    pr=pr-1;
  }
  return nume;
}
%>
 
<%
 int precision=Integer.parseInt(request.getParameter("precision"));
 out.print("O número 'e' calculado cunha precision de "+precision+" vale "+numeroe(precision));
%>

Exemplo 2

Os dous exemplos seguintes mostran o procesamento de Tag. O primeiro Tag visualiza unha mensaxe, e o segundo realiza unha iteración polos valores dunha clase.

Descritor da librería

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
          PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" 
          "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
<taglib>
   <!-- The version number of this tag library -->
   <tlibversion>1.0</tlibversion>
   <!-- The JSP specification version required to function -->
   <jspversion>1.1</jspversion>
   <!-- The short name of this tag library -->
   <shortname>meutag</shortname>
   <!-- Public URI that uniquely identifies this version of the tag library -->
   <uri>/meutag</uri>
   <!-- General information about this tag library -->
   <info>
      Exemplo tag Hola Mundo
   </info>
   <!-- Tag Saudo -->
   <tag>
      <name>Saudo</name>
      <tagclass>com.xavi.tagHola</tagclass>
      <bodycontent>empty</bodycontent>
      <info>
         Visualiza un Saúdo
      </info>
  </tag>
  <tag>
      <name>iteration</name>
      <tagclass>com.xavi.tagIter</tagclass>
      <teiclass>com.xavi.IterTEI</teiclass>
      <bodycontent>JSP</bodycontent>
      <attribute>
         <name>name</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
         <name>type</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
         <name>group</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
  </tag>
</taglib>

Tag Hola

package com.xavi;
 
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
 
 
public class tagHola extends BodyTagSupport {
 
    public int doStartTag() throws JspException {
        try {
               pageContext.getOut().print("Hola dende un Tag");
        } catch (Exception ex) {
              throw new JspException("IO problems");
        }
        return SKIP_BODY;
    }
}

Tag Iter

/* 
 * Copyright 2000 Sun Microsystems, Inc. All rights reserved.
 * Copyright 2000 Sun Microsystems, Inc. Tous droits réservés. 
 */
package com.xavi;
 
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.*;
import java.io.*;
 
public class tagIter extends BodyTagSupport {
   private String name, type;
   private Iterator iterator;
 
   public void setName(String name) {
      this.name = name;
   }
 
   public void setType(String type) {
      this.type = type;
   }
 
   public void setGroup(Collection members) {
      if(members.size() > 0)
         iterator = members.iterator();
   }
 
   public int doStartTag() {
      if(iterator == null) 
         return SKIP_BODY;
      if(iterator.hasNext()) {
         pageContext.setAttribute(name, iterator.next());
         return EVAL_BODY_TAG;
      }
      else {
         return SKIP_BODY;
      }
   }
 
   public int doAfterBody() throws JspException {
      BodyContent body = getBodyContent();
      try {
         body.writeOut(getPreviousOut());
      } catch (IOException e) {
         throw new JspTagException("IterationTag: " + e.getMessage());
      }
      // clear up so the next time the body content is empty
      body.clearBody();
      if (iterator.hasNext()) {
         pageContext.setAttribute(name, iterator.next());
         return EVAL_BODY_TAG;
      } else {
         return SKIP_BODY;
      }
   }
}

Tag IterTEI (Tag Extra Info)

/* 
 * Copyright 2000 Sun Microsystems, Inc. All rights reserved.
 * Copyright 2000 Sun Microsystems, Inc. Tous droits réservés. 
 */
package com.xavi;
 
import javax.servlet.jsp.tagext.*;
public class IterTEI extends TagExtraInfo {
 
   public IterTEI() {
      super();
   }
 
   public VariableInfo[] getVariableInfo(TagData data) {
      VariableInfo info1
         = new VariableInfo(
            data.getAttributeString("name"),
            data.getAttributeString("type"),	
            true,
            VariableInfo.NESTED);
      VariableInfo [] info = { info1 };
      return info;
   }
}

Exemplos de Funcionamento dos Tag Anteriores

Tag Saudo

  • index.jsp
<%@ taglib uri="/meutag" prefix="mt" %>
 
<mt:Saudo/>

Tag Iteration

  • index.jsp
<%@ taglib uri="/meutag" prefix="mt" %>
<html>
   <head>
   <title>Organization</title>
   </head>
   <body bgcolor="white">
   <jsp:useBean id="org" class="com.xavi.Organization"/>   
   <table border=2 cellspacing=3 cellpadding=3>
   <mt:iteration name="departmentName" type="String"  group="<%= org.getDepartmentNames()%>">
      <tr>
         <td><b>Departments</b></td>
      </tr>   
      <tr>
         <td><a href="list.jsp?deptName=<%= departmentName %>"> <%= departmentName %></a></td>
      </tr>
   </mt:iteration> 
   </table> 
   </body>
</html>
</java>
 
*list.jsp
<source lang='xml'>
<%--
 % Copyright 2000 Sun Microsystems, Inc. All rights reserved.
 % Copyright 2000 Sun Microsystems, Inc. Tous droits réservés. 
--%>
 
<%@ taglib uri="/meutag" prefix="mt" %>
<html>
	<jsp:useBean id="org" class="com.xavi.Organization"/>
	<%	String deptName = (String)request.getParameter("deptName");
 	  	com.xavi.Department dept = org.getDepartment(deptName); %>
	<head>
		<title><%= deptName%></title>
	</head>
	<body bgcolor="white">
   <table border=2 cellspacing=3 cellpadding=3>
		<tr>
			<td colspan=3><b><center><%= deptName%></b></center></td>
		</tr>
		<tr>
			<td width=100><b>Name</b></td>
	  		<td width=100><b>Extension</b></td>
			<td width=100><b>Email</b></td>
  		</tr>
		<%-- List all department members --%>
		<mt:iteration name="member" type="com.xavi.Member" group="<%= dept.getMembers()%>">
		<tr>
                       <td><%=member.getName()%></td>
			<td><%=member.getPhone()%></td>
			<td><%=member.getEmail()%></td>
<%--
                        <td><jsp:getProperty name="member" property="name"/></td>
	  		<td><jsp:getProperty name="member" property="phone"/></td>
	  		<td><jsp:getProperty name="member" property="email"/></td>
--%>			
 		</tr>
		</mt:iteration>		
	</table>
	</body>
</html>

Exemplo 3

Este exemplo é unha pequena aplicación de xestión dunha biblioteca, e está dispoñible na súa páxina de desenvolvemento

Enlaces de Interese

Java Server Faces

Java Server Faces QuickStart

Java Server Faces Tutorial

Java Server Standard Tag Libraries

Struts 1

JSTL

JSF

XSLT