JAX-RS - это просто API!

JAX-RS - это просто API!

1. обзор

Парадигма REST существует уже несколько лет и по-прежнему привлекает много внимания.

RESTful API может быть реализован на Java несколькими способами: вы можете использовать Spring, JAX-RS или просто написать свои собственные голые сервлеты, если вы достаточно хороши и смелы. Все, что вам нужно, - это возможность предоставлять методы HTTP, а все остальное - о том, как вы их организовываете и как вы руководите клиентом при совершении вызовов вашего API.

Как вы можете понять из названия, эта статья будет посвящена JAX-RS. Но что означает «просто API»? Это означает, что основное внимание здесь уделяется разъяснению путаницы между JAX-RS и его реализациями и предложению примера того, как выглядит правильное веб-приложение JAX-RS.

2. Включение в Java EE

JAX-RS - это не что иное, как спецификация, набор интерфейсов и аннотаций, предлагаемых Java EE. И, конечно же, у нас есть реализации; некоторые из наиболее известных - этоRESTEasy иJersey.

Кроме того, если вы когда-нибудь решите построить JEE-совместимый сервер приложений, ребята из Oracle скажут вам, что, помимо прочего, ваш сервер должен предоставить реализацию JAX-RS для использования развернутых приложений. Вот почему он называется Java Enterprise EditionPlatform.

Еще один хороший пример спецификации и реализации -JPA иHibernate..

2.1. Легкие войны

Так как же все это помогает нам, разработчикам? Помощь в том, что наши развертываемые объекты могут и должны быть очень тонкими, что позволяет серверу приложений предоставлять необходимые библиотеки. Это применимо и при разработке RESTful API: конечный артефакт не должен содержать никакой информации об используемой реализации JAX-RS.

Конечно, мы можем предоставить реализацию (руководствоhere по RESTeasy). Но тогда мы больше не можем называть наше приложение «Java EE app». Если завтра кто-нибудь придет и скажет «Ok, time to switch to Glassfish or Payara, JBoss became too expensive!», возможно, мы сможем это сделать, но это будет нелегкая работа.

Если мы предоставляем нашу собственную реализацию, мы должны убедиться, что сервер знает, как исключить свою собственную - обычно это происходит, если внутри развертываемого файла находится собственный файл XML. Само собой разумеется, что такой файл должен содержать все виды тегов и инструкций, о которых никто ничего не знает, кроме разработчиков, которые покинули компанию три года назад.

2.2. Всегда знай свой сервер

До сих пор мы говорили, что должны воспользоваться платформой, которую нам предлагают.

Прежде чем выбрать сервер для использования, мы должны посмотреть, какую реализацию JAX-RS (имя, поставщик, версия и известные ошибки) она предоставляет, по крайней мере для производственных сред. Например, Glassfish поставляется с Джерси, а Wildfly или Jboss поставляются с RESTEasy.

Это, конечно, означает, что на исследование нужно потратить немного времени, но его следует проводить только один раз, в начале проекта или при его переносе на другой сервер.

3. Пример

Если вы хотите начать играть с JAX-RS, самый короткий путь: иметь проект Maven webapp со следующей зависимостью вpom.xml:


    javax
    javaee-api
    7.0
    provided

Мы используем JavaEE 7, так как уже существует множество серверов приложений, реализующих его. Эта банка API содержит аннотации, которые вам нужно использовать, и находится в пакетеjavax.ws.rs. Почему сфера «предоставляется»? Поскольку этот jar не обязательно должен быть в окончательной сборке - он нужен нам во время компиляции, и он предоставляется сервером во время выполнения.

После добавления зависимости мы сначала должны написать класс записи: пустой класс, который расширяетjavax.ws.rs.core.Application и аннотируетсяjavax.ws.rs.ApplicationPath:

@ApplicationPath("/api")
public class RestApplication extends Application {
}

Мы определили путь входа как/api.. Какие бы другие пути мы не объявляли для наших ресурсов, они будут иметь префикс/api.

Затем давайте посмотрим на ресурс:

@Path("/notifications")
public class NotificationsResource {
    @GET
    @Path("/ping")
    public Response ping() {
        return Response.ok().entity("Service online").build();
    }

    @GET
    @Path("/get/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getNotification(@PathParam("id") int id) {
        return Response.ok()
          .entity(new Notification(id, "john", "test notification"))
          .build();
    }

    @POST
    @Path("/post/")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response postNotification(Notification notification) {
        return Response.status(201).entity(notification).build();
    }
}

У нас есть простая конечная точка ping для вызова и проверки, запущено ли наше приложение, GET и POST для уведомления (это просто POJO с атрибутами, плюс методы получения и установки).

Разверните эту войну на любом сервере приложений, реализующем JEE7, и будут работать следующие команды:

curl http://localhost:8080/simple-jaxrs-ex/api/notifications/ping/

curl http://localhost:8080/simple-jaxrs-ex/api/notifications/get/1

curl -X POST -d '{"id":23,"text":"lorem ipsum","username":"johana"}'
  http://localhost:8080/simple-jaxrs-ex/api/notifications/post/
  --header "Content-Type:application/json"

Где simple-jaxrs-ex является корневым контекстом веб-приложения.

Это было проверено на Glassfish 4.1.0 и Wildfly 9.0.1.Final. Обратите внимание, что последние две команды не будут работать с Glassfish 4.1.1 из-за ошибкиthis. Очевидно, это известная проблема в этой версии Glassfish, касающаяся сериализации JSON (если вам нужно использовать эту версию сервера, вам придется самостоятельно управлять маршалингом JSON)

4. Заключение

В конце этой статьи просто помните, что JAX-RS - это мощный API-интерфейс, и большая часть (если не все) необходимых вам компонентов уже реализована вашим веб-сервером. Нет необходимости превращать ваш развертываемый в неуправляемую кучу библиотек.

Эта статья представляет собой простой пример, и все может быть сложнее. Например, вы можете написать свои собственные маршалеры. Когда это необходимо, ищите руководства, которые решают вашу проблему с JAX-RS, а не с Jersey, Resteasy или другой конкретной реализацией. Скорее всего, вашу проблему можно решить с помощью одной или двух аннотаций.