Przesyłanie obiektu z JSP do Controllera

0

Cześć! Tworzę aplikację internetową i zmagam się z problemem dodawania produktów do koszyka. Mianowicie chciałbym żeby po naciśnięciu przycisku, produkt został przesłany do kontrolera a strona pozostała jedynie odświeżona. Na ten moment udało mi się dojść do etapu, gdzie użytkownik dodając produkt do koszyka faktycznie zostaje na bieżącej stronie ale dodatkowo w adresie pojawia się parametr ?id=${id_produktu} co przy próbie dodania innego obiektu objawia się duplikatem tego pierwszego. Ach, ale to zawiłe!

Jak pozbyć się tego niechcianego dodatkowego parametru? Bądź jak prawidłowo podejść do takiego problemu?

W każdym razie jeśli chodzi o kod wygląda to tak:

<ul>
        <c:forEach var="listValue" items="${movieList}">
                <li  style="background: orange; max-width: 500px">${listValue.getTitle()} ${listValue.getCast()} <br>
                <form:form method="POST">
                    <input type="hidden" name="movie" value="${listValue.getId()}" />
                            <input type="hidden" name="currentCategory"  value="${listValue.getCategory()}"/>
                    <input type="submit" value="+" />
                </form:form>${listValue.getPrice()}$ <br>
                </li>
            </br>
        </c:forEach>
</ul>
    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String addMovie(@ModelAttribute("movie") Integer movieId,  @RequestParam("currentCategory")  String currentCategory) {
        shoppingCart.addProduct(movieRepository.getMovieById(movieId));
        return "redirect:?category="+currentCategory;
    }
0

No musisz GDZIEŚ te dane przechowywać! Albo w jakiejś sesji usera, albo gdzieś indziej. Teraz wpychasz je do parametrów GET, ale to trochę słabe bo ma raczej spore ograniczenia. Bardziej ludzkie rozwiazanie do jednak jakiś session store (np. prosta Mapa w backendzie).

0

Zacząłem googlować jakieś frazy związane z sesjami w Springu i trafiłem na Spring Session. To jednak wydaje mi się być straszną kobyłą która znacznie przerasta tak mały projekt. Wracając do tej mapy na backendzie, którą zasugerowałeś- jak to powinno mniej więcej wyglądać? Nie mam pojęcia jak to ubrać w formę. Powinienem był stworzyć jakiś SessionService w której będę miał tą mapę do której przykładowo będę dodawać pary takie jak <"shoppingCart", List<movie>, <"defaultCurrency", Currency>? I jeśli tak to w jaki sposób operować na niej tak, żeby ominąć dodawanie tego uciążliwego parametru w adresie? Swoją drogą: dlaczego on się tam dodaje skoro wykorzystuje żądanie POST?

1
  1. Skąd ten parametr to nie wiem, bo nie pokazałeś kodu
  2. Nie, no to co sugerujesz jest idiotyczne, bo przecież musisz jakoś identyfikować usera :D Twój genialny pomysł zrobiłby jeden koszyk dla wszystkich. Normalnie robi sie tak, ze logując użytkownika do systemu nadajesz mu jakieś session ID i zostawiasz mu session cookie. Wtedy w backendzie możesz po prostu mieć jakąś mapę Map<SessionId, Data> z danymi usera. Oczywiście to przy założeniu że mamy tylko jedną instancje backendu, bo jak wchodzimy na mikroserwisy i wiele równoległych instancji, to sprawa sie trochę komplikuje i trzeba albo mieć replikacje, albo np. sharding requestów per user Id (tak że requesty danego usera zawsze trafią na te same Nody). No i dochodzi nam też kwestia wygasania tych danych. Nie chcemy żeby user mógł nam wywalić serwer logując sie milion razy (czyli dostając nowe session id) i dodając coś do koszyka... ;]

edit: możesz też trzymać ten koszyk po stronie klienta w jego local storage przeglądarki, za pomocą javascriptu. To już kwestia jak to ma działać dokładnie.

0

A tam od razu 'genialny':D Ale jeszcze trochę pobłądzę i chciałbym spytać co by się stało gdybym do takiego serwisu o którym wspomniałem wcześniej dodał adnotację Scope z wartością session? Takie rozwiązanie miałoby prawo funkcjonować?

Dodam jeszcze link do repozytorium (klik), może ktoś rzuci okiem na ten nieszczęsny parametr a przy okazji dostanę pouczający ochrzan za błędy?

@EDIT
Właściwie to całą sprawę dodatkowo utrudnia(?) to, że nie mam tam fizycznej rejestracji i logowania użytkowników. W treści zadania mam zaznaczone, że implementację tej funkcjonalności mam pominąć. Jeśli chodzi o instancje backendu to zostańmy przy jednej, chciałbym małymi krokami uczyć się tego Springa a nie rzucać się na głęboką wodę:D No i właśnie - uczyć Springa - może niekoniecznie javascriptu? No chyba, że taka lekcja implementacji prostego koszyka w Springu będzie totalnie bezwartościowa?

No i nie gniewaj się za być może dla Ciebie głupie pytania. Dla mnie to świetna okazja żeby dopytać i się czegoś dowiedzieć:D

1
  1. Ja tam jednak trochę bym nie ufał tym SessionScope, ale możesz spróbować
  2. Nie ma znaczenia rejestracja i logowanie. Zauważ że chodzi tutaj o możliwość identyfikacji usera pomiędzy requestami http, a nie o user management. Session Cookie można wysłać zawsze, nie trzeba się do tego logować ;) Po prostu bez takiej identyfikacji nie wiesz który request przychodzi od jakiego usera!
  3. Wydaje mi się że właśnie często taki koszyk jest robiony w JS po stronie przeglądarki w local storage, żeby uprościć sprawę. Bo wtedy nie musisz się martwić idenfytikacją użytkownika czy usuwaniem danych z "martwych" koszyków. Ot to leży w przeglądarce użytkownika i tyle. Oczywiście koszt jest taki, że koszyk z innej przeglądarki jest pusty, więc jakbyś miał "logowanie" to nie wspierałbyś wrzucania do koszyka rzeczy "na później".
0

Dzięki Shalom za rozjaśnienie problemu. Zostałem przy rozwiązaniu SessionScope - złapałem dzisiaj profesora który właśnie podpowiedział mi taki pomysł na projekt a nawet udostępnił jakąś tam swoją bazę z filmami - i powiedział, że takie rozwiązanie w ramach tak małej aplikacji będzie okej.
Właściwie to wiem, że nie powinno się zwracać z prośbą z projektami na studia ale akurat to zadanie ma się nijak do oceny końcowej z przedmiotu - ot, mamy dobre relacje z profesorem i dostałem zadanie dodatkowe żeby się czegoś nauczyć.

Dodatkowo jeśli chodzi o ten nieszczęsny parametr to uporałem się z nim przez ustawienie flagi setIgnoreDefaultModelOnRedirect w RequestHandlerMappingAdapterze na true. Jeślli ktoś kiedy trafi na ten wątek z tym samym problemem to pod tym linkiem znajdzie więcej informacji

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0