Перейти к основному содержимому

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

· 5 мин. чтения

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 Edition Platform .

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

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

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

Конечно, мы можем предоставить реализацию ( вот туториал по RESTeasy). Но тогда мы больше не можем называть наше приложение «Java EE app». Если завтра кто-то придет и скажет: « Окей, пора переходить на Glassfish или Payara, JBoss стал слишком дорогим! «Возможно, мы сможем это сделать, но это будет нелегкая работа.

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

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

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

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

Это, конечно, означает небольшие затраты времени на исследование, но это предполагается сделать только один раз, в начале проекта или при его переносе на другой сервер.

3. Пример

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

<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>

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

После добавления зависимости мы сначала должны написать класс входа: пустой класс, который расширяет 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 из-за этой ошибки. По-видимому, это известная проблема в этой версии Glassfish, связанная с сериализацией JSON (если вам нужно использовать эту версию сервера, вам придется самостоятельно управлять маршалингом JSON)

4. Вывод

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

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