Статьи

Легкая альтернатива JAX-RS

HTTP-RPC — это платформа с открытым исходным кодом для упрощения разработки приложений REST. Он позволяет разработчикам получать доступ к веб-службам на основе REST с использованием удобной RPC-подобной метафоры, сохраняя при этом основные принципы REST, такие как отсутствие состояния и постоянный доступ к ресурсам. В настоящее время проект включает поддержку использования веб-сервисов в Objective-C / Swift и Java (включая Android), что упрощает взаимодействие со службами независимо от целевого устройства или операционной системы.

HTTP-RPC также включает дополнительную поддержку для реализации служб REST в Java, обеспечивая легкую альтернативу более крупным средам REST, таким как JAX-RS. Вся платформа распространяется в виде двух файлов JAR размером около 30 КБ, что делает ее идеальным выбором для приложений, где требуется минимальная площадь.

В этой статье описывается структура сервера HTTP-RPC и дается обзор его основных функций.

DispatcherServlet

DispatcherServletабстрактный базовый класс для служб REST. Сервисные операции определяются путем добавления открытых методов к конкретной реализации сервиса.

Методы вызываются путем отправки HTTP-запроса на путь, связанный с экземпляром сервлета. Аргументы предоставляются либо через строку запроса, либо в теле запроса (например, в форме HTML), либо в виде JSON. DispatcherServletпреобразует параметры запроса в ожидаемые типы аргументов, вызывает метод и сериализует возвращаемое значение в выходной поток как JSON.

RequestMethodАннотации используются для связывания методы службы с HTTP глагола , такими как GETили POST. Необязательную ResourcePathаннотацию можно использовать, чтобы связать метод с конкретным путем относительно сервлета. Если не указан, метод связан с самим сервлетом.

Несколько методов могут быть связаны с одним и тем же глаголом и путем. DispatcherServletвыбирает лучший метод для выполнения на основе предоставленных значений аргумента. Например, следующий класс обслуживания может быть использован для реализации некоторых простых математических операций:

@WebServlet(urlPatterns={"/math/*"})
public class MathServlet extends DispatcherServlet {
    @RequestMethod("GET")
    @ResourcePath("/sum")
    public double getSum(double a, double b) {
        return a + b;
    }

    @RequestMethod("GET")
    @ResourcePath("/sum")
    public double getSum(List values) {
        double total = 0;

        for (double value : values) {
            total += value;
        }

        return total;
    }
}

Следующий запрос вызовет первый метод:

GET /math/sum?a=2&b=4

Этот запрос будет вызывать второй метод:

GET /math/sum?values=1&values=2&values=3

В любом случае служба вернет значение 6 в ответ.

Аргументы метода

Аргументы метода могут быть любого из следующих типов:

  • Числовой класс примитива или оболочки (например, intили Integer)
  • boolean или Boolean
  • String
  • java.util.List
  • java.util.Map
  • java.net.URL

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

URLаргументы представляют загрузку файлов. Они могут использоваться только с POSTзапросами, отправленными с использованием кодирования данных из нескольких частей. Например:

@WebServlet(urlPatterns={"/upload/*"})
@MultipartConfig
public class FileUploadServlet extends DispatcherServlet {
    @RequestMethod("POST")
    public void upload(URL file) throws IOException {
        ...
    }

    @RequestMethod("POST")
    public void upload(List files) throws IOException {
        ...
    }
}

Возвращаемые значения

Возвращаемые значения преобразуются в их эквиваленты JSON следующим образом:

  • Number: число
  • Boolean: правда / ложь
  • CharSequence: строка
  • Iterable: массив
  • java.util.Map: объект

Методы также могут возвращать voidили Voidуказывать, что они не производят значение.

Например, следующий метод создаст объект JSON, содержащий три значения. В mapOf()и entry()методах обеспечиваются основами для создания карты упрощающего:

@RequestMethod("GET")
public Map getMap() {
    return mapOf(
        entry("text", "Lorem ipsum"),
        entry("number", 123),
        entry("flag", true)
    );
}

Служба выдаст в ответ следующее:

{
    "text": "Lorem ipsum",
    "number": 123,
    "flag": true
}

Свойства запроса и ответа

DispatcherServlet предоставляет следующие методы, позволяющие службе получать доступ к объектам запросов и ответов, связанных с текущей операцией:

protected HttpServletRequest getRequest() { ... }
protected HttpServletResponse getResponse() { ... }

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

Объект ответа также можно использовать для получения пользовательского результата. Если метод службы фиксирует ответ путем записи в выходной поток, возвращаемое значение (если оно есть) будет игнорироваться DispatcherServlet. Это позволяет службе возвращать содержимое, которое не может быть легко представлено в виде JSON, например данные изображения или альтернативные текстовые форматы.

Переменные пути

Переменные пути могут быть указаны с помощью «?» персонаж в пути к ресурсу. Например:

@RequestMethod("GET")
@ResourcePath("/contacts/?/addresses/?")
public List<Map<String, ?>> getContactAddresses() { ... }

getKeys() Метод возвращает список переменных , связанных с текущим запросом:

protected List<String> getKeys() { ... }

Например, указан следующий путь:

/contacts/jsmith/addresses/home

getKeys() вернет следующее:

["jsmith", "home"]

Резюме

HTTP-RPC — это платформа с открытым исходным кодом для упрощения разработки приложений REST. Он обеспечивает легкую альтернативу более крупным инфраструктурам Java REST, таким как JAX-RS, что делает его идеальным выбором для приложений с малым размером, таких как микросервисы или IoT .

Для получения дополнительной информации см. Проект README .