1. Обзор
Link Rest -это платформа с открытым исходным кодом для создания веб-служб REST, управляемых данными. Он построен поверх JAX-RS и Apache Cayenne ORM и использует протокол сообщений на основе HTTP/JSON.
В принципе, эта структура предназначена для обеспечения простого способа представления нашего хранилища данных в Интернете.
В следующих разделах мы рассмотрим, как мы можем создать веб-службу REST для доступа к модели данных с помощью Link Rest .
2. Зависимости Maven
Чтобы начать работу с библиотекой, сначала нам нужно добавить зависимость link-rest :
com.nhl.link.rest link-rest 2.9
Это также приводит к артефакту cayenne-server .
Кроме того, мы будем использовать Jersey в качестве реализации JAX-RS , поэтому нам нужно добавить jersey-container-servlet зависимость, а также jersey-media-moxy для сериализации ответов JSON:
org.glassfish.jersey.containers jersey-container-servlet 2.25.1 org.glassfish.jersey.media jersey-media-moxy 2.25.1
В нашем примере мы будем работать с базой данных в памяти H2 , так как ее легче настроить; как следствие, мы также добавим h2 :
com.h2database h2 1.4.196
3. Модель данных Cayenne
Модель данных, с которой мы будем работать, содержит Отдел и Сотрудника сущность, представляющую отношение “один ко многим”.:
Как уже упоминалось, LinkRest работает с объектами данных, сгенерированными с помощью Apache Cayenne ORM . Работа с Cayenne не является основной темой этой статьи, поэтому для получения дополнительной информации ознакомьтесь с документацией Apache Cayenne .
Мы сохраним проект Cayenne в a cayenne-linkrest-project.xml файл.
После запуска cayenne-maven-plugin это приведет к созданию двух _Department и _Employee абстрактных классов, которые расширят класс CayenneDataObject , а также двух конкретных классов, производных от них, Department и Employee .
Эти последние классы мы можем настроить и использовать с помощью Link Rest .
4. Ссылка на Запуск приложения Rest
В следующем разделе мы будем писать и тестировать конечные точки REST, поэтому для их запуска нам необходимо настроить среду выполнения.
Поскольку мы используем Jersey в качестве реализации JAX-RS , давайте добавим класс, который расширяет ResourceConfig и указывает пакет, который будет содержать классы, в которых мы определяем конечные точки REST:
@ApplicationPath("/linkrest") public class LinkRestApplication extends ResourceConfig { public LinkRestApplication() { packages("com.baeldung.linkrest.apis"); // load linkrest runtime } }
В том же конструкторе нам нужно построить и зарегистрировать Link Rest Runtime в контейнер Jersey . Этот класс основан на первой загрузке CayenneRuntime :
ServerRuntime cayenneRuntime = ServerRuntime.builder() .addConfig("cayenne-linkrest-project.xml") .build(); LinkRestRuntime lrRuntime = LinkRestBuilder.build(cayenneRuntime); super.register(lrRuntime);
Наконец, нам нужно добавить класс в web.xml :
linkrest org.glassfish.jersey.servlet.ServletContainer javax.ws.rs.Application com.baeldung.LinkRestApplication 1 linkrest /*
5. Ресурсы для ОТДЫХА
Теперь, когда у нас есть классы моделей, мы можем начать писать ресурсы REST.
Конечные точки REST создаются с использованием стандартных аннотаций JAX-RS , в то время как ответ строится с использованием класса Link Reset .
Наш пример будет состоять из написания серии конечных точек CRUD, которые обращаются к URL-адресу /department с использованием различных методов HTTP.
Во-первых, давайте создадим класс Department Resource , который сопоставляется с /department :
@Path("department") @Produces(MediaType.APPLICATION_JSON) public class DepartmentResource { @Context private Configuration config; // ... }
Классу Link Test необходим экземпляр класса JAX-RS Configuration , который вводится с помощью аннотации Context , также предоставляемой JAX-RS .
Далее, давайте продолжим писать каждую из конечных точек, которые обращаются к объектам Department .
5.1. Создание Сущностей С Помощью POST
Для создания сущности класс Link Reset предоставляет метод create () , который возвращает объект Update Builder :
@POST public SimpleResponse create(String data) { return LinkRest.create(Department.class, config).sync(data); }
Параметром данных может быть либо один объект JSON, представляющий Отдел , либо массив объектов. Этот параметр отправляется в Update Builder с помощью метода sync() для создания одного или нескольких объектов и вставки записей в базу данных, после чего метод возвращает SimpleResponse .
Библиотека определяет 3 дополнительных формата ответов:
- DataResponse – ответ, представляющий коллекцию T
- MetadataResponse – содержит метаданные о типе
- SimpleResponse – объект, содержащий два атрибута success и message
Далее, давайте используем curl для добавления записи Department в базу данных:
curl -i -X POST -H "Content-Type:application/json" -d "{"name":"IT"}" http://localhost:8080/linkrest/department
В результате команда возвращает статус 201 Создано и атрибут успех :
{"success":true}
Мы также можем создать несколько объектов, отправив массив JSON:
curl -i -X POST -H "Content-Type:application/json" -d "[{"name":"HR"},{"name":"Marketing"}]" http://localhost:8080/linkrest/department
5.2. Чтение Сущностей С помощью GET
Основным методом запроса объектов является метод select() из класса Link Rest . Это возвращает объект Select Builder , который мы можем использовать для цепочки дополнительных методов запроса или фильтрации.
Давайте создадим конечную точку в классе Department Resource , которая возвращает все объекты Department в базе данных:
@GET public DataResponsegetAll(@Context UriInfo uriInfo) { return LinkRest.select(Department.class, config).uri(uriInfo).get(); }
Вызов url() задает информацию о запросе для Select Builder , в то время как get() возвращает коллекцию Departments , завернутую в объект DataResponse .
Давайте взглянем на отделы, которые мы добавили, прежде чем использовать эту конечную точку:
curl -i -X GET http://localhost:8080/linkrest/department
Ответ принимает форму объекта JSON с массивом data и свойством total :
{"data":[ {"id":200,"name":"IT"}, {"id":201,"name":"Marketing"}, {"id":202,"name":"HR"} ], "total":3}
В качестве альтернативы, чтобы получить коллекцию объектов, мы также можем вернуть один объект, используя get One() вместо get() .
Давайте добавим конечную точку, сопоставленную с /department/{DepartmentID} , которая возвращает объект с заданным идентификатором. Для этого мы отфильтруем записи с помощью метода byId() :
@GET @Path("{id}") public DataResponsegetOne(@PathParam("id") int id, @Context UriInfo uriInfo) { return LinkRest.select(Department.class, config) .byId(id).uri(uriInfo).getOne(); }
Затем мы можем отправить запрос GET по этому URL-адресу:
curl -i -X GET http://localhost:8080/linkrest/department/200
В результате получается массив data с одним элементом:
{"data":[{"id":200,"name":"IT"}],"total":1}
5.3. Обновление Сущностей С Помощью PUT
Для обновления записей мы можем использовать метод update() или create Или Update () . Последний обновит записи, если они существуют, или создаст их, если их нет:
@PUT public SimpleResponse createOrUpdate(String data) { return LinkRest.createOrUpdate(Department.class, config).sync(data); }
Как и в предыдущих разделах, аргумент data может быть одним объектом или массивом объектов.
Давайте обновим один из ранее добавленных отделов:
curl -i -X PUT -H "Content-Type:application/json" -d "{"id":202,"name":"Human Resources"}" http://localhost:8080/linkrest/department
Это возвращает объект JSON с сообщением об успешном выполнении или ошибке. После этого мы можем проверить, было ли изменено название отдела с идентификатором 202:
curl -i -X GET http://localhost:8080/linkrest/department/202
Конечно же, эта команда возвращает объект с новым именем:
{"data":[ {"id":202,"name":"Human Resources"} ], "total":1}
5.4. Удаление Объектов С Помощью DELETE
И, чтобы удалить объект, мы можем вызвать метод delete () , который создает DeleteBuilder , а затем указать первичный ключ объекта, который мы хотим удалить, используя метод id() :
@DELETE @Path("{id}") public SimpleResponse delete(@PathParam("id") int id) { return LinkRest.delete(Department.class, config).id(id).delete(); }
Затем мы можем вызвать эту конечную точку с помощью curl :
curl -i -X DELETE http://localhost:8080/linkrest/department/202
5.5. Работа С Отношениями Между Субъектами
Ссылка Rest также содержит методы, облегчающие работу с отношениями между объектами.
Поскольку Department имеет отношение “один ко многим” к Employee , давайте добавим /department/{DepartmentID}/employees конечную точку, которая обращается к EmployeeSubResource классу:
@Path("{id}/employees") public EmployeeSubResource getEmployees( @PathParam("id") int id, @Context UriInfo uriInfo) { return new EmployeeSubResource(id); }
Класс Employee SubResource соответствует отделу, поэтому у него будет конструктор, который задает идентификатор отдела, а также экземпляр Configuration :
@Produces(MediaType.APPLICATION_JSON) public class EmployeeSubResource { private Configuration config; private int departmentId; public EmployeeSubResource(int departmentId, Configuration configuration) { this.departmentId = departmentId; this.config = config; } public EmployeeSubResource() { } }
Обратите внимание, что для сериализации объекта в качестве объекта JSON необходим конструктор по умолчанию.
Затем давайте определим конечную точку, которая извлекает всех сотрудников из отдела:
@GET public DataResponsegetAll(@Context UriInfo uriInfo) { return LinkRest.select(Employee.class, config) .toManyParent(Department.class, departmentId, Department.EMPLOYEES) .uri(uriInfo).get(); }
В этом примере мы использовали их для многих родительских() метод Select Builder для запроса только объектов с заданным родителем.
Конечные точки для методов POST, PUT, DELETE могут быть созданы аналогичным образом.
Чтобы добавить сотрудников в отдел, мы можем вызвать конечную точку departmentid/{DepartmentID}/employees с помощью метода POST:
curl -i -X POST -H "Content-Type:application/json" -d "{"name":"John"}" http://localhost:8080/linkrest/department/200/employees
Затем давайте отправим запрос GET для просмотра сотрудников отдела:
curl -i -X GET "http://localhost:8080/linkrest/department/200/employees
Это возвращает объект JSON с массивом данных::
{"data":[{"id":200,"name":"John"}],"total":1}
6. Настройка Ответа С параметрами запроса
Ссылка Rest предоставляет простой способ настроить ответ, добавив в запрос определенные параметры. Они могут использоваться для фильтрации, сортировки, разбиения на страницы или ограничения набора атрибутов результирующего набора.
6.1. Фильтрация
Мы можем отфильтровать результаты на основе значений атрибутов с помощью параметра cayenne Exp . Как следует из названия, это соответствует формату Cayenne expressions .
Давайте отправим запрос, который возвращает только отделы с именем “IT”:
curl -i -X GET http://localhost:8080/linkrest/department?cayenneExp=name='IT'
6.2. Сортировка
Параметры, добавляемые для сортировки набора результатов, – это sort и dir . Первый из них определяет атрибут для сортировки, а второй-направление сортировки.
Давайте посмотрим, все отделы отсортированы по названиям:
curl -i -X GET "http://localhost:8080/linkrest/department?sort=name&dir=ASC"
6.3. Разбиение на страницы
Библиотека поддерживает разбиение на страницы, добавляя параметры start и limit :
curl -i -X GET "http://localhost:8080/linkrest/department?start=0&limit=2
6.4. Выбор атрибутов
Используя параметры include и exclude , мы можем контролировать, какие атрибуты или отношения возвращаются в результате.
Например, давайте отправим запрос, в котором отображаются только названия отделов:
curl -i -X GET "http://localhost:8080/linkrest/department?include=name
Чтобы показать имена, а также сотрудников отдела только с их именем, мы можем использовать атрибут include дважды:
curl -i -X GET "http://localhost:8080/linkrest/department?include=name&include=employees.name
7. Заключение
В этой статье мы показали, как мы можем быстро предоставить модель данных через конечные точки REST с помощью фреймворка Link Rest .
Полный исходный код примеров можно найти на GitHub .