feed twitter facebook LinkedIn facebook

Java » Recuperar la cabecera X-Forwarded-For

octubre 10, 2009 por Víctor Cuervo 5 Comentarios Imprimir Imprimir

X-Forwarded-For es una cabecera HTTP que nos permite conocer la IP origen de la petición. Y es que hasta ahora se utilizaba REMOTE_ADDR, la cual solo nos devolvía la IP de la última máquina por la que había pasado. A todas luces poco útil de cara a conocer el origen de la petición.

El formato de la cabecera X-Forwarded-For es el siguiente:

X-Forwarded-For: client1, proxy1, proxy2

En nuestro caso vamos a montar un servlet en Java que acceda a esta cabecera. Para acceder a los datos de la cabecera nos apoyaremos en el método .getHeader() del objeto HttpServletRequest. En este caso el nombre de la cabecera es "X-Forwarded-For", así que el código será el siguiente:

  1. String sIP = request.getHeader("X-FORWARDED-FOR");

Ahora, con esta ristra de datos podemos hacer lo que queramos. Posiblemente necesitemos apoyarnos en StringTokenizer para desmontar la cadena de IP. O, por lo menos, volcar el contenido a la pantalla:

  1. PrintWriter out = response.getWriter();
  2. out.print("La IP origen ha llegado por: " + sIP);

¿Conocías la existencia de X-Forwarded-For? ¿Crees que puede ayudarte en algo en tus programas?

Java » Recibir un parámetro numérico en una JSP

julio 30, 2009 por Víctor Cuervo 5 Comentarios Imprimir Imprimir

En el artículo Recibir parametros en una JSP veíamos como de una forma sencilla podíamos leer los parámetros que le llegan a una JSP.

El .getParameter("dato") y dejarlo en un String está muy bien. Pero, qué sucede si el dato que nos envían es un número (eso nos planteaba @Er)...

Pues la forma de hacerlo es muy sencilla. Para ello vamos a implementar una JSP a la cual le pasemos 2 datos numéricos, los cuales nos devolverá sumados.

Realmente la forma de recuperar los datos sigue siendo la misma que en Recibir parametros en una JSP. Es decir, utilizamos el método .getParameter("dato").

  1.  
  2. String datoUno = request.getParameter("dato1");
  3. String datoDos = request.getParameter("dato2");
  4.  

Lo que sucede es que tenemos que convertir los datos de tipo String en tipo numérico, por ejemplo en int. Para ello nos apoyaremos en la clase Integer y concretamente en el método .parseInt()

  1.  
  2. int uno = Integer.parseInt(request.getParameter("dato1"));
  3. int dos = Integer.parseInt(request.getParameter("dato2"));
  4.  

Pero qué sucede si el usuario no nos ha pasado un número en el parámetro. En este caso el método .parseInt() nos va a fallar, dándonos una NumberFormatException. Es por ello que tendremos que prevenir dicha excepción:

  1.  
  2. try {
  3. int uno = Integer.parseInt(request.getParameter("dato1"));
  4. int dos = Integer.parseInt(request.getParameter("dato2"));
  5.  
  6. } catch(NumberFormatException nfe) {
  7. out.println("Los datos recibidos no son números enteros");
  8. }
  9.  

Ahora solo nos quedará hacer la suma y mostrar el resultado en pantalla. En este caso convertimos un número en una cadena de caracteres mediante el método .toString(), también de la clase Integer.

Para mostrar los datos por pantalla utilizamos el método out.println(). Veamos como queda nuestro código:

  1.  
  2. try {
  3. int uno = Integer.valueOf(request.getParameter("dato1"));
  4. int dos = Integer.valueOf(request.getParameter("dato2"));
  5.  
  6. int suma = uno + dos;
  7.  
  8. out.println("La suma de " + datoUno + " + " + datoDos + " = " + Integer.toString(suma));
  9.  
  10.  
  11. } catch(NumberFormatException nfe) {
  12. out.println("Los datos recibidos no son números enteros");
  13. }
  14.  

