En introduktion til Spring DispatcherServlet

1. Introduktion

Kort sagt, i Frontcontroller design mønster, en enkelt controller er ansvarlig for at lede indgående HttpForespørgsler til alle applikationens andre controllere og håndterere.

Forårets DispatcherServlet implementerer dette mønster og er derfor ansvarlig for korrekt koordinering af HttpForespørgsler til deres højre håndtering.

I denne artikel vil vi undersøge foråret DispatcherServlet's anmodning om behandling af arbejdsgang og hvordan man implementerer flere af de grænseflader, der deltager i denne arbejdsgang.

2. DispatcherServlet Behandling af anmodning

I det væsentlige er en DispatcherServlet håndterer et indgående HttpForespørgsel, delegerer anmodningen og behandler anmodningen i henhold til den konfigurerede Handler-adapter grænseflader der er blevet implementeret inden foråret-applikationen sammen med ledsagende kommentarer, der specificerer håndterere, controller-slutpunkter og responsobjekter.

Lad os få mere dybtgående om, hvordan en DispatcherServlet behandler en komponent:

  • det WebApplicationContext tilknyttet en DispatcherServlet under nøglen DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE søges efter og stilles til rådighed for alle elementerne i processen
  • Det DispatcherServlet finder alle implementeringer af Handler-adapter interface konfigureret til din afsender ved hjælp af getHandler () - hver fundet og konfigureret implementering håndterer anmodningen via håndtere() gennem resten af ​​processen
  • det LandestandResolver er valgfrit bundet til anmodningen om at aktivere elementer i processen til at løse lokaliteten
  • det ThemeResolver er valgfrit bundet til anmodningen om at lade elementer, såsom visninger, bestemme hvilket tema der skal bruges
  • hvis en MultipartResolver angives, inspiceres anmodningen for MultipartFiles - alle fundne er pakket ind i en MultipartHttpServletRequest til yderligere behandling
  • HandlerExceptionResolver implementeringer erklæret i WebApplicationContext opfanger undtagelser, der smides under behandlingen af ​​anmodningen

Du kan lære mere om alle måder at registrere og oprette en DispatcherServlet her.

3. Handler-adapter Grænseflader

Det Handler-adapter interface letter brugen af ​​controllere, servlets, HttpForespørgslerog HTTP-stier gennem flere specifikke grænseflader. Det Handler-adapter interface spiller således en vigtig rolle gennem de mange faser af DispatcherServlet anmodning om behandling af arbejdsgang.

Først hver Handler-adapter implementering er placeret i HandlerExecutionChain fra din afsender getHandler () metode. Derefter hver af disse implementeringer håndtere() det HttpServletRequest objekt, når udførelseskæden fortsætter.

I de følgende afsnit vil vi udforske et par af de vigtigste og mest anvendte Handleradaptere mere detaljeret.

3.1. Kortlægninger

For at forstå kortlægninger skal vi først se på, hvordan man kommenterer controllere, da controllere er så vigtige for HandlerMapping interface.

Det SimpleControllerHandlerAdapter muliggør implementering af en controller eksplicit uden en @Kontrol kommentar.

Det RequestMappingHandlerAdapter understøtter metoder, der er kommenteret med @RequestMapping kommentar.

Vi fokuserer på @Kontrol kommentar her, men en nyttig ressource med flere eksempler ved hjælp af SimpleControllerHandlerAdapter er også tilgængelig.

Det @RequestMapping annotation indstiller det specifikke slutpunkt, hvor en handler vil være tilgængelig indenfor WebApplicationContext forbundet med det.

Lad os se et eksempel på en Controller der udsætter og håndterer '/ Bruger / eksempel' slutpunkt:

