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 .