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