Я пишу веб-приложение REST (NetBeans 6.9, JAX-RS, TopLink Essentials) и пытаюсь вернуть код состояния JSON и HTTP. У меня есть готовый код, который возвращает JSON при вызове метода HTTP GET с клиента. По существу:
@Path("get/id")
@GET
@Produces("application/json")
public M_機械 getMachineToUpdate(@PathParam("id") String id) {
// some code to return JSON ...
return myJson;
}
Но я также хочу вернуть код состояния HTTP (500, 200, 204 и т. Д.) Вместе с данными JSON.
Я пытался использовать HttpServletResponse
:
response.sendError("error message", 500);
Но это заставило браузер думать, что это «настоящий» 500, поэтому выходная веб-страница была обычной страницей с ошибкой HTTP 500.
Я хочу вернуть код состояния HTTP, чтобы мой клиентский JavaScript мог обрабатывать некоторую логику в зависимости от него (например, отображать код ошибки и сообщение на странице HTML). Это возможно, или коды статуса HTTP не должны использоваться для такой вещи?
Ответы:
Вот пример:
Посмотрите на класс Response .
Обратите внимание, что вы всегда должны указывать тип контента, особенно если вы передаете несколько типов контента, но если каждое сообщение будет представлено как JSON, вы можете просто аннотировать метод с помощью
@Produces("application/json")
источник
return Response.status(Response.Status.Forbidden).entity(myPOJO).build();
Работы, как если бы вы это делалиreturn myPOJO;
, но с дополнительной настройкой кода HTTP-статуса.Существует несколько вариантов использования для установки кодов состояния HTTP в веб-службе REST, и, по крайней мере, один из них недостаточно документирован в существующих ответах (т. Е. Когда вы используете автоматическую магическую сериализацию JSON / XML с использованием JAXB, и вы хотите вернуть сериализуемый объект, но также код состояния, отличный от значения по умолчанию 200).
Итак, позвольте мне попытаться перечислить различные варианты использования и решения для каждого из них:
1. Код ошибки (500, 404, ...)
Наиболее распространенный вариант использования, когда вы хотите вернуть код состояния, отличный от случая,
200 OK
когда произошла ошибка.Например:
а) бросить исключение
В этом случае, я думаю, что самый чистый способ решения проблемы - это исключение. Это исключение будет обработано
ExceptionMapper
, которое преобразует исключение в ответ с соответствующим кодом ошибки.Вы можете использовать значение по умолчанию,
ExceptionMapper
которое предварительно сконфигурировано на Джерси (и я полагаю, что то же самое с другими реализациями) и выбросить любой из существующих подклассовjavax.ws.rs.WebApplicationException
. Это предопределенные типы исключений, которые предварительно сопоставлены с различными кодами ошибок, например:И т.д. Вы можете найти список здесь: API
Кроме того, вы можете определить свои собственные исключения и
ExceptionMapper
классы и добавить эти сопоставители в Джерси с помощью@Provider
аннотации ( источник этого примера ):Провайдер:
Примечание: вы также можете написать ExceptionMappers для существующих типов исключений, которые вы используете.
б) Используйте построитель ответов
Другой способ установить код состояния - использовать
Response
построитель для создания ответа с намеченным кодом.В этом случае тип возврата вашего метода должен быть
javax.ws.rs.core.Response
. Это описано в различных других ответах, таких как принятый ответ hisdrewness, и выглядит так:2. Успех, но не 200
Другой случай, когда вы хотите установить статус возврата, это когда операция прошла успешно, но вы хотите вернуть код успеха, отличный от 200, вместе с содержимым, которое вы возвращаете в теле.
Частый случай использования - это когда вы создаете новую сущность (
POST
запрос) и хотите вернуть информацию об этой новой сущности или, возможно, о самой сущности вместе с201 Created
кодом состояния.Одним из подходов является использование объекта ответа, как описано выше, и установка тела запроса самостоятельно. Однако, делая это, вы теряете возможность использовать автоматическую сериализацию в XML или JSON, предоставляемую JAXB.
Это оригинальный метод, возвращающий объектный объект, который будет сериализован в JSON JAXB:
Это вернет JSON-представление вновь созданного пользователя, но статус возврата будет 200, а не 201.
Теперь проблема в том, что если я хочу использовать
Response
конструктор для установки кода возврата, я должен вернутьResponse
объект в моем методе. Как мне все еще вернутьUser
объект для сериализации?а) Установите код в ответе сервлета
Один из подходов к решению этой проблемы состоит в том, чтобы получить объект запроса сервлета и вручную установить код ответа, как показано в ответе Гаретт Уилсон:
Метод по-прежнему возвращает объект сущности, а код состояния будет 201.
Обратите внимание, что для того, чтобы это сработало, мне пришлось сбросить ответ. Это неприятный всплеск низкоуровневого кода API сервлета в нашем замечательном ресурсе JAX_RS, и, что еще хуже, после этого заголовки становятся неизменяемыми, поскольку они уже были отправлены по сети.
б) Используйте объект ответа с сущностью
Лучшее решение в этом случае состоит в том, чтобы использовать объект Response и установить сериализацию объекта для этого объекта ответа. Было бы неплохо сделать объект Response универсальным для указания типа объекта полезной нагрузки в этом случае, но в настоящее время это не так.
В этом случае мы используем созданный метод класса построителя Response, чтобы установить код состояния на 201. Мы передаем объект сущности (пользователя) в ответ через метод entity ().
В результате получается, что HTTP-код равен 401, как мы и хотели, и тело ответа является точно таким же JSON, как и раньше, когда мы только что вернули объект User. Он также добавляет заголовок местоположения.
Класс Response имеет несколько методов построения для различных статусов (stati?), Таких как:
Response.accepted () Response.ok () Response.noContent () Response.notAcceptable ()
Примечание: объект hateoas - это вспомогательный класс, который я разработал, чтобы помочь генерировать URI ресурсов. Вам нужно будет придумать свой собственный механизм здесь;)
Вот и все.
Надеюсь, этот длинный ответ кому-нибудь поможет :)
источник
flush
действительно грязно.Ответ от hisdrewness будет работать, но он изменяет весь подход, позволяя провайдеру, такому как Jackson + JAXB, автоматически преобразовывать возвращаемый объект в некоторый формат вывода, такой как JSON. Вдохновленный публикацией Apache CXF (которая использует класс, специфичный для CXF), я нашел один способ установить код ответа, который должен работать в любой реализации JAX-RS: внедрить контекст HttpServletResponse и вручную установить код ответа. Например, вот как установить код ответа в
CREATED
случае необходимости.Улучшение: Найдя другой связанный ответ , я узнал, что можно ввести
HttpServletResponse
переменную в качестве члена-члена даже для одноэлементного класса обслуживания (по крайней мере в RESTEasy) !! Это гораздо лучший подход, чем загрязнение API деталями реализации. Это будет выглядеть так:источник
@Produces
, и не указывать тип носителя в финалеResponse.ok
, и вы получите правильно возвращаемый JAXB-сериализованный объект в соответствующий тип носителя, соответствующий запросу. (Я только что попробовал это с помощью одного метода, который мог бы возвращать либо XML, либо JSON: сам метод не должен упоминаться, кроме как в@Produces
аннотации.)MessageBodyWriter
иProvider
допускает неявное согласование содержимого, хотя кажется, что в вашем примере отсутствует некоторый код. Вот еще один ответ, который я предоставил, который иллюстрирует это: stackoverflow.com/questions/5161466/…response.setStatus()
. Например, единственный способ отправить ответ 404 Not Found - это установить код состояния ответаresponse.setStatus(404)
en, а затем закрыть выходной поток,response.getOutputStream().close()
чтобы JAX-RS не мог сбросить мой статус.response.flushBuffer()
, чтобы избежать переопределения моего кода ответа каркасом. Не очень чисто.404 Not Found
, может быть проще просто использоватьthrow new NotFoundException()
.Если вы хотите, чтобы ваш ресурсный уровень был чистым от
Response
объектов, я рекомендую вам использовать@NameBinding
привязку к реализациямContainerResponseFilter
.Вот мясо аннотации:
Вот мясо фильтра:
И тогда реализация на вашем ресурсе просто становится:
источник
StatusFilter
с помощью@Status
: вам нужно либо указать значение по умолчанию дляvalue
поля аннотации , либо объявить его при аннотировании класса (например:)@Status(200)
. Это явно не идеально.Если вы хотите изменить код состояния из-за исключения, в JAX-RS 2.0 вы можете реализовать ExceptionMapper, как это. Это обрабатывает такого рода исключения для всего приложения.
источник
Если вашему WS-RS нужно выдать ошибку, почему бы просто не использовать исключение WebApplicationException?
источник
JAX-RS имеет поддержку стандартных / пользовательских кодов HTTP. См. ResponseBuilder и ResponseStatus, например:
http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/Response.ResponseBuilder.html#status%28javax.ws.rs.core.Response.Status%29
Имейте в виду, что информация JSON больше относится к данным, связанным с ресурсом / приложением. Коды HTTP больше о статусе запрашиваемой операции CRUD. (по крайней мере, так должно быть в системах REST-ful)
источник
Я нашел очень полезным также создать сообщение json с повторяющимся кодом, например так:
источник
Пожалуйста, посмотрите на пример здесь, он лучше всего иллюстрирует проблему и то, как она решается в последней (2.3.1) версии Джерси.
https://jersey.java.net/documentation/latest/representations.html#d0e3586
В основном это включает определение пользовательского исключения и сохранение типа возвращаемого значения в качестве объекта. При возникновении ошибки выдается исключение, в противном случае вы возвращаете POJO.
источник
Response
в нем. Просто найдитеCustomNotFoundException
класс и, возможно, скопируйте его в свой пост.Я не использую JAX-RS, но у меня есть похожий сценарий, где я использую:
источник
Также обратите внимание, что по умолчанию Джерси переопределяет тело ответа в случае http-кода 400 или более.
Чтобы получить указанную сущность в качестве тела ответа, попробуйте добавить следующий init-param к вашему Джерси в файле конфигурации web.xml:
источник
Следующий код работал для меня. Внедрение messageContext через аннотированный установщик и установка кода состояния в моем методе «add».
источник
Развивая ответ на Nthalk с микропрофилем OpenAPI можно выровнять код возврата с документацией , используя @APIResponse аннотацию.
Это позволяет пометить метод JAX-RS как
Вы можете проанализировать эту стандартизированную аннотацию с помощью ContainerResponseFilter.
Предупреждение возникает, когда вы помещаете несколько аннотаций в ваш метод, например
источник
Я использую Джерси 2.0 с читателями и авторами тел сообщений. У меня был метод возврата типа метода в качестве особой сущности, которая также использовалась в реализации средства записи тела сообщения, и я возвращал то же pojo, SkuListDTO. @GET @Consumes ({"application / xml", "application / json"}) @Produces ({"application / xml", "application / json"}) @Path ("/ skuResync")
все, что я изменил, было это, я оставил реализацию писателя в покое, и она все еще работала.
источник