Java » Obtener la IP que invoca al servlet

enero 12, 2008 por Víctor Cuervo 8 Comentarios Imprimir Imprimir

Mediante el siguiente código podremos recuperar la IP del usuario que está realizando la petición sobre el Servlet. Dadas todas las circunstancias que pueden rodear a la topología de las redes la IP que obtendremos no tiene porque ser la IP del usuario final, sino que fácilmente podría ser la IP de un proxy intermedio,... Es por ello que el ejemplo hay que utilizarle con fines didácticos y si lo usamos para producción, con un gran cuidado.

La IP de la máquina que invoca es una información que al servlet le llega en la petición, consecuentemente sus métodos doGet y doPost lo tendrán en el objeto HttpServletRequest.

Los métodos que nos permiten recuperar la información de la IP y el nombre de la máquina peticionaria son: getRemoteHost() y getRemoteAddr(). Simplemente les invocamos sobre el método HttpServletRequest.

  1. String ip = null; // IP del cliente
  2. String host = null; // Host del cliente
  3.  
  4. ip = request.getRemoteAddr();
  5. host = request.getRemoteHost();

Una vez obtenida la información, simplemente tendremos que devolverla por respuesta. Para ello nos apoyamos sobre los objetos PrintWriter y HttpServletResponse.

Veamos el código:

  1. PrintWriter out = response.getWriter();
  2. response.setContentType("text/html");
  3.  
  4. out.println("<html><head><title>Obtener IP del cliente</title></head><body>");
  5. out.println("<strong>Obtener la IP del cliente </strong>");
  6. out.println("La ip del cliente es " + ip + "<br>");
  7. out.println("El host del cliente es " + host);
  8. out.println("</body></html>");

Ver que el código que se devuelve en el stream de respuesta es una página web. De hecho, antes de devolver ninguna información indicamos que el content-type de respuesta es un "text/html".

Java » SingleThreadModel, concurrencia en servlet obsoleta

diciembre 29, 2007 por Víctor Cuervo Sin Comentarios Imprimir Imprimir

Podríamos describir el ciclo de vida de un Servlet, someramente, de la siguiente forma

Si el Servlet sobre el que se ha realizado una petición no está cargado en el contenedor web, este crea una instancia de la clase Servlet, ejecuta su método init y posteriormente dará servicio con alguno de los métodos de servicio: doGet, doPost, doPut,...

En el caso que el Servlet esté cargado en el contenedor, cuando llega la petición, simplemente se encamina dicha petición a los métodos de servicio: doGet, doPost, doPut,...

Como podemos ver la diferencia es que en el segundo caso no se ejecuta el método de inicialización.

Los métodos de servicio de los Servlet se ejecutaran de forma concurrente por cada petición que llegue al contenedor web. Esto implica que, en el caso de existir recursos compartidos, como por ejemplo las variables de sesión, estos podrán ser accedidos al mismo instante.

Hasta el API Servlet 2.4 existía el interface SingleThreadModel. Dicho interface aseguraba que solo existiría una instancia en un momento concreto gestionando una petición. De tal manera que, si llegaba otra petición en ese momento, esta era encolada y procesada posteriormente.

public class ServletNoConcurrente extends HttpServlet implements SingleThreadModel{
...
}

Si bien, este interface ha sido declarado obsoleto debido a varios puntos:

  1. Producía degradamiento del sistema.
  2. No evitaba el tener que realizar controles de concurrencia sobre los recursos compartidos, ya que aunque en la petición se aseguraba un solo hilo, no implicaba que en otro punto se estuviese accediendo al mismo recurso.

Podéis leer más sobre el interface SingleThreadModel en el API de Java.

Java » Mi primer servlet

diciembre 27, 2007 por Víctor Cuervo Sin Comentarios Imprimir Imprimir

