Шаблоны сайта содержат множество внутренних ссылок, которые ведут на меню, кнопки и формы. До сих пор мы формировали эти ссылки прямо в тех местах, где они нам нужны:
<h1>${page.getHeader()}</h1>
@if(page.getCourses().isEmpty())
<p>Пока не добавлено ни одного курса</P>
@else
@for(var course : page.getCourses())
<div>
<h2><a href="/courses/${course.getId()}">${course.getName()}</a></h2>
<p>${course.getDescription()}</p>
</div>
@endfor
@endif
Так же ссылки строятся и в обработчиках — например, при редиректах:
var id = /* Как-то формируется */;
ctx.redirect("/courses/" + id);
В примерах выше мы формируем ссылку именно там, где хотим ее использовать. У этого способа есть свои минусы. Для примера представим, что мы решили изменить маршрут с /courses/{id}
на /c/{id}
. В этом случае нам придется пройтись по всем шаблонам и вручную заменить маршрут во всех ссылках. Это долго и неудобно.
А что будет, если мы решим удалить маршрут /courses/{id}
? Тогда сайт продолжит работать, но все ссылки с удаленным маршрутом начнут вести на страницу 404. Не факт, что мы сразу заметим и исправим эту проблему. Будет лучше, если страницы с такими ссылками начнут выдавать ошибки. Тогда выявить подобные ссылки станет крайне просто. Для решения этой задачи придумали именованные маршруты, которые мы обсудим в этом уроке.
Как работают именованные маршруты
Каждому именованному маршруту фреймворка присваивается имя, которое можно использовать при построении конкретной ссылки. В Javalin такой механизм не встроен, но его легко сымитировать. Чтобы это сделать, вручную создадим класс с описанием маршрутов:
package org.example.hexlet;
public class NamedRoutes {
public static String usersPath() {
return "/users";
}
public static String buildUserPath() {
return "/users/build";
}
public static String coursesPath() {
return "/courses";
}
// Это нужно, чтобы не преобразовывать типы снаружи
public static String coursePath(Long id) {
return coursePath(String.valueOf(id));
}
public static String coursePath(String id) {
return "/courses/" + id;
}
}
В коде выше мы добавили методы. Теперь можно внедрить их в описание маршрутов Javalin и в шаблоны:
app.get(NamedRoutes.buildUserPath(), ctx -> {
app.get(NamedRoutes.coursesPath(), ctx -> {
app.get(NamedRoutes.coursePath("{id}"), ctx -> {
app.post(NamedRoutes.usersPath(), ctx -> {
Как видите, читаемость кода немного упала. Чтобы ее повысить, можно добавить комментарии над определениями маршрутов, например:
package org.example.hexlet;
public class NamedRoutes {
// Маршрут пользователей
public static String usersPath() {
return "/users";
}
}
Встраиваем в шаблон:
@import org.example.hexlet.NamedRoutes
@import org.example.hexlet.dto.CoursesPage
@param CoursesPage page
<h1>Список Курсов</h1>
@if(page.courses().isEmpty())
<p>Пока не добавлено ни одного курса</p>
@else
@for(var course : page.courses())
<div>
<h2><a href="${NamedRoutes.coursePath(course.getId())}">${course.getName()}</a></h2>
<p>${course.getDescription()}</p>
</div>
@endfor
@endif
Теперь ссылка формируется через вызов метода, что дает нам типобезопасность.
Самостоятельная работа
- Повторите на своем компьютере все шаги из урока
- Добавьте в приложение класс с именами маршрутов
- Измените код обработчиков и шаблонов так, чтобы они использовали именованные маршруты вместо ручного формирования ссылки
- Дальше вы прочувствуете преимущества именованных маршрутов. Измените в классе с именованными маршрутами адреса ссылок — например, вместо /users сделайте /u
- Запустите приложение и убедитесь, что оно продолжает работать с новыми адресами. Обратите внимание, что нам даже не пришлось менять код во всех обработчиках и шаблонах
- Залейте изменения на GitHub
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.