Všechny dosud zmíněné komponenty MVC modulu
rámce Spring hrají infrastrukturní či pomocnou roli. Místem, kde se
aplikace skutečně vytváří, je kontroler. Ve správně navržené aplikaci kontroler v podstatě jen
zpracovává parametry požadavku, přistupuje k objektům servisní vrstvy a
čerpá z nich model. Pak zvolí správný pohled a model do něj
pošle.
Webová vrstva aplikace by měla být co nejužší a neměla by se v ní
vyskytovat žádná aplikační logika. Ta je obsažena pouze v aplikační
vrstvě, aby webová vrstva mohla být snadno nahrazena například grafickým
rozhraním Swing™ či aby funkce aplikace mohly
být snadno zpřístupněny pomocí webové služby.
Rámec Spring™ kontrolerům, jako klíčové
části návrhového vzoru MVC, samozřejmě věnuje
adekvátní pozornost a poskytuje komplexní hierarchii rozhraní a tříd,
které programátorům při tvorbě webové aplikace výrazně ulehčují práci.
Stěžejní komponenty této hierarchie jsou zachyceny diagramem
3.1 – „Hierarchie kontrolerů“, který byl publikován v
[3].
Hlavní roli hraje rozhraní
org.springframework.web.servlet.mvc.Controller,
se kterým pracuje DispatcherServlet či přesněji
SimpleControllerHandlerAdapter (viz „Cesta požadavku útrobami Spring MVC“). Jedinou metodou tohoto rozhraní je
ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res)
Metodě
je předán odkaz na objekty požadavku i odpovědi, čímž se stává stejně
mocnou jako metody doGet a
doPost třídy
javax.servlet.http.HttpServlet. Pokud je
návratovou hodnotou
null, pak tím autor
kontroleru signalizuje, že požadavek byl v kontroleru vyřízen a odpověď
byla sestavena. Další kroky životního cyklu požadavku (viz „Cesta požadavku útrobami Spring MVC“) jsou vypuštěny a odpověď je odeslána
klientovi.
Reprezentace modelu a pohledu
Třídou návratové hodnoty metody
handleRequest je
org.springframework.web.servlet.ModelAndView.
Tato třída představuje dvousložkovou komponentu, obsahující jak model,
tak pohled. Zatímco model je vždy uchováván v podobě instance třídy
java.util.Map, pohled může mít dvě různé formy.
První z nich je konkrétní objekt implementující rozhraní
org.springframework.web.servlet.View, jenž se
přímo postará o zobrazení modelu. Druhou je symbolický název pohledu,
který bude teprve zpracován detektorem pohledu (objektem typu
ViewResolver) a převeden na konkrétní objekt
typu View.
Ukažme si teď implementaci triviálního kontroleru na příkladu:
public class HomeController implements Controller {
public ModelAndView handleRequest(HttpServletRequest req,
HttpServletResponse res) throws Exception {
Map model = new HashMap();
model.put("now",new Date());
return new ModelAndView("home",model);
}
}
Vidíme, že metoda vrací
ModelAndView, obsahující symbolický název
pohledu home a model s jedinou položkou.
Přestože tvorba kontroleru přímo implementujících rozhraní
Controller je možná, vhodnější je využití
některé z existujících tříd z uvedené hierarchie. Různé třídy řeší
různé běžné situace, takže abychom se mohli pro nějakou rozhodnout,
musíme alespoň o těch nejpoužívanějších něco málo vědět. Existují tři
základní scénáře použití kontrolerů rámce
Spring™.
Nejběžnějším scénářem je ten, kdy chceme na uživatelský
HTTP GET požadavek reagovat prostým zobrazením
určitých dat. V takovém případě je vhodné při tvorbě vlastního
kontroleru rozšířit abstraktní třídu
org.springframework.web.servlet.mvc.AbstractController
a implementovat abstraktní metodu ModelAndView
handleRequestInternal(HttpServletRequest,
HttpServletResponse). Tato abstraktní třída obsahuje
často používanou funkcionalitu a pomocí konfigurace lze snadno
nastavit zejména seznam povolených metod HTTP
požadavků (GET, POST, ...) a pravidla kešování zobrazené stránky.
Užitečným rozšířením této abstraktní třídy je konkrétní třída
org.springframework.web.servlet.mvc.ParameterizableViewController,
která navíc obsahuje vlastnost viewName pro možnost
konfigurace logického názvu pohledu v konfiguračním souboru. Příklad
implementace převezmeme z přiložené vzorové aplikace, konkrétně z
třídy
cz.morosystems.sportportal.controllers.ClientUsersListController.
public class ClientUsersListController extends ParameterizableViewController{
private UserManager userManager;
public ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Map model = new HashMap();
List<User> users = getUserManager().getAllClientUsers();
Collections.sort(users);
model.put("users", users);
return new ModelAndView(getViewName(), "model", model);
}
... get/set metody pro atribut userManager ...
}
A příslušné deklarace v konfiguračním souboru aplikačního
kontextu (v přiložené aplikaci v souboru
WEB-INF\spring\webApplicationContext-admin.xml)
vypadají takto:
<bean id="urlMappingForAdmin"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="3" />
<property name="mappings">
<props>
...
<prop key="/secure/admin/client-users/list.html">
clientUsersListController
</prop>
...
</props>
</property>
<property name="alwaysUseFullPath" value="false" />
</bean>
<bean id="clientUsersListController"
class="cz.morosystems.sportportal.controllers.ClientUsersListController" >
<property name="supportedMethods" value="GET,HEAD" />
<!-- hodnota 0 představuje zákaz cachování, při -1 nebudou nastaveny
žádné cachovací HTTP hlavičky -->
<property name="cacheSeconds" value="60" />
<property name="userManager" ref="userManager" />
<property name="viewName" value="secure/admin/users/client/list"/>
</bean>
V příkladu v zájmu zestručnění neuvádíme
deklaraci servisního objektu s id
userManager. V naší třídě
ClientUsersListController jsme definovali
JavaBeans™ vlastnost
userManager, vlastnost viewName
je součástí rozšiřované třídy
ParameterizableViewController, ostatní
vlastnosti jsou součástí třídy
AbstractController. Vlastnost
supportedMethods definuje čárkou oddělený seznam
povolených typů HTTP požadavků, atribut
cacheSeconds pak říká, jak dlouhé kešování dané
stránky bude nastaveno v hlavičkách HTTP
odpovědi.
Přistupovat k modelu v JSP/JSTL šabloně lze
pomocí standardních značek JSTL:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html><head><title>Seznam uživatelů</title></head>
<body>
<h1>Seznam uživatelů</h1>
<ul>
<c:forEach items="${model.users}" var="user">
<li><c:out value="${user.name}"/></li>
</c:forEach>
</ul>
</body></html>
Jednoduchý formulářový kontroler
Poněkud složitější situace nastává při dalším běžném scénáři,
při manipulaci s HTML formuláři. Pro tyto případy
existuje v uvedené hierarchii kontrolerů abstraktní třída
org.springframework.web.servlet.mvc.AbstractFormController,
kterou ovšem rozšiřují dvě užitečnější třídy. První z nich je třída
org.springframework.web.servlet.mvc.SimpleFormController,
která je vhodná pro práci s jednoduchými jednostránkovými formuláři.
Použijeme-li jako předka pro náš kontroler tuto třídu, můžeme využít
kustomizace kteréhokoliv z kroků následujícího toku řízení:
-
Na URL, kterou obsluhuje daný
kontroler, přichází HTTP GET požadavek.
Kontroler tedy ví, že jde o požadavek na první zobrazení
formulářového pohledu.
-
Je zavolána metoda kontroleru
formBackingObject, která vrací tzv.
příkazový (command) neboli
formulářový (form) objekt, jehož úkolem
bude zapouzdřit data manipulovaná ve formuláři. Tento objekt
opět musí vyhovovat standardu
JavaBeans™. Vrácený objekt může být
buď prázdný (prázdný formulář) nebo získaný například z databáze
(formulář s předvyplněnými daty již při prvním
zobrazení).
-
Je zavolána metoda kontroleru
initBinder, jejímž překrytím lze
upravit mechanismus konverze řetězcových dat formuláře na
atributy (často neřetězcového typu) formulářového objektu a
obráceně. Při konverzi jsou opět použity editory vlastností (viz
„Atributy běžných typů“) a v metodě
initBinder je v podstatě možno
registrovat konkrétní editor vlastností na konkrétní vlastnost
formulářového objektu.
-
Je zavolána metoda kontroleru
referenceData, vracející model, jenž je
potřeba pro zobrazení formulářového pohledu.
-
Je zobrazen formulářový pohled
definovaný v konfiguračním souboru pomocí vlastnosti
formView. V tomto pohledu jsou svázány
vlastnosti formulářového objektu s příslušnými formulářovými
poli (toto svázání je řešeno prostřednictvím speciální knihovny
značek, kterou představíme v následujícím oddíle) a hodnoty
vlastností jsou zobrazeny jako implicitní hodnoty v příslušných
formulářových polích.
-
Uživatel edituje formulářová data a odesílá formulář, při
čemž POST požadavek je odeslán na tutéž
URL.
-
Kontroler detekuje HTTP POST požadavek,
což je pro něj příkaz, aby spustil druhou část toku
řízení.
-
Formulářový objekt je pozměněn na základě uživatelem
zadaných dat ve formuláři.
-
Je zavolána metoda kontroleru
onBind.
-
Pokud je nastavena vlastnost kontroleru
validateOnBinding na
true, tak jsou na formulářový objekt
aplikovány všechny registrované validátory, které mají za úkol
ověřit přípustnost uživatelem zadaných dat. Validátory musí
implementovat rozhraní
org.springframework.validation.Validator
a zejména metodu validate(Object,
Errors). Všechny chyby při validaci jsou
zaznamenány v objektu s rozhraním
org.springframework.validation.Errors.
-
Je zavolána metoda kontroleru
onBindAndValidate, kde lze provést
další validace a registrovat další chyby do objektu typu
Errors.
-
Jsou-li v objektu Errors
registrovány nějaké chyby, pak je znovu zobrazen formulářový
pohled spolu s uživatelem zadanými daty v příslušných
formulářových polích. Na základě informací v objektu
Errors lze vypsat hlášení o chybách
vstupu. Následují kroky od bodu 4.
-
Nejsou-li v objektu Errors
registrovány žádné chyby, pak je zavolána metoda
onSubmit, která provede prostřednictvím
aplikační vrstvy finální zpracování formulářového objektu,
například jeho uložení v databázi.
Výhodou tohoto řešení je možnost použití objektu z
doménového modelu jako formulářového objektu, aniž bychom vždy museli
využívat speciálních transferových objektů a převádět data z
doménového objektu do transferového a naopak.
Například chceme-li editovat údaje systémového uživatele
reprezentovaného třídou User, tak překryjeme
metodu formBackingObject tak, aby získala
příslušnou instanci třídy User z databáze a
vrátila ji. Aktuální údaje systémového uživatele budou zobrazeny ve
formuláři. Po jejich editaci uživatelem aplikace bude instance třídy
User poslána zpět kontroleru, který ji pouze
předá servisní vrstvě k aktualizaci v databázi. Odpadá tak nutnost
manuálního zpracování parametrů HTTP požadavku či
použití DTO (Data Transfer Object).
Právě popsaný příklad ilustrujeme na skutečném, jen mírně
zjednodušeném formulářovém kontroleru
(cz.morosystems.sportportal.controllers.UserEditFormController)
z přiložené vzorové aplikace.
public class UserEditFormController extends SimpleFormController {
private UserManager userManager;
protected Object formBackingObject(HttpServletRequest request)
throws Exception {
String userID = request.getParameter("id");
//na základě parametru požadavku id získáme uživatele z databáze k editaci
User user = userManager.getUserByID(userID);
/* není-li uživatel pro dané id v databázi, vyhodíme výjimku, která bude
zpracována prostřednictvím objektu typu ExceptionResolver definovaného
v konfiguračním souboru (viz oddíl 4.8)
*/
if (user==null) throw new NoSuchAddressException();
return user;
}
public ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws ServletException {
/* formulářový objekt je typu uživatel a je následně prostřednictvím
manažera uložen do databáze */
User user = (User)command;
getUserManager().setUser(user);
/* následně zobrazený pohled je definován prostřednictvím vlastnosti
'successView' v konfiguračním souboru */
return new ModelAndView(getSuccessView());
}
... get/set metody pro atribut userManager ...
}
Třída User ve své nejjednodušší
podobě by vypadala takto:
public class User {
private String id;
private String firstname;
private String surname;
private String email;
... get/set metody všech atributů ...
}
Skutečná třída
cz.morosystems.sportportal.pojo.User ovšem
obsahuje množství dalších vlastností a metod. Příslušné definice v
konfiguračním XML souboru jsou následující:
<bean id="urlMappingForAdmin"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="3" />
<property name="mappings">
<props>
...
<prop key="/secure/admin/admin-users/edit.html">
adminUserEditFormController
</prop>
...
</props>
</property>
<property name="alwaysUseFullPath" value="false" />
</bean>
<bean id="adminUserEditFormController"
class="cz.morosystems.sportportal.controllers.UserEditFormController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="user"/>
<property name="commandClass" value="cz.morosystems.sportportal.pojo.User"/>
<property name="validator" ref="userEditFormValidator"/>
<property name="formView" value="secure/admin/users/admin/edit"/>
<property name="successView" value="redirect:list.html"/>
<property name="userManager" value="userManager" />
</bean>
<bean id="userEditFormValidator"
class="cz.morosystems.sportportal.validators.UserEditFormValidator" >
<property name="userManager" value="userManager" />
</bean>
Atribut sessionForm indikuje,
zda má být pro uložení formulářového objektu mezi GET a POST
požadavkem uživatele použito uživatelské sezení. V případě, že bychom
tuto možnost zakázali, nebylo by možno editovat již existující údaje
získané z databáze, tak jako jsme to předvedli v předcházejícím
příkladě, a bylo by možno pracovat v podstatě pouze s iniciálně
prázdnými formuláři. Atribut commandName určuje
název, pod kterým bude formulářový objekt přístupný ve formulářovém
pohledu jako atribut HTTP požadavku. Atribut
commandClass definuje třídu formulářového objektu,
atributy formView a successView
pak specifikují formulářový a finální pohled. No a konečně atribut
validator se odkazuje na instanci s rozhraním
Validator, která vypadá takto:
import org.apache.commons.validator.EmailValidator;
import org.springframework.validation.ValidationUtils;
import cz.morosystems.sportportal.pojo.User;
public class UserEditFormValidator implements Validator {
private UserManager userManager;
public boolean supports(Class clazz) {
return clazz.equals(User.class);
}
public void validate(Object object, Errors errors) {
User user = (User) object;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email",
"error.user.email.required", "Value can't be empty");
if (!EmailValidator.getInstance().isValid(user.getEmail())) {
errors.rejectValue("email", "error.user.email.not-valid", null,
"Value must be in correct format.");
}
}
... get/set metody pro atribut userManager ...
}
Metoda supports určuje, pro které
třídy formulářových objektů je tento validátor určen. V metodě
validate pak kontrolujeme pouze vlastnost
email formulářového objektu. Nejdříve ověříme, zda
uživatel nezadal prázdnou hodnotu a pokud ano, tak v objektu
errors zaregistrujeme chybu pro vlastnost
email s chybovým hlášením specifikovaným pomocí
i18n klíče
error.user.email.required. Při zobrazení chyby ve
formulářovém pohledu pak bude tento klíč využit pro internacionalizaci
hlášení. Při registraci chyby jsme navíc ještě uvedli defaultní
zprávu, která bude zobrazena v případě, že pro daný klíč nebude
nalezena žádná hodnota ve zdroji zpráv (viz „Zdroje zpráv“). Následně pak podobně ověříme i správnost
formátu zadaného e-mailu.
Třída
cz.morosystems.sportportal.controllers.ExistingCompetitorsFormController
v přiložené vzorové aplikaci představuje zdokumentovaný příklad
komplexního formulářového kontroleru.
Vzhledem k blízké příbuznosti s tématem formulářového
kontroleru, který jsme si představili v předchozím oddíle, si teď
ukážeme práci s knihovnou značek JSP rámce Spring pro
manipulaci s formuláři. Tato knihovna je novinkou rámce
Spring™ od verze
2.0 a je identifikována pomocí
URI
http://www.springframework.org/tags/form. Jde v
podstatě o sadu značek, které zjednodušují provázání atributů
(vlastností) formulářových objektů s formulářovými poli.
V předchozích verzích rámce Spring™ se
k tomuto účelu používala obecná knihovna značek
JSP identifikovaná prostřednictvím URI
http://www.springframework.org/tags, která je i
ve verzi 2.0 stále přítomna. K
provázání vlastností formulářového objektu s formulářovými poli
sloužily značky bind, nestedPath a
hasBindErrors.
Náš příklad s editací údajů uživatele tedy uzavřeme jednoduchým
poupraveným příkladem JSP/JSTL šablony
(/WEB-INF/jsp/secure/admin/users/admin/edit.jsp v
přiložené vzorové aplikaci), kde bude demonstrováno použití značek
bind a hasBindErrors z obecné
knihovny značek JSP.
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html><head><title>Uživatel - editace údajů</title></head>
<body>
<div class="chyby">
<%-- název formulářového objektu 'user' byl definován vlastností
'commandName' v definici kontroleru v konfiguračním souboru (viz výše) --%>
<spring:hasBindErrors name="user">
<p class="chyba"><fmt:message key="error.email.index.chyby"/></p>
<ul>
<c:forEach items="${errors.allErrors}" var="error" >
<li style="color:red"><fmt:message key="${error.code}" /></li>
</c:forEach>
</ul>
</spring:hasBindErrors>
</div>
<form method="post" action="" >
<spring:bind path="user.firstname">
<input type="text" name="<c:out value="${status.expression}" />"
value="<c:out value="${status.value}"/>" />
<c:out value="${status.errorMessage}"/>
</spring:bind>
<spring:bind path="user.surname">
příjmení: <input type="text"
name="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>" />
<c:out value="${status.errorMessage}"/>
</spring:bind>
<spring:bind path="user.email">
e-mail: <input type="text"
name="<c:out value="${status.expression}" />"
value="<c:out value="${status.value}"/>" />
<c:out value="${status.errorMessage}"/>
</spring:bind>
<input type="submit" value="Upravit" />
</form>
</body></html>
V první části jsme souhrnně
zobrazili všechny chybové zprávy, pokud nějaké existují, v samotném
formuláři jsme pak definovali jednotlivá formulářová pole a pomocí
značky bind a jejího atributu path
jsme je namapovali na vlastnosti
firstname,
surname a
email formulářového objektu
s názvem user. Proměnná s názvem
status, dostupná uvnitř značky
bind, představuje danou mapovanou vlastnost
formulářového objektu. Proměnná status.value
obsahuje aktuální hodnotu vlastnosti,
status.expression plnou cestu daného atributu
(např. user.email) a
status.errorMessage pak případné chybové hlášení
registrované k dané vlastnosti.
Pomocí nové knihovny značek pro manipulaci s formuláři bychom
tutéž šablonu navrhli takto:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html><head><title>Uživatel - editace údajů</title></head>
<body>
<form:form commandName="user" action="" method="post">
<div class="chyby">
<form:errors path="*" cssStyle="color:red" />
</div>
jméno: <form:input path="firstname" />
<form:errors path="firstname" />
příjmení: <form:input path="surname" />
<form:errors path="surname" />
email: <form:input path="email" />
<form:errors path="email" />
<input type="submit" value="Upravit" />
</form:form>
</body></html>
Je vidět výrazné zjednodušení a
odstranění opakujícího se kódu. Bohužel v této práci nemáme prostor
pro demonstraci složitějších možností obou knihoven značek ve
spolupráci s formulářovými kontrolery, které jsou ovšem k vidění v
přiložené vzorové aplikaci. Jde zejména o demonstraci dalších
formulářových prvků (select boxy, tlačítka typu radio atd., viz
např.
WEB-INF\jsp\secure\client\competitors\create-team.jsp),
mapování parametrů požadavku na kolekce objektů
(cz.morosystems.sportportal.controllers.CompetitorCreateTeamFormController.initBinder()
ve spolupráci s editorem vlastností
cz.morosystems.sportportal.editors.SportBranchEditor)
apod.
Kontroler pro vícekrokové formuláře
Chceme-li v aplikaci použít vícestránkové či vícekrokové
formuláře, pak je vhodné sáhnout po druhém z formulářových kontrolerů
a rozšířit třídu
org.springframework.web.servlet.mvc.AbstractWizardFormController.
Tok řízení tohoto kontroleru je ještě výrazně složitější než je tomu u
třídy SimpleFormController a je možné jej
nastudovat v javadoc dokumentaci třídy. Shrňme jen stručně jeho
funkcionalitu.
Návrhář kontroleru definuje sadu pohledů, které představují
jednotlivé kroky vícekrokového formuláře. Tyto kroky jsou
identifikovány svým pořadím, a to nulou počínaje. První krok má tedy
index 0, druhý index 1 atd. Přechod mezi jednotlivými kroky je
realizován pomocí detekce parametru požadavku s názvem
_targetX, kde X je index následujícího kroku.
Toho je typicky dosahováno pomocí odesílacího prvku dané části
formuláře, tedy například takto:
<input type="submit" name="_target2" value="Další krok" />
<input type="submit" name="_target0" value="Krok zpět" />
Podobně
je tomu s parametrem požadavku s názvem
_finish, který indikuje definitivní ukončení a
zpracování všech dosud sebraných dat v jednotlivých krocích (v
kontroleru je zavolána metoda onFinish), a s
parametrem požadavku s názvem _cancel, jehož
přítomnost kontroler interpretuje jako požadavek ukončení práce s
formulářem bez zpracování sebraných dat (je zavolána metoda
onCancel).
Na pozadí práce s formulářem je rovněž v akci formulářový
objekt, na nějž jsou jednotlivá formulářová pole jednotlivých kroků
mapována. Tento objekt je průběžně validován a ve finále zpracován a
například uložen do databáze.
Příkladem komplexního a zdokumentovaného vícekrokového
kontroleru je třída
cz.morosystems.sportportal.controllers.SportEventCreateFormController
z přiložené vzorové aplikace.
Kontroler pro více podobných akcí
Tento kontroler, tedy kontroler třídy
org.springframework.web.servlet.mvc.multiaction.MultiActionController,
je jako předek využíván v případech, kdy by jinak bylo nutno nasadit
několik jednoduchých kontrolerů, jejichž funkčnost by byla do značné
míry podobná. Příkladem takového kontroleru je třída
cz.morosystems.sportportal.controllers.PublicSportEventRenderStructureController
z přiložené vzorové aplikace (viz také příslušné definice v
konfiguračním XML souboru).
Rozhraní
org.springframework.web.servlet.mvc.throwaway.ThrowawayController
je vyděleno z celé dosud popisované hierarchie kontrolerů. Dosud jsme
předpokládali, že naše implementace kontrolerů jsou bezstavové a že
tedy budou v rámci naší aplikace definovány jako jedináčci
(Singleton). Tyto kontrolery (a to se týká zejména formulářových
kontrolerů) pak pracují s dočasnými formulářovými objekty, které drží
stav.
Návrh rozhraní ThrowawayController byl
inspirován zejména pojetím kontrolerů (neboli akcí) v aplikačních
rámcích WebWork™ či
Maverick™. ThrowawayController je vytvářen
vždy znovu pro každý požadavek a obsahuje dočasná data stejně jako
aplikační logiku, která s nimi pracuje. Jde tedy o jakýsi kontroler a
příkazový či formulářový objekt v jednom.
Tento typ kontroleru je však součástí rámce
Spring™ přece jen spíše pro ty uživatele,
kteří jsou na podobnou filozofii zvyklí, než pro začátečníky, kteří se
s webovým MVC návrhovým vzorem teprve
seznamují.