2017-02-25 12 views
10

Jestem nowy na wiosnę i rejestruję użytkownika. Podobało mi się to.Spring: obiekt wiązania zi bez @ModelAttribute

@RequestMapping("/register") 
    public String register(@ModelAttribute User user,BindingResult result){ 
     if(!result.hasErrors()){ 
     userSerive.register(user); 
     } 
    return "welcome"; 
} 

To działało w porządku, ale problemem jest to, że nie trzeba tego user obiekt w moim welcome.jsp stronie, więc dlaczego Marka Model obiektu heavier.So Próbowałem bez @ModelAttribute, działa to również dla mnie jak poniżej.

@RequestMapping("/register") 
    public String register(User user,BindingResult result){ 
     if(!result.hasErrors()){ 
     userSerive.register(user); 
     } 
    return "welcome"; 
} 

Więc po prostu chcesz wiedzieć, jakie są plusy & minusy obu i która jest najlepsza praktyka, jeśli naprawdę nie trzeba user obiekt w jsp. Czy @ModelAttribute robi coś innego oprócz dodawania obiektu do modelu, którego niejawne wiązanie sprężyny nie ma. Czy jest to bezpieczniejszy sposób wiązania?

Chcę kategoriach moje zapytanie w następujących 4 typ request.what byłaby różnica zi bez @ModelAttribute gdybym nie trzeba wysyłać dane w widoku i moja prośba jest dowolny of-

  1. łańcuch zapytania tj dane formularzy Get
  2. prośba ładowność lub organ tj forma dane POST
  3. danych json w ajaxified GET requst
  4. danych json w post requst- Chyba nie byłoby to wiążą się w żadnej z obu. Wymagane jest @RequestBody.
+0

Nie można rozpocząć nagrody za to pytanie, ponieważ nagrody muszą wzrastać za każdym razem, a następny przyrost to 100 powtórzeń. – Ryan

Odpowiedz

0

Jak opisano w wiosennej dokumentacji MVC - adnotacja @ModelAttribute może być używana w metodach lub w argumentach metody. I oczywiście możemy używać obu jednocześnie w jednym kontrolerze.

Metoda adnotacja

@ModelAttribute("person") 
public Person getPerson(){ 
    return new Person(); 
} 

Celem takiego sposobu jest to, aby dodać atrybut w modelu. W naszym przypadku klucz personalny będzie miał obiekt osoby jako wartość w Modelu. Metody @ModelAttribute w kontrolerze są wywoływane przed metodami @RequestMapping w tym samym kontrolerze.

Metoda Argument

public String processForm(@ModelAttribute("person") Person person){ 
    person.getStuff(); 
} 

Patrz dokumentacja wiosna http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args

+0

brakuje kontekstu. W moim przypadku użycia nie potrzebuję modelu w warstwie widoku, mogę powiązać formdata w java zi bez '@ ModelAttribute', jaka jest różnica między obydwoma podejściami, jeśli nie potrzebujemy tego modelu w jsp. – TheCurious

3

Prawdopodobnie (patrz niżej ...) żadnej różnicy w zachowaniu między dwoma podpisami metoda, w Twoim przypadku.

Obydwa wiążą parametry żądania do user i dodać wynikowy do modelu jako atrybut user - nazwa ta cecha powstały z zdekapitalizowanej nazwy typ argumentu metody, User. Aby dostosować nazwę atrybutu, można użyć

@ModelAttribute@ModelAttribute("theUser") lub dać wskazówkę czytelnikowi kodu, że ten argument jest używany w widoku. Ale jak mówisz, żadna z nich nie ma zastosowania w twoim przypadku użycia.

Dokładnie ten sam kod na wiosnę będzie użyty do wypełnienia argumentu, niezależnie od tego, czy używasz adnotacji @ModelAttribute - kod ten to org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.

Dlatego bardziej sensowne jest dla mnie używanie podpisu public String register(User user, BindingResult result) w kodzie. Dodanie adnotacji do argumentów metody, które nie są wymagane w modelu, może być mylące dla osób czytających twój kod.


Nieco dłużej odpowiedź brzmi, że nie może tylko o być powodem do określania @ModelAttribute w Twoim przypadku - ale to całkiem tajemna i nieprawdopodobne.

Argumenty metod w metodach obsługi w Spring są wypełniane przez instancje HandlerMethodArgumentResolver. Są one konfigurowalne i są podejmowane z kolei dla każdego parametru.

Domyślna metoda obsługi argumentem przeliczniki wyglądać następująco (patrz RequestMappingHandlerAdapter):

resolvers.add(new ServletModelAttributeMethodProcessor(false)); 

... 

resolvers.add(new ServletModelAttributeMethodProcessor(true)); 

