Spring Web MVC Ievads Spring ir atklta koda
Spring Web MVC
Ievads • Spring ir atklāta koda Java/J 2 EE aplikāciju ietvars • Viens no interesantākiem komponentiem ir Spring Web MVC
Web aplikāciju uzdevumi • Svarīgie uzdevumi, kuri ir jāatrisina izstrādājot web aplikāciju: • Stāvokļu pārvaldība (state management) • Darba plūsma (workflow) • Validācija • Spring web ietvars ir uzprojektēts, lai palīdzet izstrādātājiem risināt šīs problēmas
Model-View-Controller Pattern • Model-View-Controller (MVC) ir arhitektūras paraugs (aprakstīts 1979. gadā, Smalltalk valodā) • Pamata mērķis: atdalīt datus (Model) no lietotāja interfeisa (View) • MVC atrisina problēmu ieviešot starpnieka komponenti - kontrolieri (Controller)
Model-View-Controller Pattern • Model - Represents enterprise data and the business rules. • View - Renders the contents of a model. Accesses enterprise data through the model and specifies how that data should be presented. • Controller - Translates interactions with the view (button clicks, menu selections) into actions to be performed by the model (activating processes, changing the state of the model).
Spring MVC • Spring MVC sastāv no vairākiem komponentiem, starp kuriem notiek sadarbība apstrādājot klienta pieprasījumu
Pieprasījuma dzīves cikls (1) • Klients sūta pieprasījumu, kurš tiek nodots Dispatcher. Servlet komponentam • Visi pieprasījumi vienmēr tiek nodoti vienam servletam, kuru sauc par priekšējo kontrolieri (front controller)
Pieprasījuma dzīves cikls (2) • Komponents, kurš atbild par pieprasījuma apstrādi ir Controller • Lai nolemt kuram kontrolierim atdot pieprasījumu, Dispatcher. Controller izmanto Handler. Mapping komponentus • Handler. Mapping: URL piesaistīšana kontrolieriem
Pieprasījuma dzīves cikls (3 -4) • Kad Dispatcher. Servlet nolemj par kontroliera objektu, tad parsūta tam pieprasījumu, lai kontrolieris izpilda biznesa loģiku • Pēc darba pabeigšanas Controller atgriež Model. And. View objektu • Model. And. View satur View objektu vai skata loģisko vārdu
Pieprasījuma dzīves cikls (5) • Ja Model. And. View objekts satur skata loģisko vārdu, tad Dispatcher. Servlet izmanto View. Resolver komponenti • View. Resolver atrod atbilstošu View objektu, lai attēlot atbildi klientam
Pieprasījuma dzīves cikls (6) • Visbeidzot, Dispatcher. Servlet atdod pieprasījumu tam View objektam, uz kuru norāda Model. And. View • View objekts ir atbildīgs par pieprasījuma atbildes atgriešanu un parādīšanu klientam
Spring MVC Sequence Diagram
Front Controller • At the heart of Spring MVC is Dispatcher. Servlet, a servlet that functions as front controller • A front controller is a common webapplication pattern where a single servlet delegates responsibility for a request to other components of an application to perform the actual processing
Dispatcher. Servlet config • Jākonfigurē web aplikācijas web. xml failā: <servlet> <servlet-name>training</servlet-name> <servlet-class>org. springframework. web. servlet. Dispatcher. Servlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> • Nākamais solis ir nodefinēt servlet mapping: <servlet-mapping> <servlet-name>training</servlet-name> <url-pattern>*. htm</url-pattern> </servlet-mapping>
Dispatcher. Servlet context • Web. Application. Context tiek ielādēts no faila: training-servlet. xml kurš atrodas direktorijā WEB-INF web. xml failam) • Ir iespējams arī sadalīt konfigurāciju starp vairākiem failiem (līdzīgi
Vienkāršas Web lapas izveidošana • Nepieciešamie soļi, lai izveidot web lapu ar Spring MVC: 1. Uzrakstīt kontroliera klasi, kas izpildīs biznesa loģiku 2. Iekonfigurēt kontrolieri Dispatcher. Servlet konteksta konfigurācijas failā (training-servlet. xml) 3. Iekonfigurēt view resolver, kurš piesaistīs kontrolieri pie JSP 4. Uzrakstīt JSP, kas attēlos lapu klientam
Kontroliera izveidošana public class Home. Controller implements Controller { public Model. And. View handle. Request(Http. Servlet. Request request, Http. Servlet. Response response) throws Exception { return new Model. And. View("home", "message", greeting); } private String greeting; public void set. Greeting(String greeting) { this. greeting = greeting; } } • Nodarbojas ar pieprasījuma apstrādāšanu • Pamata metodes signatūra ir līdzīga servleta service() metodei • Atgriež Model. And. View objektu
Kontroliera konfigurēšana • Kontrolieri ir jāieraksta Dispatcher. Servlet konteksta konfigurācijas failā: <bean name="/home. htm" class="com. springinaction. training. mvc. Home. Controller"> <property name="greeting"> <value>Welcome to Spring Training!</value> </property> </bean> • The default handler mapping is Bean. Name. Url. Handler. Mapping, which uses the base name as the URL pattern • When a request comes with a URL that ends with “/home. htm”, Dispatcher. Servlet will dispatch the request to Home. Controller
View Resolver deklarēšana • View resolver darbs ir pēc skata loģiska vārda (kurš ir atgriezts Model. And. View objektā) atrast pašu skatu • Viens no variantiem ir izmantot skata vārdu kā JSP faila vārdu: <bean id="view. Resolver" class="org. springframework. web. servlet. view. Internal. Resource. View. Resolver"> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>. jsp</value> </property> </bean> “home” /WEB-INF/jsp/home. jsp
JSP izveidošana • Pēdējais kas palika – izveidot pašu JSP <html> <head><title>Spring Training, Inc. </title></head> <body> <h 2>${message}</h 2> </body> </html> • Failu ir jānosauc par “home. jsp” un ir jānoliek zem /WEB-INF/jsp/ direktorijas
Kopsavilkums
Handler. Mapping • Tipiski piesaista specifisku kontrolieri pie URL adreses parauga • Spring piedāvā četras noderīgas Handler. Mapping implementācijas • Bean. Name. Url. Handler. Mapping • Simple. Url. Handler. Mapping • Commons. Path. Map. Handler. Mapping
Bean. Name. Url. Handler. Mapping • Piesaista URL adresi pie kontroliera, kurš ir reģistrēts konfigurācijas failā ar tādu pašu vārdu • e. g. /simple. htm maps to a bean named “/simple. htm” <bean class="org. springframework. web. servlet. handler. Bean. Name. Url. Handler. Mapping"/> <bean name="/simple. htm" class="com. mvc. web. Simple. Controller"> . . . </bean> • Ir jāizmanto name atribūtu, jo “/” nav atļauts XML atribūtā id
Simple. Url. Handler. Mapping • Pats vispārīgs veids kā piesaistīt pieprasījuma URLus kontrolieriem • Tiek konfigurēts kā saraksts no name/value pāriem (URL/kontrolieru vārds) <bean id="simple. Url. Mapping" class="org. springframework. web. servlet. handler. Simple. Url. Handler. Mapping"> <property name="mappings"> <props> <prop key="/list. Courses. htm">list. Courses. Controller</prop> <prop key="/register. htm">register. Student. Controller</prop> <prop key="/display. Course. htm">display. Course. Controller</prop> </props> </property> </bean>
Commons. Path. Map. Handler. Mapping • Considers source-level metadata placed in a controller’s source code to determine the URL mapping <bean id="url. Mapping" class="org. springframework. web. servlet. handler. metadata. Commons. Path. Map. Handler. Mapping"/> • Need to set up build to include the Commons Attributes compiler so that the attributes will be compiled into application code /** @@org. springframework. web. servlet. handler. commonsattributes. Path. Map( "/display. Course. htm") */ public class Display. Course. Controller extends Abstract. Command. Controller { … }
Multiple handler mappings • Ir iespējams deklarēt vairākus handler mappings vienā aplikācijā • Handler mapping klases implementē Spring’a Ordered interfeisu • Var uzstādīt order īpašību, lai norādīt izpildes kārtību attiecībā uz citiem handler mapping komponentiem
Multiple handler mappings <bean id="bean. Name. Url. Mapping" class="org. springframework. web. servlet. handler. Bean. Name. Url. Handler. Mapping"> <property name="order"><value>1</value></property> </bean> <bean id="simple. Url. Mapping" class="org. springframework. web. servlet. handler. Simple. Url. Handler. Mapping"> <property name="order"><value>0</value></property> <property name="mappings"> … </property> </bean>
Kontrolieri • Ja Dispatcher. Servlet ir Spring MVC sirds, tad kontrolieri ir smadzenes
Kontrolieru hierarhija • Spring piedāvā bagātu kontrolieru hierarhiju • Hierarhijas virsotnē atrodas Controller interfeiss • Parasti ir jāizmanto kādu no implementācijas apakšklasēm
Abstract. Controller • Pats vienkāršākais kontrolieris public class Sample. Controller extends Abstract. Controller { public Model. And. View handle. Request. Internal( Http. Servlet. Request request, Http. Servlet. Response response) throws Exception { return new Model. And. View( "hello“, “message”, "Hello World!"); } }
Model. And. View objekts • Iekapsulē skatu un modeļa datus, kurus skats attēlos • Modelis ir realizēts kā java. util. Map • Ērts konstruktors viena modeļa objekta gadījumam: Model. And. View( String view. Name, String model. Name, Object model. Object)
Model. And. View objekts • Ir iespējams arī pievienot modelim vairākus objektus: public Model. And. View handle. Request. Internal( Http. Servlet. Request request, Http. Servlet. Response response) throws Exception { Model. And. View mav = new Model. And. View(“welcome"); mav. add. Object("message 1", “Welcome!"); mav. add. Object("message 2", "Nice to see you!"); return mav; }
Parametru apstrāde • Web pieprasījums bieži satur vienu vairākus parametrus <form action="/login" method="POST"> Login: <input id=“login" name="login"/> Password: <input id="password" name="password" type="password"/> <input type="submit" value="Login"/> </form> Kādā veidā varētu piekļūt parametriem kontroliera kodā? ? ?
Risinājums • Varētu izmantot Abstract. Controller un nolasīt parametrus no Http. Servlet. Request public Model. And. View handle. Request. Internal( Http. Servlet. Request request, Http. Servlet. Response response) throws Exception { String login = request. get. Parameter("login"); String pass = request. get. Parameter("password"); . . . } Spring piedāvā ērtāku iespēju!
Abstract. Command. Controller • Automātiski ieraksta parametrus speciālajā komandas objektā (command object) • Ir iespēja pievienot validatoru, lai nodrošināt to, ka parametri ir pareizi • Galvenā izpildes metode: handle( Http. Servlet. Request request, Http. Servlet. Response response, Object command, Bind. Exception errors)
Abstract. Command. Controller public class Display. Course. Controller extends Abstract. Command. Controller { public Display. Course. Controller() { set. Command. Class(Display. Course. Command. class); } protected Model. And. View handle(Http. Servlet. Request request, Http. Servlet. Response response, Object command, Bind. Exception errors) throws Exception { Display. Course. Command display. Command = (Display. Course. Command) command; Course course = course. Service. get. Course(display. Command. get. Id()); return new Model. And. View("course. Detail", "course", course); }
Command Object • A command object is a bean that is meant to hold request parameters for easy access public class Display. Course. Command { private Integer id; public void set. Id(Integer id) { this. id = id; } public Integer get. Id() { return id; } } • Spring will attempt to match any parameters passed in the request to properties in the command object
Pārskats
Formu apstrāde 1. Tipiska web aplikācija satur vismaz vienu formu 1. Lietotājs aizpilda formu un aizsūta to 2. Dati tiek nosūtīti serverim 3. Kad datu apstrāde ir pabeigta, tad lietotājs saņem vienu no variantiem: 1. Lapa ar veiksmīgas izpildes paziņojumu 2. Formas lapa ar kļūdu paziņojumiem Kādā veidā varētu to realizēt? ? ?
Risinājums • Izmantot Abstract. Controller formas attēlošanai • Izmantot Abstract. Command. Controller formas apstrādei • Trūkums: vajag uzturēt divus dažādus kontrolierus, kuri kopā nodarbojas ar viena uzdevuma risināšanu
Simple. Form. Controller • Formu kontroliera funkcionalitāte: • • • Attēlo formu uz HTTP GET pieprasījuma Apstrādā formu uz HTTP POST pieprasījuma Ja notiek kļūda, tad atkārtoti parāda formu public class Register. Student. Controller extends Simple. Form. Controller { public Register. Student. Controller() { set. Command. Class(Student. class); } protected void do. Submit. Action(Object command) throws Exception { Student student = (Student) command; student. Service. enroll. Student(student); } }
Simple. Form. Controller config • Kontrolieris ir uzprojektēts tādā veidā, lai pēc iespējas vairāk atdalīt skatu detaļas no kontroliera koda <bean id="register. Student. Controller" class="com. springinaction. training. mvc. Register. Student. Controller"> <property name="form. View"> <value>new. Student. Form</value> </property> HTTP GET <property name="success. View"> <value>student. Welcome</value> </property>. . . </bean> • Ja ir nepieciešams aizsūtīt datus skatam, tad vajag izmantot on. Submit() metodi
Formu validācija • Viens no svarīgiem uzdevumiem ir formas datu validācija • Par validāciju atbild sekojošais interfeiss public interface Validator { void validate(Object obj, Errors errors); boolean supports(Class clazz); } • Implementējot šī interfeisa validate() metodi vajag pārbaudīt objekta atribūtu vērtības un noraidīt nepareizas vērtības izmantojot Errors objektu
Validatora reģistrēšana • Validatoru vajag piesaistīt kontrolierim konfigurācijas failā <bean id="register. Student. Controller" class="com. springinaction. training. mvc. Register. Student. Controller"> … <property name="validator"> <bean class="com. springinaction. training. mvc. Student. Validator"/> </property> </bean>
Wizard (daudzekrānu) formas • Uzdevums – realizēt aptaujas formu ar 40 jautājumiem Kādā veidā varētu to realizēt? ? ? • Variants – izmantot Simple. Form. Controller, izvietot visus jautājumus vienā lapā • Bet tas nav ērti lietotājam!
Wizard formas • Spring piedāvā kontrolieri, kas atbild par secīgu virzīšanos cauri vairākām lapām Abstract. Wizard. Form. Controller • Līdzīgs parastai formai, bet ir iespējams validēt datus pa daļām (katrā ekrānā savu daļu) • Formas apstrāde parasti notek pašās beigās • Ir iespēja visu procesu atcelt (cancel) jebkurā brīdī
Wizard formas kontrolieris public class Feedback. Wizard. Controller extends Abstract. Wizard. Form. Controller { public Feedback. Wizard. Controller() { set. Command. Class(Feedback. Survey. class); } protected Model. And. View process. Finish( Http. Servlet. Request request, Http. Servlet. Response response, Object command, Bind. Exception errors) throws Exception { Feedback. Survey feedback = (Feedback. Survey) command; feedback. Service. submit. Feedback(feedback); return new Model. And. View("thankyou"); }
Wizard formas konfigurēšana • Formas kontroliera konfigurēšana <bean id="feedback. Controller" class="com. springinaction. training. mvc. My. Wizard. Controller"> <property name="pages"> <list> <value>general</value> <value>instructor</value> <value>course</value> </list> </property> </bean> • Šeit tiek definētas visas lapas
Wizard formas lapas • Pa lapām var pārvietoties ierakstot pieprasījumā parametru ar vārdu "_target. X", kur X ir lapas numurs <form method="POST" action="feedback. htm"> … <input type="submit" value="Back" name="_target 1"> <input type="submit" value="Next" name="_target 3"> </form>
Wizard formas finish/cancel • Formas pabeigšana - tiks izsaukta metode process. Finish() <input type="submit" value="Finish" name="_finish"> • Formas atcelšana - tiks izsaukta metode process. Cancel() <input type="submit" value="Cancel" name="_cancel">
Wizard formas validācija • Formas komandas objekts tiek validēts pa lapām protected void validate. Page( Object command, Errors errors, int page) { Feedback. Survey feedback = (Feedback. Survey) command; Feedback. Validator validator = (Feedback. Validator) get. Validator(); if(page == 0) { validator. validate. Email(feedback. get. Email(), errors); } }
Vairāku darbību apstrāde • • • Visi līdz šīm apskatītie kontrolieri pildīja kādu vienu uzdevumu Veidot vairākus kontrolierus lai pildīt līdzīgus uzdevumus nav īsti racionāli Piemērām, vajag attēlot kursu sarakstu dažādos variantos: • Nesakārtotā veidā • Sakārtoti pēc datuma • Sakārtoti pēc nosaukuma Kādā veidā varētu to realizēt? ? ?
Multi. Action. Controller public class List. Courses. Controller extends Multi. Action. Controller { public Model. And. View courses. Unsorted( Http. Servlet. Request request, Http. Servlet. Response response) {. . . } public Model. And. View courses. Sorted. By. Start. Date( Http. Servlet. Request request, Http. Servlet. Response response) {. . . } public Model. And. View courses. Sorted. By. Name( Http. Servlet. Request request, Http. Servlet. Response response) {. . . }
Metodes vārda noteikšana • Pēc noklusējuma metodes vārds tiek noteikts izmantojot URL sastāvdaļu: • “http: //…/courses. Unsorted. htm” courses. Unsorted() • “http: //…/courses. Sorted. By. Start. Date. htm” courses. Sorted. By. Start. Date() • “http: //…/courses. Sorted. By. Name. htm” courses. Sorted. By. Name()
Metodes vārda noteikšana • Ir pieejami arī citi varianti: • Parameter. Method. Name. Resolver Resolves the execution method name based on a parameter in the request • Properties. Method. Name. Resolver Resolves the name of the execution method by consulting a list of key/value pairs
Pārskats
Throwaway. Controller • Nav Controller hierarhijas daļa public interface Throwaway. Controller { Model. And. View execute() throws Exception; } • Netiek izmantots HTTP pieprasījums vai komandas objekts • Parametri tiek ierakstīti tieši kontrolierī • Ir noderīgi, kad nav modeļa objekta, kuru varētu izmantot • Atšķirībā no citiem kontrolieriem, nav singleton
Throwaway. Controller public class Display. Course. Controller implements Throwaway. Controller { private Integer id; public void set. Id(Integer id) { this. id = id; } public Model. And. View execute() throws Exception { Course course = course. Service. get. Course(id); return new Model. And. View( "course. Detail", "course", course); } }
Interceptors • Iespēja pievienot papildus funkcionalitāti pirms un pēc pieprasījuma • Satur divas interception metodes – pre. Handle un post. Handle • Satur vienu callback metodi – after. Completion • Tiek piesaistīts kontrolieru kopai kopā ar Handler. Mapping
Piemērs: Interceptor config <beans> <bean id="handler. Mapping" class="org. springframework. web. servlet. handler. Simple. Url. Handler. Mapping"> <property name="interceptors"> <list> <ref bean="office. Hours. Interceptor"/> </list> </property> <property name="mappings"> <value> /*. form=edit. Account. Form. Controller </value> </property> </bean> <bean id="office. Hours. Interceptor" class="samples. Time. Based. Access. Interceptor"> <property name="opening. Time" value="9"/> <property name="closing. Time" value="18"/> </bean> <beans>
Piemērs: Interceptor kods public class Time. Based. Access. Interceptor extends Handler. Interceptor. Adapter {. . . public boolean pre. Handle(Http. Servlet. Request request, Http. Servlet. Response response, Object handler) throws Exception { Calendar cal = Calendar. get. Instance(); int hour = cal. get(HOUR_OF_DAY); if (opening. Time <= hour < closing. Time) { return true; } else { response. send. Redirect( "http: //host. com/outside. Office. Hours. html"); return false; } } }
View Resolving • A view is a bean that renders results to the user • Spring MVC consults view resolvers when trying to determine which View bean to use
View. Resolver implementācijas Spring piedāvā četras pamata View. Resolver interfeisa implementācijas • Internal. Resource. View. Resolver – • Resolves logical view names into View objects that are rendered using template file resources (such as JSPs and Velocity templates) • Bean. Name. View. Resolver • Resolves logical view names into View beans in the Dispatcher. Servlet’s application context
View. Resolver implementācijas • Resource. Bundle. View. Resolver – • Mappings are contained within a properties file • Supports internationalization • Xml. View. Resolver – • Mappings are contained within a XML file that is separate from the Dispatcher. Servlet’s application context • Velocity. View. Resolver • Free. Marker. View. Resolver
View klases Spring piedāvā sekojošas skatu apakšklases: • Jstl. View • Attēlo view. Name par JSP lapu, kurā uzstādīti arī JSTL tagu bibliotēkām vajadzīgie mainīgie, piemēram, lokalizācija. • Redirect. View • Veic HTTP Redirect • Velocity. Layout. View, Velocity. Toolbox. View, Velocity. View • Velocity skati ar vai bez papildu objektiem, ko konfigurē toolbox. xml • Free. Marker. View
Internacionalizācija 1. Spring dod iespēju automātiski izvēlēties ziņojumu tekstus izmantojot lietotāja lokāli 2. Dispatcher. Servlet izmanto Locale. Resolver lai noteikt klienta lokāli 3. Accept. Header. Locale. Resolver 1. izmantot HTTP "Accept-language" hederi lokāles atrašanai 4. Cookie. Locale. Resolver 1. izmantot cookies lokāles atrašanai 5. Session. Locale. Resolver 1. lokāle liek glabāta sesijā
Internacionalizācija • Lokāles izmaiņas funkcionalitātei var izmantot klasi Locale. Change. Interceptor, to ir jāpieliek klāt kādam Handler. Mapping • Visbeidzot, teksta ziņojumus ir jāieraksta failos zem /WEB -INF/classes/: #msg_name=msg_text • • messages_en. properties messages_de. properties utml greetings=Hello! true=Yes false=No JSP lapā ziņojumus var ielikt izmantojot tagu <fmf: message key="<msg_name>"> <fmf: message key=“hello">
Springa tēmas • Viegli konfigurējamas un izpildes laikā nomaināmas aplikācijas "ādas“
Springa tēmas • Tēma (theme) ir statisko resursu kolekcija, kas ietekmē aplikācijas vizuālo stilu • style sheets (css), images • Resource. Bundle. Theme. Source ielāde properties failus no classpath saknes /WEB-INF/classes/ • Daudz līdzības ar internacionalizācijas konfigurēšanu
Springa tēmas • Properties faila piemērs: style. Sheet=/themes/cool/style. css background=/themes/cool/img/cool. Bg. jpg • JSP lapā ir jāizmanto <spring: theme> tagu <%@ taglib prefix="spring" uri="http: //www. springframework. org/tags"%> <html> <head> <link rel="stylesheet" href="<spring: theme code="style. Sheet"/>" type="text/css"/> </head> <body background="<spring: theme code="background"/>">. . . </body> </html>
Failu augšupielāde • Spring piedāvā failu augšupielādes funkcionalitāti (multipart file upload) • Atbalsta Common. File. Upload un COS File. Upload <h 1>Please upload a file</h 1> <form method="post" action="upload. form" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit"/> </form> <bean id="multipart. Resolver“ class="org. springframework. web. multipart. commons. Commons. Multipart. Resolver"> <property name="max. Upload. Size" value="100000"/> </bean>
Izņēmumu apstrāde • Viena no Springa īpatnībām - vairums izņēmumu ir Runtime. Exception apakštipi, tos nevajag metodēs ķert vai deklarēt • Ir piedāvāta iespēja apstrādāt negaidītas kļūdas • Simple. Mapping. Exception. Resolver • Iespēja piesaistīt skatu izņēmuma klasei konfigurācijas failā • Handler. Exception. Resolver • Interfeiss, kuru vajag implementēt, lai apstrādāt kontrolieru kļūdas
Simple. Mapping. Exception. Resolver <bean id="exception. Resolver" class="org. springframework. web. servlet. handler. Simple. Mapping. Exception. Resolver"> <property name="exception. Mappings"> <props> <prop key="java. lang. Exception"> friendly. Error </prop> </props> </property> </bean>
Countries piemērs • Spring piemēru, kuru var palaist un apskatīties kodu var atrast zem: spring-framework-2. 0. 6samplescountries Special Spring MVC features: • paged list navigation • locale and theme switching • localized view definitions • page composition through view definitions • generation of PDF and Excel views
Resursi • Spring Home http: //www. springframework. org • C. Walls, R. Breidenbach. Spring in Action http: //www. manning. com/walls 2/ • Spring Web MVC Framework http: //www. springframework. org/docs/reference/mvc. html • Spring MVC step-by-step Tutorial http: //www. springframework. org/docs/MVC-step-bystep/Spring-MVC-step-by-step. html
Resursi • Model-View-Controller pattern by Sun http: //java. sun. com/blueprints/patterns/MVC. html • Core J 2 EE Patterns - Front Controller http: //java. sun. com/blueprints/corej 2 eepatterns/Patt erns/Front. Controller. html
- Slides: 76