Введение в RESTX

Введение в RESTX

1. обзор

В этом руководстве мы познакомимся с облегченной инфраструктурой Java RESTRESTX.

2. Характеристики

Создать RESTful API довольно просто с помощью среды RESTX. Он имеет все значения по умолчанию, которые мы можем ожидать от инфраструктуры REST, такие как обслуживание и использование JSON, параметры запросов и путей, механизмы маршрутизации и фильтрации, статистика использования и мониторинг.

RESTX также поставляется с интуитивно понятной административной веб-консолью и установщиком командной строки для легкой загрузки.

Он также под лицензией Apache License 2 и поддерживается сообществом разработчиков. Минимальное требование Java для RESTX - 7 JDK.

3. конфигурация

RESTX поставляется с удобной оболочкой / командным приложением, которое полезно для быстрой загрузки проекта Java.

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

4. Установка основных плагинов

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

В оболочке RESTX выполним следующую команду:

shell install

Затем он предложит нам выбрать плагины для установки. Нам нужно выбрать число, которое указывает наio.restx:restx-core-shell. The shell will automatically restart once installation completes.

5. Shell App Bootstrap

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

Мы начнем с выполнения следующей команды в оболочке:

app new

Эта команда запустит мастера. Затем мы можем либо использовать параметры по умолчанию, либо изменить их в соответствии с нашими требованиями:

imageimage

Поскольку мы выбрали созданиеpom.xml,, проект можно легко импортировать в любую стандартную среду разработки Java.

В некоторых случаях нам может потребоваться настроитьthe IDE settings.

Нашим следующим шагом будет создание проекта:

mvn clean install -DskipTests

Once the build is successful we can run the AppServer class as a Java Application from the IDE. Это запустит сервер с консолью администратора, прослушивающей порт 8080.

Мы можем перейти кhttp://127.0.0.1:8080/api/@/ui и увидеть базовый интерфейс.

Маршруты, начинающиеся с/@/, используются для консоли администратора, которая является зарезервированным путем в RESTX.

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

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

6. Ресурс RESTX

Маршруты определены в классе <main_package>.rest.HelloResource:

@Component
@RestxResource
public class HelloResource {
    @GET("/message")
    @RolesAllowed(Roles.HELLO_ROLE)
    public Message sayHello() {
        return new Message().setMessage(String.format("hello %s, it's %s",
          RestxSession.current().getPrincipal().get().getName(),
          DateTime.now().toString("HH:mm:ss")));
    }
}

Сразу видно, что RESTX использует аннотации J2EE по умолчанию для безопасности и привязок REST. По большей части он использует свои собственные аннотации для внедрения зависимостей.

RESTX также поддерживает множество разумных значений по умолчанию дляmapping method parameters to the request.

И в дополнение к этим стандартным аннотациям есть@RestxResource, который объявляет его как ресурс, который распознает RESTX.

Базовый путь добавляется вsrc/main/webapp/WEB-INF/web.xml.. В нашем случае это/api, поэтому мы можем отправить запрос GET наhttp://localhost:8080/api/message при условии правильной аутентификации.

КлассMessage - это просто Java-компонент, который RESTX сериализует в JSON.

Мы контролируем доступ пользователей, указывая аннотациюRolesAllowed с помощьюHELLO_ROLE, которая была сгенерирована загрузчиком.

7. Модульный класс

Как отмечалось ранее, RESTX использует стандартные аннотации внедрения зависимостей J2EE, такие как@Named, и при необходимости изобретает свои собственные, вероятно, следуя реплике из инфраструктуры Dagger для@Module и@Provides..

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

@Module
public class AppModule {

    @Provides
    public SignatureKey signatureKey() {
        return new SignatureKey("restx-demo -44749418370 restx-demo 801f-4116-48f2-906b"
            .getBytes(Charsets.UTF_8));
    }

    @Provides
    @Named("restx.admin.password")
    public String restxAdminPassword() {
        return "1234";
    }

