Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00018 002241 12921103 na godz. na dobę w sumie
Spring MVC. Przewodnik dla początkujących - ebook/pdf
Spring MVC. Przewodnik dla początkujących - ebook/pdf
Autor: Liczba stron: 280
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-0520-5 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> java - programowanie
Porównaj ceny (książka, ebook (-40%), audiobook).

Wykorzystaj możliwości Spring MVC! Nauka przez praktykę, mniej teorii, więcej ćwiczeń

Spring MVC to szkielet dostarczający architekturę model-widok-kontroler (ang. Model View Controller). Z jego pomocą można zbudować wiele zaawansowanych aplikacji internetowych oraz REST-owe API. Spring MVC zapewnia niezwykłą elastyczność oraz gwarantuje programistom wygodę. To leży u podstaw jego ogromnej popularności. Wokół tego szkieletu powstała też duża społeczność, zawsze chętna do udzielania pomocy.

Jeżeli chcesz poznać możliwości Spring MVC i zbudować z nim Twoją pierwszą aplikację, nie mogłeś trafić lepiej. Ta książka wprowadzi Cię w najważniejsze zagadnienia oraz w niezwykle przejrzysty sposób przedstawi dostępne możliwości. Na samym początku zainstalujesz środowisko JDK oraz przydatne narzędzia, takie jak Maven i Spring Tool Suite. Budowana tu przykładowa aplikacja to sklep internetowy działający na serwerze Apache Tomcat. Z kolejnych rozdziałów nauczysz się, jak korzystać z kontrolerów, bibliotek znaczników oraz walidatorów. Książka ta jest obowiązkową lekturą dla wszystkich początkujących użytkowników Spring MVC.

