Kommentaren til @ServletComponentScan i Spring Boot
1. Oversikt
I denne artikkelen vil vi gå gjennom det nye @ServletComponentScan kommentar i Vårstøvel.
Målet er å støtte følgende Servlet 3.0 kommentarer:
- javax.servlet.annotation.WebFilter
- javax.servlet.annotation.WebListener
- javax.servlet.annotation.WebServlet
@WebServlet, @WebFilter, og @WebListener merkede klasser kan automatisk registreres med en innebygd Servlet container ved å kommentere @ServletComponentScan på en @Konfigurasjon klasse og spesifisere pakkene.
Vi har introdusert den grunnleggende bruken av @WebServlet i Introduksjon til Java Servlets og @WebFilter i Introduksjon til avskjæring av filtermønster i Java. Til @WebListener, kan du ta en titt på denne artikkelen som viser et typisk brukstilfelle for nettlyttere.
2. Servlets, Filtre, og Lyttere
Før du dykker inn i @ServletComponentScanla oss ta en titt på hvordan kommentarene: @WebServlet, @WebFilter og @WebListener ble brukt før @ServletComponentScan kom til spill.
2.1. @WebServlet
Nå skal vi først definere en Servlet som serverer FÅ forespørsler og svarer "Hallo":
@WebServlet ("/ hallo") offentlig klasse HelloServlet utvider HttpServlet {@Override public void doGet (HttpServletRequest request, HttpServletResponse response) {try {response .getOutputStream () .write ("hallo"); } fange (IOException e) {e.printStackTrace (); }}}
2.2. @WebFilter
Deretter et filter som filtrerer forespørsler om å målrette "/Hallo"og prepends “Filtrering“ til utgangen:
@WebFilter ("/ hallo") 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
Til slutt, en lytter som setter et tilpasset attributt inn 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 Container
Nå som vi har bygget de grunnleggende komponentene i en enkel webapplikasjon, kan vi pakke og distribuere den til en Servlet container. Hver komponents oppførsel kan lett verifiseres ved å distribuere den pakkede krigsfilen i Brygge, Tomcat eller noen Servlet containere som støtter Servlet 3.0.
3. Bruke @ServletComponentScan i Vårstøvel
Du lurer kanskje på siden vi kan bruke disse kommentarene i de fleste Servlet containere uten konfigurasjon, hvorfor trenger vi @ServletComponentScan? Problemet ligger i innebygd Servlet containere.
På grunn av det faktum at innebygde containere ikke støtter @WebServlet, @WebFilter og @WebListener merknader, Vårstøvel, stole sterkt på innebygde containere, introduserte denne nye kommentaren @ServletComponentScan for å støtte noen avhengige krukker som bruker disse 3 kommentarene.
Den detaljerte diskusjonen finner du i denne utgaven på Github.
3.1. Maven avhengigheter
Å bruke @ServletComponentScan, vi trenger Vårstøvel med versjon 1.3.0 eller nyere. La oss legge til den siste versjonen av 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 hjelp av @ServletComponentScan
De Vårstøvel appen er ganske enkel. Vi legger til @ServletComponentScan for å aktivere skanning etter @WebFilter, @WebListener og @WebServlet:
@ServletComponentScan @ SpringBootApplication offentlig klasse SpringBootAnnotatedApp {public static void main (String [] args) {SpringApplication.run (SpringBootAnnotatedApp.class, args); }}
Uten noen endring i forrige webapplikasjon, fungerer det bare:
@Autowired privat TestRestTemplate restTemplate; @Test offentlig ugyldig givenServletFilter_whenGetHello_thenRequestFiltered () {ResponseEntity responseEntity = restTemplate.getForEntity ("/ hallo", String.class); assertEquals (HttpStatus.OK, responseEntity.getStatusCode ()); assertEquals ("filtrering hei", responseEntity.getBody ()); }
@Autowired privat ServletContext servletContext; @Test offentlig ugyldig givenServletContext_whenAccessAttrs_thenFoundAttrsPutInServletListner () {assertNotNull (servletContext); assertNotNull (servletContext.getAttribute ("servlet-context-attr")); assertEquals ("test", servletContext.getAttribute ("servlet-context-attr")); }
3.3. Spesifiser pakker som skal skannes
Som standard, @ServletComponentScan vil skanne fra pakken til den merkede klassen. For å spesifisere hvilke pakker som skal skannes, kan vi bruke attributtene:
- verdi
- basePackages
- basePackageClasses
Standaren verdi attributt er et alias for basePackages.
Si vår SpringBootAnnotatedApp er under pakke com.baeldung.annotation, og vi vil skanne klasser i pakken com.baeldung.annotation.components opprettet i webapplikasjonen ovenfor, er følgende konfigurasjoner ekvivalente:
@ServletComponentScan
@ServletComponentScan ("com.baeldung.annotation.components")
@ServletComponentScan (basePackages = "com.baeldung.annotation.components")
@ServletComponentScan (basePackageClasses = {AttrListener.class, HelloFilter.class, HelloServlet.class})
4. Under hetten
De @ServletComponentScan merknader behandles av ServletComponentRegisteringPostProcessor. Etter skanning av spesifiserte pakker for @WebFilter, @WebListener og @WebServlet merknader, en liste over ServletComponentHandlers vil behandle merkeattributtene og registrere skannede bønner:
klasse ServletComponentRegisteringPostProcessor implementerer BeanFactoryPostProcessor, ApplicationContextAware {private static final List HANDLERS; statisk {List handlers = new 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 offisielle Javadoc, @ServletComponentScan kommentar fungerer bare i innebygd Servlet containere, som er det som følger med Vårstøvel som standard.
5. Konklusjon
I denne artikkelen introduserte vi @ServletComponentScan og hvordan den kan brukes til å støtte applikasjoner som er avhengige av kommentarene: @WebServlet, @WebFilter, @WebListener.
Implementeringen av eksemplene og koden finner du i GitHub-prosjektet.