2015-10-08 27 views
7

Mam prosty kontroler REST napisany w aplikacji Spring-boot, ale nie jestem pewien, jak zaimplementować negocjację treści, aby zwrócić JSON lub XML na podstawie parametru Content-Type w nagłówku żądania . Czy ktoś mógłby mi wytłumaczyć, co robię źle?Negocjacja zawartości kontrolera rozruchowego

metoda Kontroler:

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

zawsze dotrzesz JSON gdy wywołanie tej metody (nawet jeśli określić Content-Type być application/xml lub text/xml).

Kiedy zaimplementuję dwie metody, z których każda ma inne odwzorowanie i inny typ zawartości, mogę uzyskać XML z xml, ale nie działa, jeśli określę dwa mediaType w jednej metodzie (jak w podanym przykładzie).

Co chciałbym to nazwać punkt końcowy \message i odbierać

  • XML gdy Content-Type żądania GET jest ustawione na application/xml
  • JSON gdy Content-Type jest application/json

Każda pomoc jest doceniana.

EDIT: zaktualizowałem moją kontroler przyjąć wszystkie typy nośników

@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

Musisz podać nagłówek 'Accept' z wartością' application/xml' lub z dowolnym obsługiwanym typem mediów. – systemfreund

+0

Nagłówek "Content-Type" określa, jaki rodzaj wysyłanej treści nie jest wysyłany - nie dotyczy to nagłówka "Accept", więc użycie nagłówka "Content-Type" dla żądania GET " ma sens, ponieważ nie może mieć żadnej treści (ciała) Tak więc w twoim przypadku powinieneś użyć nagłówka "Accept" dla swojego żądania, a w odpowiedzi nagłówka "Content-Type", aby nazwać rodzaj treści, która jest właściwie wyślij: –

Odpowiedz

9

Można znaleźć kilka wskazówek w blogu @RequestMapping with Produces and Consumes w punkcie 6.

zwrócić uwagę na odcinku około Content-Type Akceptuj i nagłówki:

@RequestMapping z Produkuje i zużywa: Możemy użyć nagłówka Content-Type i Akceptuj, aby dowiedzieć się, r equest content i jaka jest wiadomość mime, którą chce w odpowiedzi. W celu zwiększenia czytelności @RequestMapping udostępnia zmienne produkujące i konsumujące, w których możemy określić typ zawartości żądania , dla której metoda będzie wywoływana, oraz typ zawartości odpowiedzi: . Na przykład:

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

Nad metody można spożywać tylko komunikat z Content-Type jako text/html i jest w stanie produkować wiadomości typu application/json i application/xml.

Można też spróbować innego podejścia this (za pomocą obiektu ResponseEntity), który pozwala, aby dowiedzieć się typ wiadomości przychodzące i wytworzyć odpowiedni komunikat (również expoliting adnotacji @ResponseBody)

17

Można użyć ContentNegotiationConfigurer

po pierwsze, należy zastąpić metodę configureContentNegotiation w swojej klasie konfiguracji:

@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) - włączanie faworyzowania wyrażeń ścieżki przez parametry lub akceptowanie nagłówków.

defaultContentType(MediaType.APPLICATION_JSON) - ustawia domyślny typ zawartości. oznacza to, że jeśli nie przekażesz wyrażenia ścieżki, Spring wygeneruje JSON jako odpowiedź.

mediaType("xml", MediaType.APPLICATION_XML) - Ustawia klucz wyrażeń ścieżki dla XML.

Teraz, jeśli deklarują kontrolerze jak:

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

i nazywają to coś jak localhost:8080/app/accounts.json, potem wiosna przyniesie JSON jako odpowiedź. Więc jeśli zadzwonisz pod numer localhost:8080/app/accounts.xml, otrzymasz odpowiedź XML

Możesz znaleźć więcej informacji na ten temat here.

+2

tylko mały przypis na domyślnyContentType: [przeglądarki zazwyczaj wysyłają nagłówki akceptujące preferujące XML] (https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring- mvc.html). Omijanie (zakładając, że go nie używasz) Nagłówek Accept można zrobić w twoim zastąpieniu treściNegotiation: 'configurer.ignoreAcceptHeader (true)' –

+1

Myślę, że tutaj jest drobny błąd - sposób w jaki aby kontroler działał, powinieneś ustawić wartość favorPathExtension, aby była prawdziwa, a nie favorParameter. – user31415

+0

Czy można to zrobić dla konkretnego identyfikatora URI? –

Powiązane problemy