В 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();
}
}
Ответ 4
Я не думаю, что это возможно. Кажется, для него открытая Jira:
SPR-6702: явно задать ответ Content-Type в @ResponseBody
Ответ 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;
}
}