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
Эта команда запустит мастер. Затем мы можем либо использовать параметры по умолчанию, либо изменить их в соответствии с нашими требованиями:
Поскольку мы решили сгенерировать 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 перечислены все доступные маршруты, включая все параметры:
И мы можем нажать на отдельные маршруты и попробовать их на самой консоли:
11.2. Мониторинг
Раздел JVM Metrics показывает метрики приложения с активными сеансами, использованием памяти и дампом потока:
В Application Metrics у нас есть в основном две категории элементов, отслеживаемых по умолчанию:
BUILD
соответствует созданию экземпляров компонентов приложения.HTTP
соответствует HTTP-запросам, обрабатываемым RESTX.
11.3. Статистика
RESTX позволяет пользователю собирать и делиться анонимной статистикой в приложении, чтобы предоставлять информацию сообществу RESTX. Мы можем легко отказаться, исключив модуль restx-stats-admin
.
Статистика сообщает о таких вещах, как базовая ОС и версия JVM:
Поскольку на этой странице отображается конфиденциальная информация, обязательно проверьте ее параметры конфигурации .
Помимо этого, консоль администратора также может помочь нам:
- проверить журналы сервера (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 .