web-dev-qa-db-fra.com

Négociation du contenu du contrôleur de démarrage de printemps

J'ai un simple contrôleur REST écrit dans une application Spring-boot mais je ne sais pas comment implémenter la négociation de contenu pour lui faire retourner JSON ou XML en fonction du paramètre Content-Type dans la demande Quelqu'un pourrait-il m'expliquer ce que je fais mal?

Méthode du contrôleur:

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

J'obtiens toujours JSON lors de l'appel de cette méthode (même si je spécifie le Content-Type être application/xml ou text/xml).

Lorsque j'implémente deux méthodes chacune avec un mappage différent et un type de contenu différent, je peux obtenir du XML à partir du XML mais cela ne fonctionne pas si je spécifie deux mediaTypes dans une seule méthode (comme l'exemple fourni).

Ce que je voudrais, c'est appeler le \message endpoint et recevoir

  • XML lorsque le Content-Type de la demande GET est défini sur application/xml
  • JSON lorsque le Content-Type est application/json

Toute aide est appréciée.

EDIT: j'ai mis à jour mon contrôleur pour accepter tous les types de médias

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

Vous pouvez trouver quelques astuces dans le billet de blog @ RequestMapping with Produces and Consumes au point 6.

Faites attention à la section sur les en-têtes Content-Type et Accept:

@RequestMapping avec des produits et des consommations: nous pouvons utiliser l'en-tête Content-Type et Accept pour connaître le contenu de la demande et quel est le message MIME qu'il souhaite en réponse. Pour plus de clarté, @RequestMapping fournit des variables de production et de consommation où nous pouvons spécifier le type de contenu de la demande pour laquelle la méthode sera invoquée et le type de contenu de la réponse. Par exemple:

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

La méthode ci-dessus peut consommer un message uniquement avec Content-Type en tant que texte/html et est capable de produire des messages de type application/json et application/xml.

Vous pouvez également essayer cette approche différente (en utilisant l'objet ResponseEntity) qui vous permet de trouver le type de message entrant et de produire le message correspondant (en expolant également l'annotation @ResponseBody)

14
abarisone

Vous pouvez utiliser ContentNegotiationConfigurer

Tout d'abord, vous devez remplacer la méthode configureContentNegotiation dans votre classe de configuration:

@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) - permettant de privilégier les expressions de chemin par rapport au paramètre ou d'accepter les en-têtes.

defaultContentType(MediaType.APPLICATION_JSON) - définit le type de contenu par défaut. cela signifie que si vous ne transmettez pas d'expression de chemin, Spring générera JSON comme réponse.

mediaType("xml", MediaType.APPLICATION_XML) - définit la clé d'expression de chemin pour XML.

Maintenant, si vous déclarez votre contrôleur comme:

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

et appelez-le quelque chose comme localhost:8080/app/accounts.json, alors Spring générera JSON comme réponse. Donc, si vous appelez localhost:8080/app/accounts.xml, Vous recevrez une réponse XML

Vous pouvez trouver plus d'informations à ce sujet ici .

25
Artur Boruński