Tavaszi webes összefüggések

1. Bemutatkozás

Amikor a Spring webalkalmazásban használjuk, számos lehetőségünk van az alkalmazás kontextusainak rendezésére, amelyek mindent összekötnek.

Ebben a cikkben elemezzük és elmagyarázzuk a Spring által kínált leggyakoribb lehetőségeket.

2. A gyökér webalkalmazás kontextusa

Minden tavaszi webalkalmazáshoz társított alkalmazáskörnyezet kapcsolódik az életciklusához: a gyökér webalkalmazás-kontextushoz.

Ez egy régi szolgáltatás, amely a Spring Web MVC-t megelőzte, ezért nincs kifejezetten egyetlen web-keretrendszerhez kötve.

A kontextus akkor indul el, amikor az alkalmazás elindul, és megsemmisül, amikor leáll, köszönhetően egy szervlet kontextusfigyelőnek. A leggyakoribb összefüggéstípusok futás közben is frissíthetők, bár nem minden ApplicationContext a megvalósítások rendelkeznek ezzel a képességgel.

A webalkalmazás kontextusa mindig a WebApplicationContext. Ez egy kiterjesztő felület ApplicationContext szerződéssel a ServletContext.

Egyébként az alkalmazásoknak általában nem kell aggódniuk a megvalósítás részletei miatt: a root webalkalmazás kontextus egyszerűen központosított hely a megosztott bab meghatározására.

2.1. A ContextLoaderListener

Az előző szakaszban leírt root webalkalmazás-környezetet az osztály hallgatója kezeli org.springframework.web.context.ContextLoaderListener, amely része a tavasz-háló modul.

Alapértelmezés szerint a hallgató egy XML alkalmazáskörnyezetet tölt be innen /WEB-INF/applicationContext.xml. Ezek az alapértelmezések azonban megváltoztathatók. Használhatunk Java megjegyzéseket például XML helyett.

Konfigurálhatjuk ezt a hallgatót akár a webapp leíróban (web.xml fájl), vagy programozottan a Servlet 3.x környezetben.

A következő szakaszokban ezeket a lehetőségeket részletesen megvizsgáljuk.

2.2. Használata web.xml és egy XML alkalmazás kontextus

Használat során web.xml, a szokásos módon konfiguráljuk a hallgatót:

  org.springframework.web.context.ContextLoaderListener 

Megadhatjuk az XML kontextus konfigurációjának alternatív helyét a contextConfigLocation paraméter:

 contextConfigLocation /WEB-INF/rootApplicationContext.xml 

Vagy egynél több helyet vesszővel elválasztva:

 contextConfigLocation /WEB-INF/context1.xml, /WEB-INF/context2.xml 

Még mintákat is használhatunk:

 contextConfigLocation /WEB-INF/*-context.xml 

Mindenesetre, csak egy kontextus van meghatározva, a megadott helyekről betöltött összes babdefiníció kombinálásával.

2.3. Használata web.xml és Java alkalmazás kontextus

Az alapértelmezett XML-alapú mellett más típusú kontextusokat is megadhatunk. Lássuk például, hogyan lehet helyette használni a Java kommentárok konfigurációját.

Használjuk a contextClass paraméter, amely megmondja a hallgatónak, hogy milyen típusú kontextust kell példázni:

 contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext 

Minden kontextustípusnak lehet alapértelmezett konfigurációs helye. Esetünkben a AnnotationConfigWebApplicationContext nincs, ezért biztosítanunk kell.

Így felsorolhatunk egy vagy több jegyzetelt osztályt:

 contextConfigLocation com.baeldung.contexts.config.RootApplicationConfig, com.baeldung.contexts.config.NormalWebAppConfig 

Vagy meg tudjuk mondani a kontextust, hogy egy vagy több csomagot vizsgáljon:

 contextConfigLocation com.baeldung.bean.config 

És természetesen keverhetjük a két lehetőséget.

2.4. Programozási konfiguráció a Servlet 3.x

A Servlet API 3. verziója konfigurálta a web.xml fájl teljesen opcionális. A könyvtárak biztosíthatják az internetes töredékeiket, amelyek az XML-konfiguráció darabjai, amelyek regisztrálhatják a hallgatók, szűrők, szervletek és így tovább.

Ezenkívül a felhasználók hozzáférhetnek egy API-hoz, amely lehetővé teszi a szervlet-alapú alkalmazás minden elemének programozott meghatározását.

A tavasz-háló modul használja ezeket a szolgáltatásokat, és felajánlja API-ját az alkalmazás összetevőinek regisztrálásához, amikor elindul.

Spring megvizsgálja az alkalmazás osztályútvonalát a org.springframework.web.WebApplicationInitializer osztály. Ez egy interfész egyetlen módszerrel, void onStartup (ServletContext servletContext) dobja a ServletException-t, erre hivatkoznak az alkalmazás indításakor.

Most nézzük meg, hogyan használhatjuk ezt a lehetőséget arra, hogy ugyanolyan típusú root webalkalmazás-kontextusokat hozzunk létre, mint korábban láttuk.

2.5. A Servlet 3.x és az XML alkalmazás kontextusának használata

Kezdjük egy XML kontextussal, csakúgy, mint a 2.2 szakaszban.

A fentieket megvalósítjuk Indításkor módszer:

public class ApplicationInitializer megvalósítja a WebApplicationInitializer {@Override public void onStartup (ServletContext servletContext) dobja a ServletException {// ...}}

Bontjuk soronként a megvalósítást.

Először létrehozunk egy gyökérkörnyezetet. Mivel XML-t akarunk használni, annak XML-alapú alkalmazáskontextusnak kell lennie, és mivel webes környezetben vagyunk, meg kell valósítania WebApplicationContext is.

Az első sor tehát a contextClass paraméter, amellyel korábban találkoztunk, és amellyel eldönthetjük, hogy melyik kontextus megvalósítást használjuk:

XmlWebApplicationContext rootContext = új XmlWebApplicationContext ();

Ezután a második sorban elmondjuk a kontextust, ahonnan töltsük be a babdefinícióit. Újra, setConfigLocations a programozott analógja contextConfigLocation paraméter be web.xml:

rootContext.setConfigLocations ("/ WEB-INF / rootApplicationContext.xml");

Végül létrehozunk egy ContextLoaderListener a root kontextussal, és regisztrálja a servlet tárolóban. Ahogy látjuk, ContextLoaderListener megfelelő konstruktorral rendelkezik, amely a WebApplicationContext és elérhetővé teszi az alkalmazás számára:

servletContext.addListener (új ContextLoaderListener (rootContext));

2.6. A Servlet 3.x és a Java alkalmazás kontextusának használata

Ha annotáció-alapú kontextust akarunk használni, akkor az előző szakasz kódrészletét megváltoztathatjuk, hogy az AnnotationConfigWebApplicationContext helyette.

Lássunk azonban egy speciálisabb megközelítést ugyanazon eredmény eléréséhez.

A WebApplicationInitializer osztály, amelyet korábban láthattunk, egy általános célú felület. Kiderült, hogy Spring néhány konkrétabb megvalósítást nyújt, köztük egy absztrakt osztályt AbstractContextLoaderInitializer.

Feladata, amint a neve is mutatja, a ContextLoaderListener és regisztrálja a szervletet tartalmazó tartályban.

Csak azt kell elmondanunk neki, hogyan építsük fel a gyökérkörnyezetet:

public class AnnotationsBasedApplicationInitializer kiterjeszti az AbstractContextLoaderInitializer {@Orride védett WebApplicationContext createRootApplicationContext () {AnnotationConfigWebApplicationContext rootContext = új AnnotationConfigWebApplicationContext (); rootContext.register (RootApplicationConfig.class); return rootContext; }}

Itt láthatjuk, hogy már nem kell regisztrálnunk a ContextLoaderListener, ami megment minket egy kis kazán kódtól.

Vegye figyelembe a Regisztráció módszer, amely specifikus AnnotationConfigWebApplicationContext az általánosabb helyett setConfigLocations: annak meghívásával regisztrálhatunk egyént @ Konfiguráció jegyzetelt osztályokat a kontextussal, elkerülve ezzel a csomagok beolvasását.

3. Dispatcher Servlet-összefüggések

Most koncentráljunk egy másik típusú alkalmazáskörnyezetre. Ezúttal egy olyan funkcióra fogunk hivatkozni, amely a Spring MVC-re jellemző, és nem a Spring általános webalkalmazás-támogatásának része.

A tavaszi MVC alkalmazásokban legalább egy Dispatcher Servlet van konfigurálva (de lehet, hogy több is, erről később beszélünk). Ez az a kiszolgáló kisalkalmazás, amely fogadja a beérkező kéréseket, azokat a megfelelő vezérlő módszerhez továbbítja, és visszaadja a nézetet.

Minden egyes DispatcherServlet társított alkalmazáskörnyezettel rendelkezik. Az ilyen összefüggésekben definiált bab konfigurálja a szervletet, és meghatározza az MVC objektumokat, például a vezérlőket és a nézetfeloldókat.

Lássuk, hogyan állítsuk be először a szervlet kontextusát. Később megnézünk néhány részletes részletet.

3.1. Használata web.xml és egy XML alkalmazás kontextus

DispatcherServlet tipikusan a web.xml névvel és feltérképezéssel:

 normal-webapp org.springframework.web.servlet.DispatcherServlet 1 normal-webapp / api / * 

Ha másként nincs meghatározva, akkor a szervlet nevét használja a betöltendő XML fájl meghatározásához. Példánkban a fájlt fogjuk használni WEB-INF / normal-webapp-servlet.xml.

Megadhatunk egy vagy több elérési utat is az XML fájlokhoz, a hasonló módon ContextLoaderListener:

 ... contextConfigLocation /WEB-INF/normal/*.xml 

3.2. Használata web.xml és Java alkalmazás kontextus

Amikor egy másik típusú kontextust akarunk használni, úgy járunk el, mint amilyen ContextLoaderListener, újra. Vagyis megadjuk a contextClass paraméter mellett egy megfelelő contextConfigLocation:

 normal-webapp-annotations org.springframework.web.servlet.DispatcherServlet contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext contextConfigLocation com.baeldung.contexts.config.NormalWebApp 

3.3. A Servlet 3.x és az XML alkalmazás kontextusának használata

Ismét két különböző módszert vizsgálunk meg az a programozott deklarálására DispatcherServlet, és az egyiket XML-kontextusra, a másikat Java-kontextusra alkalmazzuk.

Tehát kezdjük egy általános WebApplicationInitializer és egy XML alkalmazás kontextus.

Mint korábban láthattuk, meg kell valósítanunk a Indításkor módszer. Ezúttal azonban létrehozunk és regisztrálunk egy diszpécser szervletet is:

XmlWebApplicationContext normalWebAppContext = új XmlWebApplicationContext (); normalWebAppContext.setConfigLocation ("/ WEB-INF / normal-webapp-servlet.xml"); ServletRegistration.Dynamic normal = servletContext.addServlet ("normal-webapp", új DispatcherServlet (normalWebAppContext)); normal.setLoadOnStartup (1); normal.addMapping ("/ api / *");

Könnyen párhuzamot vonhatunk a fenti kód és az azzal egyenértékű között web.xml konfigurációs elemek.

3.4. A Servlet 3.x és a Java alkalmazás kontextusának használata

Ezúttal egy kommentár-alapú kontextust konfigurálunk a WebApplicationInitializer: AbstractDispatcherServletInitializer.

Ez egy absztrakt osztály, amely a gyökér webalkalmazás-kontextus létrehozása mellett, amint azt korábban láttuk, lehetővé teszi számunkra, hogy regisztráljunk egy diszpécser szervletet a minimális kazánlemezzel:

@Orride védett WebApplicationContext createServletApplicationContext () {AnnotationConfigWebApplicationContext secureWebAppContext = új AnnotationConfigWebApplicationContext (); secureWebAppContext.register (SecureWebAppConfig.class); return secureWebAppContext; } @Orride védett karakterlánc [] getServletMappings () {return new string [] {"/ s / api / *"}; }

Itt láthatunk egy módszert a szervlethez társított kontextus létrehozására, pontosan úgy, ahogy a gyökér kontextusnál korábban láttuk. Ezenkívül van egy módszerünk a szervlet leképezésének megadására, amint az web.xml.

4. Szülői és gyermeki összefüggések

Eddig két fő kontextustípust láttunk: a gyökér webalkalmazás kontextust és a diszpécser kiszolgáló kontextust. Ezután kérdésünk lehet: ezek az összefüggések összefüggenek?

Kiderült, hogy igen, vannak. Valójában, a root kontextus minden diszpécser szervlet kontextus szülője. Így a gyökér webalkalmazás környezetében definiált babok láthatók minden diszpécser szervlet kontextusában, de nem fordítva.

Tehát általában a gyökérkörnyezetet használják a szolgáltatási bab meghatározására, míg a diszpécseri környezet azokat a babokat tartalmazza, amelyek kifejezetten az MVC-hez kapcsolódnak.

Ne feledje, hogy a diszpécser kiszolgáló kontextusának programozott létrehozására is volt módunk. Ha kézzel állítjuk be a szülőjét, akkor a Spring nem írja felül a döntésünket, és ez a szakasz már nem érvényes.

Az egyszerűbb MVC alkalmazásokban elegendő egyetlen kontextust társítani az egyetlen diszpécser kiszolgálóhoz. Nincs szükség túl összetett megoldásokra!

Ennek ellenére a szülő-gyermek kapcsolat akkor válik hasznossá, ha több diszpécser kiszolgáló konfigurálva van. De mikor kell zavarnunk, hogy több is legyen?

Általánosságban, több diszpécser szervletet deklarálunk amikor többféle MVC konfigurációra van szükségünk. Például rendelkezhetünk REST API-val egy hagyományos MVC alkalmazás mellett, vagy egy webhely nem biztonságos és biztonságos szakaszával:

Megjegyzés: amikor meghosszabbítjuk AbstractDispatcherServletInitializer (lásd a 3.4. szakaszt), regisztrálunk egy gyökér webes alkalmazás kontextust és egy diszpécser szervletet is.

Tehát, ha egynél több szervletre van szükségünk, akkor többre van szükségünk AbstractDispatcherServletInitializer megvalósítások. Azonban csak egy gyökérkörnyezetet határozhatunk meg, különben az alkalmazás nem indul el.

Szerencsére a createRootApplicationContext módszer visszatérhet nulla. Így van egy AbstractContextLoaderInitializer és sok AbstractDispatcherServletInitializer megvalósítások, amelyek nem hoznak létre gyökérkörnyezetet. Ilyen esetekben célszerű az inicializálókat megrendelni @Rendelés kifejezetten.

Ezt is vegye figyelembe AbstractDispatcherServletInitializer a szervletet egy adott név alatt regisztrálja (diszpécser), és természetesen nem lehet több azonos nevű szervlet. Tehát felül kell írnunk getServletName:

@Védje felül a védett karakterláncot getServletName () {return "egy másik-diszpécser"; }

5. A Szülő és gyermek kontextus Példa

Tegyük fel, hogy két alkalmazási területünk van, például egy nyilvános, világszerte hozzáférhető és biztonságos, különböző MVC konfigurációkkal. Itt csak két vezérlőt határozunk meg, amelyek eltérő üzenetet adnak ki.

Tegyük fel továbbá, hogy a vezérlők egy részének jelentős erőforrásokkal rendelkező szolgáltatásra van szüksége; mindenütt előforduló eset a kitartás. Ezután csak egyszer szeretnénk példányosítani ezt a szolgáltatást, elkerülve az erőforrások megduplázódását, és mert hiszünk a Ne ismételje meg magát elvében!

Most folytassuk a példával.

5.1. A megosztott szolgáltatás

Helló világpéldánkban a kitartás helyett egy egyszerűbb üdvözlő szolgáltatásra kötöttünk ki:

com.baeldung.contexts.services csomag; @Service public class GreeterService {@Resource private Greeting greeting; public String greet () {return greeting.getMessage (); }}

A szolgáltatást a gyökéralkalmazás-környezetben deklaráljuk, az összetevők vizsgálatával:

@Configuration @ComponentScan (basePackages = {"com.baeldung.contexts.services"}) nyilvános osztály RootApplicationConfig {// ...}

Lehet, hogy inkább az XML-t részesítjük előnyben:

5.2. A vezérlők

Határozzunk meg két egyszerű vezérlőt, amelyek használják a szolgáltatást és üdvözletet adnak ki:

csomag com.baeldung.contexts.normal; @Controller public class HelloWorldController {@Autowired private GreeterService greeterService; @RequestMapping (elérési út = "/ welcome") nyilvános ModelAndView helloWorld () {String message = "

Normál "+ greeterService.greet () +"

"; return new ModelAndView (" welcome "," message ", message);}} //" Secure "vezérlőcsomag com.baeldung.contexts.secure; String message ="

Biztonságos "+ greeterService.greet () +"

";

Mint láthatjuk, a vezérlők két különböző csomagban fekszenek, és különböző üzeneteket nyomtatnak: az egyik „normális”, a másik „biztonságos”.

5.3. A diszpécser kiszolgáló kontextusai

Mint korábban mondtuk, két különböző diszpécser szervlet kontextusunk lesz, mindegyik vezérlőhöz egy. Tehát definiáljuk őket Java-ban:

// Normál kontextus @Configuration @EnableWebMvc @ComponentScan (basePackages = {"com.baeldung.contexts.normal"}) nyilvános osztály NormalWebAppConfig hajtja végre a WebMvcConfigurer {// ...} // "Secure" környezet @Configuration @EnableWebMvc @ basePackages = {"com.baeldung.contexts.secure"}) nyilvános osztály SecureWebAppConfig valósítja meg a WebMvcConfigurer {// ...}

Vagy ha úgy tetszik, XML-ben:

5.4. Összedobva az egészet

Most, hogy minden darab megvan, csak azt kell mondanunk Springnek, hogy kösse össze őket. Ne feledje, hogy be kell töltenünk a gyökérkörnyezetet, és meg kell határoznunk a két diszpécser kiszolgálót. Bár ennek többféle módját láttuk, most két forgatókönyvre fogunk összpontosítani, egy Java-ra és egy XML-re. Kezdjük a Java-val.

Meghatározzuk a AbstractContextLoaderInitializer a gyökérkörnyezet betöltéséhez:

@Orride védett WebApplicationContext createRootApplicationContext () {AnnotationConfigWebApplicationContext rootContext = új AnnotationConfigWebApplicationContext (); rootContext.register (RootApplicationConfig.class); return rootContext; } 

Ezután létre kell hoznunk a két szervletet, így két alosztályt definiálunk AbstractDispatcherServletInitializer. Először a „normális”:

@Orride védett WebApplicationContext createServletApplicationContext () {AnnotationConfigWebApplicationContext normalWebAppContext = új AnnotationConfigWebApplicationContext (); normalWebAppContext.register (NormalWebAppConfig.class); return normalWebAppContext; } @Orride védett karakterlánc [] getServletMappings () {return new String [] {"/ api / *"}; } @Orride védett karakterlánc getServletName () {return "normál-diszpécser"; } 

Ezután a „biztonságos”, amely más kontextust tölt be és más útra van leképezve:

@Orride védett WebApplicationContext createServletApplicationContext () {AnnotationConfigWebApplicationContext secureWebAppContext = új AnnotationConfigWebApplicationContext (); secureWebAppContext.register (SecureWebAppConfig.class); return secureWebAppContext; } @Orride védett karakterlánc [] getServletMappings () {return new string [] {"/ s / api / *"}; } @Orride védett karakterlánc getServletName () {return "biztonságos-diszpécser"; }

És készen vagyunk! Éppen azt alkalmaztuk, amit az előző szakaszokban érintettünk.

Ezzel is megtehetjük web.xml, ismét csak az eddig tárgyalt darabok ötvözésével.

Adja meg a gyökéralkalmazás környezetét:

  org.springframework.web.context.ContextLoaderListener 

„Normál” diszpécseri kontextus:

 normal-webapp org.springframework.web.servlet.DispatcherServlet 1 normal-webapp / api / * 

És végül egy „biztonságos” kontextus:

 secure-webapp org.springframework.web.servlet.DispatcherServlet 1 biztonságos-webapp / s / api / * 

6. Több összefüggés kombinálása

A szülő-gyermek kivételével többféle konfigurációs hely kombinálható, a nagy összefüggések szétválasztása és a különböző aggályok jobb elkülönítése. Láttunk már egy példát: amikor meghatározzuk contextConfigLocation több elérési útvonallal vagy csomaggal a Spring egyetlen kontextust épít fel az összes babdefiníció kombinálásával, mintha sorrendben egyetlen XML fájlba vagy Java osztályba íródtak volna.

Ugyanakkor más eszközökkel is hasonló hatást érhetünk el, sőt különböző megközelítéseket is alkalmazhatunk együtt. Vizsgáljuk meg lehetőségeinket.

Az egyik lehetőség az alkatrész-szkennelés, amelyet egy másik cikkben fejtünk ki.

6.1. Környezet importálása egy másikba

Alternatív megoldásként megadhatunk egy kontextusdefiníciót egy másik importálására. A forgatókönyvtől függően különböző típusú importjaink vannak.

Importálás a @ Konfiguráció osztály Java nyelven:

@Configuration @Import (SomeOtherConfiguration.class) public class Config {...}

Más típusú erőforrás, például egy XML-környezet definíció betöltése Java-ba:

@Configuration @ImportResource ("classpath: basicConfigForPropertiesTwo.xml") public class Config {...}

Végül, egy XML fájlt is beillesztve egy másikba:

Így sokféleképpen szervezhetjük azokat a szolgáltatásokat, összetevőket, vezérlőket stb., Amelyek együttműködnek a félelmetes alkalmazásunk létrehozásában. És az a szép, hogy az IDE-k megértik mindet!

7. Tavaszi indító webalkalmazások

A Spring Boot automatikusan konfigurálja az alkalmazás összetevőit, így általában kevésbé kell gondolkodni azon, hogyan lehet őket megszervezni.

Ennek ellenére a motorháztető alatt a Boot a Spring funkciókat használja, beleértve azokat is, amelyeket eddig láttunk. Lássunk pár figyelemre méltó különbséget.

A beágyazott tárolóban futó Spring Boot webalkalmazások nem futnak WebApplicationInitializer terv szerint.

Szükség esetén ugyanezt a logikát írhatjuk az a-ba SpringBootServletInitializer vagy a ServletContextInitializer ehelyett, a választott telepítési stratégiától függően.

Azonban a kiszolgálóalkalmazások, szűrők és hallgatók hozzáadásához, amint ez a cikk látható, nem szükséges ezt megtenni. Valójában a Spring Boot automatikusan regisztrálja az összes servlethez kapcsolódó babot a tárolóba:

@Bean nyilvános Servlet myServlet () {...}

Az így definiált objektumokat a szokások szerint hozzárendelik: a szűrőket automatikusan hozzárendelik a / *, azaz minden kéréshez. Ha egyetlen szervletet regisztrálunk, akkor az a / -hez van hozzárendelve, ellenkező esetben minden egyes servlet a bab-nevéhez tartozik.

Ha a fenti konvenciók nem működnek nálunk, definiálhatunk a FilterRegistrationBean, ServletRegistrationBean, vagy ServletListenerRegistrationBean helyette. Ezek az osztályok lehetővé teszik számunkra a regisztráció finom szempontjainak ellenőrzését.

8. Következtetések

Ebben a cikkben részletesen áttekintettük a tavaszi webalkalmazás strukturálásához és rendszerezéséhez rendelkezésre álló különféle lehetőségeket.

Kihagytunk néhány funkciót, nevezetesen a vállalati alkalmazások közös kontextusának támogatását, amely az írás idején még hiányzik az 5. tavaszból.

Mindezen példák és kódrészletek megvalósítása megtalálható a GitHub projektben.