En este ejemplo vamos a desarrollar nuestro primer Servlet, el cual nos de como respuesta la frase "Este es mi primer Servlet".

Crear el Servlet

La clase Java que implemente el Servlet deberá de extender la clase javax.servlet.HttpServlet.

  1. public class MiPrimerServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
  2. ...
  3. }

Dentro de esta clase tenemos que codificar, al menos, un método. El método doGet. Este método es el que se ejecuta cuando el Servlet recibe una petición del tipo GET (las más normales en Internet).

  1. public class MiPrimerServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. ...
  4. }
  5. }

El método método doGet recibe dos parámetros: HttpServletRequest y HttpServletResponse. Estos dos parámetros representan el stream de petición y el stream de respuesta. Y ambos llevan los datos intrínsecos a la petición o respuesta.

Por ejemplo, si la petición viene con parámetros, estos los encontraremos en el objeto HttpServletRequest. De igual manera, si queremos establecer el tipo de contenido de respuesta, lo podremos hacer manipulando el objeto HttpServletResponse.

Para nuestro ejemplo de Mi primer Servlet, vamos a centrarnos en el objeto HttpServletResponse. Y es que lo que vamos a realizar será un volcado de datos sobre el flujo de salida.

Lo primero que haremos será el definir una clase PrintWriter a la que asociar el flujo de salida.

  1. out = response.getWriter();

Una vez establecida esta relación, lo primero que haremos será indicar el tipo de contenido que queremos volcar. En este caso, será una página web. Es por ello que el contenido será “text/html”. En otros casos podremos devolver otros mime-types como “images/jpeg” para las imágenes JPEG o “application/x-gzip” para los ficheros ZIP.

  1.  
  2. response.setContentType("text/html");

Ahora solo nos quedará ir invocando al método .println con el texto que conforme la página web.

  1. out.println("<html>");
  2. out.println("<head><title>Mi Primer Servlet </title></head>");
  3. out.println("<body>");
  4. out.println("<h1>Este es mi Primer Servlet</h1>");
  5. out.println("</body></html>");

Como se puede ver en el código, se vuelcan todas las etiquetas que conforman la página web HTML, body, title,… y nuestro texto.

Configurar el descriptor de despliegue

Una vez desarrollado y compilado nuestro servlet, tendremos que configurar el descriptor de despliegue. Este es el fichero web.xml. Dicho fichero indicará los servlets que hay desplegados en nuestra aplicación web y bajo que URL van a atender las peticiones.

Tendremos que definir dos etiquetas. La primera es la etiqueta servlet. Esta etiqueta sirve para definir el servlet. Tiene las siguientes etiquetas anidadas:

  • description, descripción del servlet
  • display-name, nome del servlet
  • servlet-class, clase del servlet. Con el nombre del paquete por delante.
  1. <servlet>
  2. <description>Mi primer Servlet</description>
  3. <display-name>MiPrimerServlet</display-name>
  4. <servlet-name>MiPrimerServlet</servlet-name>
  5. <servlet-class> aulambra.com.lineadecodigo.j2ee.servlets.MiPrimerServlet </servlet-class>
  6. </servlet>

Una vez definido el servlet, solo nos quedará realizar la asociación entre la URL que atenderá las peticiones del servlet y el servlet definido. Esto lo hacemos mediante la etiqueta servlet-mapping.

En ella encontramos dos etiquetas anidadas:

  • servlet-name, que es el nombre definido anteriormente.
  • url-pattern, que es el patrón de URL al que atenderá las petciones. En nuestro caso será /MiPrimerServlet.
  1. <servlet-mapping>
  2. <servlet-name>MiPrimerServlet</servlet-name>
  3. <url-pattern>/MiPrimerServlet</url-pattern>
  4. </servlet-mapping>

De esta manera, una vez desplegada la aplicación en un contenedor web, podremos acceder al servlet de la siguiente manera:

