web-dev-qa-db-fra.com

Dans Spring MVC, comment définir l'en-tête de type mime lors de l'utilisation de @ResponseBody

J'ai un contrôleur Spring MVC qui renvoie une chaîne JSON et j'aimerais définir le type MIME sur application/json. Comment puis je faire ça?

@RequestMapping(method=RequestMethod.GET, value="foo/bar")
@ResponseBody
public String fooBar(){
    return myService.getJson();
}

Les objets métier étant déjà disponibles sous forme de chaînes JSON, utiliser MappingJacksonJsonView n'est pas la solution pour moi. @ResponseBody est parfait, mais comment puis-je définir le type MIME?

74
Sean Patrick Floyd

J'envisagerais de refactoriser le service pour qu'il retourne votre objet de domaine plutôt que les chaînes JSON et laisse Spring gérer la sérialisation (via le MappingJacksonHttpMessageConverter au fur et à mesure que vous écrivez). À compter du printemps 3.1, la mise en œuvre semble assez soignée:

@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, 
    method = RequestMethod.GET
    value = "/foo/bar")
@ResponseBody
public Bar fooBar(){
    return myService.getBar();
}

Commentaires:

Premièrement le <mvc:annotation-driven /> ou la @EnableWebMvc doit être ajouté à la configuration de votre application.

Ensuite, l'attribut produit de la @RequestMapping annotation permet de spécifier le type de contenu de la réponse. Par conséquent, il doit être défini sur MediaType.APPLICATION_JSON_VALUE (ou "application/json").

Enfin, Jackson doit être ajouté pour que toute sérialisation et dé-sérialisation entre Java et JSON soit gérée automatiquement par Spring (la dépendance de Jackson est détectée par Spring et le MappingJacksonHttpMessageConverter être sous le capot).

39
matsev

Utilisez ResponseEntity au lieu de ResponseBody. De cette façon, vous avez accès aux en-têtes de réponse et vous pouvez définir le type de contenu approprié. Selon le Spring docs :

Le HttpEntity est similaire à @RequestBody et @ResponseBody. Outre l'accès au corps de la demande et de la réponse, HttpEntity (et à la sous-classe propre à la réponse ResponseEntity) permet également d'accéder aux en-têtes de requête et de réponse.

Le code ressemblera à ceci:

@RequestMapping(method=RequestMethod.GET, value="/fooBar")
public ResponseEntity<String> fooBar2() {
    String json = "jsonResponse";
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.setContentType(MediaType.APPLICATION_JSON);
    return new ResponseEntity<String>(json, responseHeaders, HttpStatus.CREATED);
}
118
Javier Ferrero

Vous ne pourrez peut-être pas le faire avec @ResponseBody, mais quelque chose comme ceci devrait fonctionner:

package xxx;

import Java.io.ByteArrayOutputStream;
import Java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class FooBar {
  @RequestMapping(value="foo/bar", method = RequestMethod.GET)
  public void fooBar(HttpServletResponse response) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    out.write(myService.getJson().getBytes());
    response.setContentType("application/json");
    response.setContentLength(out.size());
    response.getOutputStream().write(out.toByteArray());
    response.getOutputStream().flush();
  }
}
7
GriffeyDog

Je ne pense pas que ce soit possible. Il semble y avoir une Jira ouverte pour cela:

SPR-6702: Définition explicite de la réponse Content-Type dans @ResponseBody

4
dogbane

Registre org.springframework.http.converter.json.MappingJacksonHttpMessageConverter en tant que convertisseur de message et renvoie l'objet directement à partir de la méthode.

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="webBindingInitializer">
    <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"/>
  </property>
  <property name="messageConverters">
    <list>
      <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
    </list>
  </property>
</bean>

et le contrôleur:

@RequestMapping(method=RequestMethod.GET, value="foo/bar")
public @ResponseBody Object fooBar(){
    return myService.getActualObject();
}

Cela nécessite la dépendance org.springframework:spring-webmvc.

3
OrangeDog

Je ne pense pas que vous puissiez le faire, à part response.setContentType(..)

1
Bozho