2015-10-08 32 views
7

Ich habe eine einfache REST-Controller in einer Spring-Boot-Anwendung geschrieben, aber ich bin mir nicht sicher, wie die Inhaltsverhandlung zu JSON oder XML auf der Grundlage der Content-Type-Parameter im Anfrage-Header zurückgeben zu implementieren . Könnte mir jemand erklären, was mache ich falsch?Spring Boot-Controller Inhalt Verhandlung

Controller-Methode:

@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }) 
    public Message getMessageXML(@RequestParam("text") String text) throws Exception { 
    Message message = new Message(); 
    message.setDate(new Date()); 
    message.setName("Test"); 
    message.setAge(99); 
    message.setMessage(text); 

    return message; 
    } 

ich JSON immer erhalten, wenn Sie diese Methode aufrufen (auch wenn ich die Content-Type angeben application/xml oder text/xml zu sein).

Wenn ich zwei Methoden mit unterschiedlichen Mappings und unterschiedlichen Inhaltstypen implementiere, kann ich XML aus XML holen, aber es funktioniert nicht, wenn ich zwei mediaTypes in einer einzigen Methode (wie im Beispiel) angeben.

Was würde Ich mag es, die \message Endpunkt anrufen und

  • XML empfangen, wenn der Content-Type der GET-Anforderung an application/xml
  • JSON gesetzt, wenn der Content-Type-Anwendung ist/json

Jede Hilfe wird geschätzt.

EDIT: ich mein Controller aktualisiert, um alle Medientypen zu akzeptieren

@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, consumes = MediaType.ALL_VALUE) 
    public Message getMessageXML(@RequestParam("text") String text) throws Exception { 
    Message message = new Message(); 
    message.setDate(new Date()); 
    message.setName("Vladimir"); 
    message.setAge(35); 
    message.setMessage(text); 

    return message; 
    } 
+1

Sie müssen einen 'Accept'-Header mit dem Wert' application/xml' oder mit einem der unterstützten Medientypen angeben. – systemfreund

+0

Der Header "Content-Type" definiert, welche Art von Inhalt Sie senden - nicht die, die Sie erhalten möchten (das ist der Header "Accept"). Die Verwendung des Headers "Content-Type" für eine GET-Anfrage funktioniert nicht. Sinnvoll, da kann kein (Body-) Inhalt haben. Also in Ihrem Fall sollten Sie den Header "Accept" für Ihre Anfrage und in der Antwort die "Content-Type" -Kopfzeile verwenden, um den Typ des Inhalts zu nennen tatsächlich senden. –

Antwort

9

Sie können einige Hinweise im Blog-Post @RequestMapping with Produces and Consumes am Punkt finden 6.

Achten Sie auf den Abschnitt über Content-Type und Header akzeptieren:

@RequestMapping mit produziert und konsumiert: Wir Header Content-Type verwenden können, und Accept, um herauszufinden, r Equest Inhalte und was ist die Pantomime Nachricht, die es als Antwort will. Zur Verdeutlichung bietet @RequestMapping liefert und verbraucht Variablen, in denen wir die Anfrage Inhaltstyp für welche Methode aufgerufen werden kann und die Antwort Inhaltstyp. Zum Beispiel:

@RequestMapping(value="/method6", produces={"application/json","application/xml"}, consumes="text/html") 
@ResponseBody 
public String method6(){ 
    return "method6"; 
} 

obiges Verfahren kann Nachricht nur mit Content-Type als text/html verbrauchen und in der Lage, Nachrichten vom Typ application/json und application/xml zu produzieren.

Sie auch this anderen Ansatz versuchen können (ResponseEntity-Objekt), dass Sie den eingehenden Nachrichtentyp, um herauszufinden, ermöglicht und produzieren die entsprechende Meldung (auch die @ResponseBody Anmerkung expoliting)

17

Sie ContentNegotiationConfigurer

verwenden können

Zunächst sollten Sie die configureContentNegotiation Methode in der Konfigurationsklasse außer Kraft setzen:

@Configuration 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 
    configurer.favorPathExtension(false). 
      favorParameter(true). 
      defaultContentType(MediaType.APPLICATION_JSON). 
      mediaType("xml", MediaType.APPLICATION_XML); 
    } 
} 

favorParameter(true) - Aktivieren von Pfadausdrücken über Parameter- oder Accept-Header.

defaultContentType(MediaType.APPLICATION_JSON) - legt den Standardinhaltstyp fest. Das heißt, wenn Sie keinen Pfadausdruck übergeben, generiert Spring JSON als Antwort.

mediaType("xml", MediaType.APPLICATION_XML) - legt den Pfadausdruckschlüssel für XML fest.

Nun, wenn Sie Ihre Steuer erklären wie:

@Controller 
class AccountController { 

    @RequestMapping(value="/accounts", method=RequestMethod.GET) 
    @ResponseStatus(HttpStatus.OK) 
    public @ResponseBody List<Account> list(Model model, Principal principal) { 
     return accountManager.getAccounts(principal)); 
    } 
} 

und nennen es so etwas wie localhost:8080/app/accounts.json, dann wird Frühling JSON als Reaktion erzeugen. Also, wenn Sie localhost:8080/app/accounts.xml anrufen erhalten Sie XML-Antwort

Sie können weitere Informationen über diese here finden.

+2

nur eine kleine Fußnote auf dem DefaultContentType: [Browser neigen dazu, akzeptieren Kopfzeilen, die XML bevorzugen] (https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring- mvc.html) Umgehung (vorausgesetzt, Sie verwenden es nicht) kann der Accept-Header in Ihrem Override von contentNegotiation: 'configurer.ignoreAcceptHeader (true)' –

+1

Ich denke, es ist ein kleiner Fehler hier - so wie Sie Anspruch auf den Controller zu arbeiten, sollten Sie favorPathExtension auf wahr, anstatt favorParameter festlegen. – user31415

+0

kann dies für bestimmte URI getan werden? –

Verwandte Themen