Comunicación entre Applets y Servlets
Nos ha realizado muchas consultas sobre la comunicación entre
applets y servlets.
Un applet y un servlet se pueden comunicar de muchos modos (sockets,
RMI, corba, etc) aunque el modo más sencillo de hacerlo es a través de
peticiones HTTP.
Preparación
Primero, vamos a crear un applet básico. Este applet lo hemos creado a
través de NetBeans por lo que podéis
encontrar algunas partes del código o comentarios en inglés.
/*
* appletsimple.java
*
* Created on November 5, 2003, 10:51 PM
*/
package roberto;
/**
*
* @author Roberto Canales
*/
public class appletsimple extends java.applet.Applet {
/** Initializes the applet appletsimple */
public void init() {
initComponents();
}
/** This method is called from within the init() method
to
* initialize the form.
* WARNING: Do NOT modify this code. The content
of this method is
* always regenerated by the Form Editor.
*/
private void initComponents() {
label1 = new java.awt.Label();
mensajeenviar = new
java.awt.TextArea();
label2 = new java.awt.Label();
mensajerecibir = new
java.awt.TextArea();
botonenviar = new
java.awt.Button();
setLayout(new
java.awt.GridLayout(5, 1, 2, 5));
label1.setAlignment(java.awt.Label.CENTER);
label1.setForeground(new
java.awt.Color(51, 51, 255));
label1.setText(«Introduzca
el mensaje a enviar al servidor»);
add(label1);
add(mensajeenviar);
label2.setAlignment(java.awt.Label.CENTER);
label2.setForeground(new
java.awt.Color(255, 0, 0));
label2.setText(«Mensaje
recibido del servidor»);
add(label2);
add(mensajerecibir);
botonenviar.setLabel(«Pulsar
para conectar al servidor»);
botonenviar.addActionListener(new java.awt.event.ActionListener() {
public
void actionPerformed(java.awt.event.ActionEvent evt) {
botonenviarActionPerformed(evt);
}
});
add(botonenviar);
}
private void botonenviarActionPerformed(java.awt.event.ActionEvent
evt) {
String s_textoaenviar =
mensajeenviar.getText();
mensajerecibir.setText(«Simulacion:
» + s_textoaenviar);
this.showStatus(«Botón
Pulsado»);
}
// Variables declaration – do not modify
private java.awt.Button botonenviar;
private java.awt.Label label1;
private java.awt.Label label2;
private java.awt.TextArea mensajeenviar;
private java.awt.TextArea mensajerecibir;
// End of variables declaration
}
|
Como podéis observar, en depuración, el código anterior lo
único que hace es mostrar un pequeña ventana donde al introducir un
texto en la parte superior y pulsar el botón, muestra un texto en la parte de
inferior y un mensaje en la barra de estado.
Para poder probar nuestro programa de un modo efectivo, debemos crear una
página HTML y colgarla de un servidor Web.
<html>
<body>
<p align=»left»>
<applet width=»400″ height=»300″ code=»roberto.appletsimple.class»
codebase=»./«>Applet que se comunica con servlet</applet>
</p>
</body>
</html> |
El aspecto de nuestra página en el navegador es:
Ahora, vamos a crear el servlet que se ejecutará en el servidor. Este
servlet solamente se encarga de recoger los parámetro que recibe en la
petición Get o Post y genera una página de respuesta mostrándolos.
/*
* servletsimple.java
*
* Created on November 5, 2003, 11:38 PM
*/
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
*
* @author Roberto Canales
* @version
*/
public class servletsimple extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(«text/html»);
PrintWriter out = response.getWriter();
out.println(«<html>»);
out.println(«<head>»);
out.println(«<title>Servlet</title>»);
out.println(«</head>»);
out.println(«<body>»);
Enumeration e = request.getParameterNames();
while(e.hasMoreElements())
{
String s_clave = e.nextElement().toString();
String s_aux = request.getParameter(s_clave);
out.println(«<br>El parámetro: <B>» + s_clave + «</B> vale: <B>» + s_aux + «</B>»);
}
out.println(«</body>»);
out.println(«</html>»);
out.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
} |
Podemos ver la petición y la respuesta en la siguiente pantalla.
Insertar código comunicaciones
Ahora lo único que nos queda en modificar el código del applet
para hacer la petición HTTP al servidor. Esta versión del código os muestra
como hacerlo a través de POST pero podéis ver que también está dentro del
código la gunción para hacerlo a través del comando GET.
peticionPost(s_textoaenviar)
Vamos a comentar las funciones más significativas (por ejemplo con la
fucnión GET):
Primero, recuperamos el Host del que descargamos el
Applet
String host = this.getCodeBase().getHost();
Posteriormente, debemos codificar los caracteres
especiales al juego compatible con HTTP ()
String peticion = «/servlet/servletsimple?param1=» +
URLEncoder.encode(mensaje);
Generamos la URL que representa el recurso a recuperar
(en este caso el servlet)
miurl = new URL(getCodeBase(),peticion);
Ahora conectamos con el recurso
InputStream buffer = miurl.openStream();
/*
* appletsimple.java
*
* Created on November 5, 2003, 10:51 PM
*/
package roberto;
import java.net.*;
import java.io.*;
/**
*
* @author Roberto Canales
*/
public class appletsimple extends java.applet.Applet {
/** Initializes the applet appletsimple */
public void init() {
initComponents();
}
/** This method is called from within the init() method
to
* initialize the form.
* WARNING: Do NOT modify this code. The content
of this method is
* always regenerated by the Form Editor.
*/
private void initComponents() {
label1 = new java.awt.Label();
mensajeenviar = new
java.awt.TextArea();
label2 = new java.awt.Label();
mensajerecibir = new
java.awt.TextArea();
botonenviar = new
java.awt.Button();
setLayout(new
java.awt.GridLayout(5, 1, 2, 5));
label1.setAlignment(java.awt.Label.CENTER);
label1.setForeground(new
java.awt.Color(51, 51, 255));
label1.setText(«Introduzca
el mensaje a enviar al servidor»);
add(label1);
add(mensajeenviar);
label2.setAlignment(java.awt.Label.CENTER);
label2.setForeground(new
java.awt.Color(255, 0, 0));
label2.setText(«Mensaje
recibido del servidor»);
add(label2);
add(mensajerecibir);
botonenviar.setLabel(«Pulsar
para conectar al servidor»);
botonenviar.addActionListener(new java.awt.event.ActionListener() {
public
void actionPerformed(java.awt.event.ActionEvent evt) {
botonenviarActionPerformed(evt);
}
});
add(botonenviar);
}
private void botonenviarActionPerformed(java.awt.event.ActionEvent
evt) {
String s_textoaenviar =
mensajeenviar.getText();
mensajerecibir.setText(«Simulacion:
» + peticionPost(s_textoaenviar));
}
// enviamos la peticion por post
String peticionPost(String
mensaje) {
URL miurl
= null;
String cadenaaux = null;
String cadenaretorno =
«»;
String consulta =
«param1=» + URLEncoder.encode(mensaje);
try {
String
host = this.getCodeBase().getHost();
String
peticion = «/servlet/servletsimple»;
miurl =
new URL(getCodeBase(),peticion);
URLConnection conexion = miurl.openConnection();
conexion.setDoOutput(true);
OutputStreamWriter buffersalida = new
OutputStreamWriter(conexion.getOutputStream());
buffersalida.write(consulta);
buffersalida.flush();
BufferedReader bufferentrada = new BufferedReader(new
InputStreamReader(conexion.getInputStream()));
String
linea = null;
while
((linea = bufferentrada.readLine()) != null) {
cadenaretorno += linea;
}
buffersalida.close();
bufferentrada.close();
}
catch (Exception e)
{
return
«Error al generar url » + e.getMessage();
}
return cadenaretorno;
}
// enviamos por get la petición
String peticionGet(String
mensaje) {
URL miurl
= null;
String cadenaaux = null;
String cadenaretorno =
«»;
try {
String
host = this.getCodeBase().getHost();
String
peticion = «/servlet/servletsimple?param1=» +
URLEncoder.encode(mensaje);
miurl =
new URL(getCodeBase(),peticion);
InputStream buffer = miurl.openStream();
BufferedReader bufferreader = new BufferedReader(new
InputStreamReader(buffer));
while(
(cadenaaux = bufferreader.readLine()) != null) {
cadenaretorno += cadenaaux;
}
buffer.close();
}
catch (Exception e) {
return
«Error al generar url » + e.getMessage();
}
return cadenaretorno;
}
// Variables declaration – do not modify
private java.awt.Button botonenviar;
private java.awt.Label label1;
private java.awt.Label label2;
private java.awt.TextArea mensajeenviar;
private java.awt.TextArea mensajerecibir;
// End of variables declaration
}
|
Y el resultado es
Sencillo verdad …..
Serialización de comunicaciones
Una vez que sabemos hacer esto, podemos utilizar una petición
POST de un modo un poquito especial …..
serializando la llamada entre el cliente y el servidor y de este
modo, enviar y recibir objetos completos.
Hacemos un pequeño cambio, primero en el Applet, donde vamos a
enviar un array
// enviamos la peticion por post
String peticionPost(String mensaje) {
URL miurl = null;
String cadenaaux = null;
String cadenaretorno = «»;
String consulta = «param1=» + URLEncoder.encode(mensaje);
try {
String host = this.getCodeBase().getHost();
String peticion = «/servlet/servletsimple»;
miurl = new URL(getCodeBase(),peticion);
URLConnection conexion = miurl.openConnection();
conexion.setDoOutput(true);
ObjectOutputStream buffersalida = new ObjectOutputStream(conexion.getOutputStream());
//buffersalida.write(consulta);
int array[] = new int[10];
for(int i=0;i<array.length;i++)
{
array[i] = i*3;
}
buffersalida.writeObject(array);
buffersalida.flush();
BufferedReader bufferentrada = new BufferedReader(new
InputStreamReader(conexion.getInputStream()));
String linea = null;
while ((linea = bufferentrada.readLine()) != null) {
cadenaretorno += linea;
}
buffersalida.close();
bufferentrada.close();
}
catch (Exception e)
{
return «Error al generar url » + e.getMessage();
}
return cadenaretorno;
} |
Y ahora cambiamos el servlet
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(«text/html»);
PrintWriter out = response.getWriter();
out.println(«<html>»);
out.println(«<head>»);
out.println(«<title>Servlet</title>»);
out.println(«</head>»);
out.println(«<body>»);
/*
Enumeration e = request.getParameterNames();
while(e.hasMoreElements())
{
String s_clave = e.nextElement().toString();
String s_aux = request.getParameter(s_clave);
out.println(«<br>El parámetro: <B>» + s_clave + «</B> vale: <B>» + s_aux + «</B>»);
}
*/
try
{
ObjectInputStream bufferentrada = new ObjectInputStream(request.getInputStream());
int[] arrayRecuperado = (int[])bufferentrada.readObject();
for(int i=0;i<arrayRecuperado.length;i++)
{
out.println(«El valor recuperado del elemento » + i + » es » + arrayRecuperado[i]);
}
}
catch(Exception e)
{
out.println(«Error al recuperar datos»);
}
out.println(«</body>»);
out.println(«</html>»);
out.close();
}
|
Y en el sentido contrario….. es exactamente lo mismo ……..
Esto es impresionante….. imaginaos lo rápido que es el desarrollo. Además,
cuando nos cuentan sobre nuevas tecnologías de interacción Web, como WebServices …… tampoco nos asusta tanto
Proxys y autentificación
Por cierto, si tenéis proxy ….. hay que establecer unas propiedades
System.setProperty(«proxyHost»,
«host»);
System.setProperty(«proxyPort», «puerto»);
|
Y si tenéis seguridad (autentificación simple) en el servidor,
debéis añadir unas líneas a vuestro objeto URLConnection
:
conexion.setRequestProperty( «Authorization»,»BASIC
» + passwordencriptadaenbase64);
conexion.setRequestProperty(«content-type», «text/html»);
|
De todos modos, debéis tener en cuenta donde usar los applets …. Yo
os recomendaría restringirlos a Intranets.
Sobre el
Autor ..
Hola buen tuto. Se puede envair un parametro y un objeto por ejemplo un cadena y un array de bits. ???