V souboru web.xml jsou požadavky známým
způsobem mapovány na základě svých URL na jednotlivé
servlety. Každý servlet tak zpracovává určitou množinu požadavků, která
však může být velmi rozsáhlá, často může jít i o všechny požadavky. V
případě, že by se kód pro zpracování všech těchto požadavků nacházel v
samotném servletu, byl by nepřehledný a nespravovatelný. Z toho důvodu
je obsluha požadavků rozdělena mezi kontrolery, které mají na starosti
vždy konkrétní typ požadavku, čímž přispívají k čitelnosti aplikace.
Rozhodnutí, který kontroler daný požadavek obslouží, má na starosti
objekt s rozhraním HandlerMapping. Jak již bylo řečeno, implicitně je použit objekt třídy
BeanNameUrlHandlerMapping, který zjistí
URL požadavku a řízení předá tomu kontroleru, který
je v aplikačním kontextu definován pod názvem shodným s tímto
URL. Zde je příklad:
<bean id="urlMapping1"
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="order" value="1" />
<property name="interceptors">
<list><ref bean="logInterceptor" /></list>
</property>
<property name="alwaysUseFullPath" value="true" />
</bean>
<bean name="/login.html" class="....LoginController" />
<bean name="/logout.html" class="....LogoutController" />
<bean id="logInterceptor" class="....LogInterceptor" />
Podívejme
se nejdřív na vlastnosti, kterými v tomto příkladu objekt
BeanNameUrlHandlerMapping konfigurujeme a které
lze aplikovat i na objekt
SimpleUrlHandlerMapping, jemuž se budeme věnovat
vzápětí.
Vlastnost order udává prioritu tohoto
objektu mezi ostatními registrovanými objekty s rozhraním
HandlerMapping. Objekt s nejnižší hodnotou této
vlastnosti má při výběru kontroleru přednost před objekty s vyšší
hodnotou a před těmi, které tuto vlastnost nemají. Následuje objekt s
druhou nejnižší hodnotou atd. Vlastnost order lze
přidělit objektům všech tříd, které implementují rozhraní
org.springframework.core.Ordered. Patří k nim
například i všechny implementace rozhraní
ViewResolver.
Pomocí vlastnosti interceptors definujeme
seznam interceptorů, které pro všechny kontrolery mapované v daném
HandlerMapping objektu provedou jednotné před- či
postzpracování požadavku. Interceptorům se budeme věnovat níže.
Hodnota true vlastnosti
allwaysUseFullPath říká, že
pro vyhledání kontroleru bude použita plná URL.
Konkrétně, bude-li požadavek tvaru
http://www.abc.cz/neco/cokoliv.html, bude pro
srovnání za všech okolností použit řetězec
/neco/cokoliv.html. V případě defaultní hodnoty
false bude použita URL
relativní k mapování daného objektu
DispatcherServlet v souboru
web.xml. Bude-li
DispatcherServlet mapován například na cestu
/neco/*.html, pak objekt
HandlerMapping bude brát při výběru kontroleru v
úvahu pouze řetězec /cokoliv.html.
Po příchodu požadavku s URL
http://www.abc.cz/login.html bude objektem
HandlerMapping z našeho příkladu vybrán kontroler
definovaný v aplikačním kontextu pod názvem /login.
Všimněte si, že název objektu je zadán prostřednictvím atributu
name, nikoliv id. Je to z
toho důvodu, že specifikace XML nepovoluje znak
zpětného lomítka v elementu id.
BeanNameUrlHandlerMapping dostačuje pro
použití v jednoduchých aplikacích. Výrazně mocnější implementací
rozhraní HandlerMapping je však třída
SimpleUrlHandlerMapping, která umožňuje mapování
URL ve stylu souborů properties.
Toto mapování lze definovat v externím souboru properties nebo přímo v
XML souboru aplikačního kontextu, jak je vidět v
následujícím příkladu.
<bean id="urlMapping2"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order"><value>2</value></property>
<property name="interceptors">
<list>
<ref bean="logInterceptor" />
</list>
</property>
<property name="mappings">
<props>
<prop key="/index.html">homeController</prop>
<prop key="/exception.html">exceptionController</prop>
</props>
</property>
<property name="defaultHandler" value="defaultController" />
</bean>
Jednou z výhod této implementace je fakt, že máte mapování URL na kontrolery potenciálně celé aplikace na jednom místě, což výrazně usnadňuje orientaci programátora v aktuálním stavu aplikace.
Přibyla nám také nová vlastnost -
defaultHandler. S jejím
využitím lze určit kontroler, jenž bude daným objektem
HandlerMapping vybrán v případě, že žádný jiný
kontroler vyhovovat nebude. Máme-li v aplikačním kontextu několik
objektů HandlerMapping, pak tuto vlastnost by měl
mít až ten úplně poslední, protože její použití fakticky znemožní
předání řízení objektům HandlerMapping s nižší
prioritou.
V obou uvedených implementacích rozhraní
HandlerMapping lze v definici mapování používat
zástupné znaky s významem zástupných znaků nástroje
Ant™. Následující příklad čerpáme ze vzorové aplikace, která
je přílohou této práce, konkrétně ze souboru
WEB-INF/spring/webApplicationContext-public.xml.
<bean id="urlMappingForPublic"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/user/*/index.html">userProfileController</prop>
<prop key="/*/events/*/**/index.html">portalSportEventController</prop>
</props>
</property>
</bean>