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

Введение в RESTX

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

1. Обзор

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

2. Особенности

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

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

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

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

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

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

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

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

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

shell install

Затем нам будет предложено выбрать плагины для установки. Нам нужно выбрать номер, который указывает на io.restx:restx-core-shell . Оболочка автоматически перезапустится после завершения установки.

5. Начальная загрузка приложения оболочки

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

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

app new

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

./28203c464a208ba36cc8c301b5fbc567.png

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

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

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

mvn clean install -DskipTests

После успешной сборки мы можем запустить класс AppServer как Java-приложение из 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 также поддерживает множество разумных значений по умолчанию для сопоставления параметров метода с запросом .

И в дополнение к этим стандартным аннотациям есть @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 в Spring.

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

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

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

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

И ознакомьтесь с документацией по внедрению фабрики/зависимостей компонентов RESTX , чтобы узнать больше.

8. Класс запуска

И, наконец, класс 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();
}
}

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

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

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

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

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

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 должен реагировать ( тогда ) на конкретный запрос ( когда ) с учетом текущего состояния системы ( данно ).

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

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

Класс RestxSpecTestsRunner — это настраиваемый раннер JUnit . Он содержит настраиваемые правила JUnit для:

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

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

Спецификация помогает писать интеграционные тесты и предоставляет примеры в документации по API. Спецификации также полезны для имитации HTTP-запросов и записи пар запрос/ответ .

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

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

hash md5 <clear-text-password>

И затем мы можем передать это в конечную точку /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 необходимо сначала загрузить curl.)

А теперь, если мы используем сессию как часть нашего запроса /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 перечислены все доступные маршруты, включая все параметры:

./a19441390b4ead6fbe38e05e332454bc.png

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

./1315757352717099d5753362066ec9e1.png

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

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

./087ed02b05fa0c22f482987cb310b839.png

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

  • BUILD соответствует созданию экземпляров компонентов приложения.
  • HTTP соответствует HTTP-запросам, обрабатываемым RESTX.

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

RESTX позволяет пользователю собирать и делиться анонимной статистикой в приложении, чтобы предоставлять информацию сообществу RESTX. Мы можем легко отказаться, исключив модуль restx-stats-admin .

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

./fae85258294156a41a1b0290a1e06671.png

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

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

  • проверить журналы сервера (Logs)
  • просмотреть обнаруженные ошибки (Ошибки)
  • проверьте переменные среды (Config)

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

Конечные точки RESTX защищены по умолчанию. Это означает, что если для любой конечной точки:

@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.<String> of("*")),
Paths.get("data/users.json"), Paths.get("data/credentials.json"), true)

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

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

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

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

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

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