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

Приложение для составления списка дел с использованием React

В этом руководстве мы создадим приложение To-Do List с помощью ActiveJ и React. Мы рассмотрим, как интегрировать React в проект ActiveJ и как просто управлять маршрутизацией с помощью модуля HTTP. Полные исходные тексты примеров вы можете найти на GitHub

Здесь мы рассмотрим только основной класс приложения - ApplicationLauncher. В нем используется ActiveJ HttpServerLauncher и AsyncServlet классы для настройки встроенного сервера приложений. При таком подходе вы можете создавать серверы без XML-конфигураций или зависимостей от сторонних производителей. Более того, HttpServerLauncher автоматически позаботится о запуске, работе и остановке приложения. Вам нужно будет только обеспечить launcher сервлетами.

Создание программы запуска

ApplicationLauncher - это главный класс программы. Помимо запуска приложения, он также обрабатывает маршрутизацию и большую часть соответствующей логики. Мы будем использовать ActiveJ HttpServerLauncher и расширим его:

public final class ApplicationLauncher extends HttpServerLauncher {  @Provides  RecordDAO recordRepo() {    return new RecordImplDAO();  }
  @Provides  Executor executor() {    return newSingleThreadExecutor();  }
  @Provides  DslJson<?> dslJson() {    return new DslJson<>(Settings.withRuntime());  }

Во-первых, мы предоставили RecordDAO с бизнес-логикой приложения и Executor , который необходим для нашего AsyncServlet. Для преобразования объектов в/из JSON мы выбрали библиотеку DSL-JSON, , поэтому мы предоставляем объект DslJson<?> , который будет обрабатывать маршалинг данных. AsyncServlet загружает статическое содержимое из каталога /build и заботится о маршрутизации:

@ProvidesAsyncServlet servlet(Executor executor, RecordDAO recordDAO, DslJson<?> dslJson) {  return RoutingServlet.create()      .map("/*", StaticServlet.ofClassPath(executor, "build/")          .withIndexHtml())

Маршрутизация в HTTP-модуле ActiveJ напоминает подход Express. Метод map(@Nullable HttpMethod method, String path, AsyncServlet servlet) добавляет маршруты в RoutingServlet: метод (необязательно) является одним из HTTP методов (GET, POST, и т.д.). путь - это путь на сервере сервлет определяет логику обработки запроса. Если вам необходимо получить некоторые данные из запроса в процессе обработки, вы можете использовать: request.getPathParameter(String key)/request.getQueryParameter(String key) (см. пример использования параметров запроса для указания ключа нужного параметра и получения обратно соответствующей строки request.getPostParameters() для получения карты всех параметров запроса. Обратите внимание на `в предоставленном запросе. В нем говорится, что какой бы путь до следующего/не был получен, он будет обработан нашим статическим сервлетом, который загружает статическое содержимое из каталога/build` . Сервлет должен иметь возможность добавить новую запись, получить все доступные записи, удалить запись по ее id и также отметить планы конкретной записи как завершенные или нет, поэтому мы обеспечиваем соответствующую маршрутизацию:

.map(POST, "/add", request -> request.loadBody()    .map($ -> {      ByteBuf body = request.getBody();      try {        byte[] bodyBytes = body.getArray();        Record record = dslJson.deserialize(Record.class, bodyBytes, bodyBytes.length);        recordDAO.add(record);        return HttpResponse.ok200();      } catch (IOException e) {        return HttpResponse.ofCode(400);      }    })).map(GET, "/get/all", request -> {  Map<Integer, Record> records = recordDAO.findAll();  JsonWriter writer = dslJson.newWriter();  try {    dslJson.serialize(writer, records);  } catch (IOException e) {    throw new AssertionError(e);  }  return HttpResponse.ok200()      .withJson(writer.toString());})//[START REGION_4].map(GET, "/delete/:recordId", request -> {  int id = parseInt(request.getPathParameter("recordId"));  recordDAO.delete(id);  return HttpResponse.ok200();})//[END REGION_4].map(GET, "/toggle/:recordId/:planId", request -> {  int id = parseInt(request.getPathParameter("recordId"));  int planId = parseInt(request.getPathParameter("planId"));
  Record record = recordDAO.find(id);  Plan plan = record.getPlans().get(planId);  plan.toggle();  return HttpResponse.ok200();});

Обратите внимание на запросы с :, например:

.map(GET, "/delete/:recordId", request -> {  int id = parseInt(request.getPathParameter("recordId"));  recordDAO.delete(id);  return HttpResponse.ok200();})

: утверждает, что следующие символы до следующего / - это переменная, ключевым словом которой, в данном случае, является recordId.

Запуск приложения

Для выполнения примера клонируйте ActiveJ и импортируйте его как проект Maven. Посмотрите ветку v5.0. Перед запуском примера выполните сборку проекта (Ctrl F9 для IntelliJ IDEA). Затем выполните следующую команду в каталоге activej/examples/tutorials/react-integration-2/front в терминале:

npm inpm run-script build

Откройте ApplicationLauncher и запустите его метод main . Затем откройте ваш любимый браузер и перейдите по адресу localhost:8080. Попробуйте добавить и удалить некоторые задачи или отметить их как выполненные