Itt jársz most: Kezdőlap > Alkalmazásfejlesztés > Spring XML konfiguráció cseréje Java alapúra

Szűrő megjelenítése

Spring XML konfiguráció cseréje Java alapúra

A Spring XML alapú konfigurálhatósága a mai napig egy teljesen jól használható megoldás. Rengeteg leírás lelhető fel róla, sőt egészen úgy tűnik, mintha ezt preferálnák mind a Spring készítői, mind a fejlesztők. Azonban a Java/annotáció alapú konfigurációnak megvan az a nagy előnye, hogy az alkalmazás forráskódja konzisztensen tartható az XML konfigurációs fájlok (közel) teljes eliminálásával. Nem mellesleg Java fejlesztőként – személyes véleményem szerint – hálásabb feladat Java, mint XML kódot írni.

Mielőtt belevágnánk, fontos megjegyzés: a cikk végén levő link egy GitHub repository linkje, melyen megtalálható a példaalkalmazás teljes forrása. A master branch-en „ömlesztve” látható a kettő, a „config-xml” illetve „config-java” branch-ekre váltva azonban külön-külön is megtekinthetőek.

A konfiguráció cseréjét többféle megközelítésből is elkezdhetjük. Lehet részleges is, webes alkalmazás esetén meghagyhatjuk például a WAR alkalmazás csomagok által igényelt web.xml servlet inicializáló állományt, azonban a konzisztencia (és a cikkemben leírt példa összetettségének növelése) érdekében teljes csere végrehajtását fogom bemutatni. Alább látható az eredeti (XML alapú) alkalmazáskonfiguráció valamint a servlet inicializáló (web.xml) állomány tartalma. A továbbiakban minden fontosabb szekció részletesen tárgyalásra – és cserére – kerül majd.

XML konfiguráció

Az appcontext-config.xml állomány tartalmazza az alkalmazás alap-kontextus konfigurációját. Mivel nagyon pici az alkalmazás, most gyakorlatilag ez üres, de alapvetően ide (is) bean definíciók fognak kerülni.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context-4.2.xsd">
</beans>

A dispatcher-config.xml állomány már sokkal fontosabb szereppel bír, gyakorlatilag az összes MVC beállítást ő kell, hogy tartalmazza.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/mvc 
	http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
 
	<!-- (1) -->
	<context:component-scan base-package="hu.psprog.dev.tutorial.web.controller" />
 
	<!-- (2) -->
	<mvc:annotation-driven />
 
	<!-- (3) -->
	<bean id="defaultViewResolver" 
			class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/view/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
</beans>

Az (1)-es paraméterrel adható meg az MVC controllerek helye. A Spring 3-as verziója előtt azokat is manuálisan kellett bean-ként létrehozni, szerencsére az újabb verziókban – még XML konfiguráció használata mellett is – használhatóak a @Controller annotációk az MVC controllerek megjelölésére.

A (2)-es paraméter engedélyezi az annotációk használatát – az (1)-es ponttal együtt használandók.

A (3)-as paraméter a nézet feloldását végrehajtó bean definíciója. Mivel most a példa kedvéért egyszerű JSP nézeteket használunk, az InternalResourceViewResolver osztályból példányosított bean-t használunk a feladatra. A prefix és szuffix paraméterek közé lesz beszúrva a tényleges nézetnév.

A legnagyobb feladat azonban a web.xml állományra hárul. Ezen konfigurációs fájl feladata a servlet elindítása és a kontextus felépítése. A web.xml Java EE standard konfigurációs fájl, bármilyen Java EE alkalmazást írunk, erre szükség lesz a servlet indításához (kivéve inicializáló használatával, de erről később).

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
		http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
	
	<!-- (1) -->
	<servlet>
		<servlet-name>mvc-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:config/dispatcher-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<!-- (2) -->
	<servlet-mapping>
		<servlet-name>mvc-dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- (3)-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:config/appcontext-config.xml</param-value>
	</context-param>
	
	<!-- (4) -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
 
	<!-- (5) -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	
	<!-- (6) -->
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

Az (1)-es szekció feladata a dispatcher létrehozása és konfigurálása. A dispatcher fogja elcsípni a HTTP kéréseket, és továbbítani a megfelelő feldolgozók felé. A konfigurációját a dispatcher-config.xml állományból fogja gyűjteni, illetve a load-on-startup értékkel megadható, milyen prioritással induljon el a servlet a konténerbe való telepítés után.

A (2)-es szekció feladata csupán annyi, hogy a dispatcher hatáskörének gyökerét állítja be. Ez jelenleg „/”, tehát minden kérésre ez a servlet fog reagálni.

A (3)-as szekcióban levő paraméter neve kötelezően az itt látható, mivel ő adja meg a dispatcher számára az alkalmazás alap-konfigurációs állományát – ami jelen esetben az appcontext-config.xml.

A (4)-es szekcióban létrehozott ContextLoaderListener példány fogja végül ténylegesen felépíteni a kontextust, így ez is nagyon fontos elem.

