2013-09-05 16 views
5

mam kontrolera z metody GET napisane tak:wiosny Web MVC, @ModelAttribute i @RequestParam razem

@Controller 
public class ThingController { 

    @RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
    public String editThing(@RequestParam("thingId") String thingId, @ModelAttribute ThingBean thing, BindingResult result) { 
     thing = <some service call using thingId> 
     logger.debug("The thing to edit is {}", thingBean); 
     return "thing/edit"; 
    } 
} 

Fasola jest prawidłowe (pobierające i ustawiające), wywołanie usługa zwraca poprawną ThingBean z pojawi się thingId i moja strona JSP w thing/edit.jsp.

JSP jest:

<html> 
<body> 
    <h1 id="title" class="title">Edit Thing</h1> 

<form:form id="thing" modelAttribute="thing"> 
    <form:input path="subject" id="subject" tabindex="1" /> 
    <form:textarea path="message" /> 

</form:form> 

</body> 
</html> 

Jednak JSP wyświetla puste wartości przedmiotu oraz wiadomości. Tak, istnieją właściwości pobierające/ustawiające na tych właściwościach.

Mam bardzo podobny kontroler, który działa dobrze, z wyjątkiem tego, że nie ma @RequestParam w sygnaturze metody odwzorowanej GET.

Nie widziałem nigdzie w wiosennych dokumentach WebMVC, które mówią, że nie mogę tego zrobić - dlaczego to nie działa? Dlaczego zaktualizowany obiekt ModelAttribute nie jest powiązany z formularzem JSP?

EDIT:

Sterownik ten i ten sam wzór dla połączeń GET współpracował wiele wiele różnych miejsc - zmienną opatrzone @ModelAttribute wypełnia się następnie metodą dostępną dla strony JSP do wyświetlenia. Dlaczego, dodając adnotację @RequestParam, zatrzymuje się?

@RequestMapping(value = "/Things.html", method = RequestMethod.GET) 
public String getThings(@ModelAttribute ThingForm thingForm, BindingResult result) { 

    try { 
     // need to get list of Things 
     List<Thing> Things = <service call that gets list of Things>; 
     thingForm.setThings(Things); 
     logger.debug("Things are {}", Things); 

    } 
    catch (ResourceNotFoundException e) { 
     return "error"; 
    } 

    logger.debug("Thing list loading - end"); 

    // Go to jsp 
    return "thing/list"; 
} 
+0

można pokazać nam swoją drugą controller.and Co M.Deinum powiedział, jest prawidłowe. – beinghuman

+0

Edytowane pytanie w celu dodania kontrprzykładu. –

+1

Jak wspomniałem w mojej odpowiedzi w kontrolerze, który napisałeś, jesteś ** ponownie przypisujesz ** zmienną (argument metody) NIE prześladujesz obiektu, który przekazałeś do metody. W kontrolerze powiesz, że to działa ** dodajesz ** coś do obiektu, który działa jako obiekt modelu. Zasadniczo jest zupełnie inaczej. –

Odpowiedz

7

Problem polega na tym, że przydzielasz nowe odniesienie do rzeczy, które nigdy nie zadziała w Javie. Musisz umieścić go w modelu, w przeciwnym razie nie będzie znany twojemu widokowi.

@RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
public String editThing(@RequestParam("thingId") String thingId, @ModelAttribute ThingBean thing, BindingResult result) { 
    thing = <some service call using thingId> // This is only assigning a new reference not updating 
    logger.debug("The thing to edit is {}", thingBean); 
    return "thing/edit"; 
} 

Więc zamiast robić to

@RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
public String editThing(@RequestParam("thingId") String thingId, @ModelAttribute ThingBean thing, BindingResult result, Model model) { 
    thing = <some service call using thingId> 
    model.addAttribute("thing", thing); 
    logger.debug("The thing to edit is {}", thingBean); 
    return "thing/edit"; 
} 

co sprawia, że ​​zastanawiam się, dlaczego nie można nawet mieć atrybut modelu w tej metodzie? Jest to w zasadzie bezużyteczne.

Zamiast powyższego chciałbym zrobić coś takiego

@ModelAttribute("thing") 
public Thing prepareModel(@RequestParam("thingId") String thingId) { 
    return thingSergice.findById(thingId); 
} 

Teraz ta metoda zostanie wywołana przed każdą metodą żądanie obsługi. W którym można po prostu odwołać się do niego zamiast konieczności sprawdzania go za każdym razem. (A sądząc po kodzie swój atrybut modelu Thingbean w swojej metodzie jest całkiem bezużyteczny Chciałbym przepisać że do następujących)

@RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
public String editThing() { 
    return "thing/edit"; 
} 
+0

Dodałem więc kontrprzykład, a ten wzorzec zadziałał w kółko. Zmienna opisana za pomocą ModelAttribute została zaktualizowana za pomocą metody z adnotacjami GET i była dostępna na stronie JSP. Jedyną różnicą w stosunku do mojej nowej wersji było dodanie parametru z komentarzem RequestParam. –

+0

Jak wspomniałem w moim drugim komentarzu, nie są one takie same ... W tym, który nie działa, jesteś ** ponownie przypisujący **, podczas gdy drugi ** aktualizuje ** obiekt modelu. –

+0

ARGH. Głupi programator. Ostatnio robiłem zbyt wiele programowania bocznego C. Dzięki, oczywiście, widzę to teraz. –

1

Zapomniałeś określić ModelAttribute nazwisko, stosowanie następujących korekt:

public String editThing(@RequestParam("thingId") String thingId, 
@ModelAttribute("thing") ThingBean thing, BindingResult result) { 
.... 
} 

Jeśli powyżej nie działa użyj:

public String editThing(@RequestParam("thingId") String thingId, 
    @ModelAttribute("thing") ThingBean thing, BindingResult result, Model model) { 
      .... 
    thing = <some service call using thingId> 
    logger.debug("The thing to edit is {}", thingBean); 
    model.addAttribute("thing",thing); 
    return "thing/edit"; 
} 

Jeśli to możliwe, zalecamy stosowanie lepszego nazewnictwa konwencja dotycząca komponentów, na przykład: thingModel zamiast thing. Zapewnia to lepszą czytelność dla Ciebie i innych.

+0

Ja zredagowałem kod produkcyjny. Zaufaj mi, nazwa jest lepsza niż "rzecz". –

+0

Nawiasem mówiąc, nie musisz określać nazwy w języku Java 8. – naXa

Powiązane problemy