Cómo configurar el descriptor de implementación de web.xml

El archivo web.xml solo se usa cuando se implementa una aplicación de Java en un entorno de ejecución que incluye el servidor Eclipse Jetty 9/servlet 3. Para obtener más detalles, consulta Entorno de ejecución de Eclipse Jetty 9.3.

Las aplicaciones web de Java usan un archivo descriptor de implementación para determinar cómo se asignan las URL a los servlets, qué URL requieren autenticación y más información. Este archivo se llama web.xml y se encuentra en el WAR de la aplicación dentro del directorio WEB-INF/. web.xml es parte del estándar del servlet para aplicaciones web.

Para obtener más información acerca del estándar web.xml, consulta la wiki de referencia sobre web.xml de Metawerx y la especificación de Servlet.

Acerca de los descriptores de implementación

Un descriptor de implementación de una aplicación web describe las clases, los recursos y la configuración de la aplicación y cómo los usa el servidor web para entregar solicitudes web. Cuando el servidor web recibe una solicitud para la aplicación, usa el descriptor de implementación con el fin de asignar la URL de la solicitud al código que debe controlarla.

El descriptor de implementación es un archivo llamado web.xml. Se encuentra en el WAR de la app en el directorio WEB-INF/. Es un archivo XML cuyo elemento raíz es <web-app>.

