Documentos de Académico
Documentos de Profesional
Documentos de Cultura
-1-
S sobre ellas son: * Las principales ventajas de JSP Mayor encapsulamiento:G T Uso de clases T Uso de JavaBeans R Mayor escalabilidad
Uso de tags: similitud con HTML Mayor portabilidad Uso de un lenguaje estndar y muy difundido
-2-
Funcionamiento
* Cul es el funcionamiento bsico? Muy sencillo: 1) El cliente solicita una pgina .jsp (en lugar de .html) 2) La solicitud llega al servidor 3) El servidor ejecuta la pgina .jsp y obtiene un texto en formato html 4) El servidor enva el texto html al cliente 5) El navegador del cliente visualiza el texto html como si realmente hubiera estado almacenado en el servidor * Que hay dentro de un fichero .jsp? Un fichero .jsp es un fichero .html que tiene dentro algunas cosas que se pueden ejecutar y que producen como resultado ms html * El siguiente dibujo resume el funcionamiento:
* Realmente, la solicitud de la pgina JSP le llega (en nuestros ejemplos) al motor JSP a travs del puerto 8080
Captulo 15: Introduccin a JSP.
-3-
Instalacin
* El motor o servidor JSP puede ser el JSWDK, o bien Apache Tomcat * Usaremos Tomcat ya que tiene soporte para tags. JSWDK no * Consideraciones de instalaciones de Tomcat: Quitar el start de la invocacin a javac en tomcat.bat Al comienzo de startup.bat poner: set JAVA_HOME=d:\jdk1.3 El puerto de escucha se puede modificar en /conf/server.xml Los servlets se ubican en /WEB-INF/classes Los ficheros .jsp y .tld se encuentran a partir de ROOT Tomcat no acepta la etiqueta bodycontent en un fichero .tld Modificar el classpath para que se encuentren todos los .class necesarios, especialmente jdk1.3/lib/tools.jar Cuando se usan etiquetas, los ficheros .class que heredan de Tag deben pertenecer a un paquete Tomcat se arranca con startup Es conveniente crear en el directorio ROOT un directorio jsp para guardar las pginas JSP La ubicacin de los ficheros .tld se puede indicar a travs del fichero /conf/web.xml
S G R
bsicas para el
-4-
Componentes JSP
* Los componentes que se pueden meter enmedio de una pgina HTML para hacerla dinmica (hacerla JSP) son:
Expresiones: son de la forma: <%= expresin Java %> El motor traduce la expresin por la cadena que resulta de evaluarla Declaraciones: son de la forma: <%! declaraciones Java %> Lo que se escriba aqu ser global a toda la pgina JSP (realmente se inserta tal cual en el cuerpo del servlet fuera de todo mtodo) Pueden incluirse declaraciones de variables y de funciones Scriplets: son de la forma: <% cdigo Java %> Cdigo Java que se ejecutar en el punto concreto de la pgina JSP en que se encuentra
-5-
Componentes JSP
L
Comentarios: son de la forma: <%-- comentario %> No se envan al cliente Directivas: son de la forma: <%@ directiva atributo1=" valor1" atributo2=" valor2" ... %> Permiten definir la estructura de todo el documento JSP. Realmente indican aspectos bsicos del servlet en que se convertir el fichero JSP en que se encuentra. Se procesan en el momento de convertir la pgina JSP en un servlet. Las tres directivas existentes son: O <%@ page ... %> O <%@ include file=URL relativa %> Sirve para incluir un fichero dentro de otro en el momento en que la pgina JSP se convierte en servlet O <%@ taglib ... %>
S G R
Etiquetas jsp: son de la forma: <jsp:etiqueta atributos /> Realizan operaciones diversas. Su utilidad principal es para comunicarse con los JavaBeans de forma que el cdigo dela pgina .jsp sea lo ms parecido al .html
-6-
Primer ejemplo
* El ejemplo ms sencillo consiste en cambiarle la extensin a cualquier fichero .html y ponerle .jsp, as como colocarlo en un sitio donde el servidor JSP la pueda encontrar. As de sencillo! * Con esto lo nico que conseguimos es que la pgina nos la sirva el servidor JSP en lugar del servidor web * Una vez visto que todo funciona bien, podemos probar con algo sencillo, tal como
<HTML> <HEAD> <TITLE>Expresiones JSP</TITLE> </HEAD> <BODY> <H2>Expresiones JSP</H2> <UL> <LI>Fecha actual: <%= new java.util.Date().toLocaleString() %> <LI>Su mquina: <%= request.getRemoteHost() %> <LI>Su ID de sesin: <%= session.getId() %> <LI>El parmetro <CODE>testParam</CODE>: <%= request.getParameter("testParam") %> </UL> </BODY> </HTML>
-7-
Expresiones JSP
* Las pginas JSP son especialmente itles cuando el usuario enva un formulario lleno de campos en los que expresa el tipo de informacin que solicita * Los parmetros que enva el usuario se pueden conocer enviando el mensaje getParameter(String) al objeto request, que es uno de los varios objetos que el motor JSP nos suministra para que tengamos mayor control. * Los objetos ms tiles que se nos suministran son: request de tipo HttpServletRequest. Representa la solicitud realizada por el cliente response de tipo HttpServletResponse. Representa nuestra respuesta. no tiene porqu ser una pgina html sino cualquier otra cosa (ver setContentType()) session de tipo HttpSession. Representa la sesin del cliente out de tipo JspWriter (es un PrintWriter con buffer). Es el ms utilizado y representa el canal de salida de texto y datos hacia el cliente application de tipo ServletContext. Con setAttribute y getAttribute sirve para guardar objetos globales a todas las pginas JSP pageContext de tipo PageContext. Muy utilizado en las etiquetas para obtener el resto de objetos anteriores (que no son visibles en las etiquetas)
S G R
-8-
Scriptlets
* Un scriptlet es un trozo de cdigo Java * Si se ha comprendido bien el fichero .jsp anterior, se puede comprender lo que hace un scriplet (y el funcionamiento del objeto out) viendo la siguiente equivalencia:
<LI>Fecha actual: <%= new java.util.Date().toLocaleString() %>
equivale a
<% String fecha new java.util.Date().toLocaleString(); out.println(<LI>Fecha actual: +fecha); %>
-9-
Scriptlets y condiciones
* Un scriptlet puede estar formado por varios trozos. Lo que hay entre ellos se considera cuerpo del scriptlet aunque sea cdigo HTML. * Ejemplo:
<HTML> <HEAD> <TITLE>Cuerpos dentro de bloques JSP</TITLE> </HEAD> <BODY> <H1>Cuerpos dentro de <i>Scriptlets</i></H1> <% if (Math.random() < 0.5) {%> Que tenga un buen da. <% } else { %> Que tenga mucha suerte. <% } %><p> Y ahora la tabla del 7:<br> <% for (int i = 1; i <= 10; i++) { %> 7 x <%= i %> = <%= 7*i %> Perfecto <br> <% } %> </BODY> </HTML>
S G R
-10-
Declaraciones
* En las declaraciones se pueden incluir funciones y variables que pueden utilizarse en cualquier lugar de la pgina
<HTML> <HEAD><TITLE>Declaracin de funciones</TITLE></HEAD> <%! void tabla(JspWriter out, int numero){ for (int i = 1; i <= 10; i++) try{ out.print(numero + " x " + i + " = " + numero*i+"<br>"); } catch (IOException ioe){ioe.printStackTrace();} } %> <BODY><H1>Declaracin de funciones</H1> Ahora la tabla del 7 y luego la del 4:<br> <% tabla(out, 7); out.print("<p>"); tabla(out, 4); %> </BODY> </HTML>
* Una vez que la pgina JSP se carga en memoria por parte del servidor JSP se queda en ella (a menos que se modifique, en cuyo caso se recompila). Ej. que lo demuestra:
<HTML> <HEAD><TITLE>Declaracin de variables en JSP</TITLE></HEAD> <%! private int accesos = 0; %> <BODY><H1>Declaracin de variables en JSP</H1> <H2>Accesos a esta pgina desde que se carg el servidor: <%= ++accesos %> </H2> </BODY> </HTML>
.
Punto indicado
* Probar a cargar la pgina varias veces. Luego quitar el punto indicado y volverla a cargar varias veces
Captulo 15: Introduccin a JSP.
-11-
S G R
-12-
Fichero Error.html
<HTML><BODY> Esta pgina se obtiene en lugar del error tradicional <BODY><HTML>
-13-
Ejemplo de upload
* Para subir ficheros al servidor, fotos, etc. se puede usar el paquete com.oreilly.servlet.*: es muy til la clase MultipartRequest, ya que el formulario de envo debe ser multiparte. Fichero upload.jsp
<%@ page import="com.oreilly.servlet.*, java.util.*, java.io.*" %> <% try{ MultipartRequest multi = new MultipartRequest(request, ".",10000000);// .10MB out.println(multi.getParameter("line")+"<br>"); out.println("Files:"); Enumeration files = multi.getFileNames(); while (files.hasMoreElements()) { String name = (String)files.nextElement(); String filename = multi.getFilesystemName(name); String type = multi.getContentType(name); File f = multi.getFile(name); if (f==null) continue; // Por si el parmetro no est cargado BufferedReader in = new BufferedReader(new FileReader(f)); String s, s2 = new String(); while((s = in.readLine())!= null) s2 += s + "<br>"; out.println("name: " + name); out.println("filename: " + filename); out.println("type: " + type); out.println("f.length(): " + f.length()+"<br>"); out.println("fileContent: " + s2+"<br>"); in.close(); } }catch(IOException e){ //No es un error, sino tan slo la primera vez que se llama a esta pgina } %>
S G R
<FORM ENCTYPE="multipart/form-data" method="POST" action="upload.jsp"> <INPUT TYPE="text" NAME="line"> <INPUT TYPE="file" NAME="mptest"> <INPUT TYPE="submit" VALUE="upload"> </FORM>
-1-
S G R
* El formato de ambas etiquetas es muy parecido: <jsp:include page=URLRelativa flush=true> <jsp:param name=nombreParmetro value=valor> ... </jsp:include> * En el forward el atributo flush no existe, mientras que en el include es oblitarorio y adems siempre true.
-2-
Ejemplo de jsp:page
* Con el cuerpo opcional jsp:param es posible enviar campos al formulario destino. Fichero includes.jsp
<HTML><BODY> <H1>Includes selectivos</H1> Lo que se incluye a partir de aqu se va alternando. <%! boolean biestable = true; %> <% biestable = !biestable; if (biestable) { %> <jsp:include page="uno.jsp" flush="true"> <jsp:param name="color" value="red"/> </jsp:include> <% } else { %> <jsp:include page="dos.html" flush="true"/> <% } %> </BODY></HTML>
Fichero uno.jsp
<% String bgColor = request.getParameter("color"); if (bgColor == null) bgColor = "WHITE"; String texto = request.getParameter("texto"); if (texto == null) texto = "Prueba de color"; %> <H2 ALIGN="CENTER"> <FONT COLOR="<%= bgColor %>" ><%= texto %></FONT> </H2>
Fichero dos.html
<H1>Esto es un ejemplo de algo que se incluye</H1>
* Ntese como en uno.jsp se utiliza tanto el atributo recibido por includes.jsp como el que ste le enva. Invocar includes.jsp de la forma: http://betelgeuse:8080/jsp/includes.jsp?texto=prueba
Captulo 16: Etiquetas jsp: y JavaBeans.
-3-
La etiqueta jsp:plugin
* Es transformada automticamente por el servidor JSP en una etiqueta que incluye un applet que puede utilizar las extensiones del JDK 1.2 y superiores (no es necesario que se haya descargado el plug-in de Java para los navegadores). * Su formato es muy parecido al de la etiqueta APPLET. Un ejemplo comparativo puede ser:
<APPLET CODE=MiApplet.class WIDTH=465 HEIGHT=350> </APPLET>
equivale a
jsp:include, aunque deben ir, a su vez, entre <jsp:params> y </jsp:params> * Adems de losmismo atributos que permite la etiqueta APPLET, otros atributos que posee son: jreversion. Versin del JRE que requiere el applet nspluginurl. La URL completa en la que es posible encontrar el plug-in para Netscape iepluginurl. La URL completa en la que es posible encontrar el plug-in para Internet Explorer * Adems de applets tambien se pueden cargar JavaBeans
Captulo 16: Etiquetas jsp: y JavaBeans.
-4-
Uso de JavaBeans
* Desde nuestro punto de vista, un JavaBean es una clase con las siguientes caractersticas: Posee un constructor sin parmetros No posee campos pblicos Para conocer el valor de un campo llamado xxx debe disponer de una funcin getXxx (o isXxx si es de tipo boolean) Para asignarle valor a un campo llamado xxx debe disponer de una funcin setXxx * La utilizacin de los JavaBeans permite encapsular diversas funcionalidades aumentando la orientacin a objetos del sistema * Para no ensuciar el cdigo HTML de la pgina JSP, se suministran varias etiquetas jsp: que permiten gestionar los JavaBeans de forma natural * Las etiquetas jsp: para gestionar JavaBeans son: jsp:useBean. Crea un objeto (si no existe ya) de una clase que cumple ser un JavaBean y le da un nombre. A partir de este momento ese objeto se utilizar por su nombre jsp:setProperty. Invoca un mtodo setXxx de un JavaBean previamente creado jsp:getProperty. Visualiza el resultado devuelto por un mtodo getXxx de un JavaBean previamente creado
-5-
Sintaxis
* Los atributos que admite jsp:useBean son: id=nombre. Nombre que se le da a ese objeto scope=page|request|session|application. Indica dnde se puede usar dicho objeto: O page: slo en esta pgina O request: si hay un forward o un include tambin se podr usar en las pginas destino O session: se puede usar en la sesin de usuario a travs de varias pginas, pero slo para ese usuario O application: Existir hasta que se cierre el servidor JSP. Disponible para todo el mundo siempre. class=Clase.class. Nombre de la clase de la que se crea el objeto type=Clase.class. Por si se quiere hacer un upcasting
S G * Los atributos que admite jsp:getProperty son: R name=nombre. Nombre del objeto del que tomar el campo
property=nombreCampo. Nombre del campo cuyo valor se desea visualizar * Los atributos que admite jsp:setProperty son: name=nombre. Nombre del objeto en que guardar el valor property=NombreCampo. Nombre del campo cuyo valor se desea guardar value=valor. Valor que se desea guardar. Se hace una conversin automtica en funcin del tipo del campo
-6-
Fichero StringBean.jsp
<HTML> <HEAD><TITLE>Uso de JavaBeans con JSP</TITLE></HEAD> <BODY> <TABLE BORDER=5 ALIGN="CENTER"> <TR><TH CLASS="TITLE">Uso de JavaBeans con JSP </TABLE> <jsp:useBean id="stringBean" class="jsp.StringBean" /> <OL> <LI>Valor inicial (getProperty): <I><jsp:getProperty name="stringBean" property="mensaje" /></I> <LI>Valor inicial (expresin JSP): <I><%= stringBean.getMensaje() %></I> <LI><jsp:setProperty name="stringBean" property="mensaje" value="El mejor lenguaje: Java" /> Valor despus de haber cambiado el campo con setProperty: <I><jsp:getProperty name="stringBean" property="mensaje" /></I> <LI><% stringBean.setMensaje("Libertad, Igualdad y Fraternidad"); %> Valor despus de haber cambiado el campo con un <i>scriptlet</i>: <I><%= stringBean.getMensaje() %></I> </OL> </BODY> </HTML>
* El nombre dado al JavaBean puede usarse desde un scriptlet * El StringBean.class debe ir en el directorio WEB-INF\classes de la aplicacin donde est metida la pgina StringBean.jsp.
Captulo 16: Etiquetas jsp: y JavaBeans.
-7-
Asignacin de parmetros
* Si una pgina recibe parmetros que hay que asignarlos a campos de un JavaBean, jsp:setProperty suministra una forma de hacerlo de forma elegante. De esta guisa, los dos trozos de cdigo siguientes son equivalentes:
<% int numElementos = 1; try { numElementos = Integer.parseInt(request.getParameter(num)); } catch (NumberFormatException nfe) {} %> <jsp:setProperty name=articulo property=numero value=<%= numElementos %>
/>
S G * El atributo param en lugar de value toma el valor de un R JSP, lo convierte al tipo del parmetro de entrada a la pgina
equivale a
<jsp:setProperty name=articulo property=numero param=num />
campo y guarda su valor en el campo. * Para asociar todos los parmetros de entrada con campos de un JavaBean basta con indicar un asterisco como property. Ej.:
<jsp:setProperty /> name=articulo property=*
* En ste ltimo caso, los nombres de los parmetros y de los campos del JavaBean han de ser idnticos
-8-
Ejemplo
Fichero StringBean2.java
/** Un JavaBean sencillito que slo tiene un campo * mensaje de tipo String y un campo dato de tipo double */ package jsp; public class StringBean2 { private String mensaje = "Ningn mensaje"; private double dato = 0.0; public String getMensaje() { return(mensaje); } public void setMensaje(String mensaje) { this.mensaje = mensaje; } public double getDato() { return(dato); } public void setDato(double dato) { this.dato = dato; } }
Fichero StringBean2.jsp
<HTML> <HEAD><TITLE>Uso de JavaBeans con JSP</TITLE></HEAD> <BODY> <jsp:useBean id="articulo" class="jsp.StringBean2" scope ="session" /> <% if (request.getParameter("mensaje") != null) { %> <jsp:setProperty name="articulo" property="*" /> <jsp:getProperty name="articulo" property="mensaje" /><br> <jsp:getProperty name="articulo" property="dato" /><br> <% } else {%> <FORM ACTION="StringBean2.jsp"> <INPUT TYPE="TEXT" NAME="mensaje" VALUE="Algo que contar"> <INPUT TYPE="TEXT" NAME="dato" VALUE="67.9"> <INPUT TYPE="SUBMIT"> </FORM> <% } %> </BODY> </HTML>
* Como se dijo antes, con jsp:useBean se crea un objeto si ste no exista ya. Si ya exista se usa el preexistente y ya est * Entre <jsp:useBean ...> y </jsp:useBean> se puede introducir un bloque JSP que slo se ejecutar si el JavaBean se crea de verdad
Captulo 16: Etiquetas jsp: y JavaBeans.
-1-
S de cdigo Java ubicado en * Cada etiqueta se asocia a un bloque la clase cuyo nombre se indica. G * Estas clases deben heredar y utilizar clases estndares R almacenadas en el paquete java.servlet.jsp.tagext.*
* Cuando el motor JSP se encuentra una de estas etiquetas, la sustituye por su cdigo asociado y lo ejecuta. * Por tanto, necesitamos tres ficheros: La pgina JSP que utiliza las etiquetas: *.jsp La clase que contiene el cdigo a ejecutar: *.class Un fichero que indica qu clase se corresponde con cada etiqueta: *.tld (Tag Library Descriptor)
* En el cdigo asociado podemos acceder al objeto pageContext y, a travs de l, a los objetos out, request, parameter, etc.
Captulo 17: JSP y bibliotecas de etiquetas.
-2-
Primer ejemplo
Fichero ExampleTag.java
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.io.*; /** Utilizacin de etiquetas con JSP. Ejemplo que saca un sencillo mensaje. * El nombre real de la etiqueta no se da aqu, sino en el fichero tld referenciado * en la pgina JSP a travs de la directiva taglib */ public class ExampleTag extends TagSupport { public int doStartTag() { try { JspWriter out = pageContext.getOut(); out.print("Custom tag example (ExampleTag)"); } catch(IOException ioe) { System.out.println("Error in ExampleTag: " + ioe); } return(SKIP_BODY); } }
Fichero csajsp-taglib.tld
<?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-jsptaglibrary_1_1.dtd"> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>csajsp</shortname> <info>http://www.coreservlets.com/.</info> <tag> <name>example</name> <tagclass>ExampleTag</tagclass> <info>Simplest example: inserts one line of output</info> </tag> </taglib>
Fichero Ejemplo.jsp
<HTML> <HEAD> <%@ taglib uri="/csajsp-taglib.tld" prefix="csajsp" %> <TITLE><csajsp:example /></TITLE> </HEAD> <BODY><H1><csajsp:example /></H1><csajsp:example /></BODY> </HTML> Captulo 17: JSP y bibliotecas de etiquetas.
-3-
La clase Tag
* Las etiquetas se forman por un inicio, un cuerpo y un final. Cuando el sistema se encuentra el inicio ejecuta doStartTag(), y cuando encuentra el final ejecuta doEndTag(). * Estas funciones deben reescribirse en una clase que hereda de la interfaz Tag. Sun suministra dos clases de partida que heredan de Tag: O TagSupport, si la etiqueta no gestiona el cuerpo O BodyTagSupport, si se quiere tener un control completo del cuerpo * doStartTag() retorna un entero que puede ser: SKIP_BODY. Ignora lo que haya entre el inicio de etiqueta y el final de etiqueta. Contina con el resto de la pgina EVAL_BODY_INCLUDE. Evala el cuerpo que haya entre el inicio de etiqueta y el final de etiqueta. Slo TagSupport EVAL_BODY_TAG. Igual que el anterior, pero con ms control. Slo BodyTagSupport
S G R
* doEndTag() retorna un entero que puede ser: SKIP_PAGE. Ignora el resto de la pgina HTML EVAL_PAGE. Contina normalmente la evaluacin del resto de la pgina * Como en cualquier otra etiqueta HTML, las etiquetas pueden tener atributos asociados. Si una etiqueta tiene asociado el atributo miAtributo, el sistema (antes de llamar a doStartTag()) busca y llama automticamente a una funcin llamada setMiAtributo(String) y que deberemos definir en la clase asociada a la etiqueta.
Captulo 17: JSP y bibliotecas de etiquetas.
-4-
-5-
* Los atributos son siempre de tipo String y es necesario convertirlos a su tipo correcto controlando posibles errores.
Semplea la directiva taglib que * Para utilizar una biblioteca se posee como parmetros: G .tld que contiene la uri La direccin del fichero traduccin de las etiquetas. Direccin a partir del R directorio ROOT
prefix Prefijo que deben tener todas las etiquetas que procedan del uri anterior. Se utiliza para evitar conflictos de etiquetas procedentes de varios tld * La ubicacin de un fichero .tld se puede indicar a travs del fichero de configuracin web.xml, de la forma:
<taglib> <taglib-uri>/myPRlibrary</taglib-uri> <taglib-location>/WEB-INF/tlds/PRlibrary_1_4.tld</taglib-uri> </taglib>
-6-
Segundo ejemplo
Fichero SimpleTag.java
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.io.*; import java.util.*; /** Utilizacin de etiquetas con JSP. Ejemplo que saca un nmero aleatorio * entre 0 y el parmetro que se le pasa. */ public class SimpleTag extends TagSupport { protected long maximo = 100; public int doStartTag() { try { JspWriter out = pageContext.getOut(); out.print(new Random().nextLong() % maximo); } catch(IOException ioe) { System.out.println("Error in SimpleTag: " + ioe); } return(SKIP_BODY); } public void setMaximo(String maximo){ try{ this.maximo = new Long(maximo).longValue(); } catch(NumberFormatException nfe){ this.maximo=100; } } }
Ejemplo de uso
<csajsp:example3 maximo="10000"/>
-7-
S como es posible retornar * En el siguiente ejemplo se observa cualquiera de sendas etiquetas en base a un condicin de G depuracin R * Podemos invocar a la pgina como:
http://localhost:8080/jsp/EjemploDebug.jsp o bien como: http://localhost:8080/jsp/EjemploDebug.jsp?debug=si segn queramos que aparezca el cuerpo o no
-8-
Fichero EjemploDebug.jsp
<HTML> <HEAD><TITLE>Using the Debug Tag</TITLE></HEAD> <BODY> <H1>Uso de la etiqueta depurar</H1> <%@ taglib uri="/WEB-INF/tlds/csajsp-taglib.tld" prefix="csajsp" %> Comienzo de pgina. Bla, bla, bla. chiu, chiu, chiu.<P> <csajsp:depurar> <B>Debug:</B> <UL> <LI>Fecha actual: <%= new java.util.Date().toLocaleString() %> <LI>Host remoto: <%= request.getRemoteHost() %> <LI>Id de Sesin: <%= session.getId() %> </UL> </csajsp:debug> <P> Final de pgina. Bla, bla, bla. chiu, chiu, chiu.<P> </BODY> </HTML>
-9-
S T getBodyContent(). Devuelve un objeto de tipo BodyContent G * Un objeto de tipo BodyContent representa el resultado de R haber evaluado el cuerpo de una etiqueta. Los cuerpos se
evalan y el resultado se mete en un BodyContent. A continuacin, el BodyContent se suele volcar en out. BodyContent posee los siguientes mtodos: getString(). Devuelve una cadena que representa la evaluacin del cuerpo getReader(). Permite leer a travs de un Reader el BodyContent clearBody(). Resetea el contenido del BodyContent getEnclosingWriter() writeOut(Writer). Vuelca el contenido del BodyContent en el Writer especificado
-10-
Ejemplo de bucle
Fichero RepeatTag.java
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.io.*; /* Etiqueta que repite el cuerpo un nmero de veces. */ public class RepeatTag extends BodyTagSupport { private int reps; public void setReps(String repeats) { try { reps = Integer.parseInt(repeats); } catch(NumberFormatException nfe) { reps = 1; } } public int doAfterBody() { if (reps-- >= 1) { BodyContent body = getBodyContent(); try { JspWriter out = body.getEnclosingWriter(); out.println(body.getString()); body.clearBody(); // Borra para el ciclo siguiente } catch(IOException ioe) { System.out.println("Error en RepeatTag: " + ioe); } return(EVAL_BODY_TAG); } else { return(SKIP_BODY); } } }
-11-
mbito de objetos
Fichero RepetirEjemplo.jsp
<HTML> <HEAD><TITLE>Algunos nmeros aleatorios</TITLE></HEAD> <BODY> <H1>Algunos nmeros aleatorios</H1> Cada nmero de la lista siguiente es un nmero aleatorio <%@ taglib uri="/WEB-INF/tlds/csajsp-taglib.tld" prefix="csajsp" %> <OL> <!-- Se repite N veces. Si reps es null se repite una sola vez. --> <csajsp:repetir reps='<%= request.getParameter("repeats") %>'> <LI><csajsp:example3 maximo="1000000" /> </csajsp:repetir> </OL> </BODY> </HTML>
S * Como se observa en este yG anteriores ejemplos, el nmero aleatorio que se obtiene es siempre el mismo, ya que por cada R invocacin de una etiqueta se vuelve a crear un objeto de su
clase asociada. Si un objeto se quiere reutilizar de una invocacin a otra en la misma pgina, se puede almacenar en el objeto request con: request.setAttribute(clave, objeto) y se recupera con request.getAttribute(clave) * Ejemplo que soluciona el problema (SimpleTag.java)
JspWriter out = pageContext.getOut(); ServletRequest request = pageContext.getRequest(); Random rnd = (Random) request.getAttribute("rnd"); if (rnd == null){ rnd = new Random(); request.setAttribute("rnd", rnd); out.println("Creando el Random()"); } out.print(rnd.nextLong() % maximo); Captulo 17: JSP y bibliotecas de etiquetas.
-12-
Etiquetas anidadas
* Hay situaciones en las que se sabe que una etiqueta debe aparecer siempre dentro del cuerpo de alguna otra. La etiqueta exterior puede contener alguna informacin til para las internas * Desde una etiqueta interna podemos acceder al objeto de la externa mediante la funcin: Object findAncestorWithClass(Object, Class) * Los parmetros definen de quin se busca la etiqueta ancestro (normalmente this) y, por si el anidamiento es de varios niveles, que tipo de etiqueta ancestro es la que se busca (p.ej. EtiquetaExterna.class)
-13-
Bases de Datos
* En este ejemplo completo se ilustra la utilizacin de una base de datos mediante el uso de etiquetas anidadas *El cdigo JSP producido es muy similar al HTML con la ventaja con respecto a la legibilidad que ello conlleva * Las etiquetas que se usan son: T queryBlock que toma como parmetros el nombre de la fuente de datos (en ODBC). Opcionalmente podra incluir el nombre de usuario y la clave T queryStatement que tiene como cuerpo el texto de una consulta SQL T queryCreateRows que prepara la lectura del nmero de tuplas que se indique desde un inicio a un final (ambos opcionales) T queryDisplay que visualiza el contenido del campo que se indique
S G R
* Ejemplo de uso:
<html> <%@ taglib uri=http://acme.com/taglibs/simpleDB.tld prefix=x %> <x:queryBlock connData=conData1> <x:queryStatement> SELECT nombre, apellidos FROM Clientes </x:queryStatement> Los primeros diez clientes son: <table> <tr><th>ACCOUNT</th><th>BALANCE</th></tr> <x:queryCreateRows from=1 to=10> <tr> <td><x:queryDisplay field=nombre/></td> <td><x:queryDisplay field=apellidos/></td> </tr> </x:queryCreateRows> </table> </x:queryBlock> </html> Captulo 17: JSP y bibliotecas de etiquetas.
-14-
Etiquetas Java
Fichero QueryBlockTag.java
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.sql.*; import java.io.*; class Util { public static void prueba(JspWriter out, String cadena){ try { out.print(cadena); }catch(IOException ioe){ ioe.printStackTrace(); } } } public class QueryBlockTag extends TagSupport{ protected Connection conexin; protected ResultSet resultado; private String connData = "prueba1"; JspWriter out ; public void setConnData(String connData){ this.connData = connData; } public int doStartTag(){ try{ out = pageContext.getOut(); Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexin = DriverManager.getConnection("jdbc:odbc:"+connData, "", ""); }catch(Exception e){ e.printStackTrace(); Util.prueba(out, "Error en la apertura de la base de datos"); return SKIP_BODY; } return EVAL_BODY_INCLUDE; } public int doEndTag(){ try{ conexin.close(); }catch(SQLException se){se.printStackTrace();} return EVAL_PAGE; } }
-15-
Etiquetas Java
Fichero QueryStatementTag.java
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.sql.*; import java.io.*; public class QueryStatementTag extends BodyTagSupport{ public int doAfterBody(){ BodyContent body = getBodyContent(); try{ QueryBlockTag padre = (QueryBlockTag)findAncestorWithClass(this, QueryBlockTag.class); if (padre ==null) throw new SQLException("Padre es null"); Statement sentencia = padre.conexin.createStatement(); padre.resultado = sentencia.executeQuery(body.getString()); }catch(SQLException se){ Util.prueba(body.getEnclosingWriter(), "No se puede crear la sentencia."); } return SKIP_BODY; } }
S G Fichero QueryDisplayTag.java R
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.sql.*; import java.io.*;
public class QueryDisplayTag extends TagSupport{ private String field; public int doStartTag(){ ResultSet resultado = ((QueryBlockTag)findAncestorWithClass(this, QueryBlockTag.class)).resultado; JspWriter out = pageContext.getOut(); try{ out.print(resultado.getString(field)); }catch(Exception ioe){ Util.prueba(out, "Imposible cargar el campo: "+ field); } return SKIP_BODY; } public void setField(String field){ this.field = field; } } Captulo 17: JSP y bibliotecas de etiquetas.
-16-
Etiquetas Java
Fichero QueryCreateRowsTag.java
package jsp; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.sql.*; import java.io.*; public class QueryCreateRowsTag extends BodyTagSupport{ int from = 1, to = 1; ResultSet resultado; public void setFrom(String from){ this.from = Integer.parseInt(from);} public void setTo(String to){ this.to = Integer.parseInt(to); } public int doStartTag(){ re s u lt a d o = ((Q u e ryB lo c kT ag)f indAncest o rW it h Cla s s (t h is, QueryBlockTag.class)).resultado; int contador = 1; // Este bucle se posiciona en el registro anterior al que hay que mostrar try{ while ((contador < from) && resultado.next()) contador ++; }catch(SQLException se){ se.printStackTrace(); } try{ if(!resultado.next()) return SKIP_BODY; }catch(SQLException se){ Util.prueba(pageContext.getOut(), "No se puede mostrar el registro"); return SKIP_BODY; } return EVAL_BODY_TAG; } public int doAfterBody(){ BodyContent body = getBodyContent(); JspWriter out = body.getEnclosingWriter(); try{ out.print(body.getString()); body.clearBody(); }catch(IOException ioe){Util.prueba(out, "Imposible emitir registro"); } if (++from > to) return SKIP_BODY; else{ try{ if (!resultado.next()) return SKIP_BODY; }catch(SQLException sqle){ Util.prueba(out, "Error en los registros."); return SKIP_BODY; } return EVAL_BODY_TAG; } } }
-17-
Descriptor de etiquetas
Fichero bbdd-taglib.tld
<?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-jsptaglibrary_1_1.dtd"> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>bbdd</shortname> <info>http://www.coreservlets.com/.</info> <tag> <name>queryBlock</name> <tagclass>jsp.QueryBlockTag</tagclass> <info>Comienzo de una consulta. Conexin</info> <attribute> <name>connData</name> <required>false</required> </attribute> </tag> <tag> <name>queryStatement</name> <tagclass>jsp.QueryStatementTag</tagclass> <info>Ejecuta una consulta que es su propio cuerpo</info> </tag> <tag> <name>queryCreateRows</name> <tagclass>jsp.QueryCreateRowsTag</tagclass> <info>Se posiciona al comienzo de la tupla deseada</info> <attribute> <name>from</name> <required>false</required> </attribute> <attribute> <name>to</name> <required>false</required> </attribute> </tag> <tag> <name>queryDisplay</name> <tagclass>jsp.QueryDisplayTag</tagclass> <info>Visualiza el campo que se indica</info> <attribute> <name>field</name> <required>false</required> </attribute> </tag> </taglib>
S G R
-1-
S G R
-2-
Lenguaje de expresiones
* El lenguaje de expresiones (EL) sirve para facilitar la escritura de expresiones restringidas Java dentro de una pgina JSP. * Una expresin EL se escribe de la forma ${expresion} y entre las llaves puede usarse cualquier operador binario o unario que se quiera, ya sea matemtico, de cadena, relacional o lgico. Es muy til el operador unario empty para saber si algo es null o no. * Como operandos pueden usarse: Variables con mbito. Literales numricos, de cadena o lgicos. Componentes Java Beans. Colecciones. Funciones definidas en un fichero .tld * La gran ventaja de las expresiones EL es que son evaluadas por el propio motor JSP que las sustituye bajo demanda por el resultado de la evaluacin. Por tanto, las expresiones pueden usarse en cualquier lugar de una pgina JSP: T Como sustituta de un literal HTML T Como valor de un atributo de una etiqueta * Ejemplos: ${10 mod 3} devuelve 1 ${1 > 3} devuelve false <c:set var=numeroSS value=124578" /> ${numeroSS == 124578} devuelve true
Captulo 18: JSTL (Java Standard Tag Library).
-3-
Contenido de expresiones
* Una expresin EL unifica el uso del punto y de los corchetes. De esta guisa, expr-a.ident-b es equivalente a expr-a[identb]. * Para evaluar expr-a[expr-b] se evala expr-a a valor-a y expr-b a valor-b, y en base a valor-a se hacen diferentes acciones: Si es null el resultado es null. Si es de tipo Map, se retorna valor-a.get(valor-b). Si es de tipo List el resultado es valor-a.get((int)valor-b). Si es un array el resultado es Array(.get(valor-a, valorb). Si es un Java Bean se retorna la propiedad valor-b. * Las siguientes variables pueden usarse directamente (todas son listas): param: lista con los nombres de los parmetros. paramValues: lista con los valores de los parmetros. header: lista con los campos de la cabecera. headerValues: lista con los valores de los campos de la cabecera. cookie: lista con los nombres de las cookies. pageScope, requestScope, sessionScope y applicationScope: lista con las variables definidas en cada mbito. * Ejemplo:
<c:forEach item=unaCookie values=${cookie}> ${unaCookie}<br> </c:forEach>
Captulo 18: JSTL (Java Standard Tag Library).
S G R
-4-
-5-
<c:out>
* La sintaxis de esta etiqueta es: <c:out value=valor [escapeXml=true|false] [default=valorSiEsNull] /> * Emite por la salida el valor del atributo value. Si este es nulo, se saca por pantalla el valor del atributo default. * Por defecto escapeXml est puesto a true, lo que quiere decir que se traducen algunos caracteres para evitar errores: Carcter < > & Cdigo de carcter < > & ' "
S G R
* El valor dado al atributo value se convierte en String y se emite, a no se que sea un objeto de tipo java.io.Reader, en cuyo caso lo que se emite es el resultado de leer por completo dicho canal de entrada. * Puede probarse como ejemplo con la pgina completa:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <c:out value="Trabajo en Gar & ca" />
-6-
<c:out> y Reader
* Sea el siguiente Bean:
package org.apache.jsp; import java.io.*; public class StringBean { private String nombreFichero = "Ningun nombreFichero"; public String getNombreFichero() { return(nombreFichero); } public void setNombreFichero(String nombreFichero) { this.nombreFichero = nombreFichero; } public Reader getLector() throws IOException { return new FileReader(getNombreFichero()); } public void setLector(String lector) { this.nombreFichero = lector; } }
* Y el JSP:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <jsp:useBean id="stringBean" class="org.apache.jsp.StringBean" /> <jsp:setProperty name="stringBean" property="lector" value="e:/prueba.txt" /> <c:out value="${stringBean.lector}"/><br> <c:out value="Otra cosa" /><br>
* La salida de la lnea marcada es el contenido del fichero e:\prueba.txt. De una sola tacada se ha emitido el contenido de un fichero entero.
-7-
<c:set> y <c:remove>
* La sintaxis de <c:set> es: O Para asignar valor a una variable con mbito <c:set value=valor var=nombreVar [scope=page|request|session|application] /> O Para asignar una propiedad a un Java Bean, o un elemento de un mapa <c:set value=valor target=nombreVar property=nombrePropiedad /> O Para establecer un valor en diferido. Un valor diferido quiere decir que se asigna una expresin que se evala de forma perezosa, o sea, no en este momento, sino cuando se utilice la variable. Realmente esto slo tiene utilidad cuando se trabaja con JSF (Java Server Faces) y no volveremos a tratar el tema. * <c:remove> slo tiene sentido para variables con mbito. La sintaxis de <c:remove> es: <c:remove var=nombreVar [scope=page|request|session|application] /> * <c:set> hace asignaciones a variable con mbito o a propiedades de Java Beans o a datos de Mapas. <c:remove> elimina variables con mbito. * El subrayado quiere decir que slo pueden especificarse literales.
S G R
-8-
<c:catch>
* La sintaxis de <c:catch> es: <c:catch [var=nombreVar]> // Acciones que pueden producir excepciones </c:catch> * <c:catch> permite capturar excepciones dentro de bloques JSP. * La idea es que los errores graves no sean capturados, sino que se propaguen hasta la pgina de error especificada. Los errores secundarios son los que se deben capturar con <c:catch> para que no interfieran con el desarrollo normal de la pgina. * Si se indica un nombre de variable, entonces la excepsin se guarda en ella. Si no se produce excepcin, entonces esa variable se destruye con <c:remove> si es que exista. Por tanto, lo que suele venir a continuacin del <c:catch> es una accin condicional que testa dicha variable para hacer la accin correctora que sea. * Sino se quiere incluir accin correctora, entonces incluso puede omitirse el atributo var de <c:catch>.
-9-
* Como puede verse, la concatenacin de cadenas se hace mediante una mera yuxtaposicin. * En este ejemplo se ve el uso de <c:catch>:
<c:catch var="fallo"> Esto sale bien<br> <% if (1==1) throw new Exception("Fallo que se me ocurre"); %> Esto ya no sale<br> </c:catch> ${fallo}<br> Continua la cosa bien<br>
S G R
-10-
-11-
<c:if>
* La sintaxis de <c:if> es: <c:if test=condicion [var=nombreVar [scope=page|request|session|application]] > // Acciones que se ejecutan si la condicion se cumple </c:if> * Si la etiqueta <c:if> se autocierra y se indica un nombre de variable, entonces es como si se utilizara para cargar un valor booleano en dicha variable. * Como puede verse, esta etiqueta carece de clusula else. El motivo es que la clusula else, utilizada a discrecin, se convierte en unos ifs en cascada mutuamente excluyentes; y para eso, la biblioteca core suministra otras etiquetas * Ej. de control:
<c:if test="${ empty param.nombre}" > Se le ha olvidado escribir un valor para el nombre.<br> </c:if>
S G R
Puede probarse a cargar una pgina que contenga esto psando o no pasando en la direccin URL el parmetro nombre.
-12-
-13-
S G R
-14-
-15-
<c:forEach>
* La sintaxis es diferente segn se recorra una estructura o se itere un determinado nmero de veces. * La sintaxis que recorre una estructura es: <c:forEach [var=nombreVar] items=coleccion [varStatus=nombreVarEstado] [begin=comienzo] [end=final] [step=paso] > // Cuerpo a repetir </c:forEach> * Para ejecutarse un determinado nmero de veces, la sintaxis es: <c:forEach [var=nombreVar] [varStatus=nombreVarEstado] begin=comienzo end=final [step=paso] > // Cuerpo a repetir </c:forEach> * Ejemplo que saca los nmeros del 1 al 20:
<c:forEach var="cont" begin="1" end="20"> ${cont}<br> </c:forEach>
S G R
-16-
<c:forEach>
* La sintaxis de la ejecucin un determinado nmero de veces parece clara: la variable nombreVar parte del valor comienzo hasta el valor final incrementndose en cada iteracin por paso unidades. * Si el recorrido de una coleccin hace uso de begin y dems, quiere decir que se comienza en el tem de la coleccin situado en posicin comienzo. Si hay menos tems que comienzo, entonces el bucle ni se ejecuta. El primer elemento de la coleccin est en la posicin 0. * El <c:forEach> se usa para recorrer una coleccin de forma que cada elemento visitado es apuntado por nombreVar * Si la coleccin es un mapa, lo que se recorren son las entradas, que son del tipo Map.Entry. * Como coleccin tambin puede indicarse un array tradicional e incluso un String. En este ltimo caso, se supone que el String posee palabras separadas por comas, y el <c:forEach> se ejecuta para cada una de tales palabras. La coma hace las veces de carcter delimitador. * Ejemplo de recorrido de los elementos de la cabecera (header):
<c:forEach var="elemento" items="${header}"> ${elemento}<br> -> ${elemento.value}<br> </c:forEach>
-17-
<c:forTokens>
* El comportamiento de <c:forTokens> es muy parecido al de <c:forEach> cuando se recorre un String. En el caso de <c:forTokens> esposible indicar nuestros propios delimitadores. * La sintaxis de esta etiqueta es: <c:forTokens items=cadenaDeTokens delims=delimitadores [var=nombreVar] [varStatus=nombreVarEstado] [begin=comienzo] [end=final] [step=paso] > // Cuerpo a repetir </c:forEach> * El funcionamiento de esto es como el de un StringTokenizer que tiene como argumentos la cadenaDeTokens y los delimitadores. * Ntese la diferencia entre:
<c:forEach var="elemento" items="uno, dos, tres, cuatro,"> ${elemento}<br> </c:forEach> Adios.<br>
S G R
y
<c:forTokens var="elem" items="uno,dos,tres,cuatro," delims=",o" > ${elem}<br> </c:forTokens> Adios.<br>
Captulo 18: JSTL (Java Standard Tag Library).
-18-
Transferencia de variables
* En el siguiente ejemplo se puede apreciar cmo intercambiar informacin entre un scriptlet y el entorno JSP.
<% int[] miLista = new int[]{1, 3, 5, 7, 11, 13, 17, 19, 23, 29}; pageContext.getSession().putValue("miArray", miLista); %> <c:forEach var="elemento" items="${miArray}" > ${elemento}<br> </c:forEach>
* Las variables Java tambin se pueden cambiar desde JSP. En el siguiente ejemplo se le pasa un valor a JSP desde un scriptlet. Luego se cambia la variable en JSP y se recarga desde otro scriptlet:
<h3>Saludos</h3> <% int miNumero = 234544; pageContext.getSession().putValue("numero", miNumero); %> ${numero}<br> <c:set var="numero" value="16" scope="session" /> ${numero}<br> <%= miNumero %><br> <% miNumero = Integer.parseInt(pageContext.getSession(). getValue("numero").toString()); %> <%= miNumero %><br> Adios.<br>
-19-
S G R
-20-
<c:url>
* Permite construir una URL completa rescribiendo las partes que sean necesarias. * La sintaxis de esta etiqueta es: <c:url value=direccin [context=contexto] [var=nombreVar] [scope=page|request|session|application] > <c:param ...> <c:param ...> </c:url> * La direccion puede ser absoluta o relativa. Si es relativa se rescribe para hacerla absoluta. Tambin puede ser relativa a un contexto que no sea el de la pgina actual; en este caso el sistema se encarga de rescribirla convenientemente. * Si la direccion contiene caracteres raros, stos no son rescritos por el sistema. * Por defecto, la URL resultante es emitida (a travs del JspWriter actual); pero en lugar de esto puede almacenarse en una variable especificada en el atributo var. * Pueden indicarse parmetros, que se aadirn a la URL construida mediante la correspondiente recodificacin.
-21-
<c:param>
* Permite aadir parmetros de forma indirecta a una URL. * La sintaxis es: <c:param name=nombreParam value=valorParam /> o bien, si el valor del parmetro es muy complicado: <c:param name=nombreParam > valorParam </c:param> * Aunque hacer uso de esta etiqueta puede considerarse redundante, ya que se puede escribir directamente en la URL, hay que reconocer que el cdigo queda mucho ms claro. Adems, este mtodo es consistente con el utilizado por <jsp:include>, que tambin puede contener <jsp:param>. * He aqu un ejemplo de uso:
<h3>Saludos</h3> <c:url value="http://www.google.es/search" var="google" > <c:param name="hl" value="es" /> <c:param name="q" value="${param.consulta}" /> </c:url> <a href="${google}">${google}</a><br> Pincha <a href="${google}">aqu</a> para ir al mismo sitio.
S G R
-22-
<c:import>
* Esta etiqueta se va a la URL especificada y: o la mete en lnea donde se encuentra el <c:import>, o la mete en un objeto Reader para que las acciones siguientes hagan lo que quieran con el contenido. * En el primer caso la sintaxis es: <c:import url=direccion [context=contexto] [var=nombreVar] [scope=page|request|session|application] [charEncoding=codificacion] > <c:param ...> <c:param ...> </c:import> * Y en el segundo: <c:import url=direccion [context=contexto] varReader=nombreVarReader [charEncoding=codificacion] > // Cuerpo en el que consumir desde nombreVarReader </c:import> * Con la segunda sintaxis no se aceptan parmetros porque se confundiran con el cuerpo que consume el canal de entrada: no se sabra cundo acaban los parmetros y cundo hay que abrir el canal.
Captulo 18: JSTL (Java Standard Tag Library).
-23-
<c:redirect>
* La sintaxis es: <c:redirect url=direccion [context=contexto] /> * Tambin es posible indicar parmetros a esta URL, con lo que la etiqueta <c:import> quedara abierta. * Esta etiqueta cancela el procesamiento de la pgina y redirige la carga hacia la URL indicada que: Puede ser absoluta, relativa o relativa a un contexto. El contexto, como en casos anterior, debe empezar por /. Puede poseer parmetros de la forma <c:param>. * Ejemplo de uso:
* Como puede observarse, el <c:redirect> puede usarse incluso despus de haber emitido ya algo.
S G R
-24-
Ejemplo de <c:import>
* El ejemplo que vimos de <c:out > y Reader se podra haber hecho como:
<h3>Saludos</h3> <c:import url="file:///e:/prueba.txt" /> Adis<br>
* Tambin el texto que se lee se puede meter en una variable de mbito y leerlo lnea a lnea:
<h3>Saludos</h3> <c:import url="file:///e:/prueba.txt" var="lector" /> <c:forTokens var="elemento" items="${lector}" delims='<%="\n"%>' > ${elemento} -</c:forTokens> <br> Adis<br>
-25-
* Esta biblioteca permite: T Ejecutar consultas con SELECT. T Acceder fcilmente a los resultados de una consulta. T Ejecutar actualizaciones con INSERT, UPDATE y DELETE. T Agrupar operaciones SQL en una transaccin. T Cambiar rpidamente de base de datos. * Las operaciones de esta biblioteca trabajan con objetos de tipo DataSource que retorna uno de tipo Connection. El DataSource sirve para hacer referencia a una base de datos en concreto. * El DataSource con que trabajar puede especificarse de varias formas: Directamente en el atributo dataSource de algunas etiquetas, de dos formas: dando directamente la informacin que necesita el DriverManager: url [, driver] [, usuario, contrasea]. Ej.:
jdbc:pointbase:server://localhost:9092/sample, com.pointbase.jdbc.jdbcUniversalDriver,pbPublic,pbPublic
S G R
dando un valor de JNDI que ser traducido por el motor JNDI a la informacin necesaria de acceso a la base de datos. Este mtodo tiene la ventaja de que permite acceder a un pool de conexiones. Como valor del atributo de configuracin: javax.servlet.jsp.jstl.sql.dataSource
-26-
<sql:setDataSource>
* Esta etiqueta permite especificar la fuente de datos de las etiquetas sql que vendrn a continuacin. No obstante, no es obligatorio especificarlo, puesto que la fuente de datos tambin puede indicarse como atributo de un inicio de transaccin. * La sintaxis es: <sql:setDataSource var=nombreVar [scope=page|request|session|application] [ dataSource=fuenteDeDatos | url=URL_JDBC [driver=claseJavaDelDriver] [user=nombreUsuario] [password=contrasea] ] /> * El campo fuenteDeDatos, si se especifica, debe ser del tipo javax.sql.DataSource.
-27-
<sql:transaction>
* La sintaxis de esta etiqueta es: <sql:transaction [dataSource=fuenteDeDatos] [isolation= read_uncommited | read_commited | repeatable_read | serializable ] > // Cuerpo HTML que puede hacer uso de // cuantas sentencias SQL se quiera </sql:transaction> * La transaccin ejecuta automticamente el COMMIT o el ROLLBACK. El ROLLBACK lo ejecuta si captura alguna excepcin en la ejecucin del cuerpo, y el COMMIT en caso contrario. * Cada tipo de aislamiento en la transaccin es ms potentes que el anterior: read_uncommited: lo lee todo, hasta lo que todava no se le ha hecho un COMMIT. read_uncommited: no hace lecturas sucias (datos a los que no se ha hecho un COMMIT; pero s pueden suceder relecturas ambiguas: una transaccin lee un registro, otra transaccin modifica el registro, y la primera vuelve a leer el registro otra vez, pero con un valor diferente! repeatable_read: no hace relecturas ambiguas; pero s pueden suceder lecturas fantasma: una transaccin lee registros con WHERE, otra transaccin mete un nuevo registro que satisface la condicin, y la primera vuelve a leer los registros otra vez, pero con un nuevo registro aparecido! serializable: evita todos los problemas de inconsistencia.
S G R
-28-
<sql:query>
* La sintaxis de esta etiqueta es: <sql:query var=nombreVar [scope=page|request|session|application] [dataSource=fuenteDeDatos] [startRow=numRegistroInicio] [maxRows=numMaxRegistrosDevueltos] > // Sentencia SQL con el smbolo ? en el lugar // de cada parmetro <sql:param ...> <sql:param ...> </sql:query> * Esta etiqueta permite ejecutar una sentencia select parametrizada. Cada parmetro se identifica por un smbolo de interrogacin ?. Las posteriores etiquetas <sql:param> permiten sustituir cada uno de estos parmetros por un valor real. * La sentencia SELECT se ejecuta contra el DataSource especificado en la etiqueta <sql:transaction> dentro de la que se incluye, o bien contra el especificado en su atributo dataSource. * La variable indicada en el atributo var sirve para referenciar el resultado que devuelve la sentencia SELECT ejecutada y posee gran cantidad de campos.
-29-
S G R
* Es posible procesar un SELECT genrico haciendo uso de los componentes de los mtodos de la interfaz Result.
-30-
Recursos de Tomcat
* Para no tener que estar repitiendo constantemente en cada pgina los datos de una DataSource, es posible especificar en el fichero server.xml de Tomcat un recurso DataSource, darle un nombre, y luego usarlo en las etiquetas JSTL por su nombre. * De esta forma, cualquier modificacin a la cadena de conexin queda centralizada en la declaracin de este recurso en server.xml. * Ejemplo:
<Context docBase="patata5" path="/patata5" reloadable="true" debug="0"> <Resource name="jdbc/orcl" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="3" maxWait="10000" username="galvez" password="alfa00" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@localhost:1521:orcl"/> </Context>
que slo ser accesible a las pginas JSP del contexto %TOMCAT_HOME%\webapps\patata5 * Una transaccin har uso de este recurso de la forma.
<sql:transaction dataSource="jdbc/orcl" >
-31-
S G R
-32-
<sql:param> y <sql:dateParam>
* Esta etiqueta sirve para pasar parmetros a sentencias SQL preparadas. La sintaxis es: <sql:paramvalue=valor /> o bien <sql:param> // valor del parmetro </sql:param> * Esta etiqueta sirve para sustituir los smbolos ? que se hayan incluido en la sentencia SQL dentro de la cual se enmarca el propio <sql:param>. Sirve para indicar parmetros de cualquier tipo excepto fecha, para lo cual se usa la etiqueta <sql:dateParam> cuya sintaxis es: <sql:dateParam value=valorDeTipoDateDeJava type=timestamp | time | date /> * Lo ms normal es que los parmetros de entrada a una pgina JSP sean los que se utilicen para parametrizar una consulta SQL. Estos parmetros entrada deberan validarse antes de enviarlos a la consulta.
-33-
Ejemplo de <sql:query>
* El siguiente es un ejemplo de pgina completa:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <h3>Consulta genrica</h3> <c:choose> <c:when test="${empty param.limite || empty param.hora}"> <form action="index.jsp" method="GET"> Lmite de crdito: <input size=10 name="limite" value="0" /><br> Hora a partir de la cual: <input size=8 name="hora" value="0:0" /><br> <input type=submit value="Buscar" /> </form> </c:when> <c:otherwise> <% pageContext.setAttribute("horaDate", new java.util.Date("1/1/1 "+ request.getParameter("hora"))); %> <sql:transaction dataSource="jdbc:pointbase:server://localhost:9092/sample, com.pointbase.jdbc.jdbcUniversalDriver,pbPublic,pbPublic"> <sql:query var="clientes"> SELECT name, credit_limit, last_sale_time FROM customer_tbl WHERE credit_limit >= ? AND last_sale_time > ? <sql:param value="${param.limite}" /> <sql:dateParam value="${horaDate}" type="time" /> </sql:query> <table border="1"> <c:forEach var="cliente" items="${clientes.rows}" > <tr> <td>${cliente.name}</td> <td>${cliente.credit_limit}</td> <td>${cliente.last_sale_time}</td> </tr> </c:forEach> </table> </sql:transaction> </c:otherwise> </c:choose>
S G R
-34-
<sql:update>
* Esta etiqueta permite ejecutar cualquier sentencia SQL que no sea un SELECT. La sintaxis es: <sql:update [var=nombreVar] [scope=page|request|session|application] [dataSource=fuenteDeDatos] > // Sentencia SQL de DDL o DML con el smbolo ? // en el lugar de cada parmetro <sql:param ...> <sql:param ...> </sql:update> * La variable var hace referencia al nmero de elementos afectados por la sentencia. Es de especial utilidad en sentencias UPDATE y DELETE. * Con esta etiqueta tambin pueden crearse tablas, borrarlas, cambiarlas, crear restricciones, etc. * Ejecutar <sql:update sql=rollback /> o <sql:update sql=commit /> no est permitido y puede producir resultados impredecibles.
-35-
Ejemplo de <sql:update>
* El siguiente ejemplo crea una tabla, la rellena, la visualiza y la borra:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <h3>Procesamiento</h3> <sql:transaction dataSource="jdbc:pointbase:server://localhost:9092/sample, com.pointbase.jdbc.jdbcUniversalDriver,pbPublic,pbPublic" > <sql:update> CREATE TABLE a (campo1 NUMBER) </sql:update> <c:forEach var="contador" begin="1" end="20" step="3" > <sql:update> INSERT INTO a VALUES (?) <sql:param value="${contador}" /> </sql:update> </c:forEach> <sql:query var="registros" > SELECT campo1 FROM a </sql:query> <c:forEach var="registro" items="${registros.rows}"> ${registro.campo1}<br> </c:forEach> <sql:update> DROP TABLE a </sql:update> </sql:transaction> ----------<br>
S G R
-36-
* Hace uso de los conceptos de internacionalizacin que ya se han estudiado en captulos anteriores. Algunas etiquetas interesantes son: O <fmt:setLocale> especifica el Locale actual. O <fmt:bundle> especifica el nombre base de los ficheros de recursos. O <fmt:message> emite el mensaje de cdigo especificado en el idioma del Locale actual. El mensaje lo busca en el fichero de recursos del bundle actual. Se le pueden pasar parmetros. O <fmt:requestEncoding> sirve para trabajar con parmetros que proceden de un cdigo diferente al ISO8859-1. * Nosotros nos vamos a centrar principalmente en las etiquetas de formateo. <fmt:timeZone> y <fmt:setTimeZone> no las veremos.
-37-
<fmt:formatNumber> y <fmt:parseNumber>
* Estas etiquetas permiten emitir un nmero que siga el formato que se le indice, as como traducir un texto a un nmero siguiendo un patrn concreto de anlisis. Las sintaxis son: <fmt:formatNumber value=valorNumrico [var=nombreVar] [scope=page|request|session|application] [type=number | currency | percent ] [pattern=patronPersonalizado] [currencyCode=codigoDeMoneda] [currencySymbol=simboloDeMoneda] [groupingUsed=true | false ] [maxIntegerDigits=maximoNumeroDeDigitos] [minIntegerDigits=minimoNumeroDeDigitos] [maxFractionDigits=maximoNumeroDeDecimales] [minFractionDigits=minimoNumeroDeDecimales] /> y <fmt:parseNumber value=valorNumricoEnUnaCadena [var=nombreVar] [scope=page|request|session|application] [type=number | currency | percent ] [pattern=patronPersonalizado] [parseLocale=LocaleDelParser] [integerOnly=true | false] />
S G R
-38-
<fmt:formatNumber> y <fmt:parseNumber>
* El patrn de formateo debe seguir las reglas de la clase java.text.DecimalFormat. * El atributo groupingUsed permite decir si se va ausar algn carcter de agrupacin. Ver java.text.NumberFormat. setGroupingUsed() para ms informacin. * El atributo parseLocale sirve para decir el Locale en base al cual hay que hacer el anlisis del nmero almacenado en la cadena de entrada. * El atributo integerOnly especifica que slo debe reconocerse la parte entera del nmero guardado en la cadena. * Por ejemplo, el formateo :
<fmt:formatNumber value="${100000000 / 3}" type="currency" currencySymbol="" groupingUsed="true" maxIntegerDigits="4" maxFractionDigits="2" minFractionDigits="2" />
produce: 3.333,33 as que cuidado con maxIntegerDigits, ya que el resultado debiera haber sido: 33.333.333,33
Captulo 18: JSTL (Java Standard Tag Library).
-39-
<fmt:formatDate> y <fmt:parseDate>
* Estas etiquetas permiten trabajar con fechas. Las sintaxis son: <fmt:formatDate value=valorDeFecha [var=nombreVar] [scope=page|request|session|application] [type=date | time | both] [pattern=patronPersonalizado] [dateStyle=default | long | medium | short | full] [timeStyle=default | long | medium | short | full] [timeZone=zonaTemporal] /> y <fmt:parseDate value=valorFechaEnUnaCadena [var=nombreVar] [scope=page|request|session|application] [type=date | time | both] [pattern=patronPersonalizado] [dateStyle=default | long | medium | short | full] [timeStyle=default | long | medium | short | full] [timeZone=zonaTemporal] [parseLocale=LocaleDelParser]
S G R
siguien
el
formateo
de
-40-
<fmt:formatDate> y <fmt:parseDate>
* Algunos ejemplos de funcionamiento son:
<jsp:useBean id="ahora" class="java.util.Date" /> <fmt:formatDate value="${ahora}" /><br> <fmt:formatDate value="${ahora}" type="both" /><br> <fmt:formatDate value="${ahora}" type="time" /><br> <fmt:formatDate value="${ahora}" type="time" timeStyle="short" /><br> <fmt:formatDate value="${ahora}" pattern="dd/MM/yyyy" /><br>
-41-
* Esto no son etiquetas realmente, sino funciones con prefijo que pueden usarse en el interior de una expresin del lenguaje de expresiones. * Las funciones son las siguientes:
De bsqueda en cadenas: Ofn:contains(string, substring) devuelve boolean Ofn:containsIgnoreCase(string, substring) devuelve boolean Ofn:endsWith(string, sufijo) devuelve boolean Ofn:startsWith(string, prefijo) devuelve boolean Ofn:indexOf(string, substring) devuelve int. La primera posicin de string es la 0. Si no est se devuelve -1. De obtencin de subcadenas: Ofn:substring(string, beginIndex, endIndex) devuelve String. Las posiciones comienzan a partir de la 0. El carcter en beginIndex se incluye y el de enIndex se excluye. Ofn:substringAfter(string, substring) devuelve String Ofn:substringBefore(string, substring) devuelve String
S G R
-42-
Funciones (cont.)
Traduccin de cadenas: Ofn:replace(inputString, beforeSubstring, afterSubstring) devuelve String Ofn:toLowerCase(string) devuelve String Ofn:toUpperCase(string) devuelve String Ofn:trim(string) devuelve String. Elimina los espacios a ambos extremos de la cadena. Gestin de arrays y cadenas: Ofn:join(array, separador) devuelve String. Convierte un array en una cadena. Cada dos elementos estn separados por la cadena separador. Ofn:split(string, delimitadores) devuelve String[]. Trocea una cadena en un array de cadenas. Los trozos estaban originalmente separados por cualquier carcter de los que aparece en delimitadores. Ofn:length(input) devuelve integer. La entrada puede ser una cadena o un array o una coleccin y devuelve su longitud o el nmero de elementos respectivamente. Otras: Ofn:escapeXml(string) devuelve String. Vase el atributo escapeXml de <c:out>.
-43-
Ejemplos de funciones
* Algunos ejemplos son:
<%-- Trunca el nombre a 30 caracteres y lo visualiza en maysculas --%> ${fn:toUpperCase(fn:substring(nombre, 0, 30))} <%-- Visualiza el texto que precede al primer asterisco --%> ${fn:substringBefore(texto, *)} <%-- La variable custId puede tener espacios en blanco en los extremos. Esto los quita --%> <c:url var="myUrl" value="${base}/cust"> <c:param nombre="custId" value="${fn:trim(custId)}"/> </c:url> <%-- Visualiza el texto entre parntesis --%> ${fn:substring(text, fn:indexOf(texto, ()+1,fn:indexOf(texto, )))} <%-- Visualiza el nombre si contiene la cadena a buscar --%> <c:if test="${fn:containsIgnoreCase(nombre, searchString)}"> Encontrado en el nombre: ${nombre} </c:if> <%-- Visualiza los ltimos 10 caracteres --%> ${fn:substring(text, fn:length(texto)-10)} <%-- Visualiza un valor con bolillas en vez de guiones --%> ${fn:replace(texto, -, •)}
S G R
-44-
* No entraremos en detalle en sus etiquetas. Baste decir que son: O <x:parse> que analiza un documento XML y puede devolver un org.w3c.dom.Document. O <x:out> que evala una expresin Xpath y emite el resultado. O <x:set> igual al anterior pero guarda el resultado en una variable. O <x:if>, <x:choose>, <x:when>, <x:otherwise> y <x:forEach> para recorrer contenidos basados en expresiones Xpath. O <x:transform> y <x:param> para aplicar hojas XSLT a un documento XML.