Configura 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 en 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 app en el directorio WEB-INF/. web.xml es parte del servlet estándar para aplicaciones web.

Para obtener más información sobre el estándar web.xml, consulta la especificación del Servlet.

Acerca de los descriptores de implementación

Un descriptor de implementación de una aplicación web describe las clases, recursos y configuración de la aplicación y la forma en que 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 para asignar la URL de la solicitud al código que debe manejarla.

El descriptor de implementación es un archivo llamado web.xml. Se encuentra en el WAR de la app en el directorio WEB-INF/. El archivo 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, declara el servlet con el elemento <servlet> y, luego, define una asignación de una ruta de URL a una declaración de servlet con el elemento <servlet-mapping>.

El elemento <servlet> declara el servlet, lo que incluye un nombre que otros elementos del archivo usan en el archivo, la clase que se usará para el servlet 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 varios comodines en un solo patrón. El patrón coincide con la ruta completa de la URL, incluida la barra diagonal (/) que sigue al nombre de 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>

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

El servlet puede acceder a sus parámetros de inicialización si obtiene su configuración de servlet con su propio método getServletConfig() y, luego, llama 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 app 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 le asigna la ruta de URL equivalente a la ruta al archivo JSP desde la raíz del WAR. Por ejemplo, si una app tiene un archivo JSP llamado start.jsp en un subdirectorio llamado register/ en su WAR, 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>, debes especificar 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>

Puedes instalar bibliotecas de etiquetas JSP con el elemento <taglib>. Una biblioteca de etiquetas tiene una ruta al archivo Descriptor de bibliotecas de etiquetas (TLD) JSP (<taglib-location>) y un 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>

La lista de archivos de bienvenida

Cuando las URL de tu sitio representan rutas a archivos estáticos o JSP en tu WAR, suele ser 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/ para encontrar una página que presente la documentación del sistema de 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> en el descriptor de implementación le dice al servidor que busque 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 <filter-name> que coincide con el nombre de un filtro declarado, y 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 para aplicar el filtro cada vez que 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>

Controladores de errores

Puedes personalizar lo que el servidor envía al usuario cuando se produce un error mediante el descriptor de implementación. El servidor puede mostrar una ubicación de página alternativa cuando está por 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 (por ejemplo, 500) o un elemento <exception-type> con el nombre de la clase de la excepción esperada (como java.io.IOException). También contiene un elemento <location> que contiene la ruta de URL del recurso para mostrar cuando se produce el error.

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

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 admite variables de entorno JNDI (<env-entry>).
  • App Engine no admite recursos EJB (<resource-ref>).
  • No se admite la notificación de destrucción de servlets, contexto de servlet ni filtros.
  • Se ignora el elemento <distributable>.
  • No se admite la programación de servlets con <run-at>.
  • Las restricciones de seguridad no son compatibles. Para obtener una funcionalidad equivalente, consulta Autentícate en servicios de Cloud con bibliotecas cliente.
  • CONFIDENTIAL no se admite en web.xml.