JDC Tech Tips (21 de Agosto del 2001)

Bienvenido a los Consejos Técnicos de la Conexión del Desarrollador Java (JDC), del 21 de agosto del 2001. Esta edición cubre:

  • Soporte de un Número Ilimitado de parámetros en un Applet .
  • Distribución de Imágenes Dinámicas desde Páginas con Tecnología JSP.

Estos consejos fueron desarrollados usando Java(tm) 2 SDK, Standard Edition v 1.3

Se puede ver esta edición (en su original en inglés) de los Consejos Técnicos en formato html en http://java.sun.com/jdc/JDCTechTips/2001/tt0821.html

Soporte de un número ilimitado de parámetros en un Applet

¿Nunca ha tenido un applet que quiso que soportara un número ilimitado de parámetros?. Debido a que las applet no pueden preguntar que parámetros se le pasan, ellas necesitan conocer los nombres de los parámetros, ¿cómo hace una Applet para conocer los nombres anticipadamente?. Aquí hay dos formas que se pueden usar en una applet para soportar un número ilimitado de parámetros.

La primera forma de soportar ilimitados parámetros hace un poco a un lado el problema. En lugar de pasar un número ilimitado de parámetros, se les pone a todos en un parámetro y se desglosan los parámetros usando la clase java.util.StringTokenizer. Por ejemplo, si se necesita pasar una lista de opciones para mostrarlas luego en control List, los valores de los parámetros pueden ser los siguientes:


<param
           name="NombresChinos"
           value="Shu, Niu, Hu, T'u, Lung, She, Ma, Yang,
Hou,Chi,    Kou, Chu">
       <param
           name="NombresHispanos"
           	value="Rata, Buey, Tigre, Conejo, Dragón, 
 Serpiente,  Caballo,Carnero, Mono, Gallo, Perro, Cerdo">

En este punto, se puede leer cada parámetro con el método estándar getParameter de Applet.

String nombresChinos = getParameter("NombresChinos");
String nombresHispanos = getParameter("NombresHispanos");

Para analizar la cadena, todo lo que tiene que hacer es crear un objeto java.utill.StringTokenizer, con los delimitadores apropiados, Se puede iterar a través de los parámetros individuales, como una enumeración, o usar el los métodos hasMoreTokens() / nextToken(). El método nextToken() retorna una cadena así no se tiene que hace el cast de Object a otro tipo de datos más apropiado, en este caso String.

StringTokenizer chino = new StringTokenizer(nombresChinos, ", ");
       while (chino.hasMoreTokens()) {
           System.out.println(chino.nextToken());
       }

En lugar de usar StringTokenizer para dividir un solo parámetro en sus partes, ¿no sería mejor si se pudiera dar los parámetros por separado?. Mientras los nombres chinos de los años en el ejemplo anterior son relativamente cortos, imagine si cada parámetro fuera algo así como un URL con un ancho mínimo de veinte caracteres. La segunda forma de soportar parámetros ilimitados permite especificar cada nombre como un parámetro separado.

A fin de soportar un número ilimitado de parámetros especificando cada parámetro por separado, el parámetro debe seguir un patrón común de nombre. Por ejemplo, PARAM1, PARAM2, PARAM3, ... . Entonces, todo lo que tiene que hacer es mirar el siguiente parámetro numerado hasta que no haya más. Una vez encontrada que uno de los parámetros no está disponible, por ejemplo, PARAM4, ya no se tiene que ver si están PARAM5, PARAM6 o PARAM7. Si se separamos aparte la configuración de parámetros usados en la primera forma y seguimos el patrón de nombres, ,conseguimos algo así:

<param
           name="Chino1"
           value="Shu">
       <param
            name="Chino2"
           value="Niu">
       <param
            name="Chino3"
           value="Hu">
       <param
           name="Chino4"
           value="T'u">
       <param
           name="Chino5"
           value="Lung">
       <param
            name="Chino6"
           value="She">
       <param
           name="Chino7"
           value="Ma">
       <param
           name="Chino8"
           value="Yang">
       <param
           name="Chino9"
           value="Hou">
       <param
           name="Chino10"
            value="Chi">
       <param
           name="Chino11"
           value="Kou">
       <param
           name="Chino12"
           value="Chu">
       <param
            name="Hispano1"
           value="Rata">
       <param
            name="Hispano2"
            value="Buey">
       <param
           name="Hispano3"
            value="Tigre">
       <param
           name="Hispano4"
            value="Conejo">
       <param
           name="Hispano5"
           value="Dragón">
       <param
           name="Hispano6"
            value="Serpiente">
       <param
           name="Hispano7"
           value="Caballo">
       <param
            name="Hispano8"
           value="Carnero">
       <param
           name="Hispano9"
           value="Mono">
       <param
           name="Hispano10"
            value="Gallo">
       <param
           name="Hispano11"
            value="Perro">
       <param
           name="Hispano12"
           value="Cerdo">

Leer los parámetros se pone un poco más complicado. Pero uno no se debe molestar con un StringTokenizer cadenas excesivamente largas en un archivo HTML. Todo lo que se tiene que hacer es poner una llama a getParameter() en un bucle while, donde se incremente el índice con cada pasada a través del bucle. Cuando no haya más parámetros entonces se para.

String value;
       int i = 1;
       while ((value = getParameter("Chinese" + i))!= null) {
           System.out.println ("Param" + i + ": " + value);
           i++;
        }

Esta forma de trabajar con parámetros ilimitados es demostrada enteramente en con la siguiente Applet. La Applet lee los nombres chinos y castellanos de los años chinos, que usan nombres de animales. También tiene un campo de texto, que se usa para ingresar un año en él, la Applet encuentra el nombre apropiado para ese año.

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.StringTokenizer;
   
     public class AnimalYears2 extends Applet {
         List listaChina = new List();
         List listaEspañol = new List();
         TextField inputField = new TextField();
   
         /**Inicializar la Applet */
         public void init() {
   
             setLayout(new BorderLayout());
   
             String value;
             int i = 1;
             while ((value = getParameter("Chino" + i))!=   null) {
                 listaChina.add(value);
                 i++;
             }
             listaChina.setEnabled(false);
             add(listaChina, BorderLayout.WEST);
   
             i = 1;
             while ((value = getParameter("Hispano" + i))!=   null) {
                 listaEspañol.add(value);
                 i++;
             }
             listaEspañol.setEnabled(false);
             add(listaEspañol, BorderLayout.EAST);
   
             inputField.addActionListener(new 
			java.awt.event.ActionListener()   {
                 public void actionPerformed(ActionEvent  e) {
                     String yearString  = inputField.getText();
                     try {
                        
		int  year = Integer.parseInt(yearString);
                        year  = year - 1900;
                        int  index = year % 12;
                        if  (index < 0) {
                            index = 12+index;
                        }
                        listaChina.select(index);
                        listaEspañol.select(index);
                  } catch (NumberFormatException exc) {
                        getToolkit().beep();
                     }
                 }
             }
             add(inputField,  BorderLayout.NORTH);
         }
     }

Para ver el applet en funcionamiento pulsa aquí

Descarga el código fuente del ejemplo aquí

Distribuyendo Imágenes Dinámicas desde Páginas con tecnología JavaServer Pages (JSP)

¿Usted siempre ha querido distribuir imágenes generadas dinámicamente desde sus páginas JSP (o servlets)?. Este consejo nos mostrará como hacerlo. Para correr el código de este consejo, necesitará Tomcat o cualquier otro servidor Web que soporte JSP 1.1. Puede descargar Tomcat de la página del Proyecto Jakarta en http://jakarta.apache.org/tomcat.

Cuando una página Web se distribuye con una imagen jpeg (o cualquier otro formato) de tipo MIME, el navegador trata la respuesta como una imagen. El navegador entonces muestra la imagen, como parte de una página web más grande o sola. Para configurar el tipo MIME para las páginas JSP, se necesita establecer el atributo contentType de la página de atributos en el archivo .jsp para la página específica.

<%@ page contentType="image/jpeg" ... %>

Entonces se necesitará crear un BufferedImage a utilizar para la imágen dinámica

 
BufferedImage image = new BufferedImage(width, height, 
			BufferedImage.TYPE_INT_RGB);

Después de crear el BufferedImage, se necesita obtener un contexto gráfico para dibujar mediante él, u objetos Graphics o Graphics2D, se puede hacer así:

Graphics   g   = image.getGraphics();
  // o
Graphics2d g2d = image.createGraphics();

Desde aquí, se puede dibujar el contenido de la imagen. Dibujando en el contexto gráfico se dibuja sobre el BufferedImage. Inicialmente, la imagen entera es negra, así que es una buena idea rellenar la imagen con el color de fondo deseado. Entonces, una vez finalizado el dibujo hay que liberar el contexto:

g.dispose();
  // o
 g2d.dispose();

Una vez que la imagen ha sido completamente dibujada, se envía la el fondo de la imagen en la respuesta. Se puede usar la clase JPEGImageEncoder del paquete com.sun.image.codec.jpeg para codificar la imagen. O, si usamos usa el Java 2 SDK Standard Edition v1.4 Beta, podemos usar la clase ImageIO. Hay una parte delicada de usar JPEGImageEncoder. Se debe buscar y obtener el ServletOutputStream de ServletResponse (el objeto de respuesta), y no usar la variable output que es la implícita de salida de JSP.

 
ServletOutputStream sos = response.getOutputStream();
 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos);
 encoder.encode(image);
  // o
 ImageIO.write(image, "JPEG", out);

