3.5.13.2. API маршрутизации

В этом разделе описываются ключевые понятия API маршрутизации.

Регистрация маршрута

Для регистрации маршрута экрана добавьте аннотацию @Route к контроллеру экрана, например:

@Route("my-screen")
public class MyScreen extends Screen {
}

Аннотация имеет три параметра:

  • path (или value) – собственно маршрут;

  • parentPrefix используется для сжатия маршрутов (смотрите ниже).

  • root – это свойство типа boolean, позволяющее указать, зарегистрирован ли маршрут для корневого экрана (например, экран входа в систему или главный экран). Значение по умолчанию – false.

    Если вы хотите создать корневой экран с маршрутом, отличным от login, и сделать его доступным по ссылке без входа в систему, вы должны разрешить его просмотр анонимным пользователям. В противном случае при вводе URL вида /app/#your_root_screen пользователь будет перенаправлен на /app/#login вместо открытия вашего корневого экрана.

    1. Добавьте cuba.web.allowAnonymousAccess = true в файл web-app.properties.

    2. Разрешите просмотр созданного экрана для анонимных пользователей: запустите приложение, перейдите в Администрирование > Роли и создайте новую роль с доступом к вашему экрану. Затем назначьте созданную роль пользователю anonymous.

Если вам нужно определить маршрут для устаревшего экрана, добавьте атрибут route (и необязательно routeParentPrefix, эквивалентный параметру parentPrefix, и rootRoute, эквивалентный параметру root) к элементу экрана в файле screens.xml, например:

<screen id="myScreen" template="..." route="my-screen" />
Сжатие маршрута

Эта функция предназначена для того, чтобы URL был понятным и читаемым при открытии нескольких экранов с маршрутами, имеющими одинаковые части.

Предположим, что у нас есть экраны браузера и редактора для сущности Order:

@Route("orders")
public class OrderBrowser extends StandardLookup<Order> {
}

@Route("orders/edit")
public class OrderEditor extends StandardEditor<Order> {
}

Сжатие URL используется, чтобы избежать повторения маршрута orders в URL, когда экран редактора открывается сразу после браузера. Просто укажите повторяющуюся часть в параметре parentPrefix аннотации @Route на экране редактора:

@Route("orders")
public class OrderBrowser extends StandardLookup<Order> {
}

@Route(value = "orders/edit", parentPrefix = "orders")
public class OrderEditor extends StandardEditor<Order> {
}

Теперь, когда редактор открыт в той же вкладке, что и браузер, полученный адрес будет похож на app/#main/0/orders/edit?id=…​

Отображение состояния пользовательского интерфейса на URL

Бин UrlRouting позволяет изменять текущий URL приложения в соответствии с текущим экраном и некоторыми параметрами. Он имеет следующие методы:

  • pushState() – изменяет адрес и отправляет новую запись истории браузера;

  • replaceState() – заменяет адрес без добавления новой записи истории браузера;

  • getState() – возвращает текущее состояние как объект NavigationState.

Методы pushState()/replaceState() принимают текущий контроллер экрана и дополнительный мэп параметров.

Смотрите пример использования UrlRouting в разделе ниже.

Фильтр навигации

Механизм фильтров навигации позволяет предотвратить переход на некоторые маршруты.

Фильтр навигации – это бин, реализующий интерфейс NavigationFilter. Аннотацию @Order можно использовать для настройки порядка вызова всех фильтров навигации. Используйте константы NavigationFilter.HIGHEST_PLATFORM_PRECEDENCE и NavigationFilter.LOWEST_PLATFORM_PRECEDENCE чтобы задать диапазон, используемый фильтрами, определенными в фреймворке.

Интерфейс NavigationFilter имеет метод allowed(), который принимает два аргумента: текущее состояние навигации fromState и запрошенное состояние навигации toState. Метод возвращает экземпляр AccessCheckResult и проверяет, разрешен ли переход из текущего состояния навигации в запрошенное состояние.

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

@Component
@Order(NavigationFilter.LOWEST_PLATFORM_PRECEDENCE)
public class CubaLoginScreenFilter implements NavigationFilter {
    @Inject
    protected Messages messages;

    @Override
    public AccessCheckResult allowed(NavigationState fromState, NavigationState toState) {
        if (!"login".equals(toState.getRoot())) {
            return AccessCheckResult.allowed();
        }
        boolean authenticated = App.getInstance().getConnection().isAuthenticated();
        return authenticated
                ? AccessCheckResult.rejected(messages.getMainMessage("navigation.unableToGoToLogin"))
                : AccessCheckResult.allowed();
    }
}