Az (5)-ös és (6)-os szekciók opcionálisak, bár szinte biztosan szükség lesz rájuk: a karakterkódolás beállítása a feladatuk. Jelen esetben UTF-8 használatára kényszerítem a servlet-et, a „/*” minta miatt pedig minden kérésre érvényes lesz a filter használata.

Java/annotációs konfiguráció

Most hogy láttuk az XML alapú konfigurációt, egy laza mozdulattal dobjuk ki az egészet, és írjuk át Java/annotáció alapúra. A teljes példaalkalmazásban látható lesz, de fontos megemlítenem, hogy az alkalmazás POM-jában külön jelezni kell, hogy a** továbbiakban nem lesz web.xml**. Ez azért fontos, mert – mint említettem – minden Java EE alkalmazásnak kötelezően rendelkeznie kell ilyennel. Azonban mi ezt most egy inicializálóra fogjuk cserélni. De előbb:

Az appcontext-config.xml állományt felváltja az AppContextConfig osztály.

package hu.psprog.dev.tutorial.web.config;
 
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@ComponentScan("hu.psprog.dev.tutorial.web")
public class AppContextConfig {
}

A szemfülesebbeknek feltűnhet, hogy némiképp több értékes információval bír, mint az XML-testvére. Megjelenik a @Configuration annotáció, mely azt fogja jelezni a kontextus betöltőnek (melyet most külön nem is kell majd létrehoznunk), hogy ez az osztály konfigurációs paramétereket, bean definíciókat fog tartalmazni. A @ComponentScan pedig egy (vagy több) csomagnevet vár, ahol a további konfigurációs osztályok, controllerek, bean-ek, komponensek, egy szóval minden olyan elem található, melyet a Spring-nek felügyelni kell.

Továbbhaladva a dispatcher-config.xml állomány helyét is átveszi a DispatcherConfig osztály.

package hu.psprog.dev.tutorial.web.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
 
@Configuration
@EnableWebMvc
public class DispatcherConfig extends WebMvcConfigurerAdapter {
 
	@Bean
	public ViewResolver defaultViewResolver() {
		
		InternalResourceViewResolver viewResolver = 
				new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/view/");
		viewResolver.setSuffix(".jsp");
		
		return viewResolver;
	}
}

Nem meglepő módon ő is megkapja a @Configuration annotációt, továbbá kapni fog egy @EnableWebMvc nevűt is. Emlékszünk az <mvc:annotation-driven /> szekcióra? Ez annak a megfelelője Java konfigurációban. Az osztályban létrehozott bean definíció pedig a nézetfeloldásért felelős – pont, mint az XML konfigurációban.

Végül már csak a web.xml cseréje maradt hátra. Helyette fogunk inicializálót használni, méghozzá az alábbi módon:

package hu.psprog.dev.tutorial.web.init;
 
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
 
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
 
import hu.psprog.dev.tutorial.web.config.AppContextConfig;
 
public class ApplicationInitializer implements WebApplicationInitializer {
 
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		
		// (1)
		AnnotationConfigWebApplicationContext appContext = 
				new AnnotationConfigWebApplicationContext();
		appContext.register(AppContextConfig.class);
		
		// (2)
		ServletRegistration.Dynamic dispatcherServlet = 
				servletContext.addServlet("mvc-dispatcher", 
						new DispatcherServlet(appContext));
		
		// (3)
		dispatcherServlet.addMapping("/");
		dispatcherServlet.setLoadOnStartup(1);
		
		// (4)
		FilterRegistration characterEncodingFilter = 
				servletContext.addFilter("CharacterEncodingFilter", 
						new CharacterEncodingFilter());
		characterEncodingFilter.setInitParameter("encoding", "UTF-8");
		characterEncodingFilter.setInitParameter("forceEncoding", "true");
		characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
	}
}

Az inicializáló létrehozásához implementálni kell a WebApplicationInitializer interfészt, melynek csupán egy metódusa van, ami az onStartup() nevet viseli. A Tomcat, a servlet indításakor meg fogja találni ezt a leszármazott osztályt, majd meghívja azt, átadva neki egy konfigurálásra váró servlet kontextus objektumot. Innentől nagyjából ugyanaz a helyzet, mint XML alapú konfiguráció esetén, azonban külön ContextLoaderListener-re ez esetben nem lesz szükség.

Az (1)-es szekció létrehoz egy annotáció alapú web alkalmazás kontextust (a web MVC környezet csak így fog működni, szóval fontos, hogy ilyet hozzunk létre), melynek szüksége lesz az alap-konfigurációt beállító konfigurációs osztály nevére. A register() metódussal akár több ilyet is hozzáadhatunk, de jobb, ha a konfigurációs osztály importálja (vagy keresteti meg) a többit.

A (2)-es szekció regisztrálja az alkalmazás saját dispatcher servlet-jét a servlet kontextusban – ezzel összekapcsolja a konténert (Tomcat) és az alkalmazást. A dispatcher-nek át kell adni létrehozáskor az alkalmazás kontextus példányt, így a servlet elindulásával a kontextus is azonnal fel fog épülni.

A (3)-as szekció az XML alapú konfigurációból ismerős beállításokat végzi el: a dispatcher minden kérésre reagálni fog, és a konténer elindulása után a servlet magas prioritással (azonnal) be fog töltődni.

Végül a (4)-es szekció a karakterkódolás beállításáért felel.

Konklúzió

A fenti példából remélem jól látható volt, milyen könnyedén átjárható a két konfigurációs megközelítés. Természetesen mindkettő jó, mindkettő használható, ízlés – és kényszer – válogatja, mikor melyiket érdemes – vagy kell – használni. Az előnyök és hátrányok egyaránt megvannak mindkét oldalon. Az XML alapú konfigurációhoz sokkal több segédlet található, valamint a web.xml állomány használata miatt a Java EE standardokat is tiszteletben tartjuk. A Java/annotáció alapú konfiguráció viszont egységessé teszi az alkalmazás forráskódját, mivel teljesen meg lehet szabadulni az XML konfigurációs fájloktól. Helyenként könnyebb a használata, ugyanakkor az XML paraméterek némiképp egységesebbnek érződnek.

Példaalkalmazás forrása

Kommentek

Komment írásához jelentkezz be
Bejelentkezés

Még senki nem szólt hozzá ehhez a bejegyzéshez.