Aquí hay un ejemplo completo que escoge una opción de todas las opciones (por ejemplo, g.dispose(); versus g2d.dispose(); ). El ejemplo usa el objeto Graphics para dibujar un polígono aleatorio. La imagen se dibuja en el fondo con JPEGImageEncoder. Juegue con toda confianza con el número de puntos del polígono para conseguir figuras más complejas, en otras palabras, figuras con más puntos y lados.

Para ejecutar este ejemplo, ponga el código JSP desde "<%@ " hasta el último "%>" en un archivo llamado image.jsp. Ponga el archivo image.jsp en un directorio en el que su servidor web pueda encontrarlo. En el caso de Tomcat, es el directorio ROOT, en el directorio webapps, en el directorio de instalación de Tomcat. Para iniciar Tomcat se necesita ejecutar el script de inicio (startup.bat o startup.sh dependiendo de su plataforma) en directorio bin dentro del directorio donde ha instalado Tomcat. Asegúrese que tiene la variable de entorno JAVA_HOME establecida al nivel de raíz de su instalación del Java 2 SDK, por ejemplo C:jdk1.2.2 . Una vez que el archivo está en el directorio apropiado y Tomcat está ejecutándose, se debe cargar la imagen generada con http://localhost:8080/image.jsp

 
<%@ page contentType="image/jpeg" 
import="java.awt.*,java.awt.image.*, com.sun.image.codec.jpeg.*,java.util.*" 
%>
 
 <%
 
     // Crear la imagen
     int width=200, height=200;
     BufferedImage image = new BufferedImage(width,height, 
			BufferedImage.TYPE_INT_RGB);
 
     // Obtener el contexto para dibujar
     Graphics g = image.getGraphics();
 
     // Rellenar el fondo
     g.setColor(Color.white);
     g.fillRect(0, 0, width, height);
 
     // Crear el polígono aleatorio
     Polygon poly = new Polygon();
     Random random = new Random();
     for (int i=0; i < 5; i++) {
         poly.addPoint(random.nextInt(width),random.nextInt(height));
     }
 
     // Rellenar el polígono
     g.setColor(Color.cyan);
     g.fillPolygon(poly);
 
     // Liberar el contexto
     g.dispose();
 
     // Enviar el fondo de la imagen
     ServletOutputStream sos = response.getOutputStream();
     JPEGImageEncoder encoder =
     JPEGCodec.createJPEGEncoder(sos);
     encoder.encode(image);
 %>

Corrección al consejo anterior

Este consejo equivocadamente genera un contenido binario de una página JSP. La especificación del Servlet requiere que los servlets no llamen a ServletResponse.getOutputStream() y ServletResponse.getWriter(). Porque las páginas JSP ya llaman a getWriter(), tampoco deben llamar a getOutputStream(). Algunas versiones de Tomcat retrasan la llamada de getWriter(). así que el consejo puede trabajar para esas versiones. Sin embargo las operaciones demostradas en el artículo se deben considerar como indebidas. Las páginas JSP solamente están entregando salida textual.