http://servidor:8080/nombre_app_web/MiPrimerServlet

Java » Recibir parámetros en un Servlet

diciembre 25, 2007 por Víctor Cuervo 10 Comentarios Imprimir Imprimir

A la hora de enviar información a un Servlet tenemos dos formas: mediante el método GET y mediante el método POST. Existen una serie de diferencias entre pasarlos de una forma u otra:

Metodo POST. Este método solo esta accesible desde los formularios. Se envían los parámetros de forma implícita junto a la página, es decir, al pasar los parámetros, nosotros no vemos reflejado en ningún sitio qué parámetros son y cual es su valor.

Método GET. Este método envía los parámetros de forma explicita junto a la página, mostrando en la barra de navegación los parámetros y sus valores. Son esas largas cadenas que aparecen en algunas páginas en nuestra barra de navegación, del estilo: buscar?id=1806&valor=0987&texto=todo&...

Las cadenas toman el aspecto parametro1=valor1&parametro2=valor2&....&parametroN=valorN. Es decir es una concatenación a través de & de pares parámetro-valor.

Preparando la página de envío

La página de envío será una simple página HTML. Lo primero que tenemos que hacer es montar las URL de envío. La URL está compuesta por el nombre del servidor, en nuestro caso localhost, el puerto (8080), el nombre de la aplicación web, en nuestro caso "lineadecodigo_j2ee" y el nombre del servlet.

Así la URL quedará de la siguiente forma:

http://localhost:8080/lineadecodigo_j2ee/RecibirParametros

La URL la montaremos en un formulario:

  1. <form action="http://localhost:8080/lineadecodigo_j2ee
  2. /RecibirParametros" method="post">
  3. <label for="texto1">Texto 1</label><input type="text" id="texto1" name="texto1" size=20><br>
  4. <label for="texto2">Texto 2</label><input type="text" id="texto2" name="texto2" size=20>
  5. <input type="submit" value="Enviar">
  6. </form>

y en un enlace:

<a href="http://localhost:8080/lineadecodigo_j2ee/RecibirParametros?texto1=lineadecodigo&texto2=imagen">Mandar parametros por GET</a>


Codificando el Servlet

Lo primero que hay que saber es que la clase que implemente el Servlet extiende de HttpServlet. Así el código será el siguiente:

  1. public class RecibirParametros extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
  2. ...
  3. }

Dentro del Servlet hay dos métodos importantes: doGet y doPost. Estos métodos son los que atienden las peticiones POST y GET de la página, respectivamente.

  1. public class RecibirParametros extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
  2.  
  3. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. ...
  5. }
  6.  
  7. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  8. ...
  9. }
  10. }

Ambos métodos reciben como parámetros los datos de la petición HttpServletRequest y el flujo de la salida de respuesta HttpServletResponse.

Podemos codificar los dos métodos para hacer cosas diferentes si viene una petición POST u otra GET. O bien, como en nuestro caso, encaminar una petición a la otra para tratarlas de una misma forma.

  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. doPost(request,response);
  3. }

Para recibir los parámetros nos vamos a apoyar en el objeto HttpServletRequest y en concreto en el método .getParameter(). En este método indicaremos el nombre del parámetro que queremos recuperar.

  1. String parametro1 = request.getParameter("texto1");
  2. String parametro2 = request.getParameter("texto2");
  3.  

En este caso los parámetros se llaman texto1 y texto2.

Lo siguiente que haremos será montar la respuesta. Ahora nos apoyaremos en el objeto HttpServletResponse. Mediante el método .getWriter() obtendremos el stream de salida. Esto lo manejamos mediante el objeto PrintWriter.

  1. out = response.getWriter();

Antes de empezar a volcar texto en el flujo de salida tenemos que indicar el tipo de contenido que se vuelca. En este caso es "text/html". Es lo que se denomina content-type.

  1. response.setContentType("text/html");