Dzięki tej książce:
Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: Spring MVC: Beginner s Guide Tłumaczenie: Andrzej Bobak ISBN: 978-83-283-0517-5 Copyright © 2014 Packt Publishing First published in the English language under the title ‘Spring MVC: Beginner s Guide’ (9781783284870). Polish edition copyright © 2015 by Helion S.A. All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/sprimv.zip Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/sprimv Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci O autorze O recenzentach Przedmowa Rozdzia(cid:239) 1. Konfiguracja (cid:258)rodowiska do programowania w Springu Instalacja Javy Konfiguracja narz(cid:218)dzia do budowy Instalacja serwera WWW Konfiguracja (cid:258)rodowiska programistycznego Tworzenie pierwszego projektu opartego na Springu MVC Podsumowanie 7 8 9 15 15 18 19 21 25 36 Rozdzia(cid:239) 2. Architektura Springa MVC — projektowanie Twojego sklepu internetowego 37 Serwlet przekazuj(cid:200)cy Kontekst aplikacji internetowej Kontekst konfiguracji aplikacji internetowej Resolwery widoków Model – widok – kontroler Przegl(cid:200)d przep(cid:239)ywu (cid:285)(cid:200)dania w Springu MVC Architektura aplikacji internetowej Warstwa domeny Warstwa danych Warstwa us(cid:239)ug Rzut oka na architektur(cid:218) aplikacji internetowej Podsumowanie 37 40 44 46 49 50 51 51 57 64 69 71 Kup książkęPoleć książkę Spis tre(cid:286)ci Rozdzia(cid:239) 3. Kontroluj swój sklep za pomoc(cid:200) kontrolerów Definiowanie kontrolera Rola kontrolera w Springu MVC Interfejs HandlerMapping U(cid:285)ywanie szablonów wzorców URI U(cid:285)ywanie zmiennych tablicowych Zrozumie(cid:202) parametry (cid:285)(cid:200)dania Podsumowanie Rozdzia(cid:239) 4. Praca z bibliotekami znaczników Springa Prezentowanie i przetwarzanie formularzy Dostosowywanie wi(cid:200)zania danych Wyodr(cid:218)bnianie napisów U(cid:285)ywanie znaczników Spring Security Podsumowanie Rozdzia(cid:239) 5. Praca z resolwerami widoków Odwzorowywanie widoków Widok przekierowuj(cid:200)cy Serwowanie statycznych zasobów (cid:191)(cid:200)dania typu multipart w praktyce ContentNegotiatingViewResolver w praktyce Praca z resolwerem obs(cid:239)ugi wyj(cid:200)tków Podsumowanie Rozdzia(cid:239) 6. Przechwytywacze w akcji Praca z przechwytywaczami Internacjonalizacja (i18n) Raportowanie zdarze(cid:241) Warunkowe przekierowanie Podsumowanie Rozdzia(cid:239) 7. Walidatory w akcji Walidacja beanów W(cid:239)asna walidacja z u(cid:285)yciem JSR-303/walidacji beanów Walidacja Springa Podsumowanie 4 73 73 78 79 79 84 89 96 97 97 105 109 111 121 123 123 125 128 131 137 141 147 149 149 155 160 163 168 169 169 175 179 187 Kup książkęPoleć książkę Spis tre(cid:286)ci Rozdzia(cid:239) 8. Ajax i us(cid:239)ugi REST Wprowadzenie do REST Obs(cid:239)uga us(cid:239)ugi internetowej za pomoc(cid:200) Ajaksa Podsumowanie Rozdzia(cid:239) 9. Apache Tiles oraz Spring Web Flow w praktyce Praca ze Spring Web Flow Zwi(cid:218)kszanie mo(cid:285)liwo(cid:258)ci ponownego u(cid:285)ycia kodu interfejsu u(cid:285)ytkownika za pomoc(cid:200) Apache Tiles Podsumowanie Rozdzia(cid:239) 10. Testowanie aplikacji Testowanie jednostkowe Testy integracyjne z u(cid:285)yciem szkieletu Spring Test Context Podsumowanie Dodatek A. Gradle — alternatywne narz(cid:218)dzie do budowy projektów Instalacja Gradle Skrypt budowy Twojego projektu w Gradle Zrozumie(cid:202) skrypt Gradle Dodatek B. Odpowiedzi do krótkich testów Rozdzia(cid:239) 2. Architektura Springa MVC — projektowanie Twojego sklepu internetowego Rozdzia(cid:239) 3. Kontroluj swój sklep za pomoc(cid:200) kontrolerów Rozdzia(cid:239) 5. Praca z resolwerami widoków Rozdzia(cid:239) 6. Przechwytywacze w akcji Rozdzia(cid:239) 9. Apache Tiles oraz Spring Web Flow w praktyce Skorowidz 189 189 204 212 213 213 239 247 249 249 253 265 267 267 268 269 271 271 272 272 272 273 275 5 Kup książkęPoleć książkę Spis tre(cid:286)ci Zespó(cid:239) Author Amuthan G Reviewers Rafa(cid:239) Borowiec Pawan Chopra Rubén Clemente Serna Acquisition Editor Vinay Argekar Content Development Editor Azharuddin Sheikh Technical Editors Monica John Neha Mankare Shiny Poojary Copy Editors Gladson Monteiro Insiya Morbiwala Aditya Nair Stuti Srivastava Project Coordinators Kinjal Bari Wendell Palmer Proofreaders Simran Bhogal Stephen Copestake Maria Gould Ameesha Green Paul Hindle Indexer Hemangini Bari Graphics Disha Haria Abhinash Sahu Producti on Coordinator Aparna Bhagat Cover Work Aparna Bhagat 6 Kup książkęPoleć książkę 9 Apache Tiles oraz Spring Web Flow w praktyce Podczas implementacji aplikacji internetowej musisz mie(cid:202) na uwadze mo(cid:285)liwo(cid:258)(cid:202) ponownego u(cid:285)ycia oraz utrzymywania kodu. Spring Web Flow jest niezale(cid:285)nym szkieletem u(cid:239)atwiaj(cid:200)cym pisanie wysoce konfi- gurowalnych aplikacji internetowych opartych na przep(cid:239)ywach. Z kolei Apache Tiles jest popularnym otwartym szkieletem usprawniaj(cid:200)cym tworzenie aplikacji opartych na szablonach wielokrotnego u(cid:285)ytku. W tym rozdziale nauczysz si(cid:218), jak w(cid:239)(cid:200)czy(cid:202) wspomniane szkielety do aplikacji Springa MVC. Apache Tiles znacz(cid:200)co poprawia mo(cid:285)liwo(cid:258)(cid:202) ponownego u(cid:285)ycia szablonów interfejsu u(cid:285)ytkownika. Z kolei Spring Web Flow zmniejsza koszty utrzymania logiki aplikacji. Pami(cid:218)taj, (cid:285)e oba szkielety s(cid:200) niezale(cid:285)ne. Nie musisz u(cid:285)ywa(cid:202) ich jednocze(cid:258)nie. Apache Tiles jest zazwyczaj u(cid:285)ywany, by zmniejszy(cid:202) rozmiar nadmiarowego kodu po stronie interfejsu u(cid:285)ytkownika. Natomiast Spring Web Flow umo(cid:285)liwia implementacj(cid:218) stanowych aplikacji internetowych z kontrolowanym prze- p(cid:239)ywem nawigacji. Po zapoznaniu si(cid:218) z zawarto(cid:258)ci(cid:200) rozdzia(cid:239)u b(cid:218)dziesz mia(cid:239) poj(cid:218)cie o poni(cid:285)- szych zagadnieniach: (cid:81) jak budowa(cid:202) aplikacje oparte na przep(cid:239)ywie za pomoc(cid:200) Spring Web Flow; (cid:81) jak dekomponowa(cid:202) strony, u(cid:285)ywaj(cid:200)c szablonów wielokrotnego u(cid:285)ycia Apache Tiles. Praca ze Spring Web Flow Spring Web Flow u(cid:239)atwia implementacj(cid:218) aplikacji internetowych opartych na przep(cid:239)ywie. Przep(cid:239)yw w aplikacji internetowej jest seri(cid:200) kroków prowadz(cid:200)cych u(cid:285)ytkownika przez biznesow(cid:200) operacj(cid:218), tak(cid:200) jak meldunek w hotelu, podanie o prac(cid:218) lub zamówienie zawarto(cid:258)ci koszyka. Zazwyczaj przep(cid:239)yw ma jasny punkt pocz(cid:200)tkowy oraz ko(cid:241)cowy, obs(cid:239)uguje wiele (cid:285)(cid:200)da(cid:241) i odpowie- dzi, a u(cid:285)ytkownik musi odwiedzi(cid:202) zbiór ekranów w okre(cid:258)lonej kolejno(cid:258)ci, by zrealizowa(cid:202) przep(cid:239)yw. Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych We wszystkich poprzednich rozdzia(cid:239)ach odpowiedzialno(cid:258)(cid:202) za zdefiniowanie przep(cid:239)ywu na stronie (interfejsie u(cid:285)ytkownika) spoczywa(cid:239)a na kontrolerze. Przep(cid:239)yw by(cid:239) podzielony na pojedyncze kontrolery i widoki. Na przyk(cid:239)ad odwzorowywa(cid:239)e(cid:258) (cid:285)(cid:200)danie na metod(cid:218) kontrolera, a ona zwra- ca(cid:239)a nazw(cid:218) odpowiedniego widoku generowanego jako odpowied(cid:283). Takie podej(cid:258)cie jest proste i wystarczaj(cid:200)ce dla podstawowych przep(cid:239)ywów stron. Jednak gdy przep(cid:239)yw w aplikacji staje si(cid:218) coraz bardziej skomplikowany, utrzymanie du(cid:285)ego i z(cid:239)o(cid:285)onego przep(cid:239)ywu na stronie staje si(cid:218) k(cid:239)opotliwe. Je(cid:258)li planujesz napisanie z(cid:239)o(cid:285)onej aplikacji wykorzystuj(cid:200)cej przep(cid:239)ywy, Spring Web Flow (SWF) mo(cid:285)e si(cid:218) okaza(cid:202) bardzo pomocny. Za jego pomoc(cid:200) mo(cid:285)esz zdefiniowa(cid:202) i wykona(cid:202) przep(cid:239)ywy w interfejsie u(cid:285)ytkownika (User Interface — UI) swojej aplikacji internetowej. Pora zaj(cid:200)(cid:202) si(cid:218) Spring Web Flow i zdefiniowa(cid:202) kilka przep(cid:239)ywów stron w projekcie. W poprzednim rozdziale uda(cid:239)o Ci si(cid:218) zaimplementowa(cid:202) funkcjonalno(cid:258)(cid:202) koszyka. Jednak bez mo(cid:285)liwo(cid:258)ci przeprowadzenia zakupu i wysy(cid:239)ki do klienta jest ona bezu(cid:285)yteczna. Teraz zaimple- mentujesz brakuj(cid:200)ce funkcjonalno(cid:258)ci w dwóch etapach. Najpierw utworzysz po stronie serwera wymagane us(cid:239)ugi, obiekty domenowe oraz implementacj(cid:218) repozytorium. Nie s(cid:200) one bezpo(cid:258)rednio powi(cid:200)zane ze Spring Web Flow, jednak potrzebujesz ich do przetwarzania zamówienia. W dru- gim etapie ustalisz definicj(cid:218) Spring Web Flow, u(cid:285)ywaj(cid:200)c(cid:200) zaimplementowanych us(cid:239)ug serwe- rowych, by wykona(cid:202) ustalony przep(cid:239)yw. Ustawisz te(cid:285) konfiguracj(cid:218) oraz definicj(cid:218) przep(cid:239)ywu. (cid:109)wiczenie praktyczne — implementacja us(cid:239)ugi obs(cid:239)uguj(cid:200)cej zamówienie Rozpoczniesz od implementacji us(cid:239)ugi serwerowej przetwarzaj(cid:200)cej zamówienie. Wykonaj poni(cid:285)sze kroki: 1. Utwórz klas(cid:218) o nazwie Address w pakiecie com.packt.webstore.domain w katalogu src/main/java. Nast(cid:218)pnie umie(cid:258)(cid:202) w niej zawarto(cid:258)(cid:202) listingu 9.1. Zauwa(cid:285), (cid:285)e nie ma w nim implementacji getterów, setterów oraz metod hashCode i equals. Dodaj je podczas tworzenia klasy. Listing 9.1. Implementacja klasy Address package com.packt.webstore.domain; import java.io.Serializable; public class Address implements Serializable{ private static final long serialVersionUID = -530086768384258062L; private String doorNo; private String streetName; private String areaName; private String state; private String country; private String zipCode; 214 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce // Tu dodaj gettery i settery dla wszystkich pól. // Nast(cid:218)pnie nadpisz metody equals i hashCode, by opiera(cid:239)y si(cid:218) na wszystkich polach. // Kod mo(cid:285)esz pobra(cid:202) ze strony: www.helion.pl/ksiazki/sprimv.html. } 2. Utwórz w tym samym pakiecie klas(cid:218) Customer i umie(cid:258)(cid:202) w niej zawarto(cid:258)(cid:202) listingu 9.2. Listing 9.2. Implementacja klasy Customer package com.packt.webstore.domain; import java.io.Serializable; public class Customer implements Serializable{ private static final long serialVersionUID = 2284040482222162898L; private String customerId; private String name; private Address billingAddress; private String phoneNumber; public Customer() { super(); this.billingAddress = new Address(); } public Customer(String customerId, String name) { this(); this.customerId = customerId; this.name = name; } // Tu dodaj gettery i settery dla wszystkich pól. // Nast(cid:218)pnie nadpisz metody equals i hashCode, by opiera(cid:239)y si(cid:218) na wszystkich polach. // Kod mo(cid:285)esz pobra(cid:202) ze strony: www.helion.pl/ksiazki/sprimv.html. } 3. W tym samym pakiecie utwórz klas(cid:218) domenow(cid:200) ShippingDetail i umie(cid:258)(cid:202) w niej zawarto(cid:258)(cid:202) listingu 9.3. Listing 9.3. Implementacja klasy ShippingDetail package com.packt.webstore.domain; import java.io.Serializable; import java.util.Date; import org.springframework.format.annotation.DateTimeFormat; public class ShippingDetail implements Serializable{ private static final long serialVersionUID = 6350930334140807514L; private String name; @DateTimeFormat(pattern = dd/MM/yyyy ) private Date shippingDate; private Address shippingAddress; public ShippingDetail() { this.shippingAddress = new Address(); 215 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych } // Dodaj gettery i settery dla powy(cid:285)szych pól. } 4. W bie(cid:285)(cid:200)cym pakiecie utwórz jeszcze jedn(cid:200) klas(cid:218) domenow(cid:200), o nazwie Order, i umie(cid:258)(cid:202) w niej zawarto(cid:258)(cid:202) listingu 9.4. Listing 9.4. Implementacja klasy Order package com.packt.webstore.domain; import java.io.Serializable; public class Order implements Serializable{ private static final long serialVersionUID = -3560539622417210365L; private Long orderId; private Cart cart; private Customer customer; private ShippingDetail shippingDetail; public Order() { this.customer = new Customer(); this.shippingDetail = new ShippingDetail(); } // Tu dodaj gettery i settery dla wszystkich pól. // Nast(cid:218)pnie nadpisz metody equals i hashCode, by opiera(cid:239)y si(cid:218) na polu orderId. // Kod mo(cid:285)esz pobra(cid:202) ze strony: www.helion.pl/ksiazki/sprimv.html. } 5. Spraw, (cid:285)eby klasy domenowe Product, CartItem oraz Cart by(cid:239)y serializowalne, implementuj(cid:200)c w nich interfejs Serializable (java.io.Serializable). Dodaj w nich równie(cid:285) pole serialVersionUID. 6. Utwórz interfejs o nazwie OrderRepository w pakiecie com.packt.webstore.domain. (cid:180)repository w katalogu src/main/java i umie(cid:258)(cid:202) w nim przedstawion(cid:200) poni(cid:285)ej deklaracj(cid:218) metody: Long saveOrder(Order order); 7. Utwórz klas(cid:218) o nazwie InMemoryOrderRepositoryImpl w pakiecie com.packt.webstore. (cid:180)domain.repository.impl w katalogu src/main/java i umie(cid:258)(cid:202) w niej zawarto(cid:258)(cid:202) listingu 9.5. Listing 9.5. Implementacja klasy InMemoryOrderRepositoryImpl package com.packt.webstore.domain.repository.impl; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Repository; import com.packt.webstore.domain.Order; import com.packt.webstore.domain.repository.OrderRepository; @Repository 216 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce public class InMemoryOrderRepositoryImpl implements OrderRepository{ private Map Long, Order listOfOrders; private long nextOrderId; public InMemoryOrderRepositoryImpl() { listOfOrders = new HashMap Long, Order (); nextOrderId = 1000; } public Long saveOrder(Order order) { order.setOrderId(getNextOrderId()); listOfOrders.put(order.getOrderId(), order); return order.getOrderId(); } private synchronized long getNextOrderId() { return nextOrderId++; } } 8. Otwórz interfejs OrderService w pakiecie com.packt.webstore.service w katalogu src/main/java i umie(cid:258)(cid:202) w nim deklaracj(cid:218) metody przedstawion(cid:200) w listingu 9.6. Listing 9.6. Interfejs OrderService package com.packt.webstore.domain.repository; import com.packt.webstore.domain.Order; public interface OrderRepository { void processOrder(String productId, long quantity); Long saveOrder(Order order); } 9. Otwórz klas(cid:218) OrderServiceImpl znajduj(cid:200)c(cid:200) si(cid:218) w pakiecie com.packt.webstore. (cid:180)service.impl w katalogu src/main/java i umie(cid:258)(cid:202) w niej referencje przedstawione w listingu 9.7. Listing 9.7. Referencje do dodania w klasie OrderServiceImpl @Autowired private OrderRepository orderRepository; @Autowired private CartService cartService; 10. Umie(cid:258)(cid:202) przedstawion(cid:200) w listingu 9.8 implementacj(cid:218) metody saveOrder w klasie OrderServiceImpl. Listing 9.8. Implementacja metody saveOrder public Long saveOrder(Order order) { Long orderId = orderRepository.saveOrder(order); 217 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych cartService.delete(order.getCart().getCartId()); return orderId; } 11. Utwórz klas(cid:218) wyj(cid:200)tku o nazwie InvalidCartException w pakiecie com.packt.webstore. (cid:180)exception w katalogu src/main/java i umie(cid:258)(cid:202) w niej zawarto(cid:258)(cid:202) listingu 9.9. Listing 9.9. Implementacja klasy InvalidCartException package com.packt.webstore.exception; public class InvalidCartException extends RuntimeException { private static final long serialVersionUID = -5192041563033358491L; private String cartId; public InvalidCartException(String cartId) { this.cartId = cartId; } public String getCartId() { return cartId; } } 12. Otwórz interfejs CartService znajduj(cid:200)cy si(cid:218) w pakiecie com.packt.webstore. (cid:180)service w katalogu src/main/java i umie(cid:258)(cid:202) w nim poni(cid:285)sz(cid:200) sygnatur(cid:218) metody: Cart validate(String cartId); 13. Nast(cid:218)pnie otwórz klas(cid:218) CartServiceImpl znajduj(cid:200)c(cid:200) si(cid:218) w pakiecie com.packt. (cid:180)webstore.service.impl w katalogu src/main/java i umie(cid:258)(cid:202) w niej implementacj(cid:218) metody validate zaprezentowan(cid:200) w listingu 9.10. Listing 9.10. Implementacja metody validate public Cart validate(String cartId) { Cart cart = cartRepository.read(cartId); if(cart==null || cart.getCartItems().size()==0) { throw new InvalidCartException(cartId); } return cart; } Co si(cid:218) w(cid:239)a(cid:258)nie wydarzy(cid:239)o? Przeprowadzone operacje s(cid:200) Ci ju(cid:285) znane. Utworzy(cid:239)e(cid:258) kilka klas domenowych (Address, Customer, ShippingDetail oraz Order), interfejs OrderRepository oraz jego implementacj(cid:218) w klasie InMe (cid:180)moryOrderRepositoryImpl przechowuj(cid:200)c(cid:200) przetworzone obiekty klasy domenowej Order. Na koniec utworzy(cid:239)e(cid:258) interfejs OrderService oraz jego implementacj(cid:218) w klasie OrderServiceImpl. 218 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce Na pierwszy rzut oka wszystkie operacje wygl(cid:200)daj(cid:200) jak zwykle, s(cid:200) jednak pewne drobne detale wymagaj(cid:200)ce wyja(cid:258)nienia. Jak zauwa(cid:285)y(cid:239)e(cid:258), utworzone w krokach 1. – 4. klasy domenowe imple- mentuj(cid:200) interfejs Serializable. Oprócz tego w kroku 5. doda(cid:239)e(cid:258) wspomniany interfejs do istnie- j(cid:200)cych klas domenowych Product, CartItem oraz Cart. Zrobi(cid:239)e(cid:258) to, poniewa(cid:285) pó(cid:283)niej b(cid:218)dziesz u(cid:285)ywa(cid:202) tych obiektów domenowych w szkielecie Spring Web Flow. On z kolei b(cid:218)dzie przecho- wywa(cid:202) wspomniane obiekty w sesji, by zarz(cid:200)dza(cid:202) stanem pomi(cid:218)dzy przep(cid:239)ywami strony. Dane sesji mog(cid:200) zosta(cid:202) zapisane na dysku lub przes(cid:239)ane do innego serwera WWW w klastrze. Podczas pobierania obiektu sesji z dysku Spring Web Flow zdeserializuje obiekt domenowy (bean for- mularza), by zarz(cid:200)dza(cid:202) stanem strony. Dlatego te(cid:285) obiekty domenowe i beany formularza musz(cid:200) by(cid:202) serializowalne. Spring Web Flow u(cid:285)ywa bytu Snapshot, by przechowa(cid:202) stany w sesji. Kroki 6. – 13. nie wymagaj(cid:200) szerszego wyja(cid:258)nienia. Utworzy(cid:239)e(cid:258) interfejsy OrderRepository i OrderService oraz ich implementacje w klasach InMemoryOrderRepositoryImpl i OrderService (cid:180)Impl. Ich zadaniem jest zapisywanie obiektu domenowego Order. Metoda saveOrder klasy OrderServiceImpl usuwa obiekt Cart z CartRepository po zapisaniu obiektu domenowego klasy Order. Uda(cid:239)o Ci si(cid:218) utworzy(cid:202) wszystkie us(cid:239)ugi oraz obiekty domenowe po stronie serwera wyma- gane do rozpocz(cid:218)cia prac nad konfiguracj(cid:200) i definicj(cid:200) Spring Web Flow. (cid:109)wiczenie praktyczne — implementacja przep(cid:239)ywu zakupu W tym (cid:202)wiczeniu wzbogacisz aplikacj(cid:218) o wsparcie Spring Web Flow. Nast(cid:218)pnie zdefiniujesz przep(cid:239)yw zamówienia zawarto(cid:258)ci koszyka. Wykonaj poni(cid:285)sze kroki: 1. Otwórz plik pom.xml. Znajdziesz go w katalogu g(cid:239)ównym projektu. 2. Na dole okna prezentuj(cid:200)cego zawarto(cid:258)(cid:202) pliku znajduje si(cid:218) kilka zak(cid:239)adek. Przejd(cid:283) do tej o nazwie Dependencies i u(cid:285)yj przycisku Add w sekcji Dependencies. 3. Pojawi si(cid:218) okno o nazwie Select Dependency. W polu Group Id wprowad(cid:283) org.springframework.webflow, a w Artifact Id spring-webflow. Polu Version nadaj warto(cid:258)(cid:202) 2.3.3.RELEASE, a polu Scope warto(cid:258)(cid:202) compile. Nast(cid:218)pnie naci(cid:258)nij przycisk OK i zapisz plik pom.xml. 4. W katalogu src/main/webapp/WEB-INF/ utwórz podkatalog flows/checkout/. W nim utwórz plik checkout-flow.xml i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.11. Listing 9.11. Definicja przep(cid:239)ywów w pliku checkout-flow.xml ?xml version= 1.0 encoding= UTF-8 ? flow xmlns= http://www.springframework.org/schema/webflow xmlns:xsi= http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation= http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd var name= order class= com.packt.webstore.domain.Order / action-state id= addCartToOrder 219 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych evaluate expression= cartServiceImpl.validate(requestParameters.cartId) (cid:180)result= order.cart / transition to= InvalidCartWarning (cid:180)on-exception= com.packt.webstore.exception.InvalidCartException / transition to= collectCustomerInfo / /action-state view-state id= collectCustomerInfo view= collectCustomerInfo.jsp (cid:180)model= order transition on= customerInfoCollected to= collectShippingDetail / /view-state view-state id= collectShippingDetail model= order transition on= shippingDetailCollected to= orderConfirmation / transition on= backToCollectCustomerInfo to= collectCustomerInfo / /view-state view-state id= orderConfirmation transition on= orderConfirmed to= processOrder / transition on= backToCollectShippingDetail (cid:180)to= collectShippingDetail / /view-state action-state id= processOrder evaluate expression= orderServiceImpl.saveOrder(order) (cid:180)result= order.orderId / transition to= thankCustomer / /action-state view-state id= InvalidCartWarning transition to= endState / /view-state view-state id= thankCustomer model= order transition to= endState / /view-state end-state id= endState / end-state id= cancelCheckout view = checkOutCancelled.jsp / global-transitions transition on = cancel to= endState / /global-transitions /flow 5. Otwórz plik DispatcherServlet-context.xml, zawieraj(cid:200)cy kontekst konfiguracji aplikacji internetowej, i umie(cid:258)(cid:202) na pocz(cid:200)tku znacznika beans poni(cid:285)szy atrybut, definiuj(cid:200)cy przestrze(cid:241) nazw: xmlns:webflow-config= http://www.springframework.org/schema/ (cid:180)webflow-config 6. Dodaj przedstawiony poni(cid:285)ej fragment kodu do atrybutu xsi:schemaLocation znacznika beans : http://www.springframework.org/schema/webflow-config http://www. (cid:180)springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd 220 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce 7. Umie(cid:258)(cid:202) przedstawione w listingu 9.12 znaczniki konfiguracji przep(cid:239)ywu w pliku konfiguracji kontekstu aplikacji internetowej (DispatcherServlet-context.xml). Listing 9.12. Znaczniki konfiguracji przep(cid:239)ywu w aplikacji webflow-config:flow-executor id= flowExecutor flowregistry= flowRegistry / webflow-config:flow-registry id= flowRegistry base-path= /WEBINF/flows webflow-config:flow-location path= /checkout/ (cid:180)checkout-flow.xml id= checkout / /webflow-config:flow-registry 8. Na koniec w pliku DispatcherServlet-context.xml zdefiniuj beany FlowHandlerMapping oraz FlowHandlerAdapter, przedstawione w listingu 9.13. Nast(cid:218)pnie zapisz plik. Listing 9.13. Deklaracja beanów FlowHandlerMapping oraz FlowHandlerAdapter bean id= flowHandlerMapping class= org.springframework.webflow.mvc.servlet.FlowHandlerMapping property name= flowRegistry ref= flowRegistry / /bean bean id= flowHandlerAdapter class= org.springframework.webflow.mvc. (cid:180)servlet.FlowHandlerAdapter property name= flowExecutor ref= flowExecutor / /bean Co si(cid:218) w(cid:239)a(cid:258)nie wydarzy(cid:239)o? W krokach 1. – 3. doda(cid:239)e(cid:258) do projektu zale(cid:285)no(cid:258)(cid:202) Spring Web Flow za po(cid:258)rednictwem Mavena. Na nim spoczywa odpowiedzialno(cid:258)(cid:202) za pobranie i skonfigurowanie wymaganych plików JAR powi(cid:200)zanych z przep(cid:239)ywem w Twojej aplikacji. W kroku 4. utworzy(cid:239)e(cid:258) pierwsz(cid:200) definicj(cid:218) prze- p(cid:239)ywu w pliku checkout-flow.xml w katalogu src/main/webapp/WEB-INF/flows/checkout/. Spring Web Flow u(cid:285)ywa pliku z definicj(cid:200) przep(cid:239)ywów, aby nim sterowa(cid:202). Pora zapozna(cid:202) si(cid:218) z podstawowymi za(cid:239)o(cid:285)eniami Spring Web Flow, aby zrozumie(cid:202), jakie informacje zosta(cid:239)y umiesz- czone w pliku. Po przyswojeniu sobie za(cid:239)o(cid:285)e(cid:241) wrócisz do analizy zawarto(cid:258)ci pliku checkout- flow.xml. Zrozumie(cid:202) definicj(cid:218) przep(cid:239)ywu Definicja przep(cid:239)ywu sk(cid:239)ada si(cid:218) ze zbioru stanów. Ka(cid:285)dy stan posiada unikalny identyfikator w definicji przep(cid:239)ywu. W Spring Web Flow istnieje sze(cid:258)(cid:202) typów stanów: (cid:81) start–state. Ka(cid:285)dy przep(cid:239)yw musi posiada(cid:202) jeden stan pocz(cid:200)tkowy, pomagaj(cid:200)cy w tworzeniu startowego stanu przep(cid:239)ywu. Pami(cid:218)taj, (cid:285)e je(cid:258)li stan startowy nie jest zdefiniowany, staje si(cid:218) nim pierwszy stan umieszczony w definicji przep(cid:239)ywu. 221 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych (cid:81) action–state. Przep(cid:239)yw mo(cid:285)e mie(cid:202) dowoln(cid:200) liczb(cid:218) stanów akcji. Ka(cid:285)dy taki stan wywo(cid:239)uje konkretn(cid:200) akcj(cid:218). Jest ni(cid:200) zazwyczaj interakcja z us(cid:239)ugami serwerowymi, np. wywo(cid:239)anie metody w beanie Springa. Spring Web Flow u(cid:285)ywa j(cid:218)zyka wyra(cid:285)e(cid:241) Springa (Spring Expression Language) do interakcji z serwerowymi beanami us(cid:239)ug. (cid:81) view–state. Stan widoku wskazuje nazw(cid:218) widoku oraz model wchodz(cid:200)ce w interakcje z u(cid:285)ytkownikiem. Przep(cid:239)yw mo(cid:285)e mie(cid:202) zdefiniowane wiele stanów widoków. Je(cid:285)eli atrybut view nie jest zdefiniowany, wtedy identyfikator stanu widoku jest u(cid:285)ywany jako nazwa widoku. (cid:81) decision–state. Stan decyzyjny jest u(cid:285)ywany do rozga(cid:239)(cid:218)ziania przep(cid:239)ywu. Na podstawie wyniku logicznego wyra(cid:285)enia przep(cid:239)yw jest kierowany do nast(cid:218)pnego stanu. (cid:81) subflow–state. Podprzep(cid:239)yw jest niezale(cid:285)nym przep(cid:239)ywem, który mo(cid:285)e by(cid:202) u(cid:285)yty wewn(cid:200)trz innego przep(cid:239)ywu. Gdy aplikacja trafia do niego, g(cid:239)ówny przep(cid:239)yw zostaje wstrzymany do czasu zako(cid:241)czenia pracy w podprzep(cid:239)ywie. (cid:81) end–state. Stan ko(cid:241)cowy wskazuje zako(cid:241)czenie wykonywania przep(cid:239)ywu. Mo(cid:285)e wyst(cid:218)powa(cid:202) w przep(cid:239)ywie wielokrotnie. Jego atrybut view pozwala wskaza(cid:202) widok, który ma zosta(cid:202) wy(cid:258)wietlony u(cid:285)ytkownikowi po osi(cid:200)gni(cid:218)ciu stanu ko(cid:241)cowego. Dowiedzia(cid:239)e(cid:258) si(cid:218), (cid:285)e opis przep(cid:239)ywu sk(cid:239)ada si(cid:218) ze zbioru stanów. Jednak aby przenie(cid:258)(cid:202) si(cid:218) pomi(cid:218)dzy stanami, musisz zdefiniowa(cid:202) przej(cid:258)cia mi(cid:218)dzy nimi. Ka(cid:285)dy stan w przep(cid:239)ywie (poza pocz(cid:200)tkowym i ko(cid:241)cowym) wskazuje przej(cid:258)cia pozwalaj(cid:200)ce na przeniesienie do innego stanu. Przej(cid:258)cie mo(cid:285)e zosta(cid:202) wywo(cid:239)ane przez zdarzenie zasygnalizowane w stanie. Zrozumie(cid:202) przep(cid:239)yw zakupu Zapozna(cid:239)e(cid:258) si(cid:218) z podstawowym wprowadzeniem do Spring Web Flow. Jest to zaledwie u(cid:239)amek zagadnie(cid:241) powi(cid:200)zanych z tym narz(cid:218)dziem, jednak zapoznanie si(cid:218) z nimi wszystkimi jest dobrym pomys(cid:239)em na osobn(cid:200) ksi(cid:200)(cid:285)k(cid:218). Wiesz ju(cid:285) wystarczaj(cid:200)co du(cid:285)o, by móc przeanalizowa(cid:202) zawarto(cid:258)(cid:202) pliku checkout-flow.xml. Zanim to jednak zrobisz, przyjrzyj si(cid:218) diagramowi przep(cid:239)ywu zakupu zaprezentowanemu na rysunku 9.1. Diagram przep(cid:239)ywu zakupu ma stan pocz(cid:200)tkowy oraz stan ko(cid:241)cowy. Ka(cid:285)dy prostok(cid:200)t z zaokr(cid:200)glo- nymi rogami jest stanem akcji, a ka(cid:285)dy prostok(cid:200)t z zaokr(cid:200)glonymi rogami i podwójn(cid:200) ramk(cid:200) jest stanem widoku. Strza(cid:239)ki oznaczaj(cid:200) przej(cid:258)cia, a ich nazwy wskazuj(cid:200) na zdarzenia wywo(cid:239)u- j(cid:200)ce przej(cid:258)cie. Plik checkout-flow.xml zawiera przedstawiony przep(cid:239)yw w formacie XML. Po otwarciu pliku zauwa(cid:285)ysz, (cid:285)e pierwszym znacznikiem wewn(cid:200)trz znacznika flow jest przedstawiony poni(cid:285)ej znacznik tag : var name= order class= com.packt.webstore.domain.Order / Znacznik var tworzy zmienn(cid:200) w przep(cid:239)ywie. Jest ona dost(cid:218)pna we wszystkich jego stanach. Oznacza to, (cid:285)e mo(cid:285)esz si(cid:218) do niej odwo(cid:239)ywa(cid:202) i u(cid:285)ywa(cid:202) jej w dowolnym stanie przep(cid:239)ywu. We wspomnianym znaczniku var utworzy(cid:239)e(cid:258) now(cid:200) instancj(cid:218) klasy Order i umie(cid:258)ci(cid:239)e(cid:258) j(cid:200) w zmiennej o nazwie order. 222 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce Rysunek 9.1. Diagram przep(cid:239)ywu zakupu Kolejnym elementem w pliku checkout-flow.xml jest deklaracja action-state , u(cid:285)ywana zazwy- czaj do wywo(cid:239)ywania us(cid:239)ug serwera. W omawianym stanie wywo(cid:239)ujesz metod(cid:218) validate obiektu cartServiceImpl i przechowujesz jej wynik w obiekcie order.cart, tak jak przedstawia to lis- ting 9.14. Listing 9.14. Implementacja stanu addCartToOrder action-state id= addCartToOrder evaluate expression = cartServiceImpl.validate(requestParameters.cartId) (cid:180)result= order.cart / transition to= InvalidCartWarning on-exception = com.packt.webstore. (cid:180)exception.InvalidCartException / transition to= collectCustomerInfo / /action-state Jak ju(cid:285) wiesz, zmienna order jest dost(cid:218)pna we wszystkich stanach przep(cid:239)ywu. Dlatego te(cid:285) u(cid:285)y(cid:239)e(cid:258) jej w znaczniku evaluate , by przechowywa(cid:202) wynik operacji, w tym przypadku wywo(cid:239)a- nia metody cartServiceImpl.validate(requestParameters.cartId). 223 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych Metoda validate obiektu cartServiceImpl próbuje odczyta(cid:202) obiekt cart na podstawie otrzy- manego parametru cartId. Je(cid:285)eli odnajdzie poprawny obiekt cart, zwraca go. W przeciwnym razie zg(cid:239)asza wyj(cid:200)tek InvalidCartException. W takim wypadku przep(cid:239)yw zostaje przekiero- wany do stanu o identyfikatorze InvalidCartWarning: transition to= InvalidCartWarning on-exception = (cid:180) com.packt.webstore.exception.InvalidCartException / Je(cid:258)li wyj(cid:200)tek nie zosta(cid:239) zg(cid:239)oszony, przep(cid:239)yw zostaje przekierowany ze stanu addCartToOrder do stanu collectCustomerInfo: transition to= collectCustomerInfo / Jak zapewne zauwa(cid:285)y(cid:239)e(cid:258), collectCustomerInfoState jest stanem widoku zdefiniowanym w pliku checkout-flow.xml. Listing 9.15 prezentuje, w jaki sposób okre(cid:258)li(cid:239)e(cid:258) widok, który ma zosta(cid:202) wyge- nerowany u(cid:285)ytkownikowi, oraz model, który musi zosta(cid:202) do(cid:239)(cid:200)czony do obiektu model. Listing 9.15. Deklaracja stanu collectCustomerInfo view-state id= collectCustomerInfo view= collectCustomerInfo.jsp (cid:180)model= order transition on= customerInfoCollected to= collectShippingDetail / /view-state Po przej(cid:258)ciu do tego stanu Spring Web Flow wygeneruje widok collectCustomerInfo i zatrzyma wykonywanie przep(cid:239)ywu do czasu podj(cid:218)cia przez u(cid:285)ytkownika akcji. Gdy u(cid:285)ytkownik wprowadzi informacje i prze(cid:258)le formularz, przep(cid:239)yw zostanie przekierowany do stanu widoku collectShip (cid:180)pingDetail. Jak ju(cid:285) wiesz, przekierowanie mo(cid:285)e zosta(cid:202) wywo(cid:239)ane za pomoc(cid:200) zdarzenia. W tym przypadku przekierowanie do stanu collectShippingDetail zostanie wywo(cid:239)ane po wywo- (cid:239)aniu zdarzenia customerInfoCollected. Pojawia si(cid:218) pytanie: jak wywo(cid:239)a(cid:202) to zdarzenie (customer (cid:180)InfoCollected) z poziomu widoku? Odpowied(cid:283) na nie znajdziesz w dalszej cz(cid:218)(cid:258)ci rozdzia(cid:239)u. Przyjrzyj si(cid:218) poni(cid:285)szemu fragmentowi kodu: transition on= customerInfoCollected to= collectShippingDetail / Nast(cid:218)pnym zdefiniowanym stanem w przep(cid:239)ywie zakupu jest stan widoku collectShipping (cid:180)Detail zaprezentowany w listingu 9.16. Ma zdefiniowane dwa przep(cid:239)ywy: pierwszy cofaj(cid:200)cy do stanu collectCustomerInfo, drugi przekierowuj(cid:200)cy do nast(cid:218)pnego stanu (o nazwie orderCon (cid:180)firmation). Listing 9.16. Definicja stanu collectShippingDetail view-state id= collectShippingDetail model= order transition on= shippingDetailCollected to= orderConfirmation / transition on= backToCollectCustomerInfo to= collectCustomerInfo / /view-state 224 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce Zauwa(cid:285), (cid:285)e w stanie collectShippingDetail nie zdefiniowa(cid:239)e(cid:258) atrybutu view. W zwi(cid:200)zku z tym Spring Web Flow potraktuje nazw(cid:218) stanu jako nazw(cid:218) widoku. Definicja stanu orderConfirmation, przedstawionego w listingu 9.17, nie wymaga wyja(cid:258)nienia. Przypomina stan collectShippingDetail, w którym aplikacja prezentuje wszystkie informacje powi(cid:200)zane z zamówieniem i oczekuje na potwierdzenie u(cid:285)ytkownika. Po potwierdzeniu zostajesz przekierowany do stanu processOrder. Listing 9.17. Definicja stanu orderConfirmation view-state id= orderConfirmation transition on= orderConfirmed to= processOrder / transition on= backToCollectShippingDetail to= collectShippingDetail / /view-state Stan akcji processOrder komunikuje si(cid:218) z obiektem orderServiceImpl w celu zapisania obiektu order. Po pomy(cid:258)lnym zapisaniu obiektu jego identyfikator zostaje zapisany w zmiennej (order. (cid:180)orderId). Nast(cid:218)pnie przep(cid:239)yw zostaje przekierowany do zaprezentowanego w listingu 9.18 stanu thankCustomer. Listing 9.18. Definicja stanu thankCustomer view-state id= thankCustomer model= order transition to= endState / /view-state Twój przep(cid:239)yw obs(cid:239)ugi zakupu ma dwa stany ko(cid:241)cowe, zaprezentowane w listingu 9.19. Przep(cid:239)yw dociera do pierwszego z nich, gdy przejdzie przez wszystkie zak(cid:239)adane stany. Drugi z nich jest osi(cid:200)gany, je(cid:258)li u(cid:285)ytkownik w dowolnym momencie naci(cid:258)nie przycisk Anuluj. Listing 9.19. Definicje stanów ko(cid:241)cowych przep(cid:239)ywu end-state id= endState / end-state id= cancelCheckout view= checkOutCancelled.jsp / Zauwa(cid:285), (cid:285)e w stanie ko(cid:241)cowym cancelCheckout wskaza(cid:239)e(cid:258) widok za pomoc(cid:200) atrybutu view. Przekierowanie do niego odbywa si(cid:218) za pomoc(cid:200) konfiguracji global-transitions zaprezento- wanej w listingu 9.20. Listing 9.20. Definicja globalnych przep(cid:239)ywów global-transitions transition on = cancel to= cancelCheckout / /global-transitions 225 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych Globalne przep(cid:239)ywy s(cid:239)u(cid:285)(cid:200) do wspó(cid:239)dzielenia przej(cid:258)(cid:202) pomi(cid:218)dzy stanami. Zamiast powtarza(cid:202) defini- cje przej(cid:258)cia w ka(cid:285)dym stanie, mo(cid:285)esz ustawi(cid:202) je jako globalne przep(cid:239)ywy. Dzi(cid:218)ki temu s(cid:200) one dost(cid:218)pne dla ka(cid:285)dego stanu w przep(cid:239)ywie. Dlatego zdefiniowa(cid:239)e(cid:258) przej(cid:258)cie do stanu cancel (cid:180)Checkout w sekcji global-transitions. Wiesz ju(cid:285), jak wygl(cid:200)da definicja przep(cid:239)ywu zakupu (checkout-flow.xml). Spring MVC powinien odczyta(cid:202) ten plik podczas startu aplikacji, (cid:285)eby móc przekierowa(cid:202) (cid:285)(cid:200)dania powi(cid:200)zane z prze- p(cid:239)ywem do szkieletu Spring Web Flow. W tym celu w krokach 5. – 8. umie(cid:258)ci(cid:239)e(cid:258) kilka znacz- ników konfiguracji przep(cid:239)ywu w pliku konfiguracji kontekstu aplikacji (DispatherServlet- context.xml). W krokach 5. i 6. doda(cid:239)e(cid:258) w pliku DispatcherServlet-context.xml wymagan(cid:200) przestrze(cid:241) nazw webflow-config oraz lokalizacj(cid:218) schematu. W kroku 7. utworzy(cid:239)e(cid:258) znaczniki flow-executor oraz flow-registry. Pierwszy z nich tworzy przep(cid:239)yw na podstawie definicji pobieranej z flow-re (cid:180)gistry. Mo(cid:285)esz utworzy(cid:202) dowoln(cid:200) liczb(cid:218) znaczników flow-registry. Ka(cid:285)dy z nich jest kolekcj(cid:200) definicji przep(cid:239)ywów. Gdy (cid:285)(cid:200)danie u(cid:285)ytkownika trafia do przep(cid:239)ywu, zostaje dla tego (cid:285)(cid:200)dania utworzona instancja przep(cid:239)ywu na podstawie definicji (listing 9.21). Listing 9.21. Konfiguracja przep(cid:239)ywu zakupu webflow-config:flow-executor id= flowExecutor flowregistry= flowRegistry / webflow-config:flow-registry id= flowRegistry base-path= /WEB-INF/flows webflow-config:flow-location path= /checkout/checkout-flow.xml (cid:180)id= checkout / /webflow-config:flow-registry W przedstawionej w listingu 9.21 konfiguracji utworzy(cid:239)e(cid:258) element flow-registry, którego para- metr base-path ma warto(cid:258)(cid:202) /WEB-INF/flows. Oznacza to, (cid:285)e definicje przep(cid:239)ywów powinny znajdowa(cid:202) si(cid:218) w katalogu /WEB-INF/flows, by by(cid:239)y odczytane przez flow-registry. Dlatego w kroku 4. utworzy(cid:239)e(cid:258) plik checkout-flow.xml w katalogu src/main/webapp/WEB-INF/flows/ checkout/. Jak ju(cid:285) zosta(cid:239)o wspomniane, flow-registry mo(cid:285)e mie(cid:202) wiele definicji przep(cid:239)ywów. Ka(cid:285)dy przep(cid:239)yw jest oznaczony identyfikatorem flow-registry. W Twoim przypadku utworzy(cid:239)e(cid:258) pojedyncz(cid:200) definicj(cid:218) przep(cid:239)ywu o identyfikatorze checkout i relatywnej (cid:258)cie(cid:285)ce /checkout/checkout- flow.xml. Pami(cid:218)taj, (cid:285)e atrybut path znacznika webflow-config:flow-location jest relatywny wobec atrybutu base-path znacznika webflow-config:flow-registry . Wa(cid:285)nym zagadnieniem jest sposób wzbudzania przep(cid:239)ywu. Odbywa si(cid:218) to poprzez przes(cid:239)anie (cid:285)(cid:200)dania GET pod relatywny adres równy identyfikatorowi przep(cid:239)ywu. Tak wi(cid:218)c aby wzbudzi(cid:202) przep(cid:239)yw zakupu (checkout), nale(cid:285)y przes(cid:239)a(cid:202) (cid:285)(cid:200)danie typu GET pod adres: http://localhost:8080/ webstore/checkout. W definicji przep(cid:239)ywu (checkout-flow.xml) nie zdefiniowa(cid:239)e(cid:258) (cid:285)adnego stanu pocz(cid:200)tkowego, dlatego te(cid:285) pierwszy zdefiniowany stan (addCartToOrder) jest stanem pocz(cid:200)t- kowym. Przedstawiony w listingu 9.22 stan addCartToOrder oczekuje, (cid:285)e w (cid:285)(cid:200)daniu b(cid:218)dzie obecny parametr o nazwie cartId. 226 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce Listing 9.22. Ilustracja parametrów wymaganych przez stan addCartToOrder action-state id= addCartToOrder evaluate expression = cartServiceImpl.validate(requestParameters.cartId) (cid:180)result= order.cart / transition to= InvalidCartWarning (cid:180)on-exception= com.packt.webstore.exception.InvalidCartException / transition to= collectCustomerInfo / /action-state Poprawna posta(cid:202) (cid:285)(cid:200)dania wzbudzaj(cid:200)cego przep(cid:239)yw jest mniej wi(cid:218)cej podobna do: http://localhost: 8080/webstore/checkout?cartId=55AD1472D4EC. Cz(cid:218)(cid:258)(cid:202) (cid:285)(cid:200)dania za znakiem zapytania (cartId= 55AD1472D4EC) jest uznawana za parametr (cid:285)(cid:200)dania. Zdefiniowa(cid:239)e(cid:258) przep(cid:239)yw zakupu i skonfigurowa(cid:239)e(cid:258) go w Spring Web Flow. Kolejnym krokiem by(cid:239)o utworzenie w kroku 8. (listing 9.23) dwóch beanów w kontek(cid:258)cie aplikacji internetowej (DispatcherServlet-context.xml), by przekazywa(cid:202) wszystkie (cid:285)(cid:200)dania zwi(cid:200)zane z przep(cid:239)ywem do obiektu flow-executor. Listing 9.23. Deklaracja beanów obs(cid:239)uguj(cid:200)cych (cid:285)(cid:200)dania powi(cid:200)zane z przep(cid:239)ywem bean id= flowHandlerMapping class= org.springframework.webflow.mvc. (cid:180)servlet.FlowHandlerMapping property name= flowRegistry ref= flowRegistry / /bean bean id= flowHandlerAdapter class= org.springframework.webflow.mvc. (cid:180)servlet.FlowHandlerAdapter property name= flowExecutor ref= flowExecutor / /bean Parametr flowHandlerMapping tworzy i konfiguruje uchwyt odwzorowuj(cid:200)cy (cid:285)(cid:200)dania na przep(cid:239)ywy na podstawie identyfikatora ka(cid:285)dego przep(cid:239)ywu skonfigurowanego we flowRegistry. Bean flowHandlerAdapter zachowuje si(cid:218) jak pomost pomi(cid:218)dzy serwletem przekazuj(cid:200)cym a Spring Web Flow, wspomagaj(cid:200)c wykonanie instancji przep(cid:239)ywu. Krótki test — przep(cid:239)yw Pytanie 1. Przyjmij konfiguracj(cid:218) rejestru przep(cid:239)ywu zaprezentowan(cid:200) w listingu 9.24, deklaruj(cid:200)c(cid:200) jeden przep(cid:239)yw zdefiniowany w pliku. Jak(cid:200) posta(cid:202) ma mie(cid:202) URL wzbudzaj(cid:200)cy przep(cid:239)yw? Listing 9.24. Przyk(cid:239)adowa deklaracja rejestru przep(cid:239)ywów webflow-config:flow-registry id= flowRegistry base-path= /WEB-INF/flows webflow-config:flow-location path= /customer/ (cid:180)validate.xml id= validateCustomer / /webflow-config:flow-registry 227 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych 1. http://localhost:8080/webstore/customer/validate. 2. http://localhost:8080/webstore/validate. 3. http://localhost:8080/webstore/validateCustomer. Pytanie 2. Zak(cid:239)adaj(cid:200)c, (cid:285)e URL wzbudzaj(cid:200)cy przep(cid:239)yw na posta(cid:202): http://localhost:8080/webstore/ validate?customerId=C1234, jak w pliku definiuj(cid:200)cym przep(cid:239)yw zadeklarujesz pobieranie parametru (cid:285)(cid:200)dania o nazwie customerId? 1. evaluate expression = requestParameters.customerId result = customerId / . 2. evaluate expression = requestParameters(customerId) result = customerId / . 3. evaluate expression = requestParameters[customerId ] result = customerId / . (cid:109)wiczenie praktyczne — tworzenie widoków dla ka(cid:285)dego stanu widoku Wykona(cid:239)e(cid:258) niezb(cid:218)dne operacje, by uruchomi(cid:202) przep(cid:239)yw zakupu. Pozosta(cid:239)a do zrobienia jeszcze jedna rzecz. Musisz utworzy(cid:202) widoki dla wszystkich stanów widoków obecnych w przep(cid:239)ywie. (cid:146)(cid:200)cznie zdefiniowa(cid:239)e(cid:258) sze(cid:258)(cid:202) stanów widoków (collectCustomerInfo, collectShippingDetail, orderConfirmation, InvalidCartWarning, thankCustomer oraz cancelCheckout), wi(cid:218)c potrzebujesz sze(cid:258)ciu plików JSP. Pora je utworzy(cid:202): 1. Utwórz plik widoku JSP o nazwie collectCustomerInfo.jsp w katalogu src/main/ webapp/WEB-INF/flows/checkout/ i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.25. Zauwa(cid:285), (cid:285)e nie zosta(cid:239)y w nim umieszczone znaczniki input dla wi(cid:218)kszo(cid:258)ci pól obiektu domenowego Customer. Znajdziesz je w pe(cid:239)nej wersji kodu (cid:283)ród(cid:239)owego, który mo(cid:285)esz pobra(cid:202) ze strony: www.helion.pl/ksiazki/SPRIMV.html. Listing 9.25. Implementacja widoku collectCustomerInfo @page pageEncoding= UTF-8 contentType= text/html; charset=UTF-8 @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core @ taglib prefix= form uri= http://www.springframework.org/tags/form @ taglib prefix= spring uri= http://www.springframework.org/tags html head meta http-equiv= Content-Type content= text/html; charset= utf-8 link rel= stylesheet href= //netdna.bootstrapcdn.com/bootstrap/ (cid:180)3.0.0/css/bootstrap.min.css title Klient /title /head body section div class= jumbotron div class= container h1 Klient /h1 228 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce p Dane klienta /p /div /div /section section class= container form:form modelAttribute= order.customer class= formhorizontal fieldset legend Dane klienta /legend div class= form-group label class= control-label col-lg-2 col-lg-2 (cid:180)for= customerId / Identyfikator klienta /label div class= col-lg-10 form:input id= customerId path= customerId type= text (cid:180)class= form:input-large / /div /div !-- Tutaj umie(cid:258)(cid:202) pomini(cid:218)te pola formularza dla pozosta(cid:239)ych pól obiektu (cid:180)domenowego klasy Customer. -- input type= hidden name= _flowExecutionKey (cid:180)value= ${flowExecutionKey} / div class= form-group div class= col-lg-offset-2 col-lg-10 input type= submit id= btnAdd class= btn btnprimary (cid:180)value= Utwórz name= _eventId_customerInfoCollected / button id= btnCancel class= btn btn-default (cid:180)name= _eventId_cancel Anuluj /button /div /div /fieldset /form:form /section /body /html 2. Nast(cid:218)pnie utwórz w tym samym katalogu plik widoku JSP o nazwie collectShippingDetail.jsp i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.26. Zauwa(cid:285), (cid:285)e nie zosta(cid:239)y w nim umieszczone znaczniki input dla wi(cid:218)kszo(cid:258)ci pól obiektu domenowego typu Address o nazwie shippingAddress. Znajdziesz je w pe(cid:239)nej wersji kodu (cid:283)ród(cid:239)owego, który mo(cid:285)esz pobra(cid:202) ze strony: www.helion.pl/ksiazki/ sprimv.html. Listing 9.26. Implementacja widoku collectShippingDetails @page pageEncoding= UTF-8 contentType= text/html; charset=UTF-8 @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core @ taglib prefix= form uri= http://www.springframework.org/tags/form @ taglib prefix= spring uri= http://www.springframework.org/tags html 229 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych head meta http-equiv= Content-Type content= text/html; charset= utf-8 link rel= stylesheet href= //netdna.bootstrapcdn.com/bootstrap/ (cid:180)3.0.0/css/bootstrap.min.css title Klient /title /head body section div class= jumbotron div class= container h1 Wysy(cid:239)ka /h1 p Dane do wysy(cid:239)ki /p /div /div /section section class= container form:form modelAttribute= order.shippingDetail class= (cid:180) form-horizontal fieldset legend Dane do wysy(cid:239)ki /legend div class= form-group label class= control-label col-lg-2 col-lg-2 for= name (cid:180)/ Nazwa /label div class= col-lg-10 form:input id= name path= name type= text (cid:180)class= form:input-large / /div /div div class= form-group label class= control-label col-lg-2 col-lg-2 (cid:180)for= shippingDate / Data wysy(cid:239)ki (dd/mm/yyyy) /label div class= col-lg-10 form:input id= shippingDate path= shippingDate (cid:180)type= text class= form:input-large / /div /div div class= form-group label class= control-label col-lg-2 for= doorNo Numer (cid:180)mieszkania /label div class= col-lg-10 form:input id= doorNo path= shippingAddress.doorNo (cid:180)type= text class= form:input-large / /div /div !-- Tutaj umie(cid:258)(cid:202) pomini(cid:218)te pola formularza dla pozosta(cid:239)ych pól obiektu (cid:180)domenowego shippingAddress klasy Address. -- input type= hidden name= _flowExecutionKey (cid:180)value= ${flowExecutionKey} / div class= form-group 230 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce div class= col-lg-offset-2 col-lg-10 button id= back class= btn btn-default name= (cid:180)_eventId_backToCollectCustomerInfo wstecz /button input type= submit id= btnAdd class= btn btnprimary (cid:180)value= Utwórz name= _eventId_shippingDetailCollected / button id= btnCancel class= btn btn-default (cid:180)name= _eventId_cancel Anuluj /button /div /div /fieldset /form:form /section /body /html 3. Nadal pracuj(cid:200)c w tym samym katalogu, utwórz kolejny plik widoku JSP, o nazwie orderConfirmation.jsp, i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.27. Zadaniem widoku b(cid:218)dzie potwierdzenie zamówienia z(cid:239)o(cid:285)onego przez klienta. Zauwa(cid:285), (cid:285)e w listingu dla wi(cid:218)kszo(cid:258)ci pól obiektu domenowego typu Order nie zosta(cid:239)y umieszczone znaczniki input . Kompletn(cid:200) posta(cid:202) pliku widoku orderConfirmation.jsp znajdziesz w pe(cid:239)nej wersji kodu (cid:283)ród(cid:239)owego, który mo(cid:285)esz pobra(cid:202) ze strony: www.helion.pl/ksiazki/sprimv.html. Listing 9.27. Implementacja widoku orderConfirmation @page pageEncoding= UTF-8 contentType= text/html; charset=UTF-8 @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core @ taglib prefix= form uri= http://www.springframework.org/tags/form @ taglib prefix= spring uri= http://www.springframework.org/tags @ taglib prefix= fmt uri= http://java.sun.com/jsp/jstl/fmt html head meta http-equiv= Content-Type content= text/html; charset= utf-8 link rel= stylesheet href= //netdna.bootstrapcdn.com/bootstrap/ (cid:180)3.0.0/css/bootstrap.min.css title Potwierdzenie zamówienia /title /head body section div class= jumbotron div class= container h1 Zamówienie /h1 p Potwierdzenie zamówienia /p /div /div /section div class= container div class= row 231 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych form:form modelAttribute= order class= form-horizontal input type= hidden name= _flowExecutionKey (cid:180)value= ${flowExecutionKey} / div class= well col-xs-10 col-sm-10 col-md-6 col-xsoffset-1 (cid:180)col-sm-offset-1 col-md-offset-3 div class= text-center h1 Paragon /h1 /div div class= row div class= col-xs-6 col-sm-6 col-md-6 address strong Adres do wysy(cid:239)ki /strong br (cid:180)${order.shippingDetail.name} br !-- W podobny sposób umie(cid:258)(cid:202) warto(cid:258)ci pozosta(cid:239)ych pól (cid:180)obiektu order.shippingDetail. W tym listingu zosta(cid:239)y (cid:180)pomini(cid:218)te. -- /address /div /div !-- Umie(cid:258)(cid:202) warto(cid:258)ci wszystkich pól obiektu order w tabelce HTML, (cid:180)u(cid:285)ywaj(cid:200)c wyra(cid:285)enia ${} . W tym listingu zosta(cid:239)y pomini(cid:218)te. -- button id= back class= btn btn-default name= (cid:180)_eventId_backToCollectShippingDetail wstecz /button button type= submit class= btn btn-success name= (cid:180)_eventId_orderConfirmed Zatwierd(cid:283) span class= glyphicon (cid:180)glyphiconchevron-right /span /button button id= btnCancel class= btn btn-default name= (cid:180)_eventId_cancel Anuluj /button /div /div /form:form /div /div /body /html 4. Potrzebujesz widoku prezentuj(cid:200)cego komunikat b(cid:239)(cid:218)du w przypadku, gdy u(cid:285)ytkownik spróbuje z(cid:239)o(cid:285)y(cid:202) zamówienie, nie umieszczaj(cid:200)c wcze(cid:258)niej (cid:285)adnych przedmiotów w koszyku. Utwórz plik InvalidCartWarning.jsp i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.28. Listing 9.28. Implementacja widoku InvalidCartWarning @page pageEncoding= UTF-8 contentType= text/html; charset=UTF-8 @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core @ taglib prefix= spring uri= http://www.springframework.org/tags html head 232 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce meta http-equiv= Content-Type content= text/html; charset= utf-8 link rel= stylesheet href= //netdna.bootstrapcdn.com/bootstrap/ (cid:180)3.0.0/css/bootstrap.min.css title Niepoprawny koszyk /title /head body section div class= jumbotron div class= container h1 class= alert alert-danger Niepoprawny koszyk /h1 /div /div /section section div class= container p a href= spring:url value= /products / class= btn btn- (cid:180)primary span class= glyphicon-hand-left glyphicon /span produkty /a /p /div /section /body /html 5. Potrzebujesz widoku prezentuj(cid:200)cego podzi(cid:218)kowanie u(cid:285)ytkownikowi po pomy(cid:258)lnym zrealizowaniu przep(cid:239)ywu zakupu. Utwórz plik widoku JSP o nazwie thankCustomer.jsp i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.29. Listing 9.29. Implementacja widoku thankCustomer @page pageEncoding= UTF-8 contentType= text/html; charset=UTF-8 @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core @ taglib prefix= spring uri= http://www.springframework.org/tags @ taglib prefix= fmt uri= http://java.sun.com/jsp/jstl/fmt html head meta http-equiv= Content-Type content= text/html; charset= utf-8 link rel= stylesheet href= //netdna.bootstrapcdn.com/bootstrap/ (cid:180)3.0.0/css/bootstrap.min.css title Dzi(cid:218)kujemy! /title /head body section div class= jumbotron div class= container h1 class= alert alert-danger Dzi(cid:218)kujemy! /h1 233 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych p Dzi(cid:218)kujemy za z(cid:239)o(cid:285)enie zamówienia. Zostanie przes(cid:239)ane fmt:formatDate type= date value= ${order.shippingDetail. (cid:180)shippingDate} pattern= dd.MM.yyyy / ! /p p Numer Twojego zamówienia to ${order.orderId}. /p /div /div /section section div class= container p a href= spring:url value= /products / class= (cid:180) btn btn-primary span class= glyphicon-hand-left glyphicon /span produkty /a /p /div /section /body /html 6. Je(cid:258)li u(cid:285)ytkownik zdecyduje si(cid:218) na anulowanie sk(cid:239)adanego zamówienia w dowolnym z widoków, musisz przedstawi(cid:202) mu informacj(cid:218), (cid:285)e ta operacja si(cid:218) powiod(cid:239)a. W tym celu utwórz plik widoku checkOutCancelled.jsp i umie(cid:258)(cid:202) w nim zawarto(cid:258)(cid:202) listingu 9.30. Listing 9.30. Implementacja widoku checkOutCancelled @page pageEncoding= UTF-8 contentType= text/html; charset=UTF-8 @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core @ taglib prefix= spring uri= http://www.springframework.org/tags html head meta http-equiv= Content-Type content= text/html; charset= utf-8 link rel= stylesheet href= //netdna.bootstrapcdn.com/bootstrap/ (cid:180)3.0.0/css/bootstrap.min.css title Sk(cid:239)adanie zamówienia anulowane! /title /head body section div class= jumbotron div class= container h1 class= alert alert-danger Sk(cid:239)adanie zamówienia (cid:180)anulowano. /h1 p Proces sk(cid:239)adania zamówienia zosta(cid:239) anulowany! Mo(cid:285)esz wróci(cid:202) (cid:180)do zakupów ... /p /div /div /section 234 Kup książkęPoleć książkę Rozdzia(cid:225) 9. • Apache Tiles oraz Spring Web Flow w praktyce section div class= container p a href= spring:url value= /products / class= btn (cid:180)btn-primary span class= glyphicon-hand-left glyphicon /span produkty /a /p /div /section /body /html 7. Otwórz plik cart.jsp znajduj(cid:200)cy si(cid:218) w katalogu src/main/webapp/WEB-INF/views i atrybutowi href hiper(cid:239)(cid:200)cza Kupuj(cid:218) nadaj warto(cid:258)(cid:202) spring:url value= / (cid:180)checkout?cartId=${cartId} / , tak jak przedstawia listing 9.31. Listing 9.31. Implementacja hiper(cid:239)(cid:200)cza rozpoczynaj(cid:200)cego przep(cid:239)yw zakupu a href= spring:url value= /checkout?cartId=${cartId} / class= btn (cid:180)btn-success pull-right span class= glyphicon-shopping-cart glyphicon /span Kupuj(cid:218) /a 8. Uruchom aplikacj(cid:218) i odwied(cid:283) adres: http://localhost:8080/webstore/products. Naci(cid:258)nij przycisk Szczegó(cid:239)y dowolnego produktu, aby przej(cid:258)(cid:202) na stron(cid:218) ze szczegó(cid:239)owymi informacjami o produkcie. Tam dodaj go do koszyka, u(cid:285)ywaj(cid:200)c przycisku Zamów teraz. Przejd(cid:283) do strony prezentuj(cid:200)cej zawarto(cid:258)(cid:202) koszyka, u(cid:285)ywaj(cid:200)c przycisku Koszyk. Znajdziesz na niej przycisk Z(cid:239)ó(cid:285) zamówienie. Naci(cid:258)nij go, by wy(cid:258)wietli(cid:239)a si(cid:218) zaprezentowana na rysunku 9.2 strona s(cid:239)u(cid:285)(cid:200)ca do wprowadzania informacji o kliencie. 9. Je(cid:258)li po wprowadzeniu danych klienta naci(cid:258)niesz przycisk Dodaj, Spring Web Flow przekieruje Ci(cid:218) do nast(cid:218)pnego stanu. W nim zostanie wy(cid:258)wietlony formularz s(cid:239)u(cid:285)(cid:200)cy do wprowadzenia danych do dostawy, a nast(cid:218)pnie zostaniesz poproszony o potwierdzenie zamówienia. Na koniec Spring Web Flow zaprezentuje Ci stron(cid:218) z podzi(cid:218)kowaniem, b(cid:218)d(cid:200)c(cid:200) jednocze(cid:258)nie stanem ko(cid:241)cowym przep(cid:239)ywu. Co si(cid:218) w(cid:239)a(cid:258)nie wydarzy(cid:239)o? W krokach 1. – 6. utworzy(cid:239)e(cid:258) pliki widoków JSP dla ka(cid:285)dego stanu widoku. Jak zapewne pami(cid:218)- tasz, zdefiniowa(cid:239)e(cid:258) atrybut model, dost(cid:218)pny dla ka(cid:285)dego stanu widoku w pliku checkout-flow.xml. Model zdefiniowany w listingu 9.32 zosta(cid:239) u(cid:285)yty w znaczniku form:form widoku w sposób przedstawiony w listingu 9.33. 235 Kup książkęPoleć książkę Spring MVC. Przewodnik dla pocz(cid:261)tkuj(cid:261)cych Rysunek 9.2. Formularz wprowadzania danych klienta Listing 9.32. Definicja modelu w stanie collectCustomerInfo view-state id= collectCustomerInfo view= collectCustomerInfo.jsp (cid:180)model= order transition on= customerInfoCollected to= collectShippingDetail / /view-state Listing 9.33. U(cid:285)ycie modelu stanu przep(cid:239)ywu w widoku form:form modelAttribute= order.customer class= form-horizontal fieldset legend Dane klienta /legend div class= form-group label class= control-label col-lg-2 col-lg-2 (cid:180)for= customerId Identyfikator klienta /label div class= col-lg-10 form:input id= customerId path= customerId type= text (cid:180)class= form:input-large / /div /div Listing 9.33 zawiera fragment pliku widoku collectCustomerInfo.jsp, w którym z
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Spring MVC. Przewodnik dla początkujących
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: