Kommentar til @ ServletComponentScan i Spring Boot
1. Oversigt
I denne artikel gennemgår vi det nye @ServletComponentScan kommentar i Spring Boot.
Målet er at støtte følgende Servlet 3.0 kommentarer:
- javax.servlet.annotation.WebFilter
- javax.servlet.annotation.WebListener
- javax.servlet.annotation.WebServlet
@WebServlet, @WebFilterog @WebListener annoterede klasser kan automatisk registreres med en integreret Servlet container ved at kommentere @ServletComponentScan på en @Konfiguration klasse og specificering af pakkerne.
Vi har introduceret den grundlæggende brug af @WebServlet i Introduktion til Java Servlets og @WebFilter i introduktion til aflytning af filtermønster i Java. Til @WebListener, kan du kigge på denne artikel, der viser et typisk brugstilfælde for weblyttere.
2. Servlets, Filtreog Lyttere
Før du dykker ned i @ServletComponentScan, lad os se på hvordan kommentarerne: @WebServlet, @WebFilter og @WebListener blev brugt før @ServletComponentScan kom i spil.
2.1. @WebServlet
Nu definerer vi først en Servlet der tjener FÅ anmodninger og svar "Hej":
@WebServlet ("/ hej") offentlig klasse HelloServlet udvider HttpServlet {@Override public void doGet (HttpServletRequest anmodning, HttpServletResponse svar) {prøv {respons .getOutputStream () .write ("hej"); } fange (IOException e) {e.printStackTrace (); }}}
2.2. @WebFilter
Derefter et filter, der filtrerer anmodninger om at målrette mod "/Hej"og forbereder “Filtrering“ til output:
@WebFilter ("/ hej") offentlig klasse HelloFilter implementerer filter {// ... @ Override public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) kaster IOException, ServletException {servletResponse .getOutputStream ("print"). ); filterChain.doFilter (servletRequest, servletResponse); } // ...}
2.3. @WebListener
Endelig en lytter, der indstiller en brugerdefineret attribut i ServletContext:
@WebListener offentlig klasse AttrListener implementerer ServletContextListener {@Override public void contextInitialized (ServletContextEvent servletContextEvent) {servletContextEvent .getServletContext () .setAttribute ("servlet-context-attr", "test"); } // ...}
2.4. Implementere til en Servlet Beholder
Nu hvor vi har bygget de grundlæggende komponenter i en simpel webapplikation, kan vi pakke og implementere den i en Servlet beholder. Hver komponents adfærd kan let verificeres ved at indsætte den pakkede krigsfil i Anløbsbro, Tomcat eller nogen Servlet containere, der understøtter Servlet 3.0.
3. Brug @ServletComponentScan i Spring Boot
Du undrer dig måske, da vi kan bruge disse kommentarer i de fleste Servlet containere uden nogen konfiguration, hvorfor har vi brug for det @ServletComponentScan? Problemet ligger i indlejret Servlet containere.
På grund af det faktum, at indlejrede containere ikke understøtter @WebServlet, @WebFilter og @WebListener anmærkninger, Spring Boot, stole meget på indlejrede containere, introducerede denne nye kommentar @ServletComponentScan til at understøtte nogle afhængige krukker, der bruger disse 3 kommentarer.
Den detaljerede diskussion kan findes i dette nummer på Github.
3.1. Maven afhængigheder
At bruge @ServletComponentScan, vi behøver Spring Boot med version 1.3.0 eller nyere. Lad os tilføje den nyeste version af spring-boot-starter-parent og spring-boot-starter-web til 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. Ved brug af @ServletComponentScan
Det Spring Boot app er ret enkel. Vi tilføjer @ServletComponentScan for at aktivere scanning efter @WebFilter, @WebListener og @WebServlet:
@ServletComponentScan @ SpringBootApplication offentlig klasse SpringBootAnnotatedApp {public static void main (String [] args) {SpringApplication.run (SpringBootAnnotatedApp.class, args); }}
Uden nogen ændring af den forrige webapplikation fungerer det bare:
@Autowired privat TestRestTemplate restTemplate; @Test offentlig ugyldighed givenServletFilter_whenGetHello_thenRequestFiltered () {ResponseEntity responsEntity = restTemplate.getForEntity ("/ hej", String.class); assertEquals (HttpStatus.OK, responseEntity.getStatusCode ()); assertEquals ("filtrering hej", responseEntity.getBody ()); }
@Autowired privat ServletContext servletContext; @Test offentlig ugyldighed givenServletContext_whenAccessAttrs_thenFoundAttrsPutInServletListner () {assertNotNull (servletContext); assertNotNull (servletContext.getAttribute ("servlet-context-attr")); assertEquals ("test", servletContext.getAttribute ("servlet-context-attr")); }
3.3. Angiv pakker, der skal scannes
Som standard, @ServletComponentScan scanner fra pakken i den kommenterede klasse. For at specificere hvilke pakker der skal scannes, kan vi bruge dets attributter:
- værdi
- basePackages
- basePackageClasses
Standardindstillingen værdi attribut er et alias for basePackages.
Sig vores SpringBootAnnotatedApp er under pakke com.baeldung.annotation, og vi vil scanne klasser i pakke com.baeldung.annotation.components oprettet i webapplikationen ovenfor, er følgende konfigurationer ækvivalente:
@ServletComponentScan
@ServletComponentScan ("com.baeldung.annotation.components")
@ServletComponentScan (basePackages = "com.baeldung.annotation.components")
@ServletComponentScan (basePackageClasses = {AttrListener.class, HelloFilter.class, HelloServlet.class})
4. Under hætten
Det @ServletComponentScan annotering behandles af ServletComponentRegistringPostProcessor. Efter scanning af specificerede pakker til @WebFilter, @WebListener og @WebServlet kommentarer, en liste over ServletComponentHandlers behandler deres annoteringsattributter og registrerer scannede bønner:
klasse ServletComponentRegisteringPostProcessor implementerer BeanFactoryPostProcessor, ApplicationContextAware {privat statisk endelig Liste HÅNDTAGERE; statisk {List handlers = ny ArrayList (); handlers.add (ny WebServletHandler ()); handlers.add (ny WebFilterHandler ()); handlers.add (ny WebListenerHandler ()); HANDLERS = Collections.unmodifiableList (handlers); } // ... private void scanPackage (ClassPathScanningCandidateComponentProvider componentProvider, String packageToScan) {// ... for (ServletComponentHandler handler: HANDLERS) {handler.handle ((((ScannedGenericBeanDefinition) kandidat), (BeanDefinitionRegistry) this.application; }}}
Som sagt i den officielle Javadoc, @ServletComponentScan kommentar fungerer kun i integreret Servlet containere, hvilket er hvad der følger med Spring Boot som standard.
5. Konklusion
I denne artikel introducerede vi @ServletComponentScan og hvordan det kan bruges til at understøtte applikationer, der afhænger af en af kommentarerne: @WebServlet, @WebFilter, @WebListener.
Implementeringen af eksemplerne og koden findes i GitHub-projektet.