Ahora solo quedará el ir volcando información mediante métodos .println(). El cual tiene como parámetro el texto a volcar a la página.

  1. out.println("<html>");
  2. out.println("<head><title>Enviar parametros a un Servlet</title></head>");
  3. out.println("<body>");
  4. out.println("<h1>Enviar parametros a un Servlet</h1>");
  5. out.println("La primera palabra pasada como parámetro es <strong>" + parametro1 + "</strong><br>");
  6. out.println("La segunda palabra pasada como parámetro es <strong>" + parametro2 + "</strong>");
  7. out.println("</body></html>");

Java » Redirigir todas las JSP a un Servlet

noviembre 30, 2006 por Víctor Cuervo 5 Comentarios Imprimir Imprimir

Ciertos modelos de arquitectura son participes de evitar el acceso directo a las páginas JSP para poder hacer ciertas validaciones. Esto implica que cada vez que alguien ponga una URL sobre nuestro sitio con *.jsp sea reenviado a un servlet.

Continue reading Redirigir todas las JSP a un Servlet...

Java » Crear un mapping a un servlet

noviembre 14, 2006 por Víctor Cuervo 3 Comentarios Imprimir Imprimir

El proceso de puesta en servicio de un servlet podríamos resumirlo en dos pasos. El primero de ellos es crear el servlet. Para ello implementaremos una clase java que extienda de HttpServlet, la cual implementará la funcionalidad de negocio que estemos resolviendo.

Pero de nada nos sirve el crear un servlet si no lo publicicamos al exterior. Este mecanismo de publicación es lo que se conoce como mapping.

La idea del mapping es la de asociar una URL o un patrón de una URL a un servlet.

Para ello deberemos de configurar el descriptor de despliegue de la aplicación. Este es el fichero que encontramos en /WEB-INF/web.xml

En este fichero necesitaremos de la etiqueta <servlet-mapping>. Esta etiqueta nos permitirá definir un nuevo mapping. Anidado a esta etiqueta encontramos dos: la primera especificará el nombre del servlet sobre el que queremos establecer el mapping <servlet-name>, mientras que la segunda especificará sobre que URL se realiza el mapping <url-pattern>.

<servlet-mapping>
  <servlet-name>MiServlet</servlet-name>
  <url-pattern>/URLDelServlet</url-pattern>
</servlet-mapping>

Con este mapping toda las peticiones que se hagan a la URL http://miservidor/URLDelServet serán procesadas por el Servlet "MiServlet".

Java » Modificar time-out de sesión

noviembre 12, 2006 por Víctor Cuervo 9 Comentarios Imprimir Imprimir

Cuando un usuario realiza una conexión contra una aplicación web se le crea una sesión. La sesión es la identidad que tiene dicho usuario en el servidor hasta que se desconecta.

En la sesión de un usuario se podrá almacenar información que queramos que previva mientras el usuario permanezca conectado a nuestra web.

Y esta última frase es el kit de la cuestión. ¿Cúando sabemos que un usuario se ha desconectado? Pues es difícil, ya que el protocolo HTTP es sin estado y las peticiones vienen y van sin un control. Es por ello que la única forma de saber que un usuario se ha ido es indicando un tiempo de caducidad de la sesión, más conocido como timeout de sesión.

Dependiendo del contenedor de servlets que estemos utilizando, este establecerá el timeout de sesión en un valor u otro atendiendo a unos parámetos de configuración.

Por ejemplo, Tomcat utiliza el fichero /conf/web.xml para configurarla, como podemos ver en estas líneas de código:

<!-- ==== Default Session Configuration ==== -->
<!-- You can set the default session timeout (in minutes) for all newly   -->
<!-- created sessions by modifying the value below.                       -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>

Como vemos, establece 30 minutos como tiempo máximo de inactividad.

Pero cuando creemos una aplicación podemos indicar un tiempo de timeout sobre esta aplicación. Y es que quien no nos dice que nuestra aplicación pueda correr sobre varios contenedores de servlets.

