Разбираюсь со Spring MVC, скоро надо начинать проект на этом фреймворке.
Столкнулся с одной проблемой, не понимаю как её красиво разрулить.
Допустим, что у меня есть основная страница, на ней форма, ну скажем редактирования профиля пользователя, я считал данные пользователя положил в formBackingObject и используя стандарный таг <spring:bind> эту форму отобразил.
А ещё в headerе для каждой станицы у меня есть маленькая формочка, которая позволяет отправить е-мейл другу о моём замечательном сайте. Это отдельный контроллер, он отрабатывает и переходит на последний view, который видел пользователь. Идея состоит в том, чтобы пользователь мог отправить е-майл другу и вернуться обратно к тому же view, т.е. к форме редактирования профиля пользователя, естественно полностью заполненной.
Но это уже ДРУГОЙ запрос и естественно, данных пользователя уже нет и я получаю javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'ххх' available as request attribute.
Когда-то давно в самописном MVC на PHP, я тупо клал всё, что мне нужно в сессию и не имел никаких проблем заново отобразить view, все данные были в сессии. Но <spring:bind> таг не умеет брать обьекты из сессии.
Как лучше всего разрешить эту проблему в Spring MVC?
Проблема-то стандартная наверняка, но поисков в Гыгле, нашёл, только несколько некрасивых хаков на эту тему.
Нельзя просто с другого контроллера показать левый view, естественно нужно туда еще и модель нужную положить. Я бы посоветовал редирект (имя view имеет вид "redirect:" и нужный url.)
Ну а если честно, то проблему можно обойти легко и просто. Отправляй фому яваскриптом и показывай результат в новом окне, а еще лучше при помощи ajax, благо совместно со spring это делается в 5 минут.
В том-то и дело, что не хочется перегружать всю страницу, лезть заново в базу и т.д. Ведь все данные модели у меня УЖЕ ЕСТЬ и они не менялись, надо только как-то изящно их перекинуть на новую страницу или достать из сессии.
Ajax и новое окно совсем не подходят к проекту.
Здравствуйте, O.Bender, Вы писали:
OB>В том-то и дело, что не хочется перегружать всю страницу, лезть заново в базу и т.д. Ведь все данные модели у меня УЖЕ ЕСТЬ и они не менялись, надо только как-то изящно их перекинуть на новую страницу или достать из сессии. OB>Ajax и новое окно совсем не подходят к проекту.
как вариант обновлять iframe
Здравствуйте, O.Bender, Вы писали:
OB>В том-то и дело, что не хочется перегружать всю страницу, лезть заново в базу и т.д. Ведь все данные модели у меня УЖЕ ЕСТЬ и они не менялись, надо только как-то изящно их перекинуть на новую страницу или достать из сессии. OB>Ajax и новое окно совсем не подходят к проекту.
hidden поля?
Здравствуйте, O.Bender, Вы писали:
OB>Разбираюсь со Spring MVC, скоро надо начинать проект на этом фреймворке. OB>Столкнулся с одной проблемой, не понимаю как её красиво разрулить. OB>Допустим, что у меня есть основная страница, на ней форма, ну скажем редактирования профиля пользователя, я считал данные пользователя положил в formBackingObject и используя стандарный таг <spring:bind> эту форму отобразил. OB>А ещё в headerе для каждой станицы у меня есть маленькая формочка, которая позволяет отправить е-мейл другу о моём замечательном сайте. Это отдельный контроллер, он отрабатывает и переходит на последний view, который видел пользователь. Идея состоит в том, чтобы пользователь мог отправить е-майл другу и вернуться обратно к тому же view, т.е. к форме редактирования профиля пользователя, естественно полностью заполненной. OB>Но это уже ДРУГОЙ запрос и естественно, данных пользователя уже нет и я получаю javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'ххх' available as request attribute. OB>Когда-то давно в самописном MVC на PHP, я тупо клал всё, что мне нужно в сессию и не имел никаких проблем заново отобразить view, все данные были в сессии. Но <spring:bind> таг не умеет брать обьекты из сессии. OB>Как лучше всего разрешить эту проблему в Spring MVC? OB>Проблема-то стандартная наверняка, но поисков в Гыгле, нашёл, только несколько некрасивых хаков на эту тему.
Могу предложить следующее решение.
Как я понимаю ты используешь наследника от org.springframework.web.servlet.mvc.AbstractFormController. А у него есть метод formBackingObject(HttpServletRequest). Который по сути позваляет вытаскивать данные из реквеста и создавать начальные данные формы. Вообще этот механизм используется для правильной обработки кнопки back в браузере.
Так вот, предлагаю в форму послания письма добавить небольшой джаваскрипт, который бы собирал введенную информацию из основной формы и вставлял его в hidden поле формы отправки письма. Этат джяваскрипт вешается на форму отправки сообщения на onSubmit (могу ошибаться в джаваскрипте, но вроде так делать можно). Контроллер отправки письма будет отправлять письмо. Обрабатывать соответсвующее hidden поле и передавать введенные до этого данные в качестве параметров реквеста при редиректе на форму, а основной контроллер будет обрабатывать эти данные в методе formBackingObject(HttpServletRequest) и создавать парвильный объект.
N>Как я понимаю ты используешь наследника от org.springframework.web.servlet.mvc.AbstractFormController. А у него есть метод formBackingObject(HttpServletRequest). Который по сути позваляет вытаскивать данные из реквеста и создавать начальные данные формы. Вообще этот механизм используется для правильной обработки кнопки back в браузере.
N>Так вот, предлагаю в форму послания письма добавить небольшой джаваскрипт, который бы собирал введенную информацию из основной формы и вставлял его в hidden поле формы отправки письма. Этат джяваскрипт вешается на форму отправки сообщения на onSubmit (могу ошибаться в джаваскрипте, но вроде так делать можно). Контроллер отправки письма будет отправлять письмо. Обрабатывать соответсвующее hidden поле и передавать введенные до этого данные в качестве параметров реквеста при редиректе на форму, а основной контроллер будет обрабатывать эти данные в методе formBackingObject(HttpServletRequest) и создавать парвильный объект.
Нет, это не подходит. Основных форм будут десятки и ещё несколько маленьких вспомогательных форм, которые будут на каждой странице (смена языка, голосования, подписка на рассылку и т.д.). Для каждой основной формы подобным образом сохранять данные — не вариант.
Здравствуйте, O.Bender, Вы писали:
OB>Нет, это не подходит. Основных форм будут десятки и ещё несколько маленьких вспомогательных форм, которые будут на каждой странице (смена языка, голосования, подписка на рассылку и т.д.). Для каждой основной формы подобным образом сохранять данные — не вариант.
Так и не надо для каждой формы. Просто определится с общим морматом. В такм случае котроллеру отправки письма ненадо обрабатывать каждую основную форму как то специально. Просто тупо получает hidden поле и не парять вставляет его в реквест при редиректе. А проблема нескольких маленьких вспомогательных форм решается наследованием от одного общего контроллера.
N>Так и не надо для каждой формы. Просто определится с общим морматом. В такм случае котроллеру отправки письма ненадо обрабатывать каждую основную форму как то специально. Просто тупо получает hidden поле и не парять вставляет его в реквест при редиректе. А проблема нескольких маленьких вспомогательных форм решается наследованием от одного общего контроллера.
Т.е. собирать данные JavaScriptом в некий формат, слать их назад на сервер, потом редиректить на контроллер основной формы, там парсить эти даные в formBackingObject()?
На мой взгляд — излишне сложный, не очень красивый хак.
Что такое MVC? Грубо говоря контроллер обрабатывает запрос, подготавливает все данные (модель) и вызывает view. У меня уже есть модель, казалось бы надо просто вызвать view и всё, а начинаются танцы с бубнами.
Пока писал придумал вариант: объект формы в каждом "основном" контроллере класть в сессию с каким-то определённым именем типа "formBackingObject" и в каждом контроллере "маленькой" формы (или вообще в каком-нибудь interceptore) этот объект доставать из сессии и класть в модель.
Здравствуйте, O.Bender, Вы писали:
OB>Т.е. собирать данные JavaScriptом в некий формат, слать их назад на сервер, потом редиректить на контроллер основной формы, там парсить эти даные в formBackingObject()? OB>На мой взгляд — излишне сложный, не очень красивый хак.
Вообще эти проблемы извечны в web. И 100% красивого решения нет ни в одном фреймворке.
OB>Что такое MVC? Грубо говоря контроллер обрабатывает запрос, подготавливает все данные (модель) и вызывает view. У меня уже есть модель, казалось бы надо просто вызвать view и всё, а начинаются танцы с бубнами. OB>Пока писал придумал вариант: объект формы в каждом "основном" контроллере класть в сессию с каким-то определённым именем типа "formBackingObject" и в каждом контроллере "маленькой" формы (или вообще в каком-нибудь interceptore) этот объект доставать из сессии и класть в модель.
Так не бдует работет. Как я понимаю у тебя на отсылку письма и на редактирование пользователя две разных формы, два разных экшена и два разных контроллера. Понятное дело что если ты что то ввел на странице в одну форму а потом нажал на сабмит у другой форме, то данные из первой формы нифига не передадутся в реквесте. Так что в сессию то класть нечего. Тоесть без хидден поля никак.
Если бы отправку писма и редактирование пользователя обрабатывал один контроллер, то конечно таких проблем бы небыло.
N>Так не бдует работет. Как я понимаю у тебя на отсылку письма и на редактирование пользователя две разных формы, два разных экшена и два разных контроллера. Понятное дело что если ты что то ввел на странице в одну форму а потом нажал на сабмит у другой форме, то данные из первой формы нифига не передадутся в реквесте. Так что в сессию то класть нечего. Тоесть без хидден поля никак.
N>Если бы отправку писма и редактирование пользователя обрабатывал один контроллер, то конечно таких проблем бы небыло.
Не, мне данные формы, которые пользователь изменил не нужны (если он не хочет их сохранять, значит и ему не нужны), нужны данные, которые я изначально получил из базы данных, чтобы не лезть в базу и вообще не вызывать контороллер основной формы ещё раз.
Я в "основном" контроллере в formBackingObject(), собираю данные и кладу этот объект в сессию как "formBackingObject". А все "маленькие" наследуют контроллер, который достаёт из сессии мой "formBackingObject", кладёт его в модель и направляет пользователя на последний view, который пользователь видел.
Здравствуйте, O.Bender, Вы писали:
N>>Так не бдует работет. Как я понимаю у тебя на отсылку письма и на редактирование пользователя две разных формы, два разных экшена и два разных контроллера. Понятное дело что если ты что то ввел на странице в одну форму а потом нажал на сабмит у другой форме, то данные из первой формы нифига не передадутся в реквесте. Так что в сессию то класть нечего. Тоесть без хидден поля никак.
N>>Если бы отправку писма и редактирование пользователя обрабатывал один контроллер, то конечно таких проблем бы небыло.
OB>Не, мне данные формы, которые пользователь изменил не нужны (если он не хочет их сохранять, значит и ему не нужны), нужны данные, которые я изначально получил из базы данных, чтобы не лезть в базу и вообще не вызывать контороллер основной формы ещё раз. OB>Я в "основном" контроллере в formBackingObject(), собираю данные и кладу этот объект в сессию как "formBackingObject". А все "маленькие" наследуют контроллер, который достаёт из сессии мой "formBackingObject", кладёт его в модель и направляет пользователя на последний view, который пользователь видел.
Здравствуйте, O.Bender, Вы писали:
OB>Разбираюсь со Spring MVC, скоро надо начинать проект на этом фреймворке. OB>Столкнулся с одной проблемой, не понимаю как её красиво разрулить. OB>Допустим, что у меня есть основная страница, на ней форма, ну скажем редактирования профиля пользователя, я считал данные пользователя положил в formBackingObject и используя стандарный таг <spring:bind> эту форму отобразил. OB>А ещё в headerе для каждой станицы у меня есть маленькая формочка, которая позволяет отправить е-мейл другу о моём замечательном сайте. Это отдельный контроллер, он отрабатывает и переходит на последний view, который видел пользователь. Идея состоит в том, чтобы пользователь мог отправить е-майл другу и вернуться обратно к тому же view, т.е. к форме редактирования профиля пользователя, естественно полностью заполненной. OB>Но это уже ДРУГОЙ запрос и естественно, данных пользователя уже нет и я получаю javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'ххх' available as request attribute. OB>Когда-то давно в самописном MVC на PHP, я тупо клал всё, что мне нужно в сессию и не имел никаких проблем заново отобразить view, все данные были в сессии. Но <spring:bind> таг не умеет брать обьекты из сессии. OB>Как лучше всего разрешить эту проблему в Spring MVC? OB>Проблема-то стандартная наверняка, но поисков в Гыгле, нашёл, только несколько некрасивых хаков на эту тему.
Я простые дополнительные формы обрабатываю в интерцепторе. Их поля совсем не биндятся в команду основной формы. В интерцепторе достаю их непосредственно из запроса.