Jeśli było dodać własny w środku, na przykład a UserHandlerMethodArgumentResolver, możesz wtedy użyć @ModelAttribute, aby nakazać Springowi, aby przetwarzał określony argument w sposób domyślny, zamiast używać niestandardowej klasy przelicznika argumentów.

+0

To jest odpowiedź na pytanie PO. – John

1

Oprócz dodawania obiektu do modelu, Spring MVC używa go do dostarczania związanego obiektu do metody Controller, gdzie można go użyć, w twoim przypadku do "rejestracji".

I tak @ModelAtttribute jest najbezpieczniejszym i najlepszym sposobem w Spring MVC do wiązania przychodzących danych pocztowych do obiektu.

0

Sprawdź ten wpis here. Obejmuje znaczną ilość szczegółów dotyczących ModelAttribute.

Funkcja ModelAttribute może być używana tylko z danymi żądania zakodowanymi w formularzu. Nie może powiązać danych żądania json/xml z obiektami danych. W tym celu będziesz musiał użyć RequestBody.

1

To pytanie jest bardzo przydatne, ale nie widzę odpowiedzi tutaj, prawidłowo odpowiedz na pytanie.

czytam przez więcej wątków w stackoverflow, i że ten jeden bardzo przydatne: https://stackoverflow.com/a/26916920/1542363

Dla siebie jak zdecydować, który z nich korzystać, jeśli tylko potrzebne są wiążące i nie chcą, aby zapisać obiekt parametru w modelu, a następnie nie używaj @ModelAttribute.

+0

Nie znalazłem żadnej przyczyny przechowywania obiektu parametru w modelu oprócz wysyłania do widoków takich jak jsp.yes o co w tym wszystkim chodzi, czy istnieje jakikolwiek inny powód dla tego samego. – TheCurious

0

oprócz @ryanp „s doskonałą odpowiedź, chciałbym dodać:

nowoczesnej MVC wiosny projektu, to najpewniejszym jeden użyłby adnotacje jak @Controller i @RequestMapping etc w celu zapewnienia obsługi żądań , wewnętrznie, Spring MVC używa RequestMappingHandlerAdapter.invokeHandlerMethod() do przetworzenia żądania z dostarczonym przez użytkownika HandlerMethod. jeśli spojrzysz na RequestMappingHandlerAdapter, to ustawia on kolekcję resolwera argumentów, aby przygotować argument do HandlerMethod, patrząc na zestaw, rozumiesz, w jaki sposób iw jakiej kolejności ma sparsować Spring MVC i zapełnić podane przez użytkownika argumenty.tak oto kod źródłowy:

`` `Java

/** 
* Return the list of argument resolvers to use including built-in resolvers 
* and custom resolvers provided via {@link #setCustomArgumentResolvers}. 
*/ 
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { 
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>(); 

    // Annotation-based argument resolution 
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); 
    resolvers.add(new RequestParamMapMethodArgumentResolver()); 
    resolvers.add(new PathVariableMethodArgumentResolver()); 
    resolvers.add(new PathVariableMapMethodArgumentResolver()); 
    resolvers.add(new MatrixVariableMethodArgumentResolver()); 
    resolvers.add(new MatrixVariableMapMethodArgumentResolver()); 
    resolvers.add(new ServletModelAttributeMethodProcessor(false)); 
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); 
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); 
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); 
    resolvers.add(new RequestHeaderMapMethodArgumentResolver()); 
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); 
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); 
    resolvers.add(new SessionAttributeMethodArgumentResolver()); 
    resolvers.add(new RequestAttributeMethodArgumentResolver()); 

    // Type-based argument resolution 
    resolvers.add(new ServletRequestMethodArgumentResolver()); 
    resolvers.add(new ServletResponseMethodArgumentResolver()); 
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); 
    resolvers.add(new RedirectAttributesMethodArgumentResolver()); 
    resolvers.add(new ModelMethodProcessor()); 
    resolvers.add(new MapMethodProcessor()); 
    resolvers.add(new ErrorsMethodArgumentResolver()); 
    resolvers.add(new SessionStatusMethodArgumentResolver()); 
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); 

    // Custom arguments 
    if (getCustomArgumentResolvers() != null) { 
     resolvers.addAll(getCustomArgumentResolvers()); 
    } 

    // Catch-all 
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); 
    resolvers.add(new ServletModelAttributeMethodProcessor(true)); 

    return resolvers; 
} 

` ``

Co warto zauważyć, jest catch-all przeliczniki na dole. Spring MVC używa tych samych dwóch resolwerów, które obsługują atrybuty @RequestParam i @ModelAttribute, aby obsłużyć odpowiednio nieopisane typy proste i typy pojo. Dlatego w teście OP nie ma znaczenia, czy istnieje @ModelAttribute, czy nie.

To wstyd, że nie jest krystalicznie jasne w referencji Spring MVC.

Powiązane problemy