@Controller @RequestMapping ("/ bruger") @ResponseBody offentlig klasse UserController {@GetMapping ("/ eksempel") offentlig bruger fetchUserExample () {// ...}}

De stier, der er angivet af @RequestMapping annotering styres internt via HandlerMapping interface.

URL-strukturen er naturligvis i forhold til DispatcherServlet sig selv - og bestemt af servlet-kortlægningen.

Således, hvis DispatcherServlet er kortlagt til '/', så vil alle kortlægninger blive dækket af denne kortlægning.

Men hvis servlet-kortlægningen er '/ afsender‘I stedet, så enhver @RequestMapping annoteringer vil være i forhold til den rod-URL.

Husk at '/' ikke er det samme som '/ *' til servletkortlægninger! '/' Er standardkortlægningen og udsætter alle webadresser for afsenderens ansvarsområde.

‘/ * 'Er forvirrende for mange nyere Spring-udviklere. Det specificerer ikke, at alle stier med samme URL-kontekst er under afsenderens ansvarsområde. I stedet tilsidesætter den og ignorerer de andre afsendertilknytninger. Så, '/ eksempel' vil komme op som en 404!

Af den grund, ‘/ * 'Bør ikke bruges undtagen i meget begrænsede omstændigheder (som at konfigurere et filter).

3.2. HTTP-anmodningshåndtering

Det centrale ansvar for en DispatcherServlet er at sende indgående HttpForespørgsler til de korrekte håndtere specificeret med @Kontrol eller @RestController kommentarer.

Som en sidebemærkning er den største forskel mellem @Kontrol og @RestController er, hvordan svaret genereres - @RestController definerer også @ResponseBody som standard.

En opskrivning, hvor vi går i langt større dybde med hensyn til Spring's controllere, kan findes her.

3.3. Det ViewResolver Interface

EN ViewResolver er knyttet til en DispatcherServlet som en konfigurationsindstilling på en ApplicationContext objekt.

EN ViewResolver bestemmer både hvilken type synspunkter, der sendes af afsenderen, og hvorfra de serveres.

Her er et eksempel på en konfiguration, som vi placerer i vores AppConfig til gengivelse af JSP-sider:

@Configuration @EnableWebMvc @ComponentScan ("com.baeldung.springdispatcherservlet") offentlig klasse AppConfig implementerer WebMvcConfigurer {@Bean public UrlBasedViewResolver viewResolver () {UrlBasedViewResolver resolver = new UrlBas resolver.setPrefix ("/ WEB-INF / visning /"); resolver.setSuffix (". jsp"); resolver.setViewClass (JstlView.class); returopløsning; }}

Meget ligetil! Der er tre hoveddele til dette:

  1. indstilling af præfikset, som indstiller standard-URL-stien til at finde de indstillede visninger inden for
  2. standardvisningstypen, der indstilles via suffikset
  3. indstilling af en visningsklasse på opløseren, der gør det muligt at tilknytte teknologier som JSTL eller Tiles til de gengivne visninger

Et almindeligt spørgsmål involverer, hvor nøjagtigt en afsender er ViewResolverog den overordnede projektmappestruktur er relateret. Lad os se på det grundlæggende.

Her er et eksempel på stykonfiguration for en InternalViewResolver ved hjælp af Spring's XML-konfiguration:

Af hensyn til vores eksempel antager vi, at vores applikation hostes den:

// localhost: 8080 /

Dette er standardadressen og porten til en lokalt hostet Apache Tomcat-server.

Forudsat at vores ansøgning kaldes forsendelseseksempel-1.0.0, vores JSP-synspunkter vil være tilgængelige fra:

//localhost:8080/dispatcherexample-1.0.0/jsp/

Vejen til disse synspunkter inden for et almindeligt forårsprojekt med Maven er denne:

src - | vigtigste - | Java ressourcer webapp - | jsp WEB-INF

Standardplaceringen for visninger er inden for WEB-INF. Den vej, der er angivet for vores InternalViewResolver i uddraget ovenfor bestemmer underkatalogen til 'src / main / webapp', hvor dine synspunkter vil være tilgængelige.

3.4. Det LandestandResolver Interface

Den primære måde at tilpasse session-, anmodnings- eller cookieoplysninger til vores afsender på er via LandestandResolver interface.

CookieLocaleResolver er en implementering, der tillader konfiguration af statsløse applikationsegenskaber ved hjælp af cookies. Lad os tilføje det til AppConfig.

@Bean offentlig CookieLocaleResolver cookieLocaleResolverExample () {CookieLocaleResolver localeResolver = ny CookieLocaleResolver (); localeResolver.setDefaultLocale (Locale.ENGLISH); localeResolver.setCookieName ("eksempel på locale-cookie-resolver"); localeResolver.setCookieMaxAge (3600); return localeResolver; } @Bean offentlig LocaleResolver sessionLocaleResolver () {SessionLocaleResolver localeResolver = ny SessionLocaleResolver (); localeResolver.setDefaultLocale (Locale.US); localResolver.setDefaultTimeZone (TimeZone.getTimeZone ("UTC")); return localeResolver; } 

SessionLocaleResolver muliggør session-specifik konfiguration i en stateful applikation.

Det setDefaultLocale() metode repræsenterer en geografisk, politisk eller kulturel region, hvorimod setDefaultTimeZone() bestemmer det relevante Tidszone objekt til applikationen Bønne i spørgsmålet.

Begge metoder er tilgængelige på hver af ovenstående implementeringer af LandestandResolver.

3.5. Det ThemeResolver Interface

Spring giver stilistisk tema til vores synspunkter.

Lad os se på, hvordan vi konfigurerer vores afsender til at håndtere temaer.

Først, lad os opsætte al den nødvendige konfiguration til at finde og bruge vores statiske temafiler. Vi er nødt til at indstille en statisk ressourceplacering til vores ThemeSource for at konfigurere den aktuelle Temaer dem selv (Tema objekter indeholder alle de konfigurationsoplysninger, der er angivet i disse filer). Føj dette til AppConfig:

@Override public void addResourceHandlers (ResourceHandlerRegistry registry) {registry.addResourceHandler ("/ resources / **") .addResourceLocations ("/", "/ resources /") .setCachePeriod (3600) .resourceChain (true) .addResolver (new PathResourceResolver ()); } @Bean public ResourceBundleThemeSource themeSource () {ResourceBundleThemeSource themeSource = ny ResourceBundleThemeSource (); themeSource.setDefaultEncoding ("UTF-8"); themeSource.setBasenamePrefix ("temaer."); returner themeSource; } 

Anmodninger administreret af DispatcherServlet kan ændre temaet gennem en specificeret parameter, der sendes til setParamName() tilgængelig på ThemeChangeInterceptor objekt. Tilføj til AppConfig:

@Bean offentlig CookieThemeResolver themeResolver () {CookieThemeResolver resolver = ny CookieThemeResolver (); resolver.setDefaultThemeName ("eksempel"); resolver.setCookieName ("eksempel-tema-cookie"); returopløsning; } @Bean offentlig ThemeChangeInterceptor themeChangeInterceptor () {ThemeChangeInterceptor interceptor = ny ThemeChangeInterceptor (); interceptor.setParamName ("tema"); tilbagevenden interceptor } @ Override public void addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (themeChangeInterceptor ()); } 

Følgende JSP-tag tilføjes vores synspunkt for at få den korrekte styling til at vises:

Følgende URL-anmodning gengiver eksempel tema ved hjælp af 'tema'-parameteren sendt til vores konfigurerede ThemeChangeIntercepter:

//localhost:8080/dispatcherexample-1.0.0/?theme=example

3.6. Det MultipartResolver Interface

EN MultipartResolver implementering inspicerer en anmodning om multiparts og indpakker dem i en MultipartHttpServletRequest til yderligere behandling af andre elementer i processen, hvis der findes mindst en multipart. Tilføj til AppConfig:

@Bean public CommonsMultipartResolver multipartResolver () kaster IOException {CommonsMultipartResolver resolver = ny CommonsMultipartResolver (); resolver.setMaxUploadSize (10000000); returopløsning; } 

Nu hvor vi har konfigureret vores MultipartResolver bønne, lad os oprette en controller, der skal behandles MultipartFile anmodninger:

@Controller offentlig klasse MultipartController {@Autowired ServletContext context; @PostMapping ("/ upload") offentlig ModelAndView FileuploadController (@RequestParam ("fil") MultipartFile-fil) kaster IOException {ModelAndView modelAndView = ny ModelAndView ("indeks"); InputStream in = file.getInputStream (); Strengsti = ny fil ("."). GetAbsolutePath (); FileOutputStream f = ny FileOutputStream (path.substring (0, path.length () - 1) + "/ uploads /" + file.getOriginalFilename ()); int ch; mens ((ch = in.read ())! = -1) {f.write (ch); } f.flush (); f.close (); i. luk (); modelAndView.getModel () .put ("besked", "Fil uploadet med succes!"); returner modelAndView; }}

Vi kan bruge en normal form til at indsende en fil til det angivne slutpunkt. Uploadede filer vil være tilgængelige i 'CATALINA_HOME / bin / uploads'.

3.7. Det HandlerExceptionResolver Interface

Forårets HandlerExceptionResolver giver ensartet fejlhåndtering for en hel webapplikation, en enkelt controller eller et sæt controllere.

For at give applikationsomfattende brugerdefineret håndtering af undtagelser skal du oprette en klasse, der er kommenteret med @ControllerAdvice:

@ControllerAdvice public class EksempelGlobalExceptionHandler {@ExceptionHandler @ResponseBody public String handleExampleException (Exception e) {// ...}}

Alle metoder inden for den klasse, der er kommenteret med @ExceptionHandler vil være tilgængelig på enhver controller inden for afsenderens ansvarsområde.

Implementeringer af HandlerExceptionResolver interface i DispatcherServlets ApplicationContext er tilgængelige for aflytte en bestemt controller under denne afsenders ansvarsområde hver gang @ExceptionHandler bruges som en kommentar, og den korrekte klasse sendes ind som parameter:

@Controller offentlig klasse FooController {@ExceptionHandler ({CustomException1.class, CustomException2.class}) offentlig ugyldig handleException () {// ...} // ...}

Det handleException () metode vil nu fungere som en undtagelsesbehandler for FooController i vores eksempel ovenfor, hvis begge undtagelser CustomException1 eller CustomException2 opstår.

Her er en artikel, der går mere i dybden med undtagelseshåndtering i en Spring-webapplikation.

4. Konklusion

I denne vejledning har vi gennemgået forårets DispatcherServlet og flere måder at konfigurere det på.

Som altid er kildekoden, der bruges i denne vejledning, tilgængelig på Github.


$config[zx-auto] not found$config[zx-overlay] not found