Cómo registrar un servlet en Java

1. Introducción

Este artículo proporcionará una descripción general de cómo registrar un servlet dentro de Jakarta EE y Spring Boot. Específicamente, veremos dos formas de registrar un Servlet Java en Jakarta EE: una usando un archivo web.xml y la otra usando anotaciones. Luego, registraremos los servlets en Spring Boot usando la configuración XML, la configuración de Java y mediante propiedades configurables.

Puede encontrar un gran artículo introductorio sobre servlets aquí.

2. Registro de servlets en Yakarta EE.

Repasemos dos formas de registrar un servlet en Jakarta EE. Primero, podemos registrar un servlet a través de web.xml . Alternativamente, podemos usar la anotación Jakarta EE @WebServlet .

2.1. Vía web.xml

La forma más común de registrar un servlet dentro de su aplicación Jakarta EE es agregarlo a su archivo web.xml :

 index.html index.htm index.jsp   Example com.baeldung.Example   Example /Example 

Como puede ver, esto implica dos pasos: (1) agregar nuestro servlet a la etiqueta del servlet , asegurándose de especificar también la ruta de origen a la clase en la que reside el servlet, y (2) especificar la ruta URL en la que se expondrá el servlet on en la etiqueta url-pattern .

El archivo Jakarta EE web.xml generalmente se encuentra en WebContent / WEB-INF .

2.2. A través de anotaciones

Ahora registremos nuestro servlet usando la anotación @WebServlet en nuestra clase de servlet personalizada. Esto elimina la necesidad de mapeos de servlets en server.xml y registro del servlet en web.xml :

@WebServlet( name = "AnnotationExample", description = "Example Servlet Using Annotations", urlPatterns = {"/AnnotationExample"} ) public class Example extends HttpServlet { @Override protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("

Hello World!

"); } }

El código anterior demuestra cómo agregar esa anotación directamente a un servlet. El servlet seguirá estando disponible en la misma ruta URL que antes.

3. Registro de servlets en Spring Boot

Ahora que hemos mostrado cómo registrar servlets en Jakarta EE, echemos un vistazo a varias formas de registrar servlets en una aplicación Spring Boot.

3.1. Registro programático

Spring Boot admite la configuración 100% programática de una aplicación web.

Primero, implementaremos la interfaz WebApplicationInitializer , luego implementaremos la interfaz WebMvcConfigurer , que le permite anular los valores predeterminados preestablecidos en lugar de tener que especificar cada ajuste de configuración en particular, ahorrándole tiempo y permitiéndole trabajar con varias configuraciones probadas y verdaderas fuera de -la caja.

Veamos una implementación de ejemplo de WebApplicationInitializer :

public class WebAppInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(WebMvcConfigure.class); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet( "dispatcherExample", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/"); } }

A continuación, implementemos la interfaz WebMvcConfigurer :

@Configuration public class WebMvcConfigure implements WebMvcConfigurer { @Bean public ViewResolver getViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/"); resolver.setSuffix(".jsp"); return resolver; } @Override public void configureDefaultServletHandling( DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/").setCachePeriod(3600) .resourceChain(true).addResolver(new PathResourceResolver()); } }

Arriba especificamos algunas de las configuraciones predeterminadas para servlets JSP explícitamente para admitir vistas .jsp y servicio de recursos estáticos.

3.2. Configuración XML

Otra forma de configurar y registrar servlets dentro de Spring Boot es a través de web.xml :

 dispatcher org.springframework.web.servlet.DispatcherServlet  contextConfigLocation /WEB-INF/spring/dispatcher.xml  1   dispatcher / 

El web.xml utilizado para especificar la configuración en Spring es similar al que se encuentra en Jakarta EE. Arriba, puede ver cómo especificamos algunos parámetros más a través de atributos en la etiqueta del servlet .

Aquí usamos otro XML para completar la configuración:

Recuerde que su Spring web.xml generalmente residirá en src / main / webapp / WEB-INF .

3.3. Combinando XML y registro programático

Combinemos un enfoque de configuración XML con la configuración programática de Spring:

public void onStartup(ServletContext container) throws ServletException { XmlWebApplicationContext xctx = new XmlWebApplicationContext(); xctx.setConfigLocation('classpath:/context.xml'); xctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet( "dispatcher", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/"); }

Configuremos también el servlet del despachador:

3.4. Registro por Bean

También podemos configurar y registrar mediante programación nuestros servlets usando un ServletRegistrationBean . A continuación, lo haremos para registrar un HttpServlet (que implementa la interfaz javax.servlet.Servlet ):

@Bean public ServletRegistrationBean exampleServletBean() { ServletRegistrationBean bean = new ServletRegistrationBean( new CustomServlet(), "/exampleServlet/*"); bean.setLoadOnStartup(1); return bean; }

La principal ventaja de este enfoque es que le permite agregar tanto varios servlets como diferentes tipos de servlets a su aplicación Spring.

En lugar de simplemente utilizar un DispatcherServlet, que es un tipo más específico de HttpServlet y el tipo más común utilizado en el enfoque programático de configuración de WebApplicationInitializer que exploramos en la sección 3.1, usaremos una instancia de subclase HttpServlet más simple que expone las cuatro operaciones básicas de HttpRequest a través de cuatro funciones: doGet () , doPost () , doPut () y doDelete () al igual que en Jakarta EE.

Recuerde que HttpServlet es una clase abstracta (por lo que no se puede crear una instancia). Sin embargo, podemos crear una extensión personalizada fácilmente:

public class CustomServlet extends HttpServlet{ ... }

4. Registro de servlets con propiedades

Another, though uncommon, way to configure and register your servlets is to use a custom properties file loaded into the app via a PropertyLoader, PropertySource, or PropertySources instance object.

This provides an intermediate kind of configuration and the ability to otherwise customize application.properties which provide little direct configuration for non-embedded servlets.

4.1. System Properties Approach

We can add some custom settings to our application.properties file or another properties file. Let's add a few settings to configure our DispatcherServlet:

servlet.name=dispatcherExample servlet.mapping=/dispatcherExampleURL

Let's load our custom properties into our application:

System.setProperty("custom.config.location", "classpath:custom.properties");

And now we can access those properties via:

System.getProperty("custom.config.location");

4.2. Custom Properties Approach

Let's start with a custom.properties file:

servlet.name=dispatcherExample servlet.mapping=/dispatcherExampleURL

We can then use a run-of-the-mill Property Loader:

public Properties getProperties(String file) throws IOException { Properties prop = new Properties(); InputStream input = null; input = getClass().getResourceAsStream(file); prop.load(input); if (input != null) { input.close(); } return prop; }

And now we can add these custom properties as constants to our WebApplicationInitializer implementation:

private static final PropertyLoader pl = new PropertyLoader(); private static final Properties springProps = pl.getProperties("custom_spring.properties"); public static final String SERVLET_NAME = springProps.getProperty("servlet.name"); public static final String SERVLET_MAPPING = springProps.getProperty("servlet.mapping");

We can then use them to, for example, configure our dispatcher servlet:

ServletRegistration.Dynamic servlet = container.addServlet( SERVLET_NAME, new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping(SERVLET_MAPPING);

The advantage of this approach is the absence of .xml maintenance but with easy-to-modify configuration settings that don't require redeploying the codebase.

4.3. The PropertySource Approach

A faster way to accomplish the above is to make use of Spring's PropertySource which allows a configuration file to be accessed and loaded.

PropertyResolver is an interface implemented by ConfigurableEnvironment, which makes application properties available at servlet startup and initialization:

@Configuration @PropertySource("classpath:/com/yourapp/custom.properties") public class ExampleCustomConfig { @Autowired ConfigurableEnvironment env; public String getProperty(String key) { return env.getProperty(key); } }

Above, we autowire a dependency into the class and specify the location of our custom properties file. We can then fetch our salient property by calling the function getProperty() passing in the String value.

4.4. The PropertySource Programmatic Approach

We can combine the above approach (which involves fetching property values) with the approach below (which allows us to programmatically specify those values):

ConfigurableEnvironment env = new StandardEnvironment(); MutablePropertySources props = env.getPropertySources(); Map map = new HashMap(); map.put("key", "value"); props.addFirst(new MapPropertySource("Map", map));

We've created a map linking a key to a value then add that map to PropertySources enabling invocation as needed.

5. Registering Embedded Servlets

Lastly, we'll also take a look at basic configuration and registration of embedded servlets within Spring Boot.

An embedded servlet provides full web container (Tomcat, Jetty, etc.) functionality without having to install or maintain the web-container separately.

You can add the required dependencies and configuration for simple live server deployment wherever such functionality is supported painlessly, compactly, and quickly.

We'll only look at how to do this Tomcat but the same approach can be undertaken for Jetty and alternatives.

Let's specify the dependency for an embedded Tomcat 8 web container in pom.xml:

 org.apache.tomcat.embed tomcat-embed-core 8.5.11 

Now let's add the tags required to successfully add Tomcat to the .war produced by Maven at build-time:

 embeddedTomcatExample   org.codehaus.mojo appassembler-maven-plugin 2.0.0  target   launch.Main webapp      package  assemble      

If you are using Spring Boot, you can instead add Spring's spring-boot-starter-tomcat dependency to your pom.xml:

 org.springframework.boot spring-boot-starter-tomcat provided 

5.1. Registration Through Properties

Spring Boot supports configuring most possible Spring settings through application.properties. After adding the necessary embedded servlet dependencies to your pom.xml, you can customize and configure your embedded servlet using several such configuration options:

server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet server.jsp-servlet.registered=true server.port=8080 server.servlet-path=/

Above are some of the application settings that can be used to configure the DispatcherServlet and static resource sharing. Settings for embedded servlets, SSL support, and sessions are also available.

There are really too many configuration parameters to list here but you can see the full list in the Spring Boot documentation.

5.2. Configuration Through YAML

Similarly, we can configure our embedded servlet container using YAML. This requires the use of a specialized YAML property loader — the YamlPropertySourceLoader — which exposes our YAML and makes the keys and values therein available for use within our app.

YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader(); PropertySource yamlProps = sourceLoader.load("yamlProps", resource, null);

5.3. Programmatic Configuration Through TomcatEmbeddedServletContainerFactory

Programmatic configuration of an embedded servlet container is possible through a subclassed instance of EmbeddedServletContainerFactory. For example, you can use the TomcatEmbeddedServletContainerFactory to configure your embedded Tomcat servlet.

El TomcatEmbeddedServletContainerFactory envuelve el org.apache.catalina.startup.Tomcat objeto proporcionar opciones de configuración adicionales:

@Bean public ConfigurableServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcatContainerFactory = new TomcatServletWebServerFactory(); return tomcatContainerFactory; }

Entonces podemos configurar la instancia devuelta:

tomcatContainerFactory.setPort(9000); tomcatContainerFactory.setContextPath("/springboottomcatexample");

Cada uno de esos ajustes particulares se puede configurar mediante cualquiera de los métodos descritos anteriormente.

También podemos acceder y manipular directamente el objeto org.apache.catalina.startup.Tomcat :

Tomcat tomcat = new Tomcat(); tomcat.setPort(port); tomcat.setContextPath("/springboottomcatexample"); tomcat.start();

6. Conclusión

En este artículo, hemos revisado varias formas de registrar un Servlet en una aplicación Jakarta EE y Spring Boot.

El código fuente utilizado en este tutorial está disponible en el proyecto Github.