Servlets (I) Mario Muñoz Organero & Norberto Fernández Departamento de Ingeniería Telemática http://www.it.uc3m.es/mario http://www.it.uc3m.es/berto Índice Introducción a los servlets de Java Qué es un servlet? Contenedores Web Despliegue y configuración de servlets API de servlets Mario Muñoz Organero & Norberto Fernández Servidores de Información 2
Qué es un servlet? Según SUN: A servlet is a Java programming language class used to extend the capabilities of servers that host applications accessed via a request-response programming model. Although servlets can respond to any type of request, they are commonly used to extend the applications hosted by Web servers. For such applications, Java Servlet technology defines HTTP-specific servlet classes. Fuente: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/servlets2.html (10/08/2008) Mario Muñoz Organero & Norberto Fernández Servidores de Información 3 Clase Java Qué es un servlet? Independencia de la plataforma Extender el servidor Lógica en el servidor (vs. en cliente con Applet) Generar respuestas a solicitudes recibidas Comúnmente para aplicaciones Web Servlets y JSP Componentes Web bloques básicos de JEE para el desarrollo de aplicaciones Web Pero puede haber otros: HTML, CSS, EJBs, JS, etc. Mario Muñoz Organero & Norberto Fernández Servidores de Información 4
Interacción servlet - servidor Web Los servlets no se pueden invocar directamente por el usuario La interacción se lleva a cabo a través de un contenedor o motor de servlets en el que la aplicación está desplegada Mario Muñoz Organero & Norberto Fernández Servidores de Información 5 Contenedores o motores servlet Contenedores Web para albergar las aplicaciones Evita al programador de los componentes Web tener en cuenta los detalles de la conexión a la red, la obtención de las peticiones y la generación correcta de respuestas (comunicación con el servidor Web) Soporte para la ejecución de aplicaciones Creación de componentes Web ante una solicitud Paso de parámetros al componente (petición y objeto para contener la respuesta) Mario Muñoz Organero & Norberto Fernández Servidores de Información 6
El contenedor de servlets (I) Responsable de: Manejar las peticiones de los clientes Pasar las peticiones al servlet Devolver los resultados al cliente API de servlets define la interfaz entre el contenedor y los servlets Básicamente, el ciclo de vida de un servlet consiste en: Inicialización El contenedor crea una instancia del servlet El contenedor llama al método init de la instancia Servicio Cada vez que el contenedor tiene una petición para el servlet, llama a al método service de la instancia Finalización Antes de destruir un servlet, el contenedor llama a su método destroy Mario Muñoz Organero & Norberto Fernández Servidores de Información 7 El contenedor de servlets (II) Qué ocurre si el contenedor recibe una nueva petición cuando el método service está en ejecución? Podría esperar a que terminara antes de volver a llamarlo, o Puede crear otro hilo de ejecución e invocar el método service en él La especificación no garantiza que el método service sólo sea invocado por un hilo en un momento cualquiera Soluciones: Usar sincronización (synchronized) Forzar a que el contenedor no llame desde varios hilos al servlet (SingleThreadModel) Mario Muñoz Organero & Norberto Fernández Servidores de Información 8
El contenedor de servlets (III) El modelo general de funcionamiento del servlet una vez invocado Recibe un objeto solicitud que le pasa el contenedor y que contiene los parámetros Extrae los parámetros de la solicitud Procesa la solicitud Genera la respuesta en un objeto específico que el contenedor pone a su disposición Se pueden utilizar varios servlets para construir aplicaciones Web mayores pero todos ellos siguen este modelo general Mario Muñoz Organero & Norberto Fernández Servidores de Información 9 Despliegue de un servlet Instalación de la aplicación en un contenedor Existe una estructura de directorios estándar para contener los distintos componentes Web de la aplicación y un fichero para cada aplicación Web que la describe y que permite personalizarla (descriptor de despliegue) Mario Muñoz Organero & Norberto Fernández Servidores de Información 10
Despliegue de un servlet Estructura de una aplicación Web Toda aplicación Web tiene 4 partes: Un directorio público app-name/ Un fichero app-name/web-inf/web.xml Un directorio app-name/web-inf/classes Un directorio app-name/web-inf/lib El área pública es la raíz de la aplicación, excepto el directorio WEB- INF El directorio WEB-INF es un área privada web.xml es el descriptor de despliegue classes contendrá clases java Incluyendo las clases compiladas de los servlets lib contiene cualquier jar necesario para la aplicación Mario Muñoz Organero & Norberto Fernández Servidores de Información 11 Estructura de una aplicación Web Mario Muñoz Organero & Norberto Fernández Servidores de Información 12
Despliegue de un Servlet Descriptores de despliegue Ayudan en la gestión de la configuración de las aplicaciones Web El descriptor de despliegue es un fichero XML denominado web.xml Hay un DTD para este tipo de documento Los propósitos del descriptor de despliegue son: Parámetros de inicialización para servlets y aplicaciones Web Definiciones de servlets y JSP Información de correspondencias de URLs con servlets y JSP Seguridad etc. Mario Muñoz Organero & Norberto Fernández Servidores de Información 13 Ejemplo de descriptor de despliegue simple Mario Muñoz Organero & Norberto Fernández Servidores de Información 14
API de Servlets Mario Muñoz Organero & Norberto Fernández Servidores de Información 15 API de servlets Proporciona un marco para construir servlets Clases e interfaces que definen los servlets genéricos (sus métodos, los parámetros de los métodos,...), específicos para un protocolo dado (Ej.: HTTP) Clases e interfaces que definen los objetos que transmiten las peticiones y las respuestas Las clases e interfaces se encuentran en los paquetes: javax.servlet javax.servlet.http Los proveedores de contenedores Web (Tomcat,...) implantan la mayoría de las interfaces y clases de estos paquetes Mario Muñoz Organero & Norberto Fernández Servidores de Información 16
API de servlets Propósito Implementación Configuración Excepciones Peticiones y respuestas Clase/Interfaz javax.servlet.servlet, javax.servlet.genericservlet javax.servlet.http.httpservlet javax.servlet.servletconfig javax.servlet.servletexception javax.servlet.unavailableexception javax.servlet.servletrequest javax.servlet.servletresponse javax.servlet.http.httpservletrequest javax.servlet.http.httpservletresponse Mario Muñoz Organero & Norberto Fernández Servidores de Información 17 Implementación Interfaz Servlet (public interface Servlet) Define el ciclo de vida del servlet Será necesario implementar esta interfaz directa o indirectamente (extendiendo alguna clase que la implemente) Método void init(servletconfig config) El motor lo invoca nada más instanciarse el servlet Método void service(servletrequest req, ServletResponse res) Una vez se ha inicializado el servlet, se invoca este método para responder a las peticiones entrantes Contiene la lógica de la aplicación Los parámetros pasados a este método permiten acceder a los datos de la petición y la construcción de la respuesta Mario Muñoz Organero & Norberto Fernández Servidores de Información 18
Implementación Interfaz Servlet (continuación) Método void destroy() Invocado cuando el contenedor decide eliminar el servlet Siempre espera a que acaben los service en curso Método ServletConfig getservletconfig() Permite obtener información de configuración e información acerca de la aplicación Método String getservletinfo() Debe retornar información acerca del servlet: por ejemplo, su autor, fecha de creación, descripción, etc. Se hace disponible al contenedor, para que, por ejemplo, pueda mostrar una lista de servlets con sus descripciones Mario Muñoz Organero & Norberto Fernández Servidores de Información 19 Clase GenericServlet Implementación Clase abstracta que proporciona una implementación básica de la interfaz Servlet Tenemos así una implementación de los métodos que no tendremos que hacer excepto el método service Clase HttpServlet Extiende la clase GenericServlet Proporciona una implementación más específica para HTTP de la interfaz Servlet Métodos para tratar GET, POST, PUT, DELETE, etc. Implementa el método service para despachar peticiones HTTP: nunca debe ser reescrito El método service determina el tipo de petición (GET, POST, etc.) y la despacha al método apropiado (doget, dopost, etc.) Mario Muñoz Organero & Norberto Fernández Servidores de Información 20
Excepciones Clase ServletException Excepción genérica que puede lanzarse desde cualquiera de los métodos init, service, doget, dopost y destroy Clase UnavailableException Su propósito es indicar al contenedor Web que el servlet no está disponible (temporal o permanentemente) Mario Muñoz Organero & Norberto Fernández Servidores de Información 21 Procesando peticiones Interfaz HttpServletRequest Un objeto que implemente esta interfaz proporciona al servlet acceso a los datos de la petición a través de sus métodos (el contenedor pasará siempre uno al servlet) Lectura de parámetros de la solicitud. Métodos: String getparameter(string name) String[] getparametervalues(string name) Enumeration getparameternames() Mario Muñoz Organero & Norberto Fernández Servidores de Información 22
Manejo de cabeceras de petición Métodos de HttpServletRequest: String getheader (String name) Recibe un string con el nombre de la cabecera (no case sensitive) Devuelve un string con la cabecera, o null si no se encuentra Cookie[] getcookies() Devuelve el contenido de la cabecera Cookie en un array de Cookies String getauthtype() y String getremoteuser() Devuelve los componentes de la cabecera Authorization int getcontentlength() Devuelve el contenido en bits del cuerpo de la petición, o -1 si no se conoce la longitud String getcontenttype() Devuelve el valor de la cabecera Content-Type Mario Muñoz Organero & Norberto Fernández Servidores de Información 23 Manejo de cabeceras de petición Métodos de HttpServletRequest: long getdateheader(string name) int getintheader(string name) Convierten la cabecera especificada a valores a fecha o int Excepción si no se puede convertir o -1 si no existe la cabecera Enumeration getheadernames() Devuelve una enumeración con todos los nombres de cabecera recibidos en la petición Enumeration getheaders(string name) Devuelve una enumeración con todos los valores de todas las ocurrencias de una cabecera (por ejemplo Accept-Language puede aparecer varias veces) Mario Muñoz Organero & Norberto Fernández Servidores de Información 24
Manejo de cabeceras de petición Métodos de HttpServletRequest: String getmethod() Devuelve el método de la petición (GET, POST, etc.) String getrequesturi() Devuelve la parte de la URL de la petición entre el host y puerto, y antes de la query Ej.: GET http://foo.bar/a.html HTTP/1.0 devolvería /a.html String getprotocol() Devuelve el nombre y versión del protocolo en la forma: protocol/majorversion.minorversion Ejemplo: HTTP/1.1 Mario Muñoz Organero & Norberto Fernández Servidores de Información 25 Generando respuestas Interfaz HttpServletResponse El contenedor proporciona al servlet un objeto que implementa esta interfaz Dicho objeto permite al servlet enviar sus resultados Escribir la respuesta a la salida. Métodos: PrintWriter getwriter() Devuelve un PrintWriter para escribir la respuesta Texto, HTML, etc. ServletOutputStream getoutputstream() Devuelve un OutputStream para escribir a la salida Datos binarios Mario Muñoz Organero & Norberto Fernández Servidores de Información 26
Respuesta: Especificación del código de estado Métodos de HttpServletResponse: void setstatus(int sc) Importante: la línea de estado y las cabeceras se pueden poner en cualquier orden (el servidor las ordena) pero siempre ANTES de escribir en el PrintWriter. Desde la versión 2.2 se permite buffering de salida (las cabeceras y líneas de estado se pueden modificar hasta que el buffer se llene) Recibe como entrada una de las constantes definidas como códigos de estado void senderror(int sc, String msg) o void senderror(int sc) Manda el código de error y un mensaje que aparecerá en el navegador del cliente void sendredirect(string location) Manda una redirección temporal al cliente con la nueva URL de parámetro. Puede ser relativa al raíz de servlets (empieza con / ) o al directorio actual, el contenedor Web completa la URL Genera tanto el código de estado como la cabecera Mario Muñoz Organero & Norberto Fernández Servidores de Información 27 Generación de las cabeceras de respuesta Métodos de HttpServletResponse: void setheader(string name, String value) Recibe el nombre y el valor de la cabecera void setdateheader(string name, long date) Valor en milisegundos desde 1970 (System.currentTimeMillis) void setintheader(string name, int value) Valor como entero A partir de la versión 2.2, estos métodos reescriben las cabeceras, si se llaman dos veces. Alternativa: usar addheader, adddateheader o addintheader Mario Muñoz Organero & Norberto Fernández Servidores de Información 28
Generación de las cabeceras de respuesta Métodos de HttpServletResponse: void setcontenttype(string type) Genera la cabecera Content-Type (tipo MIME del contenido). Usado por la mayoría de servlets void setcontentlength(int len) Genera la cabecera Content-Length void addcookie(cookie cookie) Inserta un cookie en la cabecera Set-Cookie void sendredirect(string location) Mencionada anteriormente Mario Muñoz Organero & Norberto Fernández Servidores de Información 29 Accediendo a la configuración del Servlet Interfaz ServletConfig String getinitparameter(string name) Enumeration getinitparameternames() String getservletname() Para obtener una referencia al objeto ServletConfig la forma usual será llamando al método getservletconfig() de la interfaz Servlet. La configuración se especifica en el descriptor de despliegue Mario Muñoz Organero & Norberto Fernández Servidores de Información 30
Complicando el descriptor de despliegue simple Mario Muñoz Organero & Norberto Fernández Servidores de Información 31