2015-04-08 8 views
5

Ich studiere, wie Frühling Griff REST Webdienste und ich habe einige Zweifel im Zusammenhang mit dem Konzept der HttpMessageConverter.Wie genau funktioniert @RequestBody Annotation und wie es mit der HttpMessageConverter-Schnittstelle verwandt ist?

Auf der offiziellen Dokumentation kann ich lesen:

Strategie-Schnittstelle, die einen Konverter an, der von und HTTP-Anfragen und Antworten umwandeln kann.

So ist die HttpMessageConverter scheint eine Schnittstelle zu sein, aber was genau ist eine Strategie Schnittstelle? Ist etwas mit der Strategie Muster oder nicht verwandt?

Also von dem, was ich habe verstehen Frühling automatisch einige Implementierungen standardmäßig registriert bietet bei Verwendung von @EnableWebMvc oder

Aber was macht genau diese Implementierung? Können Sie mir ein praktisches Beispiel geben?

Ich denke, dass es auf diese Weise funktioniert:

Zum Beispiel ein Client ausführen ein Httprequest im Körper dieser Anfrage stellen eine JSON Nachricht (Ich bin nicht so praktisch, aber ich denke, dass ich etwas tun kann wie dies), dann verwenden die Controller, die diese HttpRequst behandeln, eine Implementierung von HttpMessageConverter, um diese JSON-Nachricht in ein Modellobjekt zu konvertieren. Ich denke, dass es auch umgekehrt stimmt.

Ist meine Argumentation richtig oder fehlt mir etwas?

Ein weiterer Zweifel bezieht sich auf die @RequestBody Annotation (die ich denke, dass es mit dem vorherigen Thema verwandt ist).

Ich habe dieses Beispiel:

@RequestMapping(value="/orders/{id}", method=RequestMethod.PUT) 
@ResponseStatus(HttpStatus.NO_CONTENT) // 204 
public void updateOrder(@RequestBody Order updatedOrder, @PathVariable("id") long id) { 
    // process updated order data and return empty response 
    orderManager.updateOrder(id, updatedOrder); 
} 

Ich denke also, dass @RequestBody Auftrag updatedOrder den Wert der updatedOrder nimmt Eingabeparameter aus dem Körper des Httprequest und wandeln sie dann mit in eine Auftrag Objekt mit einer Implementierung von HttpMessageConverter.

Ist es richtig oder fehle ich etwas? Wenn es richtig ist, wie kann der richtige Konverter gewählt werden?

Zum Beispiel hier fand ich ein weiteres Beispiel ähnlich den vorherigen: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

@Controller 
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 
public void addPet(@RequestBody Pet pet, Model model) { 
    // implementation omitted 
} 

Ich denke, dass hier ist es explizit angegeben, dass sie ein JSON Modellobjekt-Wandler zu verwenden. Warum ist im vorherigen Beispiel nicht angegeben? Wie kann der richtige Konverter ausgewählt werden?

Tnx

Antwort

9

Handler Methodenparameter erzeugt werden, durch Spring HandlerMethodArgumentResolver und Handler-Methode Rückgabewerte verarbeitet werden durch Spring HandlerMethodReturnValueHandler. Die Implementierung, die sich sowohl mit @ResponseBody als auch mit @RequestBody befasst, ist RequestResponseBodyMethodProcessor.

Eine davon ist standardmäßig registriert (@EnableWebMvc Konfiguration) mit einer Standardliste von HttpMessageConverter Instanzen. Dies geschieht in WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List). Sie können den Quellcode finden und sehen, welche in welcher Reihenfolge hinzugefügt wurden.

Wenn der Frühling geht ein Argument für einen @RequestBody Parameter zu erzeugen, ist es eine Schleife durch die HttpMessageConverter Fälle überprüft, ob diese Instanz HttpMessageConverter#canRead der Inhaltstyp in der Anfrage angegeben und kann eine Instanz des Parametertypen erzeugen. Wenn dies der Fall ist, verwendet Spring das HttpMessageConverter, um ein Argument zu erzeugen. Wenn dies nicht möglich ist, wird Spring es überspringen und die nächste Instanz versuchen, bis es ausläuft. An diesem Punkt wird eine Ausnahme ausgelöst.

Für @ResponseBody ist der Prozess der gleiche, außer dass Spring jetzt HttpMessageConverter#canWrite verwendet. Es wird überprüft, ob der HttpMessageConverter den Rückgabetyp serialisieren und den Antwortinhalt generieren kann, der dem Inhaltstyp entspricht, der in der Antwort erwartet wird (angegeben im Anforderungskopf Accept).

Das consumes Attribut @RequestParam

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 

hat nichts mit der Strategie oben erklärt zu tun. Das einzige, was tut, ist hier das Mapping des Handlers zu beschränken. Nehmen wir zum Beispiel diese beiden Handler

@RequestMapping(value = "/pets", method = RequestMethod.POST) 

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 

Die erste jede Anforderung zu /pets mit jedem Inhaltstyp verarbeiten kann. Die zweite kann nur solche Anforderungen an /pets mit dem Inhaltstyp application/json verarbeiten.

+3

Perfekte Erklärung, du bist ein Ninja, Endivie für dich Mann – AndreaNobili

Verwandte Themen