Подтвердить что ты не робот

Как обрабатывать проверку ресурсов в веб-службах REST?

Я создаю веб-сервис REST на Java с помощью Spring, Jersey и Hibernate (JPA).

Теперь я пытаюсь добавить поддержку для проверки в моих ресурсах. JSR-303 (Bean validation), естественно, явился подходящим выбором (я использую Hibernate Validator, который является эталонной реализацией JSR-303). Тем не менее, я сначала пытаюсь объединить некоторые концепции.

Мне кажется, что существует как минимум два вида возможных валидаций:

  • Регулярная проверка в полях, например. убедитесь, что свойство не равно null, проверьте, является ли свойство String допустимым адресом электронной почты, проверьте, превышает ли свойство Integer 10 и т.д. Это работает как ожидалось. Я зарегистрировал JAX-RS ExceptionMapper, который отображает javax.validation.ConstraintViolationException в соответствующие ответы HTTP.
  • Проверка целостности данных

Я объясню, что я имею в виду именно "Проверка целостности данных" с примером. Это происходит, когда есть отношения между двумя или более ресурсами. Представьте себе два ресурса: a Product и a Category. A Product имеет a Category. Когда клиент отправляет серверу представление Product для создания (HTTP-запрос POST), он должен сообщить Category о продукте. Конечно, клиент должен знать категории заранее. Представьте себе в JSON что-то вроде:

{
   "quantity": "10",
   "state": "PRODUCED",
   "category": {
      "id": "123"
   }
}

Ну, категория с id 123 может не существовать. Если мы попытаемся вставить это в базу данных, очевидно, мы получим исключение, связанное с внешним ключом. Поэтому я предполагаю, что мы должны проверить эти проблемы и вернуть правильное сообщение клиенту, так же как и в регулярных проверках свойств.


Теперь мои основные вопросы:

  • Сейчас я выполняю проверку на уровне доступа к данным через интеграцию JPA с помощью Bean Validation. Если проверки выполняются до/после процессов сериализации, до/после операций с базой данных или и?
  • Как обрабатывать проверки целостности данных? Вручную? (т.е. явно консультироваться с проверкой целостности данных базы данных). Или мы должны просто попытаться вставить его в любом случае, а затем уловить исключения базы данных (или DAO)? Bean Валидация не имеет ничего общего с такой проверкой, правильно?
  • Если у вас есть опыт работы с JAX-RS/REST и Bean Validation, я был бы рад, если вы дадите мне знать. Использование групп?

Эти вопросы несколько связаны с Java, но я также надеялся получить некоторые новые перспективы по этим вопросам. Некоторые технологически независимые.:) Было бы здорово, если бы вы могли предоставить свои собственные решения для этих проблем на веб-сервисах REST.

4b9b3361

Ответ 1

Решение оказалось подклассом Jackson JacksonJaxbJsonProvider, в котором реализованы JAX-RS MessageBodyReader и MessageBodyWriter. Я был вдохновлен удивительным подходом dropwizard. В этом провайдере нам нужно каким-то образом внедрить экземпляр Validator (я использовал Spring для Injection и Hibernate Validator для реализации JSR-303). Если вы используете Hibernate ORM, не забудьте отключить проверку объекта, иначе вы будете дважды проверять один и тот же объект. Однако это может быть желательным.

Затем в этом подклассе MessageBodyReader я проверяю объект и вывожу пользовательский InvalidEntityException с ошибками из проверки. Я также создал JAX-RS ExceptionMapper<InvalidEntityException>, который отображает каждый InvalidEntityException в правильный HTTP-ответ. В моем случае я вернул Bad Request и JSON-объект, содержащий описание ошибок.

Обратите внимание, что этот MessageBodyReader проверяет аннотации @Valid и @Validated. Это означает, что он правильно поддерживает группы. Это важно, потому что мы, вероятно, не хотим выполнять такую ​​же проверку во всем нашем приложении. Например, мы хотим сделать частичное обновление (PUT). Или, например, свойство id должно быть нулевым в запросе POST, но не нулевым везде.

Проверка целостности данных еще не решена. Но я планирую ловить исключения баз данных и преобразовывать их в свои собственные исключения для домена (например, < <29 > ), поскольку он кажется более эффективным и слабо связанным со мной.


UPDATE:

Так как JAX-RS 2, рекомендуемый способ сделать это - использовать поддержку Bean Validation. Проверьте здесь: https://jersey.java.net/documentation/latest/bean-validation.html

Ответ 3

Вы можете использовать jersey filters, где вы можете сделать некоторые проверки в своих данных запроса.

Ну, категория с id 123 может не существовать. Если мы попытаемся вставить это в базу данных, очевидно, мы получим исключение, связанное с внешним ключом.

В таких случаях можно полагаться на проверки на уровне доступа к данным. Но если вы хотите синхронно реагировать на ваш клиент, обычно лучше иметь эту бизнес-логику, предоставляемую некоторым сервисным API. т.е. у вас может быть API, например isValidCategory(int id), который может запрашиваться на более высоком уровне, чем DAO, так что вам не нужно ждать, пока уровень доступа к данным столкнется с ошибкой/исключением. Очевидно, что это все равно означает поиск базы данных (зависит от вашей системы), но оптимизация этого для улучшения времени отклика с использованием кеширования или какого-либо другого механизма - совсем другая проблема.

Говоря о валидаторах bean, вы можете посмотреть Hibernate Validator, который является реализацией JSR 303.

Ответ 4

Oval - лучший пакет для оценки объекта. Очень полезно генерировать утверждение unit test и автоматическое тестирование.