ID de región
El REGION_ID
es un código abreviado que Google asigna en función de la región que selecciones al crear tu aplicación. El código no corresponde a un país o provincia, aunque algunos IDs de región pueden parecerse a los códigos de país y provincia que se usan habitualmente. En las aplicaciones creadas después de febrero del 2020, REGION_ID.r
se incluye en las URLs de App Engine. En las aplicaciones creadas antes de esa fecha, el ID de región es opcional en la URL.
Las aplicaciones web Java usan un archivo de descriptor de despliegue para determinar cómo se asignan las URLs a los servlets, qué URLs requieren autenticación y otra información. Este archivo se llama web.xml
y se encuentra en el archivo WAR de la aplicación, en el directorio WEB-INF/
.
web.xml
forma parte del estándar de servlets para aplicaciones web.
Para obtener más información sobre el estándar web.xml
, consulta la especificación de servlet.
Descriptor de implementación web.xml
El descriptor de implementación de una aplicación web describe las clases, los recursos y la configuración de la aplicación, así como la forma en que el servidor web los usa para atender las 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 gestionar la solicitud.
El descriptor de implementación es un archivo llamado web.xml
. Se encuentra en el archivo WAR de la aplicación, en el directorio WEB-INF/
. El archivo es un archivo XML cuyo elemento raíz es <web-app>
.
Aquí tienes un ejemplo sencillo 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 gestionan las solicitudes con esas rutas. El servidor web usa esta configuración para identificar el servlet que debe gestionar una solicitud determinada y llamar al método de clase que corresponde al método de solicitud. Por ejemplo, el método doGet()
para las solicitudes HTTP GET
.
Para asignar una URL a un servlet, declara el servlet con el elemento <servlet>
y, a continuación, 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, incluido un nombre que se usa para hacer referencia al servlet por otros elementos del archivo, la clase que se va a usar para el servlet y los parámetros de inicialización. Puede declarar varios servlets usando la misma clase con diferentes parámetros de inicialización. El nombre de cada servlet debe ser único en el descriptor de despliegue.
<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 que se usará en las solicitudes cuya URL coincida 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 caracteres de cualquier tipo. El estándar no admite comodines en medio de una cadena ni permite varios comodines en un patrón. El patrón coincide con la ruta completa de la URL, empezando por la barra diagonal (/
) que va después del nombre de dominio y que también se incluye. La ruta de la URL no puede empezar por un punto (.
).
<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
gestiona una solicitud de 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 parte de la ruta de la 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 obteniendo su configuración de servlet mediante su propio método getServletConfig()
y, a continuación, llamando al método getInitParameter()
en el objeto de configuración con el nombre del parámetro como argumento.
String teamColor = getServletConfig().getInitParameter("teamColor");
Páginas JSP
Una aplicación puede utilizar la tecnología JavaServer Pages (JSP) para implementar las páginas web. Los JSPs son servlets definidos mediante contenido estático, como HTML, mezclado con código Java.
En el caso de las páginas JSP, App Engine admite tanto la compilación automática como la asignación de direcciones URL. Un archivo JSP
en el archivo WAR de la aplicación (fuera de WEB-INF/
) cuyo nombre de archivo termina en .jsp
se compila automáticamente en una clase de servlet y se asigna a la ruta de URL
equivalente a la ruta del archivo JSP desde la raíz del archivo WAR. Por ejemplo, si una aplicación tiene un archivo JSP llamado start.jsp
en un subdirectorio llamado register/
en su archivo WAR, App Engine lo compila y lo asigna a la ruta de URL /register/start.jsp
.
Si quieres tener más control sobre cómo se asigna el JSP a una URL, puedes especificar la asignación explícitamente declarándola 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 al archivo JSP desde la raíz del archivo WAR. El elemento <servlet>
del 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 de descriptor de biblioteca de etiquetas JSP (TLD) (<taglib-location>
) y un URI que usan los JSP para seleccionar la biblioteca que se va a cargar (<taglib-uri>
). Ten en cuenta que App Engine proporciona la biblioteca de etiquetas estándar de JavaServer Pages (JSTL), por lo que no es necesario instalarla.
<taglib>
<taglib-uri>/escape</taglib-uri>
<taglib-location>/WEB-INF/escape-tags.tld</taglib-location>
</taglib>
Seguridad y autenticación
Una aplicación de App Engine puede utilizar el servicio Cuentas de Google para la autenticación de usuarios. La aplicación puede usar la API Google Accounts para detectar si el usuario ha iniciado sesión, obtener la dirección de correo del usuario que ha iniciado sesión y generar URLs de inicio y cierre de sesión. Una aplicación también puede especificar restricciones de acceso para las rutas de URLs basadas en cuentas de Google mediante el descriptor de implementación.
El elemento <security-constraint>
define una restricción de seguridad para las URLs que coinciden con un patrón. Si un usuario accede a una URL cuya ruta tiene una restricción de seguridad y no ha iniciado sesión, App Engine lo redirige a la página de inicio de sesión de Cuentas de Google. Cuentas de Google redirige al usuario a la URL de la aplicación después de iniciar sesión o registrar una cuenta nueva correctamente. La aplicación no tiene que hacer nada más para asegurarse de que solo los usuarios que hayan iniciado sesión puedan acceder a la URL.
Una restricción de seguridad incluye una restricción de autorización que especifica a qué cuentas de Google pueden acceder los usuarios a la ruta. Si la restricción de autorización especifica el rol de usuario *
, cualquier usuario que haya iniciado sesión con una cuenta de Google podrá acceder a la URL. Si la restricción especifica el rol de usuario admin
, solo los desarrolladores registrados de la aplicación podrán acceder a la URL. El rol admin
permite crear fácilmente secciones de su sitio a las que solo puedan acceder los administradores.
<security-constraint>
<web-resource-collection>
<web-resource-name>profile</web-resource-name>
<url-pattern>/profile/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
App Engine no admite roles de seguridad personalizados (<security-role>
) ni mecanismos de autenticación alternativos (<login-config>
) en el descriptor de implementación.
Las restricciones de seguridad se aplican tanto a los archivos estáticos como a los servlets.
URL seguras
Google App Engine admite conexiones seguras mediante HTTPS para URLs que usen el dominio REGION_ID.r.appspot.com
. Cuando una solicitud accede a una URL mediante HTTPS y esa URL está configurada para usar HTTPS en el archivo web.xml
, tanto los datos de la solicitud como los de la respuesta se cifran por parte del remitente antes de transmitirse y se descifran por parte del destinatario después de recibirse. Las conexiones seguras son útiles para proteger los datos de los clientes, como la información de contacto, las contraseñas y los mensajes privados.
Para declarar que se debe usar HTTPS en una URL, configura una restricción de seguridad en el descriptor de implementación (como se describe en Seguridad y autenticación) con un <user-data-constraint>
cuyo <transport-guarantee>
sea CONFIDENTIAL
.
Por ejemplo:
<security-constraint>
<web-resource-collection>
<web-resource-name>profile</web-resource-name>
<url-pattern>/profile/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Las solicitudes que usan HTTP (no seguro) para URLs cuya garantía de transporte es CONFIDENTIAL
se redirigen automáticamente a la misma URL mediante HTTPS.
Cualquier URL puede usar la garantía de transporte CONFIDENTIAL
, incluidos los archivos JSP y los archivos estáticos.
El servidor web de desarrollo no admite las conexiones HTTPS. Ignora la garantía de transporte, por lo que las rutas diseñadas para usarse con HTTPS se pueden probar mediante conexiones HTTP normales al servidor web de desarrollo.
Cuando pruebas los controladores HTTPS de tu aplicación con la URL de appspot.com con versión, como https://1.latest.your_app_id.REGION_ID.r.appspot.com/
, tu navegador te avisa de que el certificado HTTPS no se ha firmado para esa ruta de dominio específica. Si aceptas el certificado de ese dominio, las páginas se cargarán correctamente. Los usuarios no verán la advertencia del certificado al acceder a https://your_app_id.REGION_ID.r.appspot.com/
.
También puedes usar una forma alternativa de la URL versionada de appspot.com diseñada para evitar este problema. Para ello, sustituye los puntos que separan los componentes del subdominio por la cadena "-dot-
". Por ejemplo, se podría acceder al ejemplo anterior sin una advertencia de certificado en https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com
.
El inicio y el cierre de sesión de las cuentas de Google siempre se realizan mediante una conexión segura y no están relacionados con la configuración de las URLs de la aplicación.
Como se ha mencionado anteriormente, las restricciones de seguridad se aplican tanto a los archivos estáticos como a los servlets. Esto incluye la garantía de transporte.
Nota: Google recomienda usar el protocolo HTTPS para enviar solicitudes a tu aplicación. Google no emite certificados SSL para dominios de doble comodín alojados en appspot.com
. Por lo tanto, con HTTPS debe usar la cadena "-dot-" en lugar de "." para separar los subdominios, tal como se muestra en los ejemplos de abajo. Puedes usar un simple "." con tu propio dominio personalizado o con direcciones HTTP. Para obtener más información, consulta HTTPS como factor de posicionamiento.
La lista de archivos de bienvenida
Cuando las URLs de su sitio representan rutas a archivos estáticos o JSPs de su archivo WAR, a menudo es una buena idea que las rutas a directorios también hagan algo útil.
Un usuario que visite la ruta de URL /help/accounts/password.jsp
para obtener información sobre las contraseñas de las cuentas podría intentar visitar /help/accounts/
para encontrar una página que presente la documentación del sistema de cuentas. El descriptor de implementación puede especificar una lista de nombres de archivo que el servidor debe probar cuando el usuario acceda a una ruta que represente un subdirectorio WAR que aún no se haya asignado explícitamente a un servlet. El estándar de servlet lo denomina "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 indica al servidor que compruebe help/accounts/index.jsp
y help/accounts/index.html
antes de informar de 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 un servlet, pero puede permitir que la solicitud se siga gestionando con otros filtros o servlets. Un filtro puede realizar una tarea auxiliar, como registrar, realizar comprobaciones de autenticación especializadas o anotar los objetos de solicitud o respuesta antes de llamar al servlet. Los filtros le permiten componer tareas de procesamiento de solicitudes a partir del 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 sencilla que registra un mensaje y pasa el control a la cadena, que puede incluir otros filtros o un servlet, tal como se describe en 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() {}
}
Al igual que los servlets, los filtros se configuran en el descriptor de implementación. Para ello, se declara el filtro con el elemento <filter>
y, a continuación, se asigna a un patrón de URL con el elemento <filter-mapping>
. También puedes asignar filtros directamente
a otros servlets.
El elemento <filter>
contiene elementos <filter-name>
, <filter-class>
y <init-param>
opcionales.
<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 URLs 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 error
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é a punto de enviar un código de estado HTTP concreto o cuando un servlet genere una excepción de Java concreta.
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 clase de la excepción esperada (como java.io.IOException
). También contiene un elemento <location>
que incluye la ruta de la URL del recurso que se debe mostrar cuando se produzca el error.
<error-page>
<error-code>500</error-code>
<location>/errors/servererror.jsp</location>
</error-page>
Funciones de web.xml no admitidas
App Engine no admite las siguientes funciones de web.xml:
- App Engine admite el elemento
<load-on-startup>
para las declaraciones de servlet. Sin embargo, la carga se produce durante la primera solicitud gestionada 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 icono legibles por humanos para usarlos en IDEs. 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 la destrucción de servlets, contextos de servlet o filtros.
- El elemento
<distributable>
se ignora. - No se admite la programación de servlets con
<run-at>
.