Para que este consejo trabaje apropiadamente, la generación de la imagen dinámica debe pasarse a un servlet. Ponga la siguiente definición de clase en un directorio apropiado del servlet para el servidor web (como webappsROOTWEB-INFclasses para Tomcat). Entonces se le debe poder llamar con un URL de la forma http://localhost:8080/servlet/MakeImage . El código, en esencia, es idéntico al usado previamente en este artículo, excepto que ahora es parte de un servlet.

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.*;
import java.util.*;

public class MakeImage extends HttpServlet {

    public void doGet(
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {

        response.setContentType("image/jpeg");

        // Crear Imagen
        int width=200, height=200;
        BufferedImage image = new BufferedImage(width,
height,
                                              
BufferedImage.TYPE_INT_RGB);

        // Objetener el contexto de dibujo
        Graphics g = image.getGraphics();

        // Rellenar el fondo
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);

        // Crear un polígono aleatorio
        Polygon poly = new Polygon();
        Random random = new Random();
        for (int i=0; i < 20; i++) {
            poly.addPoint(random.nextInt(width),
            random.nextInt(height));
        }

        // Rellenar el polígono
        g.setColor(Color.cyan);
        g.fillPolygon(poly);

        // Liberar el contexto
        g.dispose();

        // Enviar el fondo de la imagen
        ServletOutputStream sos =
        response.getOutputStream();
        JPEGImageEncoder encoder =
        JPEGCodec.createJPEGEncoder(sos);
        encoder.encode(image);
    }
}

Además, si se es un usuario Unix y se está corriendo un servidor web en un terminal tonto (headless box), se puede necesitar Xvfb, que es un búfer de imagen virtual, para emular un ambiente de muestra. Vea http://java.sun.com/products/java-media/2D/forDevelopers/java2dfaq.html#xvfb para más información acerca del soporte del al trabajar con imágenes en la capa servidor.

Copyright y notas de la traducción

Nota respecto a la traducción

El original en inglés de la presente edición de los JDC Tech Tips fue escrita por Glen McCluskey, la traducción no oficial fue hecha por Alan Ortiz, cualquier sugerencia o corrección hágala al correo [email protected] , sugerencia respecto a la edición original a mailto:[email protected]

Nota (Respecto a la edición via email)

Sun respeta su tiempo y su privacidad. La lista de correo de la Conexión del desarrollador Java se usa sólo para propósitos internos de Sun Microsystems(tm). Usted ha recibido este email porque se ha suscrito a la lista. Para desuscribirse vaya a la página de suscripciones, desmarque casilla apropiada y haga clic en el botón Update.

Suscripciones

Para suscribirse a la lista de correo de noticias de la JDC vaya a la página de suscripciones, elija los boletines a los que quiera suscribirse, y haga clic en Update.

Realimentación

¿Comentarios?, envie su sugerencias a los Consejos Técnicos de la JDC a mailto:[email protected]

Archivos

Usted encontrará las ediciones de los Consejos Técnicos de la JDC (en su original en inglés) en http://java.sun.com/jdc/TechTips/index.html

Copyright

Copyright 2001 Sun Microsystems, Inc. All rights reserved. 901 San Antonio Road, Palo Alto, California 94303 USA.

Este documento esta protegido por las leyes de autor. Para mayor información vea http://java.sun.com/jdc/copyright.html

Enlaces a sitios fuera de Sun

Los Consejos Técnicos de la JDC puede dar, p terceras pueden dar, enlaces a otros sitios y recursos. ya que Sun no tiene control sobre esos sitios o recursos usted reconoce y acepta que Sun no es responsable por la disponibilidad de tales sitios o recursos, y no se responsabiliza por cualquier contenido, anuncios , productos u otros materiales disponibles en tales sitios o recursos. Sun no será responsable, directa o indirectamente, por cualquier daño o pérdida causada o supuestamente causada por o en relación con el uso de o seguridad sobre cualquier tal contenido, bienes o servicios disponibles en o através de cualquier sitio o recurso.

El original en Ingles de esta edición de los Consejos técnicos fue escrita por Glen McCluskey.

JDC Tech Tips August 21, 2001

Sun, Sun Microsystems, Java y Java Developer Connection (JDC) son marcas registradas de Sun Microsystems Incs. en los Estados Unidos y cualquier otro país.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP