De @ServletComponentScan-annotatie in Spring Boot

1. Overzicht

In dit artikel zullen we het nieuwe bespreken @BuienRadarNL annotatie in Spring Boot.

Het doel is om het volgende te ondersteunen Servlet 3.0 annotaties:

  • javax.servlet.annotation.WebFilter
  • javax.servlet.annotation.WebListener
  • javax.servlet.annotation.WebServlet

@WebServlet, @WebFilter, en @WebListener geannoteerde klassen kunnen automatisch worden geregistreerd met een embedded Servlet container door te annoteren @BuienRadarNL op een @Configuratie class en specificeren van de pakketten.

We hebben het basisgebruik van @WebServlet in Inleiding tot Java Servlets en @WebFilter in Inleiding tot het onderscheppen van filterpatronen in Java. Voor @WebListener, kunt u een kijkje nemen in dit artikel dat een typisch gebruiksscenario van webluisteraars laat zien.

2. Servlets, Filters, en Luisteraars

Voordat je erin duikt @BuienRadarNL, laten we eens kijken hoe de annotaties: @WebServlet, @WebFilter en @WebListener werden eerder gebruikt @BuienRadarNL kwam in het spel.

2.1. @WebServlet

Nu gaan we eerst een Servlet dat dient KRIJGEN verzoeken en antwoorden "Hallo":

@WebServlet ("/ hallo") public class HelloServlet breidt HttpServlet uit {@Override public void doGet (HttpServletRequest-verzoek, HttpServletResponse-reactie) {probeer {response .getOutputStream () .write ("hallo"); } catch (IOException e) {e.printStackTrace (); }}}

2.2. @WebFilter

Vervolgens een filter dat verzoeken om te targeten filtert "/Hallo"en prepends "Filteren" naar de output:

@WebFilter ("/ hallo") public class HelloFilter implementeert Filter {// ... @Override public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) gooit IOException, ServletException {servletResponse .getOutputStreaming () .print ("filtering (). ); filterChain.doFilter (servletRequest, servletResponse); } // ...}

2.3. @WebListener

Eindelijk, een luisteraar die een aangepast kenmerk instelt in ServletContext:

@WebListener openbare klasse AttrListener implementeert ServletContextListener {@Override public void contextInitialized (ServletContextEvent servletContextEvent) {servletContextEvent .getServletContext () .setAttribute ("servlet-context-attr", "test"); } // ...}

2.4. Implementeer naar een Servlet Container

Nu we de basiscomponenten van een eenvoudige webapplicatie hebben gebouwd, kunnen we deze verpakken en implementeren in een Servlet container. Het gedrag van elk onderdeel kan gemakkelijk worden geverifieerd door het verpakte WAR-bestand in Steiger, Kater of iets anders Servlet containers die Servlet 3.0.

3. Met behulp van @BuienRadarNL in Spring Boot

Je vraagt ​​je misschien af, want we kunnen die annotaties in de meeste Servlet containers zonder enige configuratie, waarom hebben we @BuienRadarNL? Het probleem zit 'm in embedded Servlet containers.

Vanwege het feit dat embedded containers geen ondersteuning bieden voor @WebServlet, @WebFilter en @WebListener annotaties, Spring Boot, sterk afhankelijk van ingesloten containers, introduceerde deze nieuwe annotatie @BuienRadarNL om enkele afhankelijke potten te ondersteunen die deze 3 annotaties gebruiken.

De gedetailleerde discussie is te vinden in dit nummer op Github.

3.1. Afhankelijkheden van Maven

Gebruiken @BuienRadarNL, wij hebben nodig Spring Boot met versie 1.3.0 of hoger. Laten we de nieuwste versie van spring-boot-starter-parent en spring-boot-starter-web naar de pom:

 org.springframework.boot spring-boot-starter-parent 1.5.1.RELEASE 
  org.springframework.boot spring-boot-starter-web 1.5.1.RELEASE 

3.2. Gebruik makend van @BuienRadarNL

De Spring Boot app is vrij eenvoudig. We voegen toe @BuienRadarNL om scannen voor in te schakelen @WebFilter, @WebListener en @WebServlet:

@ServletComponentScan @SpringBootApplication openbare klasse SpringBootAnnotatedApp {openbare statische leegte hoofd (String [] args) {SpringApplication.run (SpringBootAnnotatedApp.class, args); }}

Zonder enige wijziging aan de vorige webapplicatie, werkt het gewoon:

@Autowired privé TestRestTemplate restTemplate; @Test openbare leegte gegevenServletFilter_whenGetHello_thenRequestFiltered () {ResponseEntity responseEntity = restTemplate.getForEntity ("/ hallo", String.class); assertEquals (HttpStatus.OK, responseEntity.getStatusCode ()); assertEquals ("filtering hallo", responseEntity.getBody ()); }
@Autowired privé ServletContext servletContext; @Test openbare leegte gegevenServletContext_whenAccessAttrs_thenFoundAttrsPutInServletListner () {assertNotNull (servletContext); assertNotNull (servletContext.getAttribute ("servlet-context-attr")); assertEquals ("test", servletContext.getAttribute ("servlet-context-attr")); }

3.3. Specificeer te scannen pakketten

Standaard, @BuienRadarNL zal scannen vanuit het pakket van de geannoteerde klasse. Om aan te geven welke pakketten moeten worden gescand, kunnen we de kenmerken ervan gebruiken:

  • waarde
  • basePackages
  • basePackageClasses

De standaard waarde attribuut is een alias voor basePackages.

Zeg onze SpringBootAnnotatedApp is onder pakket com.baeldung.annotation, en we willen klassen in pakket scannen com.baeldung.annotation.components gemaakt in de bovenstaande webapplicatie, zijn de volgende configuraties equivalent:

@BuienRadarNL
@ServletComponentScan ("com.baeldung.annotation.components")
@ServletComponentScan (basePackages = "com.baeldung.annotation.components")
@ServletComponentScan (basePackageClasses = {AttrListener.class, HelloFilter.class, HelloServlet.class})

4. Onder de motorkap

De @BuienRadarNL annotatie wordt verwerkt door ServletComponentRegisteringPostProcessor. Na het scannen van gespecificeerde pakketten voor @WebFilter, @WebListener en @WebServlet annotaties, een lijst met ServletComponentHandlers verwerkt hun annotatiekenmerken en registreert gescande bonen:

klasse ServletComponentRegisteringPostProcessor implementeert BeanFactoryPostProcessor, ApplicationContextAware {privé statische definitieve lijst HANDLERS; statische {List handlers = new ArrayList (); handlers.add (nieuwe WebServletHandler ()); handlers.add (nieuwe WebFilterHandler ()); handlers.add (nieuwe WebListenerHandler ()); HANDLERS = Collections.unmodifiableList (handlers); } // ... private void scanPackage (ClassPathScanningCandidateComponentProvider componentProvider, String packageToScan) {// ... voor (ServletComponentHandler handler: HANDLERS) {handler.handle (((ScannedGenericBeanDefinition) kandidaat), (BeanDefinitionRegistry) this.applicationContext); }}}

Zoals gezegd in de officiële Javadoc, @BuienRadarNL annotatie werkt alleen in embedded Servlet containers, dat is wat er bij hoort Spring Boot standaard.

5. Conclusie

In dit artikel hebben we geïntroduceerd @BuienRadarNL en hoe het kan worden gebruikt om toepassingen te ondersteunen die afhankelijk zijn van een van de annotaties: @WebServlet, @WebFilter, @WebListener.

De implementatie van de voorbeelden en code is te vinden in het GitHub-project.