В Spring MVC, как я могу установить заголовок типа mime при использовании @ResponseBody


У меня есть контроллер Spring MVC, который возвращает строку JSON, и я хотел бы установить тип mimetype в application/json. Как я могу это сделать?

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

бизнес-объекты уже доступны в виде строк JSON, поэтому с помощью MappingJacksonJsonView это не решение для меня. @ResponseBody - это замечательно, но как я могу установить этот фильтр?

7 67

7 ответов:

Я бы рассмотрел рефакторинг службы, чтобы вернуть ваш объект домена, а не строки JSON, и пусть Spring обрабатывает сериализацию (через MappingJacksonHttpMessageConverter Как вы пишите). По состоянию на весну 3.1 реализация выглядит довольно аккуратно:

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

комментарии:

сначала <mvc:annotation-driven /> или @EnableWebMvc должно быть добавил в конфигурации приложения.

далее производит на @RequestMapping аннотация используется для указания тип содержимого ответа. Следовательно, он должен быть установлен в MediaType.APPLICATION_JSON_VALUE (или "application/json").

наконец, Джексон должен быть добавлен так, чтобы любая сериализация и де-сериализация между Java и JSON обрабатывались автоматически Spring (зависимость Джексона обнаруживается Spring и MappingJacksonHttpMessageConverter будет под капотом).

использовать ResponseEntity вместо ResponseBody. Таким образом, у вас есть доступ к заголовкам ответов, и вы можете установить соответствующий тип контента. Согласно Spring docs:

The HttpEntity аналогично @RequestBody и @ResponseBody. Помимо получения доступа к запросу и тело ответа, HttpEntity (и подкласс, специфичный для ответа ResponseEntity) также позволяет получить доступ к заголовки запроса и ответа

код будет выглядеть например:

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

возможно, вы не сможете сделать это с помощью @ResponseBody, но что-то вроде этого должно работать:

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

Я не думаю, что это возможно. Кажется, для этого есть открытая Джира:

SPR-6702: явно установите содержимое ответа-введите в @ResponseBody

зарегистрироваться org.springframework.http.converter.json.MappingJacksonHttpMessageConverter как конвертер сообщений и возвращает объект непосредственно из метода.

<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>

и контроллером:

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

для этого требуется зависимость org.springframework:spring-webmvc.

Я не думаю, что вы можете, кроме response.setContentType(..)

моя версия реальности. Загрузка HTML-файла и потоковая передача в браузер.

@Controller
@RequestMapping("/")
public class UIController {

    @RequestMapping(value="index", method=RequestMethod.GET, produces = "text/html")
    public @ResponseBody String GetBootupFile() throws IOException  {
        Resource resource = new ClassPathResource("MainPage.html");
        String fileContents = FileUtils.readFileToString(resource.getFile());
        return fileContents;
    }
}