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

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

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

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

Ответ 1

Я бы решил реорганизовать службу, чтобы вернуть объект домена, а не строки JSON, и пусть Spring обрабатывает сериализацию (через MappingJacksonHttpMessageConverter при записи). Начиная с Spring 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 должны быть добавлены в конфигурацию вашего приложения.

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

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

Ответ 2

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

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

Ответ 3

Возможно, вы не сможете сделать это с помощью @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();
  }
}

Ответ 5

Зарегистрируйте 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.

Ответ 6

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

Ответ 7

Моя версия реальности. Загрузка 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;
    }
}