Para configurar el timeout de la sesión de nuestra aplicación deberemos de configurar el descriptor de despliegue de la misma (/WEB-INF/web.xml). Para ello utilizremos la etiqueta < session-config> y anidada a ella <session-timeout>. Vamos, que son las mismas etiquetas que utiliza Tomcat.

Así, el código nos quedaría de la siguiente forma:

<session-config>
<session-timeout>10</session-timeout>
</session-config>

En este caso establecemos el tiempo de timeout a 10 minutos.

Java » Leer parámetros de inicialización de un servlet

noviembre 11, 2006 por Víctor Cuervo 1 Comentario Imprimir Imprimir

En la vida de ejecución de un servlet, este, recuperará información de múltiples sitios. Por ejemplo recibirá en la petición información vía parámetros, recuperará datos de múltiples orígenes: bases de datos, ficheros,…

Uno de los sitios de donde podrá recuperar información son los parámetros de inicialización del servlet.

Cuando creamos un servlet y lo definimos en el descriptor de despliegue, podemos indicarle que el servlet lleva asociado parámetros de inicialización y los valores de dichos parámetros.

El uso de estos parámetros es muy potente, ya que se pueden modificar sus valores, con el fin de obtener un comportamiento diferente del servlet, sin necesidad de recompilar este.

Algunos de los usos de los parámetros de inicialización podrían ser:

  • Tiempos de control de peticiones
  • Nombres de recursos externos a los que acceder: ficheros, bases de datos,…
  • Nivel de log que se quiere aplicar al programa.

Siempre suelen ser cosas relativas a la configuración del servlet.

Lo primero que tenemos que hacer es definir en el descriptor de despliegue (/WEB-INF/web.xml) del servlet:

<servlet>
  <description>Ejemplo ...bla bla bla.</description>
  <display-name>ParametrosInicio</display-name>
  <servlet-name>ParametrosInicio</servlet-name>
  <servlet-class>com.lineadecodigo.ParametrosInicio</servlet-class>
</servlet>

El servlet se define mediante la etiqueta <servlet>. Anidada a esta tenemos dos etiquetas importantes. <servlet-name> será el nombre de referencia del servlet y <servlet-class> será la clase java que implementa dicho servlet.

Los parámetros del servlet

En nuestro ejemplo vamos a definir dos parámetros. El primero será NivelLog que almacenará el tipo de log con el que grabaremos y NumeroPeticiones que nos pasará un indicador de limitación.

<servlet>
  <init-param>
    <description>Nivel de log a aplicar</description>
    <param-name>NivelLog</param-name>
    <param-value>DEBUG</param-value>
  </init-param>
  <init-param>
    <description>Número de peticiones para atender</description>
    <param-name>NumeroPeticiones</param-name>
    <param-value>8</param-value>
  </init-param>
</servlet>

Una vez que hemos definido esto en el descriptor de despliegue, tendremos que acceder a los valores desde el servlet.

Lo más normal es acceder a esta información en el método init(). Si es que la información aplica a todas las peticiones del servlet.

Para recuperar los parámetros tenemos que acceder a el método .getInitParameter(String parámetro) que permite acceder al valor del parámetro pasado como argumento a dicho método.

Así, para recuperar los valores de nuestro ejemplo tendremos el siguiente código:

  1. _nivelLog = getInitParameter("NivelLog");
  2. _numeroPeticiones = Integer.parseInt(getInitParameter("NumeroPeticiones"));

Hay que fijarse que los valores de los parámetros de inicio son devueltos como cadenas de texto. Es por ello que tendremos que hacer el tratamiento necesario para convertirlo en otro tipo de dato.

En nuestro caso convertirlo a entero mediante Integer.parseInt(String cadena).

Tanto _nivelLog como _numeroPeticiones lo hemos definido como atributos generales del servlet para que puedan ser utilizados en todo momento.