Para aplicaciones de servlet, Spring Boot proporciona soporte para servidores integrados Tomcat, Jetty y Resaca . La mayoría de los desarrolladores utilizan un "iniciador" apropiado para obtener una instancia completamente configurada. De forma predeterminada, el servidor integrado escucha las solicitudes HTTP en el puerto 8080.

Servlets, filtros y escuchas

Cuando se utiliza el servlet integrado contenedor, puede registrar servlets, filtros y cualquier escucha (como HttpSessionListener) desde la especificación del servlet, ya sea usando Spring beans o rastreando componentes del servlet.

Registro de servlets, filtros, y oyentes como Spring beans

Cualquier instancia de un servlet Servlet, Filter o *Listener que sea un Spring Bean. Está registrado con el contenedor integrado. Esto puede ser especialmente útil si necesita hacer referencia a un valor de application.properties durante la configuración.

De forma predeterminada, si un contexto contiene solo un servlet, se asigna a /. En el caso de varios beans de servlet, el nombre del bean se utiliza como prefijo de ruta. Los filtros se asignan a /*.

Si la asignación basada en convenciones no es lo suficientemente flexible, puede utilizar ServletRegistrationBean, FilterRegistrationBean y ServletListenerRegistrationBean para un control completo.

Normalmente, no es necesario pedir el bean de filtro. Si se requiere un orden específico, entonces el Filter debe anotarse con la anotación @Order o implementarse como una clase Ordered. No puede configurar el orden de un Filter anotando su método de bean con la anotación @Order. Si no puede modificar la clase Filter para agregar la anotación @Order o implementar la clase Ordered, debe definir un FilterRegistrationBean, para Filter y establezca el orden del bean de registro utilizando el método setOrder(int). Evite configurar un filtro que lea el cuerpo de la solicitud por Ordered.HIGHEST_PRECEDENCE, ya que esto puede entrar en conflicto con la configuración de codificación de caracteres de su aplicación. Si un filtro de servlet envuelve una solicitud, su orden de ejecución configurado debe ser menor o igual a OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER.

Para ver el orden de ejecución de cada Filter en la aplicación, habilite el registro de nivel de depuración para el grupo de registro web (logging.level.web=debug). Los detalles de los filtros registrados, incluido su orden y patrones de URL, se registrarán en el inicio inicial.
Tenga cuidado al registrar Filter beans porque se crean instancias de ellos muy temprano en el ciclo de vida de la aplicación. Si necesita registrar un Filtro que interactúa con otros beans, utilice un DelegatingFilterProxyRegistrationBean en su lugar.

Inicialización de un contexto de servlet

Los contenedores de servlet integrados no ejecutan directamente la interfaz de servlet 3.0+ llamada javax.servlet.ServletContainerInitializer o la interfaz org.springframework.web.WebApplicationInitializer de Spring. Esta es una decisión de diseño deliberada para reducir el riesgo de que las bibliotecas de terceros diseñadas para ejecutarse dentro de un archivo war puedan dañar las aplicaciones Spring Boot.

Si desea inicializar un contexto de servlet en una aplicación Spring Boot, debe registrar el bean que implementa la interfaz org.springframework.boot.web.servlet.ServletContextInitializer. El método único onStartup proporciona acceso al ServletContext y, si es necesario, se puede utilizar fácilmente como adaptador a un WebApplicationInitializer existente.

Buscando servlets, filtros y oyentes

Cuando se utiliza un contenedor integrado, registra automáticamente las clases marcadas con @WebServlet, @WebFilter y @ anotaciones WebListener, se pueden activar usando la anotación @ServletComponentScan.

@ServletComponentScan no funciona en un contenedor independiente, donde en su lugar se utilizan los mecanismos de descubrimiento integrados del contenedor.

ServletWebServerApplicationContext

Internamente, Spring Boot utiliza un tipo diferente de ApplicationContext para admitir el contenedor de servlet integrado. ServletWebServerApplicationContext es un tipo especial de WebApplicationContext que se inicia buscando un único bean ServletWebServerFactory. Por lo general, TomcatServletWebServerFactory, JettyServletWebServerFactory o UndertowServletWebServerFactory se configuran automáticamente.

La mayoría de las veces, no es necesario conocer estas clases de implementación. La mayoría de las aplicaciones se configuran automáticamente y los correspondientes ApplicationContext y ServletWebServerFactory se crean sin su intervención.

En la configuración del contenedor integrado, el ServletContext está configurado como un elemento de inicio del servidor que ocurre durante la inicialización del contexto de la aplicación. Debido a esto, los beans en ApplicationContext no se pueden inicializar de manera confiable usando ServletContext. Una forma de solucionar esta limitación es implementar ApplicationContext como una dependencia de bean y solo llamar a ServletContext cuando sea necesario. Otra forma es utilizar una devolución de llamada inmediatamente después de que se inicie el servidor. Esto se puede hacer usando un ApplicationListener que escucha el ApplicationStartedEvent de esta manera:


import javax.servlet.ServletContext;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.web.context.WebApplicationContext;
public class MyDemoBean implements ApplicationListener<ApplicationStartedEvent> {
    private ServletContext servletContext;
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();
        this.servletContext = ((WebApplicationContext) applicationContext).getServletContext();
    }
}

Personalización de la configuración para contenedores de servlets integrados

La configuración general de un contenedor de servlet se puede configurar usando las Environment del entorno de Spring. Normalmente, las propiedades se definen en el archivo application.properties o application.yaml.

La configuración general del servidor incluye:

  • Parámetros de red: puerto para escuchar solicitudes HTTP entrantes (server.port), dirección de interfaz para vincular a server.address, etc.

  • Parámetros de sesión: si la sesión se almacena durante un tiempo prolongado (server.servlet.session.persistent), tiempo de espera de la sesión (server. servlet.session.timeout), ubicación de los datos de la sesión (server.servlet.session.store-dir) y configuración de las cookies de sesión (server.servlet.session.cookie.*).

  • Gestión de errores: ubicación de la página de error (server.error.path), etc.

  • SSL

  • Compresión HTTP

Spring Boot toma todas las medidas necesarias para proporcionar acceso a muchas configuraciones generales, pero esto no siempre es posible. En tales casos, los espacios de nombres especializados proporcionan configuraciones específicas del servidor (consulte server.tomcat y server.undertow). Por ejemplo, los registros de acceso se pueden configurar para que coincidan con las características específicas del contenedor de servlets integrado.

Ver clase para obtener una lista completa ServerProperties.

Atributo SameSite para cookies

Los navegadores web pueden utilizar aributo SameSite para cookies, para controlar si las cookies se pasan en solicitudes entre sitios y cómo. El atributo es especialmente relevante para los navegadores web modernos, que han comenzado a cambiar el valor predeterminado utilizado cuando falta el atributo.

Si desea cambiar el atributo SameSite de su sesión cookie, puede utilizar la propiedad server.servlet.session.cookie.same-site. Esta propiedad es compatible con los servidores Tomcat, Jetty y Undertow configurados automáticamente. También se utiliza para configurar beans SessionRepository basados en servlets de sesión en Spring.

Por ejemplo, si desea que una cookie de sesión tenga un atributo SameSite cuyo valor es None, entonces puede agregar el siguiente código al archivo application.properties o application.yaml:

Propiedades
 server.servlet.session.cookie.same-site=none
Yaml
server:
    servlet:
        session:
            cookie:
                same-site: "none"

Si desea cambiar el atributo SameSite para otras cookies agregadas a HttpServletResponse, puede utilizar CookieSameSiteSupplier. CookieSameSiteSupplier se pasa a Cookie y puede devolver SameSite o null.

Hay un Número de asistentes de fábrica y métodos de filtrado que se pueden utilizar para encontrar rápidamente cookies específicas. Por ejemplo, agregar el siguiente bean aplicará automáticamente SameSite de Lax a todas las cookies con un nombre que coincida con la expresión regular myapp.*.

Java

import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MySameSiteConfiguration {
    @Bean
    public CookieSameSiteSupplier applicationCookieSameSiteSupplier() {
        return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*");
    }
}
Kotlin

import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
class MySameSiteConfiguration {
    @Bean
    fun applicationCookieSameSiteSupplier(): CookieSameSiteSupplier {
        return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*")
    }
}

Personalizar configuración mediante programación

Si necesita configurar mediante programación un contenedor de servlet integrado, puede registrar un Spring Bean que implemente la interfaz WebServerFactoryCustomizer. WebServerFactoryCustomizer proporciona acceso a la fábrica ConfigurableServletWebServerFactory, que incluye muchos configuradores. El siguiente ejemplo muestra cómo configurar un puerto mediante programación:

Java

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }
}
Kotlin

import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory
import org.springframework.stereotype.Component
@Component
class MyWebServerFactoryCustomizer : WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
    override fun customize(server: ConfigurableServletWebServerFactory) {
        server.setPort(9000)
    }
}

TomcatServletWebServerFactory, JettyServletWebServerFactory y UndertowServletWebServerFactory son variantes especiales de ConfigurableServletWebServerFactory que tienen configuradores adicionales para Tomcat, Jetty y Undertow respectivamente. El siguiente ejemplo muestra cómo configurar un TomcatServletWebServerFactory que proporciona acceso a opciones de configuración relacionadas con Tomcat:

Java

import java.time.Duration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class MyTomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
    @Override
    public void customize(TomcatServletWebServerFactory server) {
        server.addConnectorCustomizers((connector) -> connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));
    }
}
Kotlin

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.stereotype.Component
import java.time.Duration
@Component
class MyTomcatWebServerFactoryCustomizer : WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
    override fun customize(server: TomcatServletWebServerFactory) {
        server.addConnectorCustomizers({ connector -> connector.asyncTimeout = Duration.ofSeconds(20).toMillis() })
    }
}

Personalización directa de la configuración de ConfigurableServletWebServerFactory

En casos de uso más complejos que requieren una extensión de ServletWebServerFactory, puede abrir un bean de este tipo usted mismo.

Se proporcionan configuradores para muchos parámetros de configuración. También hay varios "interceptores" para métodos protegidos si necesita hacer algo más inusual. Para obtener más información, consulte documentación en el código fuente.

Los módulos de configuración configurados automáticamente todavía se aplican a la fábrica personalizada, así que use esta opción con precaución .

Limitaciones de JSP

Cuando se ejecuta una aplicación Spring Boot que utiliza el contenedor de servlet integrado (y está empaquetada como un archivo ejecutable), existen algunas limitaciones en las funciones de soporte de JSP. .

  • Con Jetty y Tomcat todo debería funcionar si usas el empaquetado de archivos war. El archivo war ejecutable funcionará cuando se ejecute mediante java -jar y también se implementará en cualquier contenedor estándar. Las páginas JSP no son compatibles cuando se utiliza un archivo jar ejecutable.

  • Undertow no admite páginas JSP.

  • Creación de una página JSP personalizada La página error.jsp no anula la vista predeterminada de manejo de errores. En su lugar, se deben utilizar páginas de error personalizadas.