Вы должны всегда объявлять аннотации @Produces
и @Consumes
(либо на уровне класса, либо на уровне метода) с целью согласование содержимого и правильность протокола HTTP. Без этих аннотаций результат будет зависеть от запроса клиента и поведения сервера по умолчанию (которое может отличаться в разных реализациях), что приводит к непредсказуемым и неоднозначным результатам.
С этими аннотациями мы рекламируем , какие типы носителей мы можем производить и потреблять. При запросах Retrieve (GET) клиент должен отправить заголовок Accept
с типом носителя того ресурса, который он ожидает. А при создании запросов (PUT, POST) клиент должен отправить заголовок Content-Type
, сообщающий серверу, какой тип носителя представляют данные, которые они отправляют. Если эти заголовки не соответствуют тому, что сервер объявляет для обработки, тогда клиент получит ответ об ошибке, сообщающий им, в чем проблема; с запросом Retrieve и несовпадающим заголовком Accept
ответом будет 406 Not Acceptable . С запросом на создание и несоответствующим заголовком Content-Type
ответом будет 415 Неподдерживаемый тип носителя .
Так работает согласование контента. И чтобы убедиться, что наш сервер ведет себя так, как ожидают клиенты, мы должны объявить, что мы можем обработать на сервере. Аннотации делают именно это.
Как вы упомянули, когда вы остановили @Produces
, клиент сказал вам, что вам нужно изменить тип ответа. Это связано с тем, что в результате заголовок ответа Content-Type
был установлен на application/octet-stream
, что из ответов . Клиенты используют заголовок Content-Type
, чтобы определить, как обрабатывать ответ.
Последний пример был для запроса Retrieve. Если мы остановим @Consumes
на конечной точке Create, много разных вещей может пойти не так. Например, у нас есть конечная точка, которую мы хотим принять JSON, поэтому мы создаем POJO для сопоставления JSON.
@POST
public Response create(Customer customer) {}
Чтобы это работало, это зависит от того, установил ли клиент заголовок Content-Type
в запросе на application/json
. Но без аннотации @Consumes
мы в основном рекламируем эту конечную точку, чтобы иметь возможность принимать любой тип медиа, что просто смешно. Аннотация @Consumes
действует как охранник, говорящий: «Если вы не отправите правильный тип данных, вы не сможете пройти». Но так как у нас нет защиты, все данные пропускаются, и результат непредсказуем, потому что в зависимости от того, что клиент устанавливает Content-Type
, мы не знаем, что MessageBodyReader
1 будет обрабатывать преобразование из тела сущности в Customer
. Если правильный MessageBodyReader
не выбран (тот, который преобразует JSON в POPJO), то, скорее всего, это приведет к исключению, и клиент получит обратно 500 Internal Server Error, которая не так специфична, как получение 415 Неподдерживаемый тип носителя.
1. См. Главы 8 и 9 документации Джерси . Он объяснит, как тела сущностей преобразуются в объекты Java (и наоборот), используя MessageBodyReader
и MessageBodyWriter
соответственно.