Spring @RestController не возвращает текстовый ответ
Я экспериментирую с новым Spring 4.0 @RestController, чтобы вернуть простой текстовый ответ от контроллера:
@RestController
@RequestMapping(value = "/heartbeat")
public class HeartbeatController {
private static final Logger logger = LoggerFactory.getLogger(HeartbeatController.class);
@RequestMapping
public String heartbeat() {
logger.info("Received heartbeat!");
return "I'm Alive!";
}
@RequestMapping(value = "/test", produces = MediaType.TEXT_PLAIN_VALUE)
public String heartbeat2() {
logger.info("Received heartbeat!");
return "I'm Alive!";
}
}
Когда я получаю доступ /heartbeat, я возвращаюсь:
"I'm Alive!"
Результат включает двойные кавычки, чего я не ожидал.
Когда я получаю доступ к /heartbeat/test, я получаю пустой ответ, но я ожидаю, что я жив! текст.
UPDATE
curl -i http://myserver.com/rest/heartbeat
HTTP/1.1 200 OK
Content-Type: application/json; charset = UTF-8
Сервер: Разработка /1.0
Дата: Вт, 17 дек. 2013 18:59:08 GMT
Cache-Control: no-cache
Истекает: Пт, 01 янв 1990 00:00:00 GMT
Content-Length: 12
"Я жив!"
curl -i -H "Accept: application/json" http://myserver.com/rest/heartbeat
HTTP/1.1 200 OK
Content-Type: application/json; charset = UTF-8
Сервер: Разработка /1.0
Дата: Вт, 17 дек. 2013 19:01:12 GMT
Cache-Control: no-cache
Истекает: Пт, 01 янв 1990 00:00:00 GMT
Content-Length: 12
"Я жив!"
curl -i http://myserver.com/rest/heartbeat/test
HTTP/1.1 406 Не допускается
Сервер: Разработка /1.0
Дата: Вт, 17 дек. 2013 19:00:13 GMT
Cache-Control: no-cache
Истекает: Пт, 01 янв 1990 00:00:00 GMT
Content-Length: 0
curl -i -H "Accept: text/plain" http://myserver.com/rest/heartbeat/test
HTTP/1.1 406 Не допускается
Сервер: Разработка /1.0
Дата: Вт, 17 Дек. 2013 19:02:06 GMT
Cache-Control: no-cache
Истекает: Пт, 01 янв 1990 00:00:00 GMT
Content-Length: 0
Ответы
Ответ 1
Я узнал, что мне не хватает StringHttpMessageConverter в моем WebConfig configureMessageConverters.
Я настраивал конвертеры сообщений для управления ObjectMapper Jackson.
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setPrettyPrint(SystemProperty.environment.value() == Development);
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper());
converters.add(mappingJackson2HttpMessageConverter);
converters.add(new StringHttpMessageConverter()); // THIS WAS MISSING
}
Ответ 2
@RestController - это удобная аннотация, которая означает, что вам больше не нужно указывать аннотацию @ResponseBody для ваших методов.
Но это будет означать, что ваш тип ответа по умолчанию используется JSON и, следовательно, завернут в кавычки, чтобы правильно сформироваться.
Ответ 3
@RestController
объединяет @Controller
и @ResponseBody
в вашем классе Controller, как указанный в документации.
Когда вы комментируете метод/контроллер с помощью @ResponseBody
, Spring помогает вам с согласованием содержимого, используя заголовок HTTP Accept
HTTP и атрибут produces
в вашей аннотации.
В вашем случае:
- Вы получаете ответ
application/json
для вашего действия с биением, потому что ваш HTTP-клиент, вероятно, просит, чтобы Content-Type и Spring выполнили согласование содержимого.
- Вы получаете HTTP 406 для своего действия hearbeat2, потому что согласование контента не удалось. Вы указали
text/plain
как тип Content-Type на своем контроллере, тогда как ваш HTTP-клиент, вероятно, перечисляет только application/json
в заголовке запроса Accept
.
Обновление. Я использовал те же самые запросы на завивки, но не получал одинаковых результатов. Может быть, фильтр или HTTP-прокси-кеш изменяет HTTP-заголовки?
Формат по умолчанию - текстовый/обычный:
➜ curl -v http://localhost:8080/heartbeat
> GET /heartbeat HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: text/plain;charset=ISO-8859-1
< Content-Length: 13
< Date: Wed, 18 Dec 2013 13:34:12 GMT
<
Hello, World!%
И с атрибутом produces text/plain
:
➜ curl -H "Accept: text/plain" -v http://localhost:8080/heartbeat/test
> GET /heartbeat/test HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: text/plain
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: text/plain
< Content-Length: 13
< Date: Wed, 18 Dec 2013 13:39:07 GMT
<
Hello, World!%
Это пример приложения делает то же самое и получает хорошие результаты.
Ответ 4
Это решение сработало для меня. Пожалуйста, проверьте следующее.
- Убедитесь, что ваш DTO является сериализуемым и имеет сериализуемые поля, геттеры и сеттеры.
- Проверьте зависимости для jackson. Вы должны иметь
- com.fasterxml.jackson.core: джексон-ядро: 2.4.1
- com.fasterxml.jackson.core: джексон-DataBind: 2.4.1
- com.fasterxml.jackson.core: ДЖЕКСОН-аннотации: 2.4.1
- com.fasterxml.jackson.datatype: джексон-тип_данный-Joda: 2.4.1
- com.fasterxml.jackson.datatype: джексон-тип_данный-jsr310: 2.4.1
-
Исправьте аннотацию RequesMapping:
@RequestMapping(value = "/test", consumes = "*/*")
-
У вас есть директива <mvc:annotation-driven />
Ответ 5
Это работает для меня:
-
добавить это в maven
com.fasterxml.jackson.core ДЖЕКСОН-DataBind 2.4.4
-
убедитесь, что <mvc:annotation-driven />
настроен в spring