Руководство по LinkRest

Руководство по LinkRest

1. обзор

LinkRest - это платформа с открытым исходным кодом для создания веб-служб REST, управляемых данными. Он построен на основеJAX-RS иApache Cayenne ORM и использует протокол сообщений на основе HTTP / JSON.

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

В следующих разделах мы рассмотрим, как создать веб-службу REST для доступа к модели данных с помощьюLinkRest.

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

Модель данных, с которой мы будем работать, содержит сущностьDepartment иEmployee, которая представляет отношение «один ко многим»:

image

Как уже упоминалось,LinkRest works with data objects generated using Apache Cayenne ORM. Работа сCayenne не является основной темой этой статьи, поэтому для получения дополнительной информации ознакомьтесь сApache Cayenne documentation.

Сохраним проектCayenne в файлcayenne-linkrest-project.xml.

После запускаcayenne-maven-plugin это сгенерирует два абстрактных классаDepartment_ and Employee_, которые расширят классCayenneDataObject, а также два конкретных класса, производных от них,Department иEmployeeс.

Эти последние классы мы можем настроить и использовать сLinkRest.

4. LinkRest Запуск приложения

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

Поскольку мы используемJersey в качестве реализацииJAX-RS, давайте добавим класс, который расширяетResourceConfig и указывает пакет, который будет содержать классы, в которых мы определяем конечные точки REST:

@ApplicationPath("/linkrest")
public class LinkRestApplication extends ResourceConfig {

    public LinkRestApplication() {
        packages("com.example.linkrest.apis");

        // load linkrest runtime
    }
}

В том же конструкторе нам нужно построить и зарегистрироватьLinkRestRuntime в контейнере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.example.LinkRestApplication
        
    1


    linkrest
    /*

5. Ресурсы REST

Теперь, когда у нас есть классы моделей, мы можем приступить к написанию ресурсов REST.

REST endpoints are created using standard JAX-RS annotations, while the response is built using the LinkRest class.

Наш пример будет состоять из написания серии конечных точек CRUD, которые обращаются к URL-адресу/department с использованием различных методов HTTP.

Во-первых, давайте создадим классDepartmentResource, который сопоставлен с/department:

@Path("department")
@Produces(MediaType.APPLICATION_JSON)
public class DepartmentResource {

    @Context
    private Configuration config;

    // ...
}

КлассуLinkRest требуется экземпляр классаJAX-RS Configuration, который вводится с использованием аннотацииContext, также предоставляемойJAX-RS.

Затем продолжим писать каждую из конечных точек, которые обращаются к объектамDepartment.

5.1. Создание объектов с помощью POST

Для создания сущности классLinkRest предоставляет методcreate(), который возвращает объектUpdateBuilder:

@POST
public SimpleResponse create(String data) {
    return LinkRest.create(Department.class, config).sync(data);
}

Параметр данных может быть либо одним объектом JSON, представляющимDepartment, либо массивом объектов. Этот параметр отправляетсяUpdateBuilder с помощью методаsync() для создания одного или нескольких объектов и вставки записей в базу данных, после чего метод возвращаетSimpleResponse.

Библиотека определяет 3 дополнительных формата ответов:

  • DataResponse<T> - ответ, который представляет собой наборT

  • MetadataResponse<T> - содержит метаданные информации о типе

  • SimpleResponse - объект, содержащий два атрибутаsuccess иmessage

Затем давайте используемcurl, чтобы добавить записьDepartment в базу данных:

curl -i -X POST -H "Content-Type:application/json"
  -d "{"name":"IT"}" http://localhost:8080/linkrest/department

В результате команда возвращает статус201 Created и атрибутsuccess:

{"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() из классаLinkRest. Это возвращает объектSelectBuilder, который мы можем использовать для цепочки дополнительных методов запросов или фильтрации.

Давайте создадим конечную точку в классеDepartmentResource, которая возвращает все объектыDepartment в базе данных:

@GET
public DataResponse getAll(@Context UriInfo uriInfo) {
    return LinkRest.select(Department.class, config).uri(uriInfo).get();
}

Вызовuri() устанавливает информацию запроса дляSelectBuilder, а get () возвращает коллекциюDepartments, упакованную как объектDataResponse<Department>.

Давайте посмотрим на отделы, которые мы добавили перед использованием этой конечной точки:

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}

В качестве альтернативы, чтобы получить коллекцию объектов, мы также можем вернуть один объект, используяgetOne() вместоget().

Давайте добавим конечную точку, сопоставленную с/department/{departmentId}, которая возвращает объект с заданным идентификатором. Для этого отфильтруем записи с помощью методаbyId():

@GET
@Path("{id}")
public DataResponse getOne(@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() илиcreateOrUpdate(). Последний обновит записи, если они существуют, или создаст их, если их нет:

@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. Работа с отношениями между объектами

LinkRest также содержит методы, упрощающие работу с отношениями между объектами.

ПосколькуDepartment имеет отношение «один ко многим» сEmployee, давайте добавим конечную точку/department/{departmentId}/employees, которая обращается к классуEmployeeSubResource:

@Path("{id}/employees")
public EmployeeSubResource getEmployees(
  @PathParam("id") int id, @Context UriInfo uriInfo) {
    return new EmployeeSubResource(id);
}

КлассEmployeeSubResource соответствует отделу, поэтому у него будет конструктор, который устанавливает идентификатор отдела, а также экземпляр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 DataResponse getAll(@Context UriInfo uriInfo) {
    return LinkRest.select(Employee.class, config)
      .toManyParent(Department.class, departmentId, Department.EMPLOYEES)
      .uri(uriInfo).get();
}

В этом примере мы использовали методtoManyParent() дляSelectBuilder, чтобы запрашивать только объекты с данным родителем.

Конечные точки для методов POST, PUT, DELETE могут быть созданы аналогичным образом.

Чтобы добавить сотрудников в отдел, мы можем вызвать конечную точкуdepartments/{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. Настройка ответа с параметрами запроса

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

6.1. фильтрация

Мы можем отфильтровать результаты на основе значений атрибутов с помощью параметраcayenneExp. Как следует из названия, это соответствует формату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, используя фреймворкLinkRest.

Полный исходный код примеров можно найтиover on GitHub.