2015-04-08 7 views
5

Sto studiando come Spring handle REST servizi web e ho alcuni dubbi relativi al concetto di HttpMessageConverter.Come funziona esattamente l'annotazione @RequestBody e in che modo è correlata all'interfaccia HttpMessageConverter?

Sulla documentazione ufficiale posso leggere:

interfaccia strategia che specifica un convertitore che può convertire da e alle richieste HTTP e le risposte.

Così il HttpMessageConverter sembra essere un'interfaccia, ma che cosa è esattamente un'interfaccia strategia? Qualcosa è collegato al modello di strategia oppure no?

Quindi, da quello che ho capire Primavera fornire automaticamente alcune implementazioni registrati per impostazione predefinita quando si utilizza @EnableWebMvc o

Ma che cosa significa esattamente questi implementazione? Puoi fornirmi un esempio pratico?

Penso che funziona in questo modo:

Per esempio eseguire un cliente un HttpRequest mettendo nel corpo di questa richiesta un JSON messaggio (non sono così pratico ma penso che posso fare qualcosa in questo modo), quindi il controller che gestisce questo HttpRequst utilizza un'implementazione di HttpMessageConverter per convertire questo messaggio JSON in un oggetto modello. Penso che sia vero anche il contrario.

Il mio ragionamento è corretto o mi manca qualcosa?

Un altro dubbio è relativo all'annotazione @RequestBody (che penso sia correlata all'argomento precedente).

ho questo esempio:

@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); 
} 

Quindi penso che @RequestBody Ordinare updatedOrder prendere il valore del parametro di ingressoupdatedOrder dal corpo della HttpRequest e poi convertirlo con in un Ordinare l'oggetto utilizzando un'implementazione di HttpMessageConverter.

È giusto o mi manca qualcosa? Se è giusto come può scegliere il convertitore giusto?

Per esempio qui ho trovato un altro esempio simile al precedente: 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 
} 

Penso che qui è espressamente specificato che è necessario utilizzare un JSON MODELLI convertitore OGGETTO. Perché nell'esempio precedente non è specificato? Come può scegliere il convertitore giusto?

Tnx

risposta

9

parametri di metodo Handler sono generati da valori HandlerMethodArgumentResolver e metodo di gestore di ritorno della molla vengono elaborati da Spring di HandlerMethodReturnValueHandler. L'implementazione che riguarda sia @ResponseBody e @RequestBody è RequestResponseBodyMethodProcessor.

Uno di questi è registrato per impostazione predefinita (configurazione @EnableWebMvc) con un elenco predefinito di istanze HttpMessageConverter. Questo è fatto in WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List). Puoi trovare il codice sorgente e vedere quali sono aggiunti e in quale ordine.

Quando primavera va a generare un argomento per un parametro @RequestBody, si scorre i HttpMessageConverter casi, controlla se tale istanza HttpMessageConverter#canRead il tipo di contenuto dato nella richiesta e possono generare un'istanza del tipo di parametro. Se possibile, Spring userà tale HttpMessageConverter per produrre un argomento. Se non può, Spring salterà e tenterà l'istanza successiva, finché non si esaurirà. A quel punto, genererà un'eccezione.

Per @ResponseBody, il processo è lo stesso eccetto che Spring ora utilizza HttpMessageConverter#canWrite. Verificherà se il HttpMessageConverter può serializzare il tipo restituito e generare il contenuto della risposta che si adatta al tipo di contenuto previsto nella risposta (indicato nell'intestazione della richiesta Accept).

L'attributo consumes di @RequestParam

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

non ha nulla a che fare con la strategia dichiarata sopra. L'unica cosa che fa consumes qui è di limitare la mappatura del gestore. Ad esempio, prendere questi due gestori

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

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

Il primo grado di gestire qualsiasi richiesta di /pets con qualsiasi tipo di contenuto. Il secondo può gestire tali richieste solo per /pets con il tipo di contenuto application/json.

+3

Spiegazione perfetta, sei un ninja, indivia per te uomo – AndreaNobili

Problemi correlati