Возвращение JSON и HTTP-статуса вместе в JAX-RS: гид
Быстрый ответ
Чтобы вернуть JSON и HTTP-статус-код одновременно в JAX-RS, используйте строителя Response
:
return Response
.status(Response.Status.OK) // Всё в порядке? Ваш статус-код на подходе.
.entity(jsonEntity) // Ваш JSON подан горячим!
.build();
Таким образом, вы получите структурированный HTTP-ответ, который будет полезен пользователям вашего API.
Создание и возврат JSON-ответов
Для создания ответа в формате JSON, не забудьте пометить ваш JAX-RS метод аннотацией @Produces("application/json")
. Это обязательно для отправки ответа клиентам в формате JSON, так же, как шеф-повар подает свое фирменное блюдо:
@GET
@Produces("application/json")
public Response makeJson() {
MySpecialObject jsonObj = new MySpecialObject();
return Response.ok(jsonObj).build(); // Сервируем горячий JSON с кодом 200.
}
Передача настраиваемых HTTP-кодов статуса
В ходе формирования ответов может потребоваться уточнить HTTP-код статуса с использованием перечисления Response.Status
или числового значения. Если вы хотите возвратить статус 201 Created
с JSON-содержимым, достаточно написать:
return Response
.status(Response.Status.CREATED) // Код 201, свежий как с монетного двора!
.entity(jsonEntity)
.build();
Обработка исключений с настраиваемыми сообщениями об ошибках
Для корректной обработки исключений и генерации точных ответов с описанием ошибок применяйте ExceptionMapper
. Это поможет предоставить пользователям максимально информативные сообщения об ошибках:
@Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {
@Override
public Response toResponse(MyException exception) {
return Response
.status(Response.Status.BAD_REQUEST)
.entity(new ErrorMessage(exception.getMessage())) // Ответ с сообщением об ошибке для анализа
.build();
}
}
Использование строителя Response для создания идеальных ответов
Строитель Response
предлагает множество методов для формирования идеального HTTP-ответа. Например, вы можете установить заголовок Location
и добавить пользовательские заголовки при отправке статуса 201 Created
:
return Response
.created(new URI("http://example.com/myresource"))
.header("X-Custom-Header", "Дополнительный пользовательский заголовок")
.entity(jsonEntity)
.build();
Обработка отсутствующих и нулевых данных
Будьте готовы к ситуации, когда конечные точки вашего API могут получить null
или пустые данные. Внедрите необходимые проверки, чтобы избежать непредвиденных ошибок, и при необходимости возвращайте резервный ответ или сообщение об ошибке с соответствующим HTTP-кодом:
if(input == null || input.trim().isEmpty()) {
return Response
.status(Response.Status.BAD_REQUEST) // Упс, кажется, в запросе произошло недопонимание
.entity("Пустые запросы не принимаются!")
.build();
}
Удовлетворение ожиданий клиента
Ответы, которые вы отправляете, вызывают у клиентов определённые "ожидания", которые мотивируют их на выполнение определённых действий на стороне JavaScript. Это подобно описанию нюансов вашего блюда гурманом:
if (response.status === 200) {
console.log('Вкус успеха:', response.payload);
} else {
console.error('Неудача:', response.statusText);
}
Продвинутые приёмы создания ответов
Продвинутые методы работы с Response
предполагают создание пользовательских аннотаций и использование фильтров ContainerResponseFilter
для автоматизации некоторых аспектов работы ответов и лучшего разделения логики.
Визуализация
Презентация ответа от вашего API-сервиса можно сравнить с подачей блюда из двух компонентов:
Компонент | Представляет |
---|---|
🍽 Блюдо | HTTP-код статуса |
🥗 Салат | JSON-нагрузка |
Отправка такого ответа равносильна подаче комплексного обеда:
Response🍽 = HTTP-код статуса (200 OK) + JSON-салат ({"ключ":"значение"})
Ваше блюдо обозначает СТАТУС, который является индикатором качества сервиса, а в «сыром салате» представлена ИНФОРМАЦИЯ — суть запроса клиента. Такая комбинация гарантирует полное удовлетворение потребностей наших пользователей.
Курирование пользовательских фильтров ответов
Для достижения оптимального результата рекомендуется использовать пользовательские аннотации в паре с ContainerResponseFilter
, что позволит правильно задавать HTTP-коды статуса и не перегружать основную логику сервиса.
Пример аннотации:
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface CustomStatus {
Response.Status value() default Response.Status.OK;
}
И соответствующий фильтр:
@Provider
@CustomStatus
public class CustomStatusFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
CustomStatus annotation = findAnnotation(requestContext); // Найдём скрытую аннотацию!
if (annotation != null) {
responseContext.setStatus(annotation.value().getStatusCode());
}
}
}
Работа с параметрами URL
Если ваш API применяет параметры URL, используйте @PathParam
для гибкой работы с ними. Таким образом, вы создадите ответ, который максимально соответствует запросу клиента:
@GET
@Path("/{id}")
@Produces("application/json")
public Response getRecord(@PathParam("id") String id) {
MyObject jsonEntity = findEntityById(id);
if (jsonEntity == null) {
return Response.status(Response.Status.NOT_FOUND).build(); // Печально, когда клиент не может найти то, что искал…
}
return Response.ok(jsonEntity).build(); // Ваш заказ готов к подаче!
}
Искусство формирования сообщений об ошибках
Важно создавать сообщения об ошибках так, чтобы они оставляли у клиента ощущение профессионализма. Сопоставьте их с HTTP-кодами статуса для создания впечатляющего ответа:
return Response
.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ApiError("Кажется, я забыл выключить духовку!", e.toString())) // Сохраняйте спокойствие даже в стрессовых ситуациях
.build();
Ошибки, возвращаемые через такие классы как ApiError
, обеспечивают консистентность в ответах об ошибках и значительно упрощают обработку ошибок со стороны клиентов.
Учет ожиданий клиентов
Важно помнить, что клиенты ожидают от ваших ответов определённого поведения. Удостоверьтесь, что ваши HTTP-коды статуса преобразуются браузерами и прокси-серверами корректно. К примеру, коды 204 No Content
и 205 Reset Content
могут вызвать неожиданные реакции. Следование спецификации API поможет обеспечить плавное взаимодействие с клиентами.
Полезные материалы
- Response (Java(TM) EE 7 Specification APIs) — детальнее ознакомьтесь со всеми возможностями строителя
Response
в официальной документации Java EE. - 29 Построение RESTful Web Services с JAX-RS (Релиз 7) — изучите методологии от Oracle и расширьте свои знания в работе с JAX-RS.
- java – JAX-RS — Как вернуть JSON и HTTP-код статуса одновременно? – Stack Overflow — присоединяйтесь к обсуждению этой темы на Stack Overflow в сообществе разработчиков.
- Jersey — официальный сайт проекта Jersey, который предлагает реализацию JAX-RS со всеми необходимыми для разработки инструментами.
- REST с Java (JAX-RS) используя Jersey – учебник — комплексное руководство по созданию современных RESTful-сервисов на Java с использованием Jersey.