A continuación, se muestra un ejemplo simple de web.xml que asigna todas las rutas de URL (/*) a la clase de servlet mysite.server.ComingSoonServlet:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>comingsoon</servlet-name>
        <servlet-class>mysite.server.ComingSoonServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>comingsoon</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Servlets y rutas de URL

web.xml define las asignaciones entre las rutas de URL y los servlets que controlan las solicitudes con esas rutas. El servidor web usa esta configuración para identificar el servlet que controlará una solicitud determinada y llamar al método de clase que corresponde al método de la solicitud (p. ej., el método doGet() para solicitudes HTTP GET).

Para asignar una URL a un servlet, decláralo con el elemento <servlet> y define una asignación desde una ruta de URL a una declaración de servlet con el elemento <servlet-mapping>.

El elemento <servlet> declara el servlet, incluido un nombre usado por otros elementos en el archivo para referirse al servlet, la clase que se usará en este y los parámetros de inicialización. Puedes declarar varios servlets con la misma clase, pero con diferentes parámetros de inicialización. El nombre de cada servlet debe ser único en todo el descriptor de implementación.

    <servlet>
        <servlet-name>redteam</servlet-name>
        <servlet-class>mysite.server.TeamServlet</servlet-class>
        <init-param>
            <param-name>teamColor</param-name>
            <param-value>red</param-value>
        </init-param>
        <init-param>
            <param-name>bgColor</param-name>
            <param-value>#CC0000</param-value>
        </init-param>
    </servlet>

    <servlet>
        <servlet-name>blueteam</servlet-name>
        <servlet-class>mysite.server.TeamServlet</servlet-class>
        <init-param>
            <param-name>teamColor</param-name>
            <param-value>blue</param-value>
        </init-param>
        <init-param>
            <param-name>bgColor</param-name>
            <param-value>#0000CC</param-value>
        </init-param>
    </servlet>

El elemento <servlet-mapping> especifica un patrón de URL y el nombre de un servlet declarado para usar en solicitudes cuyas URL coincidan con el patrón. El patrón de URL puede usar un asterisco (*) al principio o al final del patrón para indicar cero o más de cualquier carácter. (El estándar no admite comodines en medio de una string y no permite múltiples comodines en un patrón). El patrón coincide con la ruta completa de la URL, incluida la barra inicial (/) que sigue al nombre del dominio.

    <servlet-mapping>
        <servlet-name>redteam</servlet-name>
        <url-pattern>/red/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>blueteam</servlet-name>
        <url-pattern>/blue/*</url-pattern>
    </servlet-mapping>

En este ejemplo, la clase TeamServlet controla una solicitud para la URL http://www.example.com/blue/teamProfile, con el parámetro teamColor igual a blue y el parámetro bgColor igual a #0000CC. El servlet puede obtener la porción de la ruta de URL que coincide con el comodín usando el método getPathInfo() del objeto de ServletRequest.

El servlet puede acceder a sus parámetros de inicialización con su configuración de servlet. Para obtenerla, debe usar su propio método getServletConfig() y, luego, llamar al método getInitParameter() en el objeto de configuración con el nombre del parámetro como argumento.

        String teamColor = getServletConfig().getInitParameter("teamColor");

JSP

Una aplicación puede usar JavaServer Pages (JSP) para implementar páginas web. Los JSP son servlets definidos mediante contenido estático (como HTML) mezclado con código Java.

App Engine admite la compilación automática y la asignación de URL para JSP. Un archivo JSP en el WAR de la aplicación (fuera de WEB-INF/) cuyo nombre de archivo termina en .jsp se compila en una clase de servlet de manera automática y se asigna a la ruta de URL equivalente a la ruta del archivo JSP de la raíz del WAR. Por ejemplo, si una aplicación tiene en su WAR un archivo JSP con el nombre start.jsp en un subdirectorio llamado register/, App Engine lo compila y lo asigna a la ruta de URL /register/start.jsp.

Para tener más control sobre cómo se asigna el JSP a una URL, puedes especificar la asignación de forma explícita si la declaras con un elemento <servlet> en el descriptor de implementación. En lugar de un elemento <servlet-class>, especifica un elemento <jsp-file> con la ruta del archivo JSP desde la raíz del WAR. El elemento <servlet> para el JSP puede contener parámetros de inicialización.

    <servlet>
        <servlet-name>register</servlet-name>
        <jsp-file>/register/start.jsp</jsp-file>
    </servlet>

    <servlet-mapping>
        <servlet-name>register</servlet-name>
        <url-pattern>/register/*</url-pattern>
    </servlet-mapping>

Nota: El elemento <jsp-file> debe comenzar con una barra (/), si el JSP está en el directorio raíz de la aplicación.

Puedes instalar bibliotecas de etiquetas JSP con el elemento <taglib>. Una biblioteca de etiquetas tiene una ruta al archivo Descriptor de biblioteca de etiquetas (TLD) JSP (<taglib-location>) y una URI que usan los JSP para seleccionar la biblioteca que se cargará (<taglib-uri>). Ten en cuenta que App Engine proporciona la Biblioteca de etiquetas estándar de JavaServer Pages (JSTL) y no necesitas instalarla.

    <taglib>
        <taglib-uri>/escape</taglib-uri>
        <taglib-location>/WEB-INF/escape-tags.tld</taglib-location>
    </taglib>

Lista de archivos de bienvenida

Cuando las URL de tu sitio representan rutas a archivos estáticos o JSP en tu WAR, a menudo es una buena idea que las rutas a los directorios también hagan algo útil. Un usuario que visita la ruta de URL /help/accounts/password.jsp para obtener información sobre las contraseñas de la cuenta puede intentar visitar /help/accounts/ con el fin de encontrar una página que presente la documentación del sistema sobre la cuenta. El descriptor de implementación puede especificar una lista de nombres de archivo que el servidor debe probar cuando el usuario accede a una ruta que representa un subdirectorio del WAR (que no esté asignado de manera explícita a un servlet). El estándar de servlet llama a esto la "lista de archivos de bienvenida".

Por ejemplo, si el usuario accede a la ruta de URL /help/accounts/, el siguiente elemento <welcome-file-list> del descriptor de implementación le indica al servidor que debe verificar help/accounts/index.jsp y help/accounts/index.html antes de informar que la URL no existe:

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

Filtros

Un filtro es una clase que actúa en una solicitud como servlet, pero puede permitir que la preparación de la solicitud continúe con otros filtros o servlets. Un filtro puede llevar a cabo una tarea auxiliar, como mantener registros, realizar verificaciones de autenticación especializadas o anotar los objetos de solicitud o respuesta antes de llamar al servlet. Los filtros te permiten crear tareas de procesamiento de solicitudes desde el descriptor de implementación.

Una clase de filtro implementa la interfaz javax.servlet.Filter, incluido el método doFilter(). A continuación, se muestra una implementación de filtro simple que registra un mensaje y pasa el control a lo largo de la cadena, que puede incluir otros filtros o un servlet, como lo indica el descriptor de implementación:

package mysite.server;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class LogFilterImpl implements Filter {

    private FilterConfig filterConfig;
    private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {
        log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
            + " request");

        filterChain.doFilter(request, response);
    }

    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }

    public void destroy() {}

}

De manera similar a los servlets, puedes configurar un filtro en el descriptor de implementación si lo declaras con el elemento <filter> y, luego, lo asignas a un patrón de URL con el elemento <filter-mapping>. También puedes asignar filtros directamente a otros servlets.

El elemento <filter> contiene los elementos <filter-name>, <filter-class> y, de forma opcional, <init-param>.

    <filter>
        <filter-name>logSpecial</filter-name>
        <filter-class>mysite.server.LogFilterImpl</filter-class>
        <init-param>
            <param-name>logType</param-name>
            <param-value>special</param-value>
        </init-param>
    </filter>

El elemento <filter-mapping> contiene un elemento <filter-name> que coincide con el nombre de un filtro declarado. Además puede contener un elemento <url-pattern> para aplicar el filtro a las URL o un elemento <servlet-name> que coincide con el nombre de un servlet declarado con el fin de aplicar el filtro cuando se llama al servlet.

    <!-- Log for all URLs ending in ".special" -->
    <filter-mapping>
        <filter-name>logSpecial</filter-name>
        <url-pattern>*.special</url-pattern>
    </filter-mapping>

    <!-- Log for all URLs that use the "comingsoon" servlet -->
    <filter-mapping>
        <filter-name>logSpecial</filter-name>
        <servlet-name>comingsoon</servlet-name>
    </filter-mapping>

Nota: Los filtros no se invocan en elementos estáticos, incluso si la ruta coincide con un patrón filter-mapping. Los archivos estáticos se entregan directamente al navegador.

Controladores de errores

Por medio del descriptor de implementación, puedes personalizar lo que el servidor envía al usuario cuando se produce un error. El servidor puede mostrar una ubicación de página alternativa cuando está a punto de enviar un código de estado HTTP particular o cuando un servlet genera una excepción de Java específica.

El elemento <error-page> contiene un elemento <error-code> con un valor de código de error HTTP (como 500) o un elemento <exception-type> con el nombre de la clase de excepción esperada (como java.io.IOException). También contiene un elemento <location> que incluye la ruta de URL del recurso que se muestra cuando se produce el error.

    <error-page>
        <error-code>500</error-code>
        <location>/errors/servererror.jsp</location>
    </error-page>

Nota: En la actualidad, no puedes configurar controladores de errores personalizados para algunas condiciones de error. En particular, no puedes personalizar la página de respuesta 404 cuando no se define una asignación de servlet para una URL, la página de error de cuota 403 ni la página de error del servidor 500 que aparece después de un error interno de App Engine.

Características no compatibles de web.xml

Las siguientes características de web.xml no son compatibles con App Engine:

  • App Engine es compatible con el elemento <load-on-startup> para las declaraciones de servlet. Sin embargo, la carga en realidad se produce durante la primera solicitud controlada por la instancia del servidor web, no antes.
  • Algunos elementos del descriptor de implementación pueden tener un nombre visible, una descripción y un ícono legibles para su uso en los IDE. App Engine no los usa y los ignora.
  • App Engine no es compatible con variables de entorno JNDI (<env-entry>).
  • App Engine no es compatible con recursos EJB (<resource-ref>).
  • No se admite la notificación de destrucción de servlets, contexto de servlet ni filtros.
  • El elemento <distributable> se ignora.
  • La programación de servlets con <run-at> no es compatible.
  • Las restricciones de seguridad no son compatibles. Para obtener una funcionalidad equivalente, consulta el instructivo de Bookshelf.
  • CONFIDENTIAL no se admite en web.xml.
¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Entorno flexible de App Engine para documentos de Java