1 .
Presentación
2 .
Soporte de un número ilimitado de parámetros en un Applet
3 .
Distribuyendo Imágenes Dinámicas desde Páginas con tecnología JavaServer Pages (JSP)
4 .
Corrección al consejo anterior
5 .
Copyright y notas de la traducción
Presentación
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 webapps\ROOT\WEB-INF\classes 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 acortiz@ucsm.edu.pe , sugerencia respecto a la edición original a mailto:jdc-webmaster@sun.com
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:jdc-webmaster@sun.com
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.