Come registrare un servlet in Java

1. Introduzione

Questo articolo fornirà una panoramica su come registrare un servlet in Jakarta EE e Spring Boot. Nello specifico, esamineremo due modi per registrare un servlet Java in Jakarta EE: uno utilizzando un file web.xml e l'altro utilizzando le annotazioni. Quindi registreremo i servlet in Spring Boot utilizzando la configurazione XML, la configurazione Java e le proprietà configurabili.

Un ottimo articolo introduttivo sui servlet può essere trovato qui.

2. Registrazione dei servlet in Jakarta EE

Esaminiamo due modi per registrare un servlet in Jakarta EE. Innanzitutto, possiamo registrare un servlet tramite web.xml . In alternativa, possiamo utilizzare l' annotazione Jakarta EE @WebServlet .

2.1. Tramite web.xml

Il modo più comune per registrare un servlet all'interno dell'applicazione Jakarta EE è aggiungerlo al file web.xml :

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

Come puoi vedere, ciò comporta due passaggi: (1) aggiungere il nostro servlet al tag servlet , assicurandoti di specificare anche il percorso di origine della classe in cui risiede il servlet e (2) specificare il percorso URL in cui sarà esposto il servlet on nel tag pattern URL .

Il file Jakarta EE web.xml si trova solitamente in WebContent / WEB-INF .

2.2. Tramite annotazioni

Ora registriamo il nostro servlet utilizzando l' annotazione @WebServlet sulla nostra classe servlet personalizzata. Ciò elimina la necessità di mappature servlet in server.xml e la registrazione del servlet in 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!

"); } }

Il codice sopra mostra come aggiungere quell'annotazione direttamente a un servlet. Il servlet sarà ancora disponibile nello stesso percorso URL di prima.

3. Registrazione dei servlet in Spring Boot

Ora che abbiamo mostrato come registrare i servlet in Jakarta EE, diamo un'occhiata a diversi modi per registrare i servlet in un'applicazione Spring Boot.

3.1. Registrazione programmatica

Spring Boot supporta la configurazione programmatica al 100% di un'applicazione web.

Per prima cosa, implementeremo l' interfaccia WebApplicationInitializer , quindi implementeremo l' interfaccia WebMvcConfigurer , che ti consente di ignorare i valori predefiniti invece di dover specificare ogni particolare impostazione di configurazione, risparmiando tempo e permettendoti di lavorare con diverse impostazioni provate e vere. -la scatola.

Diamo un'occhiata a un'implementazione di esempio di 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("/"); } }

Successivamente, implementiamo l' interfaccia 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()); } }

Sopra specifichiamo esplicitamente alcune delle impostazioni predefinite per i servlet JSP per supportare le viste .jsp e il servizio di risorse statiche.

3.2. Configurazione XML

Un altro modo per configurare e registrare i servlet in Spring Boot è tramite web.xml :

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

Il file web.xml utilizzato per specificare la configurazione in Spring è simile a quello trovato in Jakarta EE. Sopra, puoi vedere come specifichiamo alcuni parametri in più tramite attributi sotto il tag servlet .

Qui usiamo un altro XML per completare la configurazione:

Ricorda che il tuo Spring web.xml di solito risiede in src / main / webapp / WEB-INF .

3.3. Combinazione di XML e registrazione programmatica

Mescoliamo un approccio di configurazione XML con la configurazione programmatica di 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("/"); }

Configuriamo anche il servlet del dispatcher:

3.4. Registrazione di Bean

Possiamo anche configurare e registrare a livello di programmazione i nostri servlet utilizzando un ServletRegistrationBean . Di seguito lo faremo per registrare un HttpServlet (che implementa l' interfaccia javax.servlet.Servlet ):

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

Il vantaggio principale di questo approccio è che consente di aggiungere sia più servlet che diversi tipi di servlet all'applicazione Spring.

Invece di utilizzare semplicemente un DispatcherServlet, che è un tipo più specifico di HttpServlet e il tipo più comune utilizzato nell'approccio programmatico alla configurazione di WebApplicationInitializer esplorato nella sezione 3.1, utilizzeremo un'istanza di sottoclasse HttpServlet più semplice che espone le quattro operazioni di base di HttpRequest attraverso quattro funzioni: doGet () , doPost () , doPut () e doDelete () proprio come in Jakarta EE.

Ricorda che HttpServlet è una classe astratta (quindi non può essere istanziata). Tuttavia, possiamo creare facilmente un'estensione personalizzata:

public class CustomServlet extends HttpServlet{ ... }

4. Registrazione di servlet con proprietà

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.

Il TomcatEmbeddedServletContainerFactory avvolge l'org.apache.catalina.startup.Tomcat oggetto che fornisce ulteriori opzioni di configurazione:

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

Quindi possiamo configurare l'istanza restituita:

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

Ciascuna di queste impostazioni particolari può essere configurata utilizzando uno dei metodi descritti in precedenza.

Possiamo anche accedere e manipolare direttamente l' oggetto org.apache.catalina.startup.Tomcat :

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

6. Conclusione

In questo articolo, abbiamo esaminato diversi modi per registrare un servlet in un'applicazione Jakarta EE e Spring Boot.

Il codice sorgente utilizzato in questo tutorial è disponibile nel progetto Github.