1. Обзор
В этом уроке мы проведем экскурсию по облегченной платформе Java REST/| RESTX .
2. Особенности
Создание RESTful API довольно просто с помощью фреймворка REST. Он имеет все значения по умолчанию, которые мы можем ожидать от фреймворка REST, такие как обслуживание и потребление JSON, параметры запросов и путей, механизмы маршрутизации и фильтрации, статистика использования и мониторинг.
RESTX также поставляется с интуитивно понятной веб-консолью администратора и установщиком командной строки для легкой загрузки.
Он также лицензирован под лицензией Apache License 2 и поддерживается сообществом разработчиков. Минимальное требование Java для RESTX-JDK 7.
3. Конфигурация
REST поставляется с удобным приложением оболочки/команды, которое полезно для быстрой загрузки проекта Java.
Нам нужно сначала установить приложение, прежде чем мы сможем продолжить. Подробная инструкция по установке доступна здесь .
4. Установка Основных Плагинов
Теперь пришло время установить основные плагины, чтобы иметь возможность создавать приложение из самой оболочки.
В оболочке REST давайте выполним следующую команду:
shell install
Затем он предложит нам выбрать плагины для установки. Нам нужно выбрать число, которое указывает на io.restx:restx-core-shell . Оболочка автоматически перезапустится после завершения установки.
5. Начальная загрузка приложения Оболочки
С помощью оболочки REST очень удобно загружать новое приложение. Он предоставляет руководство на основе мастера.
Мы начинаем с выполнения следующей команды в оболочке:
app new
Эта команда запустит мастер. Затем мы можем либо использовать параметры по умолчанию, либо изменить их в соответствии с нашими требованиями:
Поскольку мы решили создать pom.xml, проект можно легко импортировать в любую стандартную среду разработки Java.
В некоторых случаях нам может потребоваться настроить настройки IDE .
Нашим следующим шагом будет создание проекта:
mvn clean install -DskipTests
После успешной сборки мы можем запустить класс AppServer в качестве Java-приложения из IDEA . Это запустит сервер с консолью администратора, прослушивая порт 8080.
Мы можем перейти к http://127.0.0.1:8080/api/@/ui и посмотрите базовый пользовательский интерфейс.
Маршруты, начинающиеся с /@/ используются для консоли администратора, которая является зарезервированным путем в REST.
Для входа в консоль администратора мы можем использовать имя пользователя по умолчанию “admin ” и пароль, который мы предоставили при создании приложения.
Прежде чем мы поиграем с консолью, давайте изучим код и поймем, что сгенерировал мастер.
6. Ресурс ОТДЫХА
Маршруты определены в файле < 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. По большей части он использует свои собственные аннотации для внедрения зависимостей.
REST X также поддерживает множество разумных значений по умолчанию для параметров метода сопоставления с запросом .
И, в дополнение к этим стандартным аннотациям, @@Restresource , который объявляет его как ресурс, который распознает 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 используется для указания имени создаваемого компонента.
Модуль приложения также предоставляет ключ Подписи , используемый для подписи содержимого, отправляемого клиентам. Например, при создании сеанса для примера приложения будет установлен файл cookie, подписанный настроенным ключом:
HTTP/1.1 200 OK ... Set-Cookie: RestxSessionSignature-restx-demo="ySfv8FejvizMMvruGlK3K2hwdb8="; RestxSession-restx-demo="..." ...
И проверьте Завод компонентов Rest/документацию по внедрению зависимостей для получения дополнительной информации.
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();
}
}Здесь режим dev используется на этапе разработки для включения таких функций, как автоматическая компиляция, которая сокращает цикл обратной связи разработки.
Мы можем упаковать приложение в виде война файл (веб-архив) для развертывания в автономном веб-контейнере J2EE.
Давайте узнаем, как протестировать приложение в следующем разделе.
9. Интеграционное Тестирование С Использованием Спецификаций
Одной из сильных особенностей REST является его концепция “спецификаций”. Образец 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 является пользовательским бегуном JUnit . Он содержит пользовательские правила JUnit для:
- настройка встроенного сервера
- подготовьте состояние системы (в соответствии с приведенным разделом в спецификациях)
- выдавать указанные запросы и
- проверьте ожидаемые ответы
Аннотация @FindSpecsIn указывает путь к файлам спецификаций, по которым должны выполняться тесты.
Спецификация помогает писать интеграционные тесты и приводить примеры в документах API. Спецификации также полезны для макетных HTTP-запросов и записи пар запрос/ответ .
10. Ручное Тестирование
Мы также можем тестировать вручную по HTTP. Сначала нам нужно войти в систему, и для этого нам нужно хэшировать пароль администратора в консоли REST:
hash md5
А затем мы можем передать это в конечную точку /сеансов :
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.)
А теперь, если мы используем сеанс как часть нашего /сообщения запроса:
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 показаны метрики приложения с активными сеансами, использованием памяти и дампом потока:
В разделе Метрики приложений у нас есть в основном две категории элементов, отслеживаемых по умолчанию:
- BUILD соответствует созданию экземпляров компонентов приложения
- HTTP соответствует HTTP-запросам, обрабатываемым RESTX
11.3. Статистика
REST позволяет пользователю выбирать сбор и обмен анонимной статистикой в приложении, чтобы предоставить информацию сообществу REST. Мы можем легко отказаться, исключив модуль rest-stats-admin .
Статистика сообщает о таких вещах, как базовая ОС и версия JVM:
Поскольку на этой странице отображается конфиденциальная информация, обязательно просмотрите параметры ее конфигурации .
Помимо этого, консоль администратора также может помочь нам:
- проверьте журналы сервера (Журналы)
- просмотр обнаруженных ошибок (ошибок)
- проверьте переменные среды (Config)
12. Авторизация
Конечные точки REST защищены по умолчанию. Это означает, что если для любой конечной точки:
@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);
}С помощью этой аннотации REST проверит, назначена ли аутентифицированному пользователю также роль администратора. В случае, если аутентифицированный пользователь без ролей администратора попытается получить доступ к конечной точке, приложение вернет 403 вместо 401 .
По умолчанию роли пользователей и учетные данные хранятся в файловой системе в отдельных файлах.
Таким образом, идентификатор пользователя с зашифрованным паролем хранится в файле /data/credentials.json file:
{
"user1": "$2a$10$iZluUbCseDOvKnoe",
"user2": "$2a$10$oym3Swr7pScdiCXu"
}И роли пользователей определены в файле /data/users.json :
[
{"name":"user1", "roles": ["hello"]},
{"name":"user2", "roles": []}
]В примере приложения файлы загружаются в модуль приложения через Файловый пользовательский репозиторий класс:
new FileBasedUserRepository<>(StdUser.class, mapper,
new StdUser("admin", ImmutableSet. of("*")),
Paths.get("data/users.json"), Paths.get("data/credentials.json"), true) Класс Std User содержит объекты пользователя. Это может быть пользовательский пользовательский класс, но он должен быть сериализуемым в JSON.
Конечно, мы можем использовать другую реализацию UserRepository , например, ту, которая попадает в базу данных.
13. Заключение
В этом учебном пособии представлен обзор облегченной платформы REST на основе Java.
Фреймворк все еще находится в разработке, и при его использовании могут возникнуть некоторые шероховатости. Проверьте официальную документацию для получения более подробной информации.
Пример загрузочного приложения доступен в нашем репозитории GitHub .