    @Provides
    public ConfigSupplier appConfigSupplier(ConfigLoader configLoader) {
        return configLoader.fromResource("restx/demo/settings");
    }

    // other provider methods to create components
}

@Module  определяет класс, который может определять другие компоненты, аналогично@Module в Dagger или@Configuration in Spring.

@Provides предоставляет компонент программно, например@Provides in Dagger или@Bean в Spring.

И, наконец, аннотация@Named используется для обозначения имени производимого компонента.

AppModule также предоставляетSignatureKey, используемый для подписи контента, отправляемого клиентам. Например, при создании сеанса для примера приложения будет установлен файл cookie, подписанный с помощью настроенного ключа:

HTTP/1.1 200 OK
...
Set-Cookie: RestxSessionSignature-restx-demo="ySfv8FejvizMMvruGlK3K2hwdb8="; RestxSession-restx-demo="..."
...

И посмотритеRESTX’s components factory/dependency injection documentation, чтобы узнать больше.

8. Класс Launcher

И, наконец, классAppServer используется для запуска приложения как стандартного Java-приложения на встроенном сервере Jetty:

public class AppServer {
    public static final String WEB_INF_LOCATION = "src/main/webapp/WEB-INF/web.xml";
    public static final String WEB_APP_LOCATION = "src/main/webapp";

    public static void main(String[] args) throws Exception {
        int port = Integer.valueOf(Optional.fromNullable(System.getenv("PORT")).or("8080"));
        WebServer server =
            new Jetty8WebServer(WEB_INF_LOCATION, WEB_APP_LOCATION, port, "0.0.0.0");
        System.setProperty("restx.mode", System.getProperty("restx.mode", "dev"));
        System.setProperty("restx.app.package", "restx.demo");
        server.startAndAwait();
    }
}

Здесь режимdev используется на этапе разработки, чтобы включить такие функции, как автоматическая компиляция, которая сокращает цикл обратной связи разработки.

Мы можем упаковать приложение в виде файлаwar (веб-архив) для развертывания в автономном веб-контейнере J2EE.

Давайте узнаем, как протестировать приложение, в следующем разделе.

9. Интеграционное тестирование с использованием спецификаций

Одной из сильных сторон RESTX является концепция «спецификаций». Примерspec будет выглядеть так:

title: should admin say hello
given:
  - time: 2013-08-28T01:18:00.822+02:00
wts:
  - when: |
      GET hello?who=xavier
    then: |
      {"message":"hello xavier, it's 01:18:00"}

Тест написан в структуреGiven-When-Then в файлеYAML, который в основном определяет, как API должен отвечать (then) на конкретный запрос (when) с учетом текущего состояния. системы (given).

КлассHelloResourceSpecTest вsrc/test/resources запускает тесты, указанные в спецификациях выше:

@RunWith(RestxSpecTestsRunner.class)
@FindSpecsIn("specs/hello")
public class HelloResourceSpecTest {}

КлассRestxSpecTestsRunner - этоcustom JUnit runner. Он содержит пользовательские правила JUnit для:

  • настроить встроенный сервер

  • подготовить состояние системы (согласно разделуgiven в спецификации)

  • выдать указанные запросы, и

  • проверить ожидаемые ответы

Аннотация@FindSpecsIn указывает путь к файлам спецификаций, по которым должны выполняться тесты.

The spec helps to write integration tests and provide examples in the API docs. Спецификации также полезны дляmock HTTP requests and record request/response pairs.

10. Ручное тестирование

Мы также можем проверить вручную через HTTP. Сначала нам нужно войти в систему, и для этого нам нужно хэшировать пароль администратора в консоли RESTX:

hash md5 

А затем мы можем передать это в конечную точку/sessions:

curl -b u1 -c u1 -X POST -H "Content-Type: application/json"
  -d '{"principal":{"name":"admin","passwordHash":"1d528266b85cf052803a57288"}}'
  http://localhost:8080/api/sessions

(Обратите внимание, что пользователям Windows нужно сначала завитьdownload.)

А теперь, если мы используем сеанс как часть нашего запроса/message:

curl -b u1 "http://localhost:8080/api/message?who=restx"

Тогда мы получим что-то вроде этого:

{"message" : "hello admin, it's 09:56:51"}

11. Изучение консоли администратора

Консоль администратора предоставляет полезные ресурсы для управления приложением.

Давайте посмотрим на ключевые функции, перейдя кhttp://127.0.0.1:8080/admin/@/ui.

11.1. API Документы

В разделе API docs перечислены все доступные маршруты, включая все параметры:

imageimage

И мы можем нажать на отдельные маршруты и опробовать их на самой консоли:

imageimage

11.2. мониторинг

В разделеJVM Metrics показаны показатели приложения с активными сеансами, использованием памяти и дампом потока:

imageimage

ВApplication Metrics мы имеем в основном две категории элементов, отслеживаемых по умолчанию:

  • BUILD соответствует экземпляру компонентов приложения

  • HTTP соответствует HTTP-запросам, обрабатываемым RESTX

11.3. Статистика

RESTX позволяет пользователю выбирать и делиться анонимной статистикой в ​​приложении, чтобы предоставлять информацию сообществу RESTX. We can easily opt out by excluding the restx-stats-admin module.с

Статистика сообщает о таких вещах, как базовая ОС и версия JVM:

imageimage

Because this page shows sensitive information,make sure to review its configuration options.

Помимо этого, консоль администратора также может помочь нам:

  • проверьте логи сервера (Logs)

  • просмотреть обнаруженные ошибки (Errors)

  • проверить переменные среды (Config)

12. авторизация

RESTX endpoints are secured by default. Это означает, что для любой конечной точки:

@GET("/greetings/{who}")
public Message sayHello(String who) {
    return new Message(who);
}

При вызове без аутентификации по умолчанию возвращается401 .

Чтобы сделать конечную точку общедоступной, нам нужно использовать аннотацию@PermitAll либо на уровне метода, либо на уровне класса:

@PermitAll
@GET("/greetings/{who}")
public Message sayHello(String who) {
    return new Message(who);
}

Обратите внимание, что на уровне класса все методы являются общедоступными.

Кроме того, фреймворк также позволяет указывать роли пользователей с помощью аннотации@RolesAllowed:

@RolesAllowed("admin")
@GET("/greetings/{who}")
public Message sayHello(String who) {
    return new Message(who);
}

С помощью этой аннотации RESTX проверит, назначена ли аутентифицированному пользователю также роль администратора. В случае, если аутентифицированный пользователь без ролей администратора попытается получить доступ к конечной точке, приложение вернет403  вместо401.

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

Итак, идентификатор пользователя с зашифрованным паролем хранится в файле/data/credentials.json:

{
    "user1": "$2a$10$iZluUbCseDOvKnoe",
    "user2": "$2a$10$oym3Swr7pScdiCXu"
}

И роли пользователей определены в файле/data/users.json:

[
    {"name":"user1", "roles": ["hello"]},
    {"name":"user2", "roles": []}
]

В примере приложения файлы загружаются вAppModule через классFileBasedUserRepository:

new FileBasedUserRepository<>(StdUser.class, mapper,
  new StdUser("admin", ImmutableSet. of("*")),
  Paths.get("data/users.json"), Paths.get("data/credentials.json"), true)

КлассStdUser содержит пользовательские объекты. Это может быть пользовательский класс пользователя, но он должен быть сериализуемым в JSON.

Конечно, мы можем использовать другую реализациюUserRepository, например, которая попадает в базу данных.


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

В этом руководстве дается обзор облегченной среды RESTX на основе Java.

Фреймворк все еще находится в разработке, и при его использовании могут возникнуть некоторые неровности. Посетитеthe official documentation для получения более подробной информации.

Образец загружаемого приложения доступен